X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=ld%2Fldlang.c;h=e640380e90181de6e68145d41a7133c797d18557;hb=c57ac5108667b52f5cde6c1bbdd4a1496626c1a8;hp=eaf90a63cba0b1850b9e90d8214befb322b2481d;hpb=139633c307eb6f5746ea04f94a0b6382e51bccb9;p=binutils-gdb.git diff --git a/ld/ldlang.c b/ld/ldlang.c index eaf90a63cba..e640380e901 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -1,5 +1,5 @@ /* Linker command language support. - Copyright (C) 1991-2020 Free Software Foundation, Inc. + Copyright (C) 1991-2022 Free Software Foundation, Inc. This file is part of the GNU Binutils. @@ -63,19 +63,12 @@ static struct obstack map_obstack; #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free static const char *entry_symbol_default = "start"; -static bfd_boolean map_head_is_link_order = FALSE; +static bool map_head_is_link_order = false; static lang_output_section_statement_type *default_common_section; -static bfd_boolean map_option_f; +static bool map_option_f; static bfd_vma print_dot; static lang_input_statement_type *first_file; static const char *current_target; -/* Header for list of statements corresponding to any files involved in the - link, either specified from the command-line or added implicitely (eg. - archive member used to resolved undefined symbol, wildcard statement from - linker script, etc.). Next pointer is in next field of a - lang_statement_header_type (reached via header field in a - lang_statement_union). */ -static lang_statement_list_type statement_list; static lang_statement_list_type *stat_save[10]; static lang_statement_list_type **stat_save_ptr = &stat_save[0]; static struct unique_sections *unique_section_list; @@ -86,23 +79,30 @@ static unsigned int opb_shift = 0; static void exp_init_os (etree_type *); static lang_input_statement_type *lookup_name (const char *); static void insert_undefined (const char *); -static bfd_boolean sort_def_symbol (struct bfd_link_hash_entry *, void *); +static bool sort_def_symbol (struct bfd_link_hash_entry *, void *); static void print_statement (lang_statement_union_type *, lang_output_section_statement_type *); static void print_statement_list (lang_statement_union_type *, lang_output_section_statement_type *); static void print_statements (void); -static void print_input_section (asection *, bfd_boolean); -static bfd_boolean lang_one_common (struct bfd_link_hash_entry *, void *); +static void print_input_section (asection *, bool); +static bool lang_one_common (struct bfd_link_hash_entry *, void *); static void lang_record_phdrs (void); static void lang_do_version_exports_section (void); static void lang_finalize_version_expr_head (struct bfd_elf_version_expr_head *); -static void lang_do_memory_regions (bfd_boolean); +static void lang_do_memory_regions (bool); /* Exported variables. */ const char *output_target; lang_output_section_statement_type *abs_output_section; +/* Header for list of statements corresponding to any files involved in the + link, either specified from the command-line or added implicitely (eg. + archive member used to resolved undefined symbol, wildcard statement from + linker script, etc.). Next pointer is in next field of a + lang_statement_header_type (reached via header field in a + lang_statement_union). */ +lang_statement_list_type statement_list; lang_statement_list_type lang_os_list; lang_statement_list_type *stat_ptr = &statement_list; /* Header for list of statements corresponding to files used in the final @@ -122,11 +122,11 @@ 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; -bfd_boolean entry_from_cmdline; -bfd_boolean lang_has_input_file = FALSE; -bfd_boolean had_output_filename = FALSE; -bfd_boolean lang_float_flag = FALSE; -bfd_boolean delete_output_file_on_failure = FALSE; +bool entry_from_cmdline; +bool lang_has_input_file = false; +bool had_output_filename = false; +bool lang_float_flag = false; +bool delete_output_file_on_failure = false; struct lang_phdr *lang_phdr_list; struct lang_nocrossrefs *nocrossref_list; struct asneeded_minfo **asneeded_list_tail; @@ -219,18 +219,18 @@ archive_path (const char *pattern) /* Given that FILE_SPEC results in a non-NULL SEP result from archive_path, return whether F matches FILE_SPEC. */ -static bfd_boolean +static bool input_statement_is_archive_path (const char *file_spec, char *sep, lang_input_statement_type *f) { - bfd_boolean match = FALSE; + bool match = false; if ((*(sep + 1) == 0 || name_match (sep + 1, f->filename) == 0) && ((sep != file_spec) == (f->the_bfd != NULL && f->the_bfd->my_archive != NULL))) { - match = TRUE; + match = true; if (sep != file_spec) { @@ -243,7 +243,7 @@ input_statement_is_archive_path (const char *file_spec, char *sep, return match; } -static bfd_boolean +static bool unique_section_p (const asection *sec, const lang_output_section_statement_type *os) { @@ -259,9 +259,9 @@ unique_section_p (const asection *sec, secnam = sec->name; for (unam = unique_section_list; unam; unam = unam->next) if (name_match (unam->name, secnam) == 0) - return TRUE; + return true; - return FALSE; + return false; } /* Generic traversal routines for finding matching sections. */ @@ -269,7 +269,7 @@ unique_section_p (const asection *sec, /* Return true if FILE matches a pattern in EXCLUDE_LIST, otherwise return false. */ -static bfd_boolean +static bool walk_wild_file_in_exclude_list (struct name_list *exclude_list, lang_input_statement_type *file) { @@ -284,11 +284,11 @@ walk_wild_file_in_exclude_list (struct name_list *exclude_list, if (p != NULL) { if (input_statement_is_archive_path (list_tmp->name, p, file)) - return TRUE; + return true; } else if (name_match (list_tmp->name, file->filename) == 0) - return TRUE; + return true; /* FIXME: Perhaps remove the following at some stage? Matching unadorned archives like this was never documented and has @@ -297,10 +297,10 @@ walk_wild_file_in_exclude_list (struct name_list *exclude_list, && file->the_bfd->my_archive != NULL && name_match (list_tmp->name, bfd_get_filename (file->the_bfd->my_archive)) == 0) - return TRUE; + return true; } - return FALSE; + return false; } /* Try processing a section against a wildcard. This just calls @@ -320,7 +320,7 @@ walk_wild_consider_section (lang_wild_statement_type *ptr, if (walk_wild_file_in_exclude_list (sec->spec.exclude_name_list, file)) return; - (*callback) (ptr, sec, s, ptr->section_flag_list, file, data); + (*callback) (ptr, sec, s, file, data); } /* Lowest common denominator routine that can handle everything correctly, @@ -339,11 +339,11 @@ walk_wild_section_general (lang_wild_statement_type *ptr, { sec = ptr->section_list; if (sec == NULL) - (*callback) (ptr, sec, s, ptr->section_flag_list, file, data); + (*callback) (ptr, sec, s, file, data); while (sec != NULL) { - bfd_boolean skip = FALSE; + bool skip = false; if (sec->spec.name != NULL) { @@ -366,30 +366,30 @@ walk_wild_section_general (lang_wild_statement_type *ptr, typedef struct { asection *found_section; - bfd_boolean multiple_sections_found; + bool multiple_sections_found; } section_iterator_callback_data; -static bfd_boolean +static bool section_iterator_callback (bfd *abfd ATTRIBUTE_UNUSED, asection *s, void *data) { section_iterator_callback_data *d = (section_iterator_callback_data *) data; if (d->found_section != NULL) { - d->multiple_sections_found = TRUE; - return TRUE; + d->multiple_sections_found = true; + return true; } d->found_section = s; - return FALSE; + return false; } static asection * find_section (lang_input_statement_type *file, struct wildcard_list *sec, - bfd_boolean *multiple_sections_found) + bool *multiple_sections_found) { - section_iterator_callback_data cb_data = { NULL, FALSE }; + section_iterator_callback_data cb_data = { NULL, false }; bfd_get_section_by_name_if (file->the_bfd, sec->spec.name, section_iterator_callback, &cb_data); @@ -403,29 +403,29 @@ find_section (lang_input_statement_type *file, /* A simple wild is a literal string followed by a single '*', where the literal part is at least 4 characters long. */ -static bfd_boolean +static bool is_simple_wild (const char *name) { size_t len = strcspn (name, "*?["); return len >= 4 && name[len] == '*' && name[len + 1] == '\0'; } -static bfd_boolean +static bool match_simple_wild (const char *pattern, const char *name) { /* The first four characters of the pattern are guaranteed valid non-wildcard characters. So we can go faster. */ if (pattern[0] != name[0] || pattern[1] != name[1] || pattern[2] != name[2] || pattern[3] != name[3]) - return FALSE; + return false; pattern += 4; name += 4; while (*pattern != '*') if (*name++ != *pattern++) - return FALSE; + return false; - return TRUE; + return true; } /* Return the numerical value of the init_priority attribute from @@ -566,7 +566,6 @@ static void output_section_callback_fast (lang_wild_statement_type *ptr, struct wildcard_list *sec, asection *section, - struct flag_info *sflag_list ATTRIBUTE_UNUSED, lang_input_statement_type *file, void *output) { @@ -583,6 +582,7 @@ output_section_callback_fast (lang_wild_statement_type *ptr, node->left = 0; node->right = 0; node->section = section; + node->pattern = ptr->section_list; tree = wild_sort_fast (ptr, sec, file, section); if (tree != NULL) @@ -599,7 +599,7 @@ output_section_callback_tree_to_list (lang_wild_statement_type *ptr, if (tree->left) output_section_callback_tree_to_list (ptr, tree->left, output); - lang_add_section (&ptr->children, tree->section, NULL, + lang_add_section (&ptr->children, tree->section, tree->pattern, NULL, (lang_output_section_statement_type *) output); if (tree->right) @@ -622,7 +622,7 @@ walk_wild_section_specs1_wild0 (lang_wild_statement_type *ptr, (should be rare), we fall back to the general algorithm because we would otherwise have to sort the sections to make sure they get processed in the bfd's order. */ - bfd_boolean multiple_sections_found; + bool multiple_sections_found; struct wildcard_list *sec0 = ptr->handler_data[0]; asection *s0 = find_section (file, sec0, &multiple_sections_found); @@ -644,7 +644,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_section_name (s); - bfd_boolean skip = !match_simple_wild (wildsec0->spec.name, sname); + bool skip = !match_simple_wild (wildsec0->spec.name, sname); if (!skip) walk_wild_consider_section (ptr, file, s, wildsec0, callback, data); @@ -660,7 +660,7 @@ walk_wild_section_specs2_wild1 (lang_wild_statement_type *ptr, asection *s; struct wildcard_list *sec0 = ptr->handler_data[0]; struct wildcard_list *wildsec1 = ptr->handler_data[1]; - bfd_boolean multiple_sections_found; + bool multiple_sections_found; asection *s0 = find_section (file, sec0, &multiple_sections_found); if (multiple_sections_found) @@ -681,7 +681,7 @@ walk_wild_section_specs2_wild1 (lang_wild_statement_type *ptr, else { const char *sname = bfd_section_name (s); - bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname); + bool skip = !match_simple_wild (wildsec1->spec.name, sname); if (!skip) walk_wild_consider_section (ptr, file, s, wildsec1, callback, @@ -700,7 +700,7 @@ walk_wild_section_specs3_wild2 (lang_wild_statement_type *ptr, struct wildcard_list *sec0 = ptr->handler_data[0]; struct wildcard_list *wildsec1 = ptr->handler_data[1]; struct wildcard_list *wildsec2 = ptr->handler_data[2]; - bfd_boolean multiple_sections_found; + bool multiple_sections_found; asection *s0 = find_section (file, sec0, &multiple_sections_found); if (multiple_sections_found) @@ -716,7 +716,7 @@ walk_wild_section_specs3_wild2 (lang_wild_statement_type *ptr, else { const char *sname = bfd_section_name (s); - bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname); + bool skip = !match_simple_wild (wildsec1->spec.name, sname); if (!skip) walk_wild_consider_section (ptr, file, s, wildsec1, callback, data); @@ -742,7 +742,7 @@ walk_wild_section_specs4_wild2 (lang_wild_statement_type *ptr, struct wildcard_list *sec1 = ptr->handler_data[1]; struct wildcard_list *wildsec2 = ptr->handler_data[2]; struct wildcard_list *wildsec3 = ptr->handler_data[3]; - bfd_boolean multiple_sections_found; + bool multiple_sections_found; asection *s0 = find_section (file, sec0, &multiple_sections_found), *s1; if (multiple_sections_found) @@ -768,8 +768,7 @@ walk_wild_section_specs4_wild2 (lang_wild_statement_type *ptr, else { const char *sname = bfd_section_name (s); - bfd_boolean skip = !match_simple_wild (wildsec2->spec.name, - sname); + bool skip = !match_simple_wild (wildsec2->spec.name, sname); if (!skip) walk_wild_consider_section (ptr, file, s, wildsec2, callback, @@ -802,7 +801,7 @@ walk_wild_section (lang_wild_statement_type *ptr, only if the prefixes of name1 and name2 are different up to the first wildcard character. */ -static bfd_boolean +static bool wild_spec_can_overlap (const char *name1, const char *name2) { size_t prefix1_len = strcspn (name1, "?*["); @@ -1114,7 +1113,7 @@ new_afile (const char *name, { lang_input_statement_type *p; - lang_has_input_file = TRUE; + lang_has_input_file = true; p = new_stat (lang_input_statement, stat_ptr); memset (&p->the_bfd, 0, @@ -1132,8 +1131,8 @@ new_afile (const char *name, case lang_input_file_is_symbols_only_enum: p->filename = name; p->local_sym_name = name; - p->flags.real = TRUE; - p->flags.just_syms = TRUE; + p->flags.real = true; + p->flags.just_syms = true; break; case lang_input_file_is_fake_enum: p->filename = name; @@ -1143,19 +1142,19 @@ new_afile (const char *name, if (name[0] == ':' && name[1] != '\0') { p->filename = name + 1; - p->flags.full_name_provided = TRUE; + p->flags.full_name_provided = true; } else p->filename = name; p->local_sym_name = concat ("-l", name, (const char *) NULL); - p->flags.maybe_archive = TRUE; - p->flags.real = TRUE; - p->flags.search_dirs = TRUE; + p->flags.maybe_archive = true; + p->flags.real = true; + p->flags.search_dirs = true; break; case lang_input_file_is_marker_enum: p->filename = name; p->local_sym_name = name; - p->flags.search_dirs = TRUE; + p->flags.search_dirs = true; break; case lang_input_file_is_search_file_enum: p->filename = name; @@ -1164,13 +1163,13 @@ new_afile (const char *name, 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; + p->flags.real = true; + p->flags.search_dirs = true; break; case lang_input_file_is_file_enum: p->filename = name; p->local_sym_name = name; - p->flags.real = TRUE; + p->flags.real = true; break; default: FAIL (); @@ -1186,7 +1185,7 @@ lang_add_input_file (const char *name, const char *target) { if (name != NULL - && (*name == '=' || CONST_STRNEQ (name, "$SYSROOT"))) + && (*name == '=' || startswith (name, "$SYSROOT"))) { lang_input_statement_type *ret; char *sysrooted_name @@ -1305,7 +1304,7 @@ lang_init (void) first_file = lang_add_input_file (NULL, lang_input_file_is_marker_enum, NULL); abs_output_section = - lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME, 0, TRUE); + lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME, 0, 1); abs_output_section->bfd_section = bfd_abs_section_ptr; @@ -1346,7 +1345,7 @@ static lang_memory_region_type **lang_memory_region_list_tail = &lang_memory_region_list; lang_memory_region_type * -lang_memory_region_lookup (const char *const name, bfd_boolean create) +lang_memory_region_lookup (const char *const name, bool create) { lang_memory_region_name *n; lang_memory_region_type *r; @@ -1383,7 +1382,7 @@ lang_memory_region_lookup (const char *const name, bfd_boolean create) new_region->last_os = NULL; new_region->flags = 0; new_region->not_flags = 0; - new_region->had_full_message = FALSE; + new_region->had_full_message = false; *lang_memory_region_list_tail = new_region; lang_memory_region_list_tail = &new_region->next; @@ -1451,7 +1450,7 @@ lang_memory_default (asection *section) return p; } } - return lang_memory_region_lookup (DEFAULT_MEMORY_REGION, FALSE); + return lang_memory_region_lookup (DEFAULT_MEMORY_REGION, false); } /* Get the output section statement directly from the userdata. */ @@ -1464,19 +1463,21 @@ lang_output_section_get (const asection *output_section) /* Find or create an output_section_statement with the given NAME. If CONSTRAINT is non-zero match one with that constraint, otherwise - match any non-negative constraint. If CREATE, always make a - new output_section_statement for SPECIAL CONSTRAINT. */ + match any non-negative constraint. If CREATE is 0 return NULL when + no match exists. If CREATE is 1, create an output_section_statement + when no match exists or if CONSTRAINT is SPECIAL. If CREATE is 2, + always make a new output_section_statement. */ lang_output_section_statement_type * lang_output_section_statement_lookup (const char *name, int constraint, - bfd_boolean create) + int create) { struct out_section_hash_entry *entry; entry = ((struct out_section_hash_entry *) bfd_hash_lookup (&output_section_statement_table, name, - create, FALSE)); + create != 0, false)); if (entry == NULL) { if (create) @@ -1491,23 +1492,19 @@ lang_output_section_statement_lookup (const char *name, struct out_section_hash_entry *last_ent; name = entry->s.output_section_statement.name; - if (create && constraint == SPECIAL) - /* Not traversing to the end reverses the order of the second - and subsequent SPECIAL sections in the hash table chain, - but that shouldn't matter. */ - last_ent = entry; - else - do - { - if (constraint == entry->s.output_section_statement.constraint - || (constraint == 0 - && entry->s.output_section_statement.constraint >= 0)) - return &entry->s.output_section_statement; - last_ent = entry; - entry = (struct out_section_hash_entry *) entry->root.next; - } - while (entry != NULL - && name == entry->s.output_section_statement.name); + do + { + if (create != 2 + && !(create && constraint == SPECIAL) + && (constraint == entry->s.output_section_statement.constraint + || (constraint == 0 + && entry->s.output_section_statement.constraint >= 0))) + return &entry->s.output_section_statement; + last_ent = entry; + entry = (struct out_section_hash_entry *) entry->root.next; + } + while (entry != NULL + && name == entry->s.output_section_statement.name); if (!create) return NULL; @@ -1528,6 +1525,8 @@ lang_output_section_statement_lookup (const char *name, entry->s.output_section_statement.name = name; entry->s.output_section_statement.constraint = constraint; + entry->s.output_section_statement.dup_output = (create == 2 + || constraint == SPECIAL); return &entry->s.output_section_statement; } @@ -1655,7 +1654,7 @@ lang_output_section_find_by_flags (const asection *sec, { /* .tdata can go after .data, .tbss after .tdata. Treat .tbss as if it were a loaded section, and don't use match_type. */ - bfd_boolean seen_thread_local = FALSE; + bool seen_thread_local = false; match_type = NULL; for (look = first; look; look = look->next) @@ -1675,7 +1674,7 @@ lang_output_section_find_by_flags (const asection *sec, previous section. */ break; found = look; - seen_thread_local = TRUE; + seen_thread_local = true; } else if (seen_thread_local) break; @@ -1803,7 +1802,7 @@ insert_os_after (lang_output_section_statement_type *after) { lang_statement_union_type **where; lang_statement_union_type **assign = NULL; - bfd_boolean ignore_first; + bool ignore_first; ignore_first = after == (void *) lang_os_list.head; @@ -1825,7 +1824,7 @@ insert_os_after (lang_output_section_statement_type *after) { if (!ignore_first) assign = where; - ignore_first = FALSE; + ignore_first = false; } } continue; @@ -1838,7 +1837,7 @@ insert_os_after (lang_output_section_statement_type *after) case lang_padding_statement_enum: case lang_constructors_statement_enum: assign = NULL; - ignore_first = FALSE; + ignore_first = false; continue; case lang_output_section_statement_enum: if (assign != NULL) @@ -1892,12 +1891,12 @@ lang_insert_orphan (asection *s, address = exp_intop (0); os_tail = (lang_output_section_statement_type **) lang_os_list.tail; - os = lang_enter_output_section_statement (secname, address, normal_section, - NULL, NULL, NULL, constraint, 0); + os = lang_enter_output_section_statement ( + secname, address, normal_section, 0, NULL, NULL, NULL, constraint, 0); if (add_child == NULL) add_child = &os->children; - lang_add_section (add_child, s, NULL, os); + lang_add_section (add_child, s, NULL, NULL, os); if (after && (s->flags & (SEC_LOAD | SEC_ALLOC)) != 0) { @@ -1921,8 +1920,8 @@ lang_insert_orphan (asection *s, if (after != NULL && os->bfd_section != NULL) { asection *snew, *as; - bfd_boolean place_after = place->stmt == NULL; - bfd_boolean insert_after = TRUE; + bool place_after = place->stmt == NULL; + bool insert_after = true; snew = os->bfd_section; @@ -1977,7 +1976,7 @@ lang_insert_orphan (asection *s, asection *after_sec; /* True if we need to insert the orphan section after a specific section to maintain output note section order. */ - bfd_boolean after_sec_note = FALSE; + bool after_sec_note = false; static asection *first_orphan_note = NULL; @@ -2021,14 +2020,14 @@ lang_insert_orphan (asection *s, alignments, place the section before all output orphan note sections. */ after_sec = first_orphan_note; - insert_after = FALSE; + insert_after = false; } } else if (first_orphan_note) { /* Don't place non-note sections in the middle of orphan note sections. */ - after_sec_note = TRUE; + after_sec_note = true; after_sec = as; for (sec = as->next; (sec != NULL @@ -2046,7 +2045,7 @@ lang_insert_orphan (asection *s, /* Search forward to insert OS after AFTER_SEC output statement. */ lang_output_section_statement_type *stmt, *next; - bfd_boolean found = FALSE; + bool found = false; for (stmt = after; stmt != NULL; stmt = next) { next = stmt->next; @@ -2054,8 +2053,8 @@ lang_insert_orphan (asection *s, { if (stmt->bfd_section == after_sec) { - place_after = TRUE; - found = TRUE; + place_after = true; + found = true; after = stmt; break; } @@ -2066,8 +2065,8 @@ lang_insert_orphan (asection *s, AFTER_SEC output statement. */ if (next && next->bfd_section == after_sec) { - place_after = TRUE; - found = TRUE; + place_after = true; + found = true; after = stmt; break; } @@ -2083,7 +2082,7 @@ lang_insert_orphan (asection *s, { if (stmt->bfd_section == after_sec) { - place_after = TRUE; + place_after = true; after = stmt; break; } @@ -2094,7 +2093,7 @@ lang_insert_orphan (asection *s, AFTER_SEC output statement. */ if (stmt->next->bfd_section == after_sec) { - place_after = TRUE; + place_after = true; after = stmt; break; } @@ -2266,7 +2265,7 @@ void lang_map (void) { lang_memory_region_type *m; - bfd_boolean dis_header_printed = FALSE; + bool dis_header_printed = false; LANG_FOR_EACH_INPUT_STATEMENT (file) { @@ -2285,10 +2284,10 @@ lang_map (void) if (! dis_header_printed) { fprintf (config.map_file, _("\nDiscarded input sections\n\n")); - dis_header_printed = TRUE; + dis_header_printed = true; } - print_input_section (s, TRUE); + print_input_section (s, true); } } @@ -2349,7 +2348,7 @@ lang_map (void) config.map_file); } -static bfd_boolean +static bool sort_def_symbol (struct bfd_link_hash_entry *hash_entry, void *info ATTRIBUTE_UNUSED) { @@ -2378,7 +2377,7 @@ sort_def_symbol (struct bfd_link_hash_entry *hash_entry, ud->map_symbol_def_tail = &def->next; ud->map_symbol_def_count++; } - return TRUE; + return true; } /* Initialize an output section. */ @@ -2389,7 +2388,7 @@ init_os (lang_output_section_statement_type *s, flagword flags) if (strcmp (s->name, DISCARD_SECTION_NAME) == 0) einfo (_("%F%P: illegal use of `%s' section\n"), DISCARD_SECTION_NAME); - if (s->constraint != SPECIAL) + if (!s->dup_output) s->bfd_section = bfd_get_section_by_name (link_info.output_bfd, s->name); if (s->bfd_section == NULL) s->bfd_section = bfd_make_section_anyway_with_flags (link_info.output_bfd, @@ -2502,10 +2501,10 @@ section_already_linked (bfd *abfd, asection *sec, void *data) /* Returns true if SECTION is one we know will be discarded based on its section flags, otherwise returns false. */ -static bfd_boolean +static bool lang_discard_section_p (asection *section) { - bfd_boolean discard; + bool discard; flagword flags = section->flags; /* Discard sections marked with SEC_EXCLUDE. */ @@ -2515,13 +2514,13 @@ lang_discard_section_p (asection *section) sections from within the group. */ if ((flags & SEC_GROUP) != 0 && link_info.resolve_section_groups) - discard = TRUE; + discard = true; /* Discard debugging sections if we are stripping debugging information. */ if ((link_info.strip == strip_debugger || link_info.strip == strip_all) && (flags & SEC_DEBUGGING) != 0) - discard = TRUE; + discard = true; return discard; } @@ -2538,12 +2537,13 @@ lang_discard_section_p (asection *section) void lang_add_section (lang_statement_list_type *ptr, asection *section, + struct wildcard_list *pattern, struct flag_info *sflag_info, lang_output_section_statement_type *output) { flagword flags = section->flags; - bfd_boolean discard; + bool discard; lang_input_section_type *new_section; bfd *abfd = link_info.output_bfd; @@ -2553,7 +2553,7 @@ lang_add_section (lang_statement_list_type *ptr, /* Discard input sections which are assigned to a section named DISCARD_SECTION_NAME. */ if (strcmp (output->name, DISCARD_SECTION_NAME) == 0) - discard = TRUE; + discard = true; if (discard) { @@ -2572,7 +2572,7 @@ lang_add_section (lang_statement_list_type *ptr, if (sflag_info) { - bfd_boolean keep; + bool keep; keep = bfd_lookup_section_flags (&link_info, sflag_info, section); if (!keep) @@ -2635,10 +2635,15 @@ lang_add_section (lang_statement_list_type *ptr, case normal_section: case overlay_section: case first_overlay_section: + case type_section: break; case noalloc_section: flags &= ~SEC_ALLOC; break; + case typed_readonly_section: + case readonly_section: + flags |= SEC_READONLY; + break; case noload_section: flags &= ~SEC_LOAD; flags |= SEC_NEVER_LOAD; @@ -2698,6 +2703,16 @@ lang_add_section (lang_statement_list_type *ptr, output->block_value = 128; } + /* When a .ctors section is placed in .init_array it must be copied + in reverse order. Similarly for .dtors. Set that up. */ + if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour + && ((startswith (section->name, ".ctors") + && strcmp (output->bfd_section->name, ".init_array") == 0) + || (startswith (section->name, ".dtors") + && strcmp (output->bfd_section->name, ".fini_array") == 0)) + && (section->name[6] == 0 || section->name[6] == '.')) + section->flags |= SEC_ELF_REVERSE_COPY; + if (section->alignment_power > output->bfd_section->alignment_power) output->bfd_section->alignment_power = section->alignment_power; @@ -2718,6 +2733,7 @@ lang_add_section (lang_statement_list_type *ptr, /* Add a section reference to the list. */ new_section = new_stat (lang_input_section, ptr); new_section->section = section; + new_section->pattern = pattern; } /* Handle wildcard sorting. This returns the lang_input_section which @@ -2751,7 +2767,7 @@ wild_sort (lang_wild_statement_type *wild, if (wild->filenames_sorted) { const char *fn, *ln; - bfd_boolean fa, la; + bool fa, la; int i; /* The PE support for the .idata section as generated by @@ -2763,23 +2779,23 @@ wild_sort (lang_wild_statement_type *wild, && file->the_bfd->my_archive != NULL) { fn = bfd_get_filename (file->the_bfd->my_archive); - fa = TRUE; + fa = true; } else { fn = file->filename; - fa = FALSE; + fa = false; } if (ls->section->owner->my_archive != NULL) { ln = bfd_get_filename (ls->section->owner->my_archive); - la = TRUE; + la = true; } else { ln = bfd_get_filename (ls->section->owner); - la = FALSE; + la = false; } i = filename_cmp (fn, ln); @@ -2823,7 +2839,6 @@ static void output_section_callback (lang_wild_statement_type *ptr, struct wildcard_list *sec, asection *section, - struct flag_info *sflag_info, lang_input_statement_type *file, void *output) { @@ -2844,14 +2859,16 @@ output_section_callback (lang_wild_statement_type *ptr, of the current list. */ if (before == NULL) - lang_add_section (&ptr->children, section, sflag_info, os); + lang_add_section (&ptr->children, section, ptr->section_list, + ptr->section_flag_list, os); else { lang_statement_list_type list; lang_statement_union_type **pp; lang_list_init (&list); - lang_add_section (&list, section, sflag_info, os); + lang_add_section (&list, section, ptr->section_list, + ptr->section_flag_list, os); /* If we are discarding the section, LIST.HEAD will be NULL. */ @@ -2877,7 +2894,6 @@ static void check_section_callback (lang_wild_statement_type *ptr ATTRIBUTE_UNUSED, struct wildcard_list *sec ATTRIBUTE_UNUSED, asection *section, - struct flag_info *sflag_info ATTRIBUTE_UNUSED, lang_input_statement_type *file ATTRIBUTE_UNUSED, void *output) { @@ -2890,7 +2906,7 @@ check_section_callback (lang_wild_statement_type *ptr ATTRIBUTE_UNUSED, return; if (section->output_section == NULL && (section->flags & SEC_READONLY) == 0) - os->all_input_readonly = FALSE; + os->all_input_readonly = false; } /* This is passed a file name which must have been seen already and @@ -2992,7 +3008,7 @@ check_excluded_libs (bfd *abfd) if (strcmp (lib->name, "ALL") == 0) { - abfd->no_export = TRUE; + abfd->no_export = true; return; } @@ -3001,7 +3017,7 @@ check_excluded_libs (bfd *abfd) || (filename[len] == '.' && filename[len + 1] == 'a' && filename[len + 2] == '\0'))) { - abfd->no_export = TRUE; + abfd->no_export = true; return; } @@ -3011,20 +3027,20 @@ check_excluded_libs (bfd *abfd) /* Get the symbols for an input file. */ -bfd_boolean +bool load_symbols (lang_input_statement_type *entry, lang_statement_list_type *place) { char **matching; if (entry->flags.loaded) - return TRUE; + return true; ldfile_open_file (entry); /* Do not process further if the file was missing. */ if (entry->flags.missing_file) - return TRUE; + return true; if (trace_files || verbose) info_msg ("%pI\n", entry); @@ -3040,7 +3056,11 @@ load_symbols (lang_input_statement_type *entry, /* See if the emulation has some special knowledge. */ if (ldemul_unrecognized_file (entry)) - return TRUE; + { + if (err == bfd_error_file_ambiguously_recognized) + free (matching); + return true; + } if (err == bfd_error_file_ambiguously_recognized) { @@ -3050,6 +3070,7 @@ load_symbols (lang_input_statement_type *entry, " matching formats:"), entry->the_bfd); for (p = matching; *p != NULL; p++) einfo (" %s", *p); + free (matching); einfo ("%F\n"); } else if (err != bfd_error_file_not_recognized @@ -3071,12 +3092,12 @@ load_symbols (lang_input_statement_type *entry, input_flags.whole_archive = entry->flags.whole_archive; input_flags.dynamic = entry->flags.dynamic; - ldfile_assumed_script = TRUE; + ldfile_assumed_script = true; parser_input = input_script; current_input_file = entry->filename; yyparse (); current_input_file = NULL; - ldfile_assumed_script = FALSE; + ldfile_assumed_script = false; /* missing_file is sticky. sysrooted will already have been restored when seeing EOF in yyparse, but no harm to restore @@ -3086,13 +3107,13 @@ load_symbols (lang_input_statement_type *entry, pop_stat_ptr (); fclose (yyin); yyin = NULL; - entry->flags.loaded = TRUE; + entry->flags.loaded = true; - return TRUE; + return true; } if (ldemul_recognized_file (entry)) - return TRUE; + return true; /* We don't call ldlang_add_file for an archive. Instead, the add_symbols entry point will call ldlang_add_file, via the @@ -3115,7 +3136,7 @@ load_symbols (lang_input_statement_type *entry, if (entry->flags.whole_archive) { bfd *member = NULL; - bfd_boolean loaded = TRUE; + bool loaded = true; for (;;) { @@ -3129,7 +3150,7 @@ load_symbols (lang_input_statement_type *entry, { einfo (_("%F%P: %pB: member %pB in archive is not an object\n"), entry->the_bfd, member); - loaded = FALSE; + loaded = false; } subsbfd = member; @@ -3143,7 +3164,7 @@ load_symbols (lang_input_statement_type *entry, if (!bfd_link_add_symbols (subsbfd, &link_info)) { einfo (_("%F%P: %pB: error adding symbols: %E\n"), member); - loaded = FALSE; + loaded = false; } } @@ -3154,7 +3175,7 @@ load_symbols (lang_input_statement_type *entry, } if (bfd_link_add_symbols (entry->the_bfd, &link_info)) - entry->flags.loaded = TRUE; + entry->flags.loaded = true; else einfo (_("%F%P: %pB: error adding symbols: %E\n"), entry->the_bfd); @@ -3388,6 +3409,22 @@ lang_get_output_target (void) static void open_output (const char *name) { + lang_input_statement_type *f; + char *out = lrealpath (name); + + for (f = (void *) input_file_chain.head; + f != NULL; + f = f->next_real_file) + if (f->flags.real) + { + char *in = lrealpath (f->local_sym_name); + if (filename_cmp (in, out) == 0) + einfo (_("%F%P: input file '%s' is the same as output file\n"), + f->filename); + free (in); + } + free (out); + output_target = lang_get_output_target (); /* Has the user requested a particular endianness on the command @@ -3449,7 +3486,7 @@ open_output (const char *name) einfo (_("%F%P: cannot open output file %s: %E\n"), name); } - delete_output_file_on_failure = TRUE; + delete_output_file_on_failure = true; if (!bfd_set_format (link_info.output_bfd, bfd_object)) einfo (_("%F%P: %s: can not make object file: %E\n"), name); @@ -3616,15 +3653,15 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode) && bfd_get_flavour (abfd) == bfd_target_elf_flavour && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0))) { - s->input_statement.flags.loaded = FALSE; - s->input_statement.flags.reload = TRUE; + s->input_statement.flags.loaded = false; + s->input_statement.flags.reload = true; } os_tail = lang_os_list.tail; lang_list_init (&add); if (!load_symbols (&s->input_statement, &add)) - config.make_executable = FALSE; + config.make_executable = false; if (add.head != NULL) { @@ -3809,6 +3846,8 @@ lang_merge_ctf (void) flags = CTF_LINK_SHARE_DUPLICATED; if (!config.ctf_variables) flags |= CTF_LINK_OMIT_VARIABLES_SECTION; + if (bfd_link_relocatable (&link_info)) + flags |= CTF_LINK_NO_FILTER_REPORTED_SYMS; if (ctf_link (ctf_output, flags) < 0) { @@ -3826,14 +3865,20 @@ lang_merge_ctf (void) lang_ctf_errs_warnings (ctf_output); } -/* Let the emulation examine the symbol table and strtab to help it optimize the - CTF, if supported. */ +/* Let the emulation acquire strings from the dynamic strtab to help it optimize + the CTF, if supported. */ void -ldlang_ctf_apply_strsym (struct elf_sym_strtab *syms, bfd_size_type symcount, - struct elf_strtab_hash *symstrtab) +ldlang_ctf_acquire_strings (struct elf_strtab_hash *dynstrtab) { - ldemul_examine_strtab_for_ctf (ctf_output, syms, symcount, symstrtab); + ldemul_acquire_strings_for_ctf (ctf_output, dynstrtab); +} + +/* Inform the emulation about the addition of a new dynamic symbol, in BFD + internal format. */ +void ldlang_ctf_new_dynsym (int symidx, struct elf_internal_sym *sym) +{ + ldemul_new_dynsym_for_ctf (ctf_output, symidx, sym); } /* Write out the CTF section. Called early, if the emulation isn't going to @@ -3860,6 +3905,11 @@ lang_write_ctf (int late) return; } + /* Inform the emulation that all the symbols that will be received have + been. */ + + ldemul_new_dynsym_for_ctf (ctf_output, 0, NULL); + /* Emit CTF. */ output_sect = bfd_get_section_by_name (link_info.output_bfd, ".ctf"); @@ -3922,11 +3972,11 @@ ldlang_open_ctf (void) static void lang_merge_ctf (void) {} void -ldlang_ctf_apply_strsym (struct elf_sym_strtab *syms ATTRIBUTE_UNUSED, - bfd_size_type symcount ATTRIBUTE_UNUSED, - struct elf_strtab_hash *symstrtab ATTRIBUTE_UNUSED) -{ -} +ldlang_ctf_acquire_strings (struct elf_strtab_hash *dynstrtab + ATTRIBUTE_UNUSED) {} +void +ldlang_ctf_new_dynsym (int symidx ATTRIBUTE_UNUSED, + struct elf_internal_sym *sym ATTRIBUTE_UNUSED) {} static void lang_write_ctf (int late ATTRIBUTE_UNUSED) {} void ldlang_write_ctf_late (void) {} #endif @@ -3942,7 +3992,7 @@ typedef struct bfd_sym_chain ldlang_undef_chain_list_type; #define ldlang_undef_chain_list_head entry_symbol.next void -ldlang_add_undef (const char *const name, bfd_boolean cmdline ATTRIBUTE_UNUSED) +ldlang_add_undef (const char *const name, bool cmdline ATTRIBUTE_UNUSED) { ldlang_undef_chain_list_type *new_undef; @@ -3963,16 +4013,14 @@ insert_undefined (const char *name) { struct bfd_link_hash_entry *h; - h = bfd_link_hash_lookup (link_info.hash, name, TRUE, FALSE, TRUE); + h = bfd_link_hash_lookup (link_info.hash, name, true, false, true); if (h == NULL) einfo (_("%F%P: bfd_link_hash_lookup failed: %E\n")); if (h->type == bfd_link_hash_new) { h->type = bfd_link_hash_undefined; h->u.undef.abfd = NULL; - h->non_ir_ref_regular = TRUE; - if (is_elf_hash_table (link_info.hash)) - ((struct elf_link_hash_entry *) h)->mark = 1; + h->non_ir_ref_regular = true; bfd_link_add_undef (link_info.hash, h); } } @@ -3990,6 +4038,23 @@ lang_place_undefineds (void) insert_undefined (ptr->name); } +/* Mark -u symbols against garbage collection. */ + +static void +lang_mark_undefineds (void) +{ + ldlang_undef_chain_list_type *ptr; + + if (is_elf_hash_table (link_info.hash)) + for (ptr = ldlang_undef_chain_list_head; ptr != NULL; ptr = ptr->next) + { + struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) + bfd_link_hash_lookup (link_info.hash, ptr->name, false, false, true); + if (h != NULL) + h->mark = 1; + } +} + /* Structure used to build the list of symbols that the user has required be defined. */ @@ -4011,7 +4076,7 @@ ldlang_add_require_defined (const char *const name) { struct require_defined_symbol *ptr; - ldlang_add_undef (name, TRUE); + ldlang_add_undef (name, true); ptr = stat_alloc (sizeof (*ptr)); ptr->next = require_defined_symbol_list; ptr->name = strdup (name); @@ -4031,7 +4096,7 @@ ldlang_check_require_defined_symbols (void) struct bfd_link_hash_entry *h; h = bfd_link_hash_lookup (link_info.hash, ptr->name, - FALSE, FALSE, TRUE); + false, false, true); if (h == NULL || (h->type != bfd_link_hash_defined && h->type != bfd_link_hash_defweak)) @@ -4151,6 +4216,7 @@ map_input_to_output_sections { lang_output_section_statement_type *tos; flagword flags; + unsigned int type = 0; switch (s->header.type) { @@ -4164,22 +4230,18 @@ map_input_to_output_sections break; case lang_output_section_statement_enum: tos = &s->output_section_statement; - if (tos->constraint != 0) + if (tos->constraint == ONLY_IF_RW + || tos->constraint == ONLY_IF_RO) { - if (tos->constraint != ONLY_IF_RW - && tos->constraint != ONLY_IF_RO) - break; - tos->all_input_readonly = TRUE; + tos->all_input_readonly = true; check_input_sections (tos->children.head, tos); if (tos->all_input_readonly != (tos->constraint == ONLY_IF_RO)) - { - tos->constraint = -1; - break; - } + tos->constraint = -1; } - map_input_to_output_sections (tos->children.head, - target, - tos); + if (tos->constraint >= 0) + map_input_to_output_sections (tos->children.head, + target, + tos); break; case lang_output_statement_enum: break; @@ -4207,6 +4269,45 @@ map_input_to_output_sections case noalloc_section: flags = SEC_HAS_CONTENTS; break; + case readonly_section: + flags |= SEC_READONLY; + break; + case typed_readonly_section: + flags |= SEC_READONLY; + /* Fall through. */ + case type_section: + if (os->sectype_value->type.node_class == etree_name + && os->sectype_value->type.node_code == NAME) + { + const char *name = os->sectype_value->name.name; + if (strcmp (name, "SHT_PROGBITS") == 0) + type = SHT_PROGBITS; + else if (strcmp (name, "SHT_STRTAB") == 0) + type = SHT_STRTAB; + else if (strcmp (name, "SHT_NOTE") == 0) + type = SHT_NOTE; + else if (strcmp (name, "SHT_NOBITS") == 0) + type = SHT_NOBITS; + else if (strcmp (name, "SHT_INIT_ARRAY") == 0) + type = SHT_INIT_ARRAY; + else if (strcmp (name, "SHT_FINI_ARRAY") == 0) + type = SHT_FINI_ARRAY; + else if (strcmp (name, "SHT_PREINIT_ARRAY") == 0) + type = SHT_PREINIT_ARRAY; + else + einfo (_ ("%F%P: invalid type for output section `%s'\n"), + os->name); + } + else + { + exp_fold_tree_no_dot (os->sectype_value); + if (expld.result.valid_p) + type = expld.result.value; + else + einfo (_ ("%F%P: invalid type for output section `%s'\n"), + os->name); + } + break; case noload_section: if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour) @@ -4216,9 +4317,10 @@ map_input_to_output_sections break; } if (os->bfd_section == NULL) - init_os (os, flags); + init_os (os, flags | SEC_READONLY); else os->bfd_section->flags |= flags; + os->bfd_section->type = type; break; case lang_input_section_enum: break; @@ -4259,7 +4361,7 @@ map_input_to_output_sections place them in amongst other sections then the address will affect following script sections, which is likely to surprise naive users. */ - tos = lang_output_section_statement_lookup (name, 0, TRUE); + tos = lang_output_section_statement_lookup (name, 0, 1); tos->addr_tree = s->address_statement.address; if (tos->bfd_section == NULL) init_os (tos, 0); @@ -4469,7 +4571,7 @@ strip_excluded_output_sections (void) { expld.phase = lang_mark_phase_enum; expld.dataseg.phase = exp_seg_none; - one_lang_size_sections_pass (NULL, FALSE); + one_lang_size_sections_pass (NULL, false); lang_reset_memory_regions (); } @@ -4478,7 +4580,7 @@ strip_excluded_output_sections (void) os = os->next) { asection *output_section; - bfd_boolean exclude; + bool exclude; if (os->constraint < 0) continue; @@ -4505,7 +4607,7 @@ strip_excluded_output_sections (void) && ((s->flags & SEC_LINKER_CREATED) != 0 || link_info.emitrelocations)) { - exclude = FALSE; + exclude = false; break; } } @@ -4515,7 +4617,7 @@ strip_excluded_output_sections (void) /* We don't set bfd_section to NULL since bfd_section of the removed output section statement may still be used. */ if (!os->update_dot) - os->ignored = TRUE; + os->ignored = true; output_section->flags |= SEC_EXCLUDE; bfd_section_list_remove (link_info.output_bfd, output_section); link_info.output_bfd->section_count--; @@ -4554,7 +4656,7 @@ lang_clear_os_map (void) /* Stop future calls to lang_add_section from messing with map_head and map_tail link_order fields. */ - map_head_is_link_order = TRUE; + map_head_is_link_order = true; } static void @@ -4606,7 +4708,7 @@ print_assignment (lang_assignment_statement_type *assignment, lang_output_section_statement_type *output_section) { unsigned int i; - bfd_boolean is_dot; + bool is_dot; etree_type *tree; asection *osec; @@ -4615,7 +4717,7 @@ print_assignment (lang_assignment_statement_type *assignment, if (assignment->exp->type.node_class == etree_assert) { - is_dot = FALSE; + is_dot = false; tree = assignment->exp->assert_s.child; } else @@ -4633,7 +4735,7 @@ print_assignment (lang_assignment_statement_type *assignment, if (assignment->exp->type.node_class != etree_provide) exp_fold_tree (tree, osec, &print_dot); else - expld.result.valid_p = FALSE; + expld.result.valid_p = false; if (expld.result.valid_p) { @@ -4657,7 +4759,7 @@ print_assignment (lang_assignment_statement_type *assignment, struct bfd_link_hash_entry *h; h = bfd_link_hash_lookup (link_info.hash, assignment->exp->assign.dst, - FALSE, FALSE, TRUE); + false, false, true); if (h != NULL && (h->type == bfd_link_hash_defined || h->type == bfd_link_hash_defweak)) @@ -4699,7 +4801,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. */ -bfd_boolean +bool print_one_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr) { asection *sec = (asection *) ptr; @@ -4720,7 +4822,7 @@ print_one_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr) minfo (" %pT\n", hash_entry->root.string); } - return TRUE; + return true; } static int @@ -4771,7 +4873,7 @@ print_all_symbols (asection *sec) /* Print information about an input section to the map file. */ static void -print_input_section (asection *i, bfd_boolean is_discarded) +print_input_section (asection *i, bool is_discarded) { bfd_size_type size = i->size; int len; @@ -5143,7 +5245,7 @@ print_statement (lang_statement_union_type *s, print_reloc_statement (&s->reloc_statement); break; case lang_input_section_enum: - print_input_section (s->input_section.section, FALSE); + print_input_section (s->input_section.section, false); break; case lang_padding_statement_enum: print_padding_statement (&s->padding_statement); @@ -5260,7 +5362,7 @@ size_input_section (lang_statement_union_type **this_ptr, lang_output_section_statement_type *output_section_statement, fill_type *fill, - bfd_boolean *removed, + bool *removed, bfd_vma dot) { lang_input_section_type *is = &((*this_ptr)->input_section); @@ -5365,7 +5467,7 @@ size_input_section struct check_sec { asection *sec; - bfd_boolean warned; + bool warned; }; static int @@ -5427,7 +5529,7 @@ lang_check_section_addresses (void) bfd_vma p_start = 0; bfd_vma p_end = 0; lang_memory_region_type *m; - bfd_boolean overlays; + bool overlays; /* Detect address space overflow on allocated sections. */ addr_mask = ((bfd_vma) 1 << @@ -5464,7 +5566,7 @@ lang_check_section_addresses (void) continue; sections[count].sec = s; - sections[count].warned = FALSE; + sections[count].warned = false; count++; } @@ -5499,7 +5601,7 @@ lang_check_section_addresses (void) einfo (_("%X%P: section %s LMA [%V,%V]" " overlaps section %s LMA [%V,%V]\n"), s->name, s_start, s_end, p->name, p_start, p_end); - sections[i].warned = TRUE; + sections[i].warned = true; } p = s; p_start = s_start; @@ -5513,14 +5615,14 @@ lang_check_section_addresses (void) this property. It is possible to intentionally generate overlays that fail this test, but it would be unusual. */ qsort (sections, count, sizeof (*sections), sort_sections_by_vma); - overlays = FALSE; + overlays = false; p_start = sections[0].sec->vma; for (i = 1; i < count; i++) { s_start = sections[i].sec->vma; if (p_start == s_start) { - overlays = TRUE; + overlays = true; break; } p_start = s_start; @@ -5597,7 +5699,7 @@ os_region_check (lang_output_section_statement_type *os, } else if (!region->had_full_message) { - region->had_full_message = TRUE; + region->had_full_message = true; einfo (_("%X%P: %pB section `%s' will not fit in region `%s'\n"), os->bfd_section->owner, @@ -5608,9 +5710,10 @@ os_region_check (lang_output_section_statement_type *os, } static void -ldlang_check_relro_region (lang_statement_union_type *s, - seg_align_type *seg) +ldlang_check_relro_region (lang_statement_union_type *s) { + seg_align_type *seg = &expld.dataseg; + if (seg->relro == exp_seg_relro_start) { if (!seg->relro_start_stat) @@ -5639,17 +5742,17 @@ lang_size_sections_1 lang_output_section_statement_type *output_section_statement, fill_type *fill, bfd_vma dot, - bfd_boolean *relax, - bfd_boolean check_regions) + bool *relax, + bool check_regions) { lang_statement_union_type *s; lang_statement_union_type *prev_s = NULL; - bfd_boolean removed_prev_s = FALSE; + bool removed_prev_s = false; /* Size up the sections from their constituent parts. */ for (s = *prev; s != NULL; prev_s = s, s = s->header.next) { - bfd_boolean removed=FALSE; + bool removed = false; switch (s->header.type) { @@ -5675,7 +5778,6 @@ lang_size_sections_1 os->addr_tree = exp_intop (0); if (os->addr_tree != NULL) { - os->processed_vma = FALSE; exp_fold_tree (os->addr_tree, bfd_abs_section_ptr, &dot); if (expld.result.valid_p) @@ -5819,7 +5921,7 @@ lang_size_sections_1 lang_size_sections_1 (&os->children.head, os, os->fill, newdot, relax, check_regions); - os->processed_vma = TRUE; + os->processed_vma = true; if (bfd_is_abs_section (os->bfd_section) || os->ignored) /* Except for some special linker created sections, @@ -5847,7 +5949,7 @@ lang_size_sections_1 /* Set section lma. */ r = os->region; if (r == NULL) - r = lang_memory_region_lookup (DEFAULT_MEMORY_REGION, FALSE); + r = lang_memory_region_lookup (DEFAULT_MEMORY_REGION, false); if (os->load_base) { @@ -5918,7 +6020,7 @@ lang_size_sections_1 os->bfd_section->lma = lma; } } - os->processed_lma = TRUE; + os->processed_lma = true; /* Keep track of normal sections using the default lma region. We use this to set the lma for @@ -6076,12 +6178,12 @@ lang_size_sections_1 i = s->input_section.section; if (relax) { - bfd_boolean again; + bool again; if (!bfd_relax_section (i->owner, i, &link_info, &again)) einfo (_("%F%P: can't relax section: %E\n")); if (again) - *relax = TRUE; + *relax = true; } dot = size_input_section (prev, output_section_statement, fill, &removed, dot); @@ -6109,7 +6211,7 @@ lang_size_sections_1 output_section_statement->bfd_section, &newdot); - ldlang_check_relro_region (s, &expld.dataseg); + ldlang_check_relro_region (s); expld.dataseg.relro = exp_seg_relro_none; @@ -6127,7 +6229,7 @@ lang_size_sections_1 /* If we don't have an output section, then just adjust the default memory address. */ lang_memory_region_lookup (DEFAULT_MEMORY_REGION, - FALSE)->current = newdot; + false)->current = newdot; } else if (newdot != dot) { @@ -6207,13 +6309,13 @@ lang_size_sections_1 the current one. */ prev_s->header.next=s->header.next; s = prev_s; - removed_prev_s = FALSE; + removed_prev_s = false; } else { /* Remove the first input section of the list. */ *prev = s->header.next; - removed_prev_s = TRUE; + removed_prev_s = true; } /* Move to next element, unless we removed the head of the @@ -6224,7 +6326,7 @@ lang_size_sections_1 else { prev = &s->header.next; - removed_prev_s = FALSE; + removed_prev_s = false; } } return dot; @@ -6235,12 +6337,12 @@ lang_size_sections_1 CURRENT_SECTION and PREVIOUS_SECTION ought to be placed into different segments. We are allowed an opportunity to override this decision. */ -bfd_boolean +bool ldlang_override_segment_assignment (struct bfd_link_info *info ATTRIBUTE_UNUSED, bfd *abfd ATTRIBUTE_UNUSED, asection *current_section, asection *previous_section, - bfd_boolean new_segment) + bool new_segment) { lang_output_section_statement_type *cur; lang_output_section_statement_type *prev; @@ -6248,7 +6350,7 @@ ldlang_override_segment_assignment (struct bfd_link_info *info ATTRIBUTE_UNUSED, /* The checks below are only necessary when the BFD library has decided that the two sections ought to be placed into the same segment. */ if (new_segment) - return TRUE; + return true; /* Paranoia checks. */ if (current_section == NULL || previous_section == NULL) @@ -6258,7 +6360,7 @@ ldlang_override_segment_assignment (struct bfd_link_info *info ATTRIBUTE_UNUSED, sections comingled in the same segment. */ if (config.separate_code && ((current_section->flags ^ previous_section->flags) & SEC_CODE)) - return TRUE; + return true; /* Find the memory regions associated with the two sections. We call lang_output_section_find() here rather than scanning the list @@ -6279,7 +6381,7 @@ ldlang_override_segment_assignment (struct bfd_link_info *info ATTRIBUTE_UNUSED, } void -one_lang_size_sections_pass (bfd_boolean *relax, bfd_boolean check_regions) +one_lang_size_sections_pass (bool *relax, bool check_regions) { lang_statement_iteration++; if (expld.phase != lang_mark_phase_enum) @@ -6288,37 +6390,38 @@ one_lang_size_sections_pass (bfd_boolean *relax, bfd_boolean check_regions) 0, 0, relax, check_regions); } -static bfd_boolean -lang_size_segment (seg_align_type *seg) +static bool +lang_size_segment (void) { /* If XXX_SEGMENT_ALIGN XXX_SEGMENT_END pair was seen, check whether a page could be saved in the data segment. */ + seg_align_type *seg = &expld.dataseg; bfd_vma first, last; - first = -seg->base & (seg->pagesize - 1); - last = seg->end & (seg->pagesize - 1); + first = -seg->base & (seg->commonpagesize - 1); + last = seg->end & (seg->commonpagesize - 1); if (first && last - && ((seg->base & ~(seg->pagesize - 1)) - != (seg->end & ~(seg->pagesize - 1))) - && first + last <= seg->pagesize) + && ((seg->base & ~(seg->commonpagesize - 1)) + != (seg->end & ~(seg->commonpagesize - 1))) + && first + last <= seg->commonpagesize) { seg->phase = exp_seg_adjust; - return TRUE; + return true; } seg->phase = exp_seg_done; - return FALSE; + return false; } static bfd_vma -lang_size_relro_segment_1 (seg_align_type *seg) +lang_size_relro_segment_1 (void) { + seg_align_type *seg = &expld.dataseg; bfd_vma relro_end, desired_end; asection *sec; /* Compute the expected PT_GNU_RELRO/PT_LOAD segment end. */ - relro_end = ((seg->relro_end + seg->pagesize - 1) - & ~(seg->pagesize - 1)); + relro_end = (seg->relro_end + seg->relropagesize - 1) & -seg->relropagesize; /* Adjust by the offset arg of XXX_SEGMENT_RELRO_END. */ desired_end = relro_end - seg->relro_offset; @@ -6351,47 +6454,35 @@ lang_size_relro_segment_1 (seg_align_type *seg) return relro_end; } -static bfd_boolean -lang_size_relro_segment (bfd_boolean *relax, bfd_boolean check_regions) +static bool +lang_size_relro_segment (bool *relax, bool check_regions) { - bfd_boolean do_reset = FALSE; - bfd_boolean do_data_relro; - bfd_vma data_initial_base, data_relro_end; + bool do_reset = false; if (link_info.relro && expld.dataseg.relro_end) { - do_data_relro = TRUE; - data_initial_base = expld.dataseg.base; - data_relro_end = lang_size_relro_segment_1 (&expld.dataseg); - } - else - { - do_data_relro = FALSE; - data_initial_base = data_relro_end = 0; - } + bfd_vma data_initial_base = expld.dataseg.base; + bfd_vma data_relro_end = lang_size_relro_segment_1 (); - if (do_data_relro) - { lang_reset_memory_regions (); one_lang_size_sections_pass (relax, check_regions); /* Assignments to dot, or to output section address in a user script have increased padding over the original. Revert. */ - if (do_data_relro && expld.dataseg.relro_end > data_relro_end) + if (expld.dataseg.relro_end > data_relro_end) { - expld.dataseg.base = data_initial_base;; - do_reset = TRUE; + expld.dataseg.base = data_initial_base; + do_reset = true; } } - - if (!do_data_relro && lang_size_segment (&expld.dataseg)) - do_reset = TRUE; + else if (lang_size_segment ()) + do_reset = true; return do_reset; } void -lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions) +lang_size_sections (bool *relax, bool check_regions) { expld.phase = lang_allocating_phase_enum; expld.dataseg.phase = exp_seg_none; @@ -6403,7 +6494,7 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions) if (expld.dataseg.phase == exp_seg_end_seen) { - bfd_boolean do_reset + bool do_reset = lang_size_relro_segment (relax, check_regions); if (do_reset) @@ -6422,7 +6513,7 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions) static lang_output_section_statement_type *current_section; static lang_assignment_statement_type *current_assign; -static bfd_boolean prefer_next_section; +static bool prefer_next_section; /* Worker function for lang_do_assignments. Recursiveness goes here. */ @@ -6431,7 +6522,7 @@ lang_do_assignments_1 (lang_statement_union_type *s, lang_output_section_statement_type *current_os, fill_type *fill, bfd_vma dot, - bfd_boolean *found_end) + bool *found_end) { for (; s != NULL; s = s->header.next) { @@ -6450,32 +6541,34 @@ 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) + newdot = dot; + if (os->bfd_section != NULL) { - if ((os->bfd_section->flags & SEC_ALLOC) != 0) + if (!os->ignored && (os->bfd_section->flags & SEC_ALLOC) != 0) { current_section = os; - prefer_next_section = FALSE; + prefer_next_section = false; } - dot = os->bfd_section->vma; + newdot = os->bfd_section->vma; } newdot = lang_do_assignments_1 (os->children.head, - os, os->fill, dot, found_end); + os, os->fill, newdot, found_end); if (!os->ignored) { if (os->bfd_section != NULL) { + newdot = os->bfd_section->vma; + /* .tbss sections effectively have zero size. */ if (!IS_TBSS (os->bfd_section) || bfd_link_relocatable (&link_info)) - dot += TO_ADDR (os->bfd_section->size); + newdot += TO_ADDR (os->bfd_section->size); if (os->update_dot_tree != NULL) exp_fold_tree (os->update_dot_tree, - bfd_abs_section_ptr, &dot); + bfd_abs_section_ptr, &newdot); } - else - dot = newdot; + dot = newdot; } } break; @@ -6560,12 +6653,12 @@ lang_do_assignments_1 (lang_statement_union_type *s, const char *p = current_assign->exp->assign.dst; if (current_os == abs_output_section && p[0] == '.' && p[1] == 0) - prefer_next_section = TRUE; + prefer_next_section = true; while (*p == '_') ++p; if (strcmp (p, "end") == 0) - *found_end = TRUE; + *found_end = true; } exp_fold_tree (s->assignment_statement.exp, (current_os->bfd_section != NULL @@ -6599,10 +6692,10 @@ lang_do_assignments_1 (lang_statement_union_type *s, void lang_do_assignments (lang_phase_type phase) { - bfd_boolean found_end = FALSE; + bool found_end = false; current_section = NULL; - prefer_next_section = FALSE; + prefer_next_section = false; expld.phase = phase; lang_statement_iteration++; lang_do_assignments_1 (statement_list.head, @@ -6637,7 +6730,7 @@ section_for_dot (void) if (stmt->header.type == lang_output_section_statement_enum) break; - os = &stmt->output_section_statement; + os = stmt ? &stmt->output_section_statement : NULL; while (os != NULL && !os->after_end && (os->bfd_section == NULL @@ -6797,6 +6890,19 @@ undef_start_stop (struct bfd_link_hash_entry *h) } h->type = bfd_link_hash_undefined; h->u.undef.abfd = NULL; + if (is_elf_hash_table (link_info.hash)) + { + const struct elf_backend_data *bed; + struct elf_link_hash_entry *eh = (struct elf_link_hash_entry *) h; + unsigned int was_forced = eh->forced_local; + + bed = get_elf_backend_data (link_info.output_bfd); + (*bed->elf_backend_hide_symbol) (&link_info, eh, true); + if (!eh->ref_regular_nonweak) + h->type = bfd_link_hash_undefweak; + eh->def_regular = 0; + eh->forced_local = was_forced; + } } } @@ -6869,17 +6975,55 @@ lang_finalize_start_stop (void) foreach_start_stop (set_start_stop); } +static void +lang_symbol_tweaks (void) +{ + /* Give initial values for __start and __stop symbols, so that ELF + gc_sections will keep sections referenced by these symbols. Must + be done before lang_do_assignments. */ + if (config.build_constructors) + lang_init_start_stop (); + + /* Make __ehdr_start hidden, and set def_regular even though it is + likely undefined at this stage. For lang_check_relocs. */ + if (is_elf_hash_table (link_info.hash) + && !bfd_link_relocatable (&link_info)) + { + struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) + bfd_link_hash_lookup (link_info.hash, "__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; + h->def_regular = 1; + h->root.linker_def = 1; + h->root.rel_from_abs = 1; + } + } +} + static void lang_end (void) { struct bfd_link_hash_entry *h; - bfd_boolean warn; + bool warn; if ((bfd_link_relocatable (&link_info) && !link_info.gc_sections) || bfd_link_dll (&link_info)) warn = entry_from_cmdline; else - warn = TRUE; + warn = true; /* Force the user to specify a root when generating a relocatable with --gc-sections, unless --gc-keep-exported was also given. */ @@ -6892,7 +7036,7 @@ lang_end (void) for (sym = link_info.gc_sym_list; sym != NULL; sym = sym->next) { h = bfd_link_hash_lookup (link_info.hash, sym->name, - FALSE, FALSE, FALSE); + false, false, false); if (h != NULL && (h->type == bfd_link_hash_defined || h->type == bfd_link_hash_defweak) @@ -6909,11 +7053,11 @@ lang_end (void) /* No entry has been specified. Look for the default entry, but don't warn if we don't find it. */ entry_symbol.name = entry_symbol_default; - warn = FALSE; + warn = false; } h = bfd_link_hash_lookup (link_info.hash, entry_symbol.name, - FALSE, FALSE, TRUE); + false, false, true); if (h != NULL && (h->type == bfd_link_hash_defined || h->type == bfd_link_hash_defweak) @@ -6940,7 +7084,8 @@ lang_end (void) if (!bfd_set_start_address (link_info.output_bfd, val)) einfo (_("%F%P: can't set start address\n")); } - else + /* BZ 2004952: Only use the start of the entry section for executables. */ + else if bfd_link_executable (&link_info) { asection *ts; @@ -6966,6 +7111,13 @@ lang_end (void) entry_symbol.name); } } + else + { + if (warn) + einfo (_("%P: warning: cannot find entry symbol %s;" + " not setting start address\n"), + entry_symbol.name); + } } } @@ -7101,7 +7253,7 @@ lang_common (void) /* Place one common symbol in the correct section. */ -static bfd_boolean +static bool lang_one_common (struct bfd_link_hash_entry *h, void *info) { unsigned int power_of_two; @@ -7109,17 +7261,17 @@ lang_one_common (struct bfd_link_hash_entry *h, void *info) asection *section; if (h->type != bfd_link_hash_common) - return TRUE; + return true; size = h->u.c.size; power_of_two = h->u.c.p->alignment_power; if (config.sort_common == sort_descending && power_of_two < *(unsigned int *) info) - return TRUE; + return true; else if (config.sort_common == sort_ascending && power_of_two > *(unsigned int *) info) - return TRUE; + return true; section = h->u.c.p->section; if (!bfd_define_common_symbol (link_info.output_bfd, &link_info, h)) @@ -7128,7 +7280,7 @@ lang_one_common (struct bfd_link_hash_entry *h, void *info) if (config.map_file != NULL) { - static bfd_boolean header_printed; + static bool header_printed; int len; char *name; char buf[50]; @@ -7137,7 +7289,7 @@ lang_one_common (struct bfd_link_hash_entry *h, void *info) { minfo (_("\nAllocating common symbols\n")); minfo (_("Common symbol size file\n\n")); - header_printed = TRUE; + header_printed = true; } name = bfd_demangle (link_info.output_bfd, h->root.string, @@ -7182,7 +7334,7 @@ lang_one_common (struct bfd_link_hash_entry *h, void *info) minfo ("%pB\n", section->owner); } - return TRUE; + return true; } /* Handle a single orphan section S, placing the orphan into an appropriate @@ -7195,13 +7347,12 @@ ldlang_place_orphan (asection *s) if (config.orphan_handling == orphan_handling_discard) { lang_output_section_statement_type *os; - os = lang_output_section_statement_lookup (DISCARD_SECTION_NAME, 0, - TRUE); + os = lang_output_section_statement_lookup (DISCARD_SECTION_NAME, 0, 1); if (os->addr_tree == NULL && (bfd_link_relocatable (&link_info) || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)) os->addr_tree = exp_intop (0); - lang_add_section (&os->children, s, NULL, os); + lang_add_section (&os->children, s, NULL, NULL, os); } else { @@ -7219,12 +7370,12 @@ ldlang_place_orphan (asection *s) os = ldemul_place_orphan (s, name, constraint); if (os == NULL) { - os = lang_output_section_statement_lookup (name, constraint, TRUE); + os = lang_output_section_statement_lookup (name, constraint, 1); if (os->addr_tree == NULL && (bfd_link_relocatable (&link_info) || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)) os->addr_tree = exp_intop (0); - lang_add_section (&os->children, s, NULL, os); + lang_add_section (&os->children, s, NULL, NULL, os); } if (config.orphan_handling == orphan_handling_warn) @@ -7266,10 +7417,9 @@ lang_place_orphans (void) { if (default_common_section == NULL) default_common_section - = lang_output_section_statement_lookup (".bss", 0, - TRUE); + = lang_output_section_statement_lookup (".bss", 0, 1); lang_add_section (&default_common_section->children, s, - NULL, default_common_section); + NULL, NULL, default_common_section); } } else @@ -7392,7 +7542,7 @@ lang_add_output (const char *name, int from_script) if (!had_output_filename || !from_script) { output_filename = name; - had_output_filename = TRUE; + had_output_filename = true; } } @@ -7400,6 +7550,7 @@ lang_output_section_statement_type * lang_enter_output_section_statement (const char *output_section_statement_name, etree_type *address_exp, enum section_type sectype, + etree_type *sectype_value, etree_type *align, etree_type *subalign, etree_type *ebase, @@ -7409,7 +7560,7 @@ lang_enter_output_section_statement (const char *output_section_statement_name, lang_output_section_statement_type *os; os = lang_output_section_statement_lookup (output_section_statement_name, - constraint, TRUE); + constraint, 2); current_section = os; if (os->addr_tree == NULL) @@ -7417,10 +7568,12 @@ lang_enter_output_section_statement (const char *output_section_statement_name, os->addr_tree = address_exp; } os->sectype = sectype; - if (sectype != noload_section) - os->flags = SEC_NO_FLAGS; - else + if (sectype == type_section || sectype == typed_readonly_section) + os->sectype_value = sectype_value; + else if (sectype == noload_section) os->flags = SEC_NEVER_LOAD; + else + os->flags = SEC_NO_FLAGS; os->block_value = 1; /* Make next things chain into subchain of this. */ @@ -7466,8 +7619,8 @@ lang_reset_memory_regions (void) os != NULL; os = os->next) { - os->processed_vma = FALSE; - os->processed_lma = FALSE; + os->processed_vma = false; + os->processed_lma = false; } for (o = link_info.output_bfd->sections; o != NULL; o = o->next) @@ -7485,7 +7638,6 @@ static void gc_section_callback (lang_wild_statement_type *ptr, struct wildcard_list *sec ATTRIBUTE_UNUSED, asection *section, - struct flag_info *sflag_info ATTRIBUTE_UNUSED, lang_input_statement_type *file ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED) { @@ -7529,7 +7681,7 @@ lang_gc_sections (void) lang_gc_sections_1 (statement_list.head); /* SEC_EXCLUDE is ignored when doing a relocatable link, except in - the special case of debug info. (See bfd/stabs.c) + the special case of .stabstr debug info. (See bfd/stabs.c) Twiddle the flag here, to simplify later linker code. */ if (bfd_link_relocatable (&link_info)) { @@ -7541,7 +7693,8 @@ lang_gc_sections (void) continue; #endif for (sec = f->the_bfd->sections; sec != NULL; sec = sec->next) - if ((sec->flags & SEC_DEBUGGING) == 0) + if ((sec->flags & SEC_DEBUGGING) == 0 + || strcmp (sec->name, ".stabstr") != 0) sec->flags &= ~SEC_EXCLUDE; } } @@ -7556,7 +7709,6 @@ static void find_relro_section_callback (lang_wild_statement_type *ptr ATTRIBUTE_UNUSED, struct wildcard_list *sec ATTRIBUTE_UNUSED, asection *section, - struct flag_info *sflag_info ATTRIBUTE_UNUSED, lang_input_statement_type *file ATTRIBUTE_UNUSED, void *data) { @@ -7568,8 +7720,8 @@ find_relro_section_callback (lang_wild_statement_type *ptr ATTRIBUTE_UNUSED, && !IGNORE_SECTION (section) && section->size != 0) { - bfd_boolean *has_relro_section = (bfd_boolean *) data; - *has_relro_section = TRUE; + bool *has_relro_section = (bool *) data; + *has_relro_section = true; } } @@ -7577,15 +7729,14 @@ find_relro_section_callback (lang_wild_statement_type *ptr ATTRIBUTE_UNUSED, static void lang_find_relro_sections_1 (lang_statement_union_type *s, - seg_align_type *seg, - bfd_boolean *has_relro_section) + bool *has_relro_section) { if (*has_relro_section) return; for (; s != NULL; s = s->header.next) { - if (s == seg->relro_end_stat) + if (s == expld.dataseg.relro_end_stat) break; switch (s->header.type) @@ -7597,15 +7748,15 @@ lang_find_relro_sections_1 (lang_statement_union_type *s, break; case lang_constructors_statement_enum: lang_find_relro_sections_1 (constructor_list.head, - seg, has_relro_section); + has_relro_section); break; case lang_output_section_statement_enum: lang_find_relro_sections_1 (s->output_section_statement.children.head, - seg, has_relro_section); + has_relro_section); break; case lang_group_statement_enum: lang_find_relro_sections_1 (s->group_statement.children.head, - seg, has_relro_section); + has_relro_section); break; default: break; @@ -7616,23 +7767,24 @@ lang_find_relro_sections_1 (lang_statement_union_type *s, static void lang_find_relro_sections (void) { - bfd_boolean has_relro_section = FALSE; + bool has_relro_section = false; /* Check all sections in the link script. */ lang_find_relro_sections_1 (expld.dataseg.relro_start_stat, - &expld.dataseg, &has_relro_section); + &has_relro_section); if (!has_relro_section) - link_info.relro = FALSE; + link_info.relro = false; } /* Relax all sections until bfd_relax_section gives up. */ void -lang_relax_sections (bfd_boolean need_layout) +lang_relax_sections (bool need_layout) { - if (RELAXATION_ENABLED) + /* NB: Also enable relaxation to layout sections for DT_RELR. */ + if (RELAXATION_ENABLED || link_info.enable_dt_relr) { /* We may need more than one relaxation pass. */ int i = link_info.relax_pass; @@ -7643,7 +7795,7 @@ lang_relax_sections (bfd_boolean need_layout) while (i--) { /* Keep relaxing until bfd_relax_section gives up. */ - bfd_boolean relax_again; + bool relax_again; link_info.relax_trip = -1; do @@ -7664,14 +7816,14 @@ lang_relax_sections (bfd_boolean need_layout) /* Perform another relax pass - this time we know where the globals are, so can make a better guess. */ - relax_again = FALSE; - lang_size_sections (&relax_again, FALSE); + relax_again = false; + lang_size_sections (&relax_again, false); } while (relax_again); link_info.relax_pass++; } - need_layout = TRUE; + need_layout = true; } if (need_layout) @@ -7679,7 +7831,7 @@ lang_relax_sections (bfd_boolean need_layout) /* Final extra sizing to report errors. */ lang_do_assignments (lang_assigning_phase_enum); lang_reset_memory_regions (); - lang_size_sections (NULL, TRUE); + lang_size_sections (NULL, true); } } @@ -7696,7 +7848,7 @@ lang_relax_sections (bfd_boolean need_layout) inserted at the head of the file_chain. */ static lang_input_statement_type * -find_replacements_insert_point (bfd_boolean *before) +find_replacements_insert_point (bool *before) { lang_input_statement_type *claim1, *lastobject; lastobject = (void *) input_file_chain.head; @@ -7716,7 +7868,7 @@ find_replacements_insert_point (bfd_boolean *before) /* No files were claimed by the plugin. Choose the last object file found on the list (maybe the first, dummy entry) as the insert point. */ - *before = FALSE; + *before = false; return lastobject; } @@ -7859,7 +8011,7 @@ lang_check_relocs (void) if (!bfd_link_check_relocs (abfd, &link_info)) { /* No object output, fail return. */ - config.make_executable = FALSE; + config.make_executable = false; /* Note: we do not abort the loop, but rather continue the scan in case there are other bad relocations to report. */ @@ -7915,7 +8067,7 @@ lang_process (void) means that when we call open_input_bfds PROVIDE statements will trigger to provide any needed symbols. The regions origins and lengths are not assigned as a result of this call. */ - lang_do_memory_regions (FALSE); + lang_do_memory_regions (false); /* Create a bfd for each input file. */ current_target = default_target; @@ -7924,7 +8076,7 @@ lang_process (void) /* Now that open_input_bfds has processed assignments and provide statements we can give values to symbolic origin/length now. */ - lang_do_memory_regions (TRUE); + lang_do_memory_regions (true); #if BFD_SUPPORTS_PLUGINS if (link_info.lto_plugin_active) @@ -7932,6 +8084,8 @@ lang_process (void) lang_statement_list_type added; lang_statement_list_type files, inputfiles; + ldemul_before_plugin_all_symbols_read (); + /* Now all files are read, let the plugin(s) decide if there are any more to be added to the link before we call the emulation's after_open hook. We create a private list of @@ -7945,7 +8099,7 @@ lang_process (void) if (plugin_call_all_symbols_read ()) einfo (_("%F%P: %s: plugin reported error after all symbols read\n"), plugin_error_plugin ()); - link_info.lto_all_symbols_read = TRUE; + link_info.lto_all_symbols_read = true; /* Open any newly added files, updating the file chains. */ plugin_undefs = link_info.hash->undefs_tail; open_input_bfds (*added.tail, OPEN_BFD_NORMAL); @@ -7963,7 +8117,7 @@ lang_process (void) after the first input file that was claimed by the plugin, unless that file was an archive in which case it is inserted immediately before. */ - bfd_boolean before; + bool before; lang_statement_union_type **prev; plugin_insert = find_replacements_insert_point (&before); /* If a plugin adds input files without having claimed any, we @@ -8079,11 +8233,7 @@ lang_process (void) files. */ ldctor_build_sets (); - /* Give initial values for __start and __stop symbols, so that ELF - gc_sections will keep sections referenced by these symbols. Must - be done before lang_do_assignments below. */ - if (config.build_constructors) - lang_init_start_stop (); + lang_symbol_tweaks (); /* PR 13683: We must rerun the assignments prior to running garbage collection in order to make sure that all symbol aliases are resolved. */ @@ -8096,6 +8246,8 @@ lang_process (void) /* Remove unreferenced sections if asked to. */ lang_gc_sections (); + lang_mark_undefineds (); + /* Check relocations. */ lang_check_relocs (); @@ -8211,7 +8363,7 @@ lang_process (void) void lang_add_wild (struct wildcard_spec *filespec, struct wildcard_list *section_list, - bfd_boolean keep_sections) + bool keep_sections) { struct wildcard_list *curr, *next; lang_wild_statement_type *new_stmt; @@ -8230,12 +8382,12 @@ lang_add_wild (struct wildcard_spec *filespec, if (strcmp (filespec->name, "*") == 0) filespec->name = NULL; else if (!wildcardp (filespec->name)) - lang_has_input_file = TRUE; + lang_has_input_file = true; } new_stmt = new_stat (lang_wild_statement, stat_ptr); new_stmt->filename = NULL; - new_stmt->filenames_sorted = FALSE; + new_stmt->filenames_sorted = false; new_stmt->section_flag_list = NULL; new_stmt->exclude_name_list = NULL; if (filespec != NULL) @@ -8269,7 +8421,7 @@ lang_section_start (const char *name, etree_type *address, precedence. */ void -lang_add_entry (const char *name, bfd_boolean cmdline) +lang_add_entry (const char *name, bool cmdline) { if (entry_symbol.name == NULL || cmdline @@ -8307,7 +8459,7 @@ lang_add_map (const char *name) switch (*name) { case 'F': - map_option_f = TRUE; + map_option_f = true; break; } name++; @@ -8385,11 +8537,11 @@ lang_startup (const char *name) } first_file->filename = name; first_file->local_sym_name = name; - first_file->flags.real = TRUE; + first_file->flags.real = true; } void -lang_float (bfd_boolean maybe) +lang_float (bool maybe) { lang_float_flag = maybe; } @@ -8411,10 +8563,10 @@ lang_get_regions (lang_memory_region_type **region, lang_memory_region_type **lma_region, const char *memspec, const char *lma_memspec, - bfd_boolean have_lma, - bfd_boolean have_vma) + bool have_lma, + bool have_vma) { - *lma_region = lang_memory_region_lookup (lma_memspec, FALSE); + *lma_region = lang_memory_region_lookup (lma_memspec, false); /* If no runtime region or VMA has been specified, but the load region has been specified, then use the load region for the runtime region @@ -8424,7 +8576,7 @@ lang_get_regions (lang_memory_region_type **region, && strcmp (memspec, DEFAULT_MEMORY_REGION) == 0) *region = *lma_region; else - *region = lang_memory_region_lookup (memspec, FALSE); + *region = lang_memory_region_lookup (memspec, false); if (have_lma && lma_memspec != 0) einfo (_("%X%P:%pS: section has both a load address and a load region\n"), @@ -8509,13 +8661,13 @@ lang_leave_group (void) void lang_new_phdr (const char *name, etree_type *type, - bfd_boolean filehdr, - bfd_boolean phdrs, + bool filehdr, + bool phdrs, etree_type *at, etree_type *flags) { struct lang_phdr *n, **pp; - bfd_boolean hdrs; + bool hdrs; n = stat_alloc (sizeof (struct lang_phdr)); n->next = NULL; @@ -8535,7 +8687,7 @@ lang_new_phdr (const char *name, { einfo (_("%X%P:%pS: PHDRS and FILEHDR are not supported" " when prior PT_LOAD headers lack them\n"), NULL); - hdrs = FALSE; + hdrs = false; } *pp = n; @@ -8626,7 +8778,7 @@ lang_record_phdrs (void) } secs[c] = os->bfd_section; ++c; - pl->used = TRUE; + pl->used = true; } } } @@ -8679,11 +8831,11 @@ lang_add_nocrossref (lang_nocrossref_type *l) n = (struct lang_nocrossrefs *) xmalloc (sizeof *n); n->next = nocrossref_list; n->list = l; - n->onlyfirst = FALSE; + n->onlyfirst = false; nocrossref_list = n; /* Set notice_all so that we get informed about all symbols. */ - link_info.notice_all = TRUE; + link_info.notice_all = true; } /* Record a section that cannot be referenced from a list of sections. */ @@ -8692,7 +8844,7 @@ void lang_add_nocrossref_to (lang_nocrossref_type *l) { lang_add_nocrossref (l); - nocrossref_list->onlyfirst = TRUE; + nocrossref_list->onlyfirst = true; } /* Overlay handling. We handle overlays with some static variables. */ @@ -8739,7 +8891,7 @@ lang_enter_overlay_section (const char *name) etree_type *size; lang_enter_output_section_statement (name, overlay_vma, overlay_section, - 0, overlay_subalign, 0, 0, 0); + 0, 0, overlay_subalign, 0, 0, 0); /* If this is the first section, then base the VMA of future sections on this one. This will work correctly even if `.' is @@ -8795,7 +8947,7 @@ lang_leave_overlay_section (fill_type *fill, sprintf (buf, "__load_start_%s", clean); lang_add_assignment (exp_provide (buf, exp_nameop (LOADADDR, name), - FALSE)); + false)); buf = (char *) xmalloc (strlen (clean) + sizeof "__load_stop_"); sprintf (buf, "__load_stop_%s", clean); @@ -8803,7 +8955,7 @@ lang_leave_overlay_section (fill_type *fill, exp_binop ('+', exp_nameop (LOADADDR, name), exp_nameop (SIZEOF, name)), - FALSE)); + false)); free (clean); } @@ -8826,7 +8978,7 @@ lang_leave_overlay (etree_type *lma_expr, lang_get_regions (®ion, &lma_region, memspec, lma_memspec, - lma_expr != NULL, FALSE); + lma_expr != NULL, false); nocrossref = NULL; @@ -8836,7 +8988,7 @@ lang_leave_overlay (etree_type *lma_expr, { overlay_list->os->update_dot = 1; overlay_list->os->update_dot_tree - = exp_assign (".", exp_binop ('+', overlay_vma, overlay_max), FALSE); + = exp_assign (".", exp_binop ('+', overlay_vma, overlay_max), false); } l = overlay_list; @@ -9016,7 +9168,7 @@ static const char * realsymbol (const char *pattern) { const char *p; - bfd_boolean changed = FALSE, backslash = FALSE; + bool changed = false, backslash = false; char *s, *symbol = (char *) xmalloc (strlen (pattern) + 1); for (p = pattern, s = symbol; *p != '\0'; ++p) @@ -9027,8 +9179,8 @@ realsymbol (const char *pattern) { /* Remove the preceding backslash. */ *(s - 1) = *p; - backslash = FALSE; - changed = TRUE; + backslash = false; + changed = true; } else { @@ -9063,7 +9215,7 @@ struct bfd_elf_version_expr * lang_new_vers_pattern (struct bfd_elf_version_expr *orig, const char *new_name, const char *lang, - bfd_boolean literal_p) + bool literal_p) { struct bfd_elf_version_expr *ret; @@ -9071,12 +9223,12 @@ lang_new_vers_pattern (struct bfd_elf_version_expr *orig, ret->next = orig; ret->symver = 0; ret->script = 0; - ret->literal = TRUE; + ret->literal = true; ret->pattern = literal_p ? new_name : realsymbol (new_name); if (ret->pattern == NULL) { ret->pattern = new_name; - ret->literal = FALSE; + ret->literal = false; } if (lang == NULL || strcasecmp (lang, "C") == 0) @@ -9367,7 +9519,7 @@ lang_do_version_exports_section (void) p = contents; while (p < contents + len) { - greg = lang_new_vers_pattern (greg, p, NULL, FALSE); + greg = lang_new_vers_pattern (greg, p, NULL, false); p = strchr (p, '\0') + 1; } @@ -9377,7 +9529,7 @@ lang_do_version_exports_section (void) sec->flags |= SEC_EXCLUDE | SEC_KEEP; } - lreg = lang_new_vers_pattern (NULL, "*", NULL, FALSE); + lreg = lang_new_vers_pattern (NULL, "*", NULL, false); lang_register_vers_node (command_line.version_exports_section, lang_new_vers_node (greg, lreg), NULL); } @@ -9391,7 +9543,7 @@ lang_do_version_exports_section (void) data structures, and throw errors if missing symbols are encountered. */ static void -lang_do_memory_regions (bfd_boolean update_regions_p) +lang_do_memory_regions (bool update_regions_p) { lang_memory_region_type *r = lang_memory_region_list; @@ -9483,7 +9635,7 @@ lang_append_dynamic_list_cpp_typeinfo (void) for (i = 0; i < ARRAY_SIZE (symbols); i++) dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++", - FALSE); + false); lang_append_dynamic_list (&link_info.dynamic_list, dynamic); } @@ -9504,7 +9656,7 @@ lang_append_dynamic_list_cpp_new (void) for (i = 0; i < ARRAY_SIZE (symbols); i++) dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++", - FALSE); + false); lang_append_dynamic_list (&link_info.dynamic_list, dynamic); } @@ -9530,7 +9682,7 @@ lang_ld_feature (char *str) sep = *q; *q = 0; if (strcasecmp (p, "SANE_EXPR") == 0) - config.sane_expr = TRUE; + config.sane_expr = true; else einfo (_("%X%P: unknown feature `%s'\n"), p); *q = sep;