13d8817e4Smiod /* Linker command language support.
23d8817e4Smiod Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
33d8817e4Smiod 2001, 2002, 2003, 2004, 2005, 2006
43d8817e4Smiod Free Software Foundation, Inc.
53d8817e4Smiod
63d8817e4Smiod This file is part of GLD, the Gnu Linker.
73d8817e4Smiod
83d8817e4Smiod GLD is free software; you can redistribute it and/or modify
93d8817e4Smiod it under the terms of the GNU General Public License as published by
103d8817e4Smiod the Free Software Foundation; either version 2, or (at your option)
113d8817e4Smiod any later version.
123d8817e4Smiod
133d8817e4Smiod GLD is distributed in the hope that it will be useful,
143d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
153d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
163d8817e4Smiod GNU General Public License for more details.
173d8817e4Smiod
183d8817e4Smiod You should have received a copy of the GNU General Public License
193d8817e4Smiod along with GLD; see the file COPYING. If not, write to the Free
203d8817e4Smiod Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
213d8817e4Smiod 02110-1301, USA. */
223d8817e4Smiod
233d8817e4Smiod #include "bfd.h"
243d8817e4Smiod #include "sysdep.h"
253d8817e4Smiod #include "libiberty.h"
263d8817e4Smiod #include "safe-ctype.h"
273d8817e4Smiod #include "obstack.h"
283d8817e4Smiod #include "bfdlink.h"
293d8817e4Smiod
303d8817e4Smiod #include "ld.h"
313d8817e4Smiod #include "ldmain.h"
323d8817e4Smiod #include "ldexp.h"
333d8817e4Smiod #include "ldlang.h"
343d8817e4Smiod #include <ldgram.h>
353d8817e4Smiod #include "ldlex.h"
363d8817e4Smiod #include "ldmisc.h"
373d8817e4Smiod #include "ldctor.h"
383d8817e4Smiod #include "ldfile.h"
393d8817e4Smiod #include "ldemul.h"
403d8817e4Smiod #include "fnmatch.h"
413d8817e4Smiod #include "demangle.h"
423d8817e4Smiod #include "hashtab.h"
433d8817e4Smiod
443d8817e4Smiod #ifndef offsetof
453d8817e4Smiod #define offsetof(TYPE, MEMBER) ((size_t) & (((TYPE*) 0)->MEMBER))
463d8817e4Smiod #endif
473d8817e4Smiod
483d8817e4Smiod /* Locals variables. */
493d8817e4Smiod static struct obstack stat_obstack;
503d8817e4Smiod static struct obstack map_obstack;
513d8817e4Smiod
523d8817e4Smiod #define obstack_chunk_alloc xmalloc
533d8817e4Smiod #define obstack_chunk_free free
543d8817e4Smiod static const char *startup_file;
553d8817e4Smiod static lang_statement_list_type input_file_chain;
563d8817e4Smiod static bfd_boolean placed_commons = FALSE;
573d8817e4Smiod static bfd_boolean stripped_excluded_sections = FALSE;
583d8817e4Smiod static lang_output_section_statement_type *default_common_section;
593d8817e4Smiod static bfd_boolean map_option_f;
603d8817e4Smiod static bfd_vma print_dot;
613d8817e4Smiod static lang_input_statement_type *first_file;
623d8817e4Smiod static const char *current_target;
633d8817e4Smiod static const char *output_target;
643d8817e4Smiod static lang_statement_list_type statement_list;
653d8817e4Smiod static struct lang_phdr *lang_phdr_list;
663d8817e4Smiod static struct bfd_hash_table lang_definedness_table;
673d8817e4Smiod
683d8817e4Smiod /* Forward declarations. */
693d8817e4Smiod static void exp_init_os (etree_type *);
703d8817e4Smiod static void init_map_userdata (bfd *, asection *, void *);
713d8817e4Smiod static lang_input_statement_type *lookup_name (const char *);
723d8817e4Smiod static bfd_boolean load_symbols (lang_input_statement_type *,
733d8817e4Smiod lang_statement_list_type *);
743d8817e4Smiod static struct bfd_hash_entry *lang_definedness_newfunc
753d8817e4Smiod (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
763d8817e4Smiod static void insert_undefined (const char *);
773d8817e4Smiod static void print_all_symbols (asection *);
783d8817e4Smiod static bfd_boolean sort_def_symbol (struct bfd_link_hash_entry *, void *);
793d8817e4Smiod static void print_statement (lang_statement_union_type *,
803d8817e4Smiod lang_output_section_statement_type *);
813d8817e4Smiod static void print_statement_list (lang_statement_union_type *,
823d8817e4Smiod lang_output_section_statement_type *);
833d8817e4Smiod static void print_statements (void);
843d8817e4Smiod static void print_input_section (asection *);
853d8817e4Smiod static bfd_boolean lang_one_common (struct bfd_link_hash_entry *, void *);
863d8817e4Smiod static void lang_record_phdrs (void);
873d8817e4Smiod static void lang_do_version_exports_section (void);
883d8817e4Smiod
893d8817e4Smiod /* Exported variables. */
903d8817e4Smiod lang_output_section_statement_type *abs_output_section;
913d8817e4Smiod lang_statement_list_type lang_output_section_statement;
923d8817e4Smiod lang_statement_list_type *stat_ptr = &statement_list;
933d8817e4Smiod lang_statement_list_type file_chain = { NULL, NULL };
943d8817e4Smiod struct bfd_sym_chain entry_symbol = { NULL, NULL };
953d8817e4Smiod static const char *entry_symbol_default = "start";
963d8817e4Smiod const char *entry_section = ".text";
973d8817e4Smiod bfd_boolean entry_from_cmdline;
983d8817e4Smiod bfd_boolean lang_has_input_file = FALSE;
993d8817e4Smiod bfd_boolean had_output_filename = FALSE;
1003d8817e4Smiod bfd_boolean lang_float_flag = FALSE;
1013d8817e4Smiod bfd_boolean delete_output_file_on_failure = FALSE;
1023d8817e4Smiod struct lang_nocrossrefs *nocrossref_list;
1033d8817e4Smiod static struct unique_sections *unique_section_list;
1043d8817e4Smiod static bfd_boolean ldlang_sysrooted_script = FALSE;
1053d8817e4Smiod
1063d8817e4Smiod /* Functions that traverse the linker script and might evaluate
1073d8817e4Smiod DEFINED() need to increment this. */
1083d8817e4Smiod int lang_statement_iteration = 0;
1093d8817e4Smiod
1103d8817e4Smiod etree_type *base; /* Relocation base - or null */
1113d8817e4Smiod
1123d8817e4Smiod /* Return TRUE if the PATTERN argument is a wildcard pattern.
1133d8817e4Smiod Although backslashes are treated specially if a pattern contains
1143d8817e4Smiod wildcards, we do not consider the mere presence of a backslash to
1153d8817e4Smiod be enough to cause the pattern to be treated as a wildcard.
1163d8817e4Smiod That lets us handle DOS filenames more naturally. */
1173d8817e4Smiod #define wildcardp(pattern) (strpbrk ((pattern), "?*[") != NULL)
1183d8817e4Smiod
1193d8817e4Smiod #define new_stat(x, y) \
1203d8817e4Smiod (x##_type *) new_statement (x##_enum, sizeof (x##_type), y)
1213d8817e4Smiod
1223d8817e4Smiod #define outside_section_address(q) \
1233d8817e4Smiod ((q)->output_offset + (q)->output_section->vma)
1243d8817e4Smiod
1253d8817e4Smiod #define outside_symbol_address(q) \
1263d8817e4Smiod ((q)->value + outside_section_address (q->section))
1273d8817e4Smiod
1283d8817e4Smiod #define SECTION_NAME_MAP_LENGTH (16)
1293d8817e4Smiod
1303d8817e4Smiod void *
stat_alloc(size_t size)1313d8817e4Smiod stat_alloc (size_t size)
1323d8817e4Smiod {
1333d8817e4Smiod return obstack_alloc (&stat_obstack, size);
1343d8817e4Smiod }
1353d8817e4Smiod
1363d8817e4Smiod bfd_boolean
unique_section_p(const asection * sec)1373d8817e4Smiod unique_section_p (const asection *sec)
1383d8817e4Smiod {
1393d8817e4Smiod struct unique_sections *unam;
1403d8817e4Smiod const char *secnam;
1413d8817e4Smiod
1423d8817e4Smiod if (link_info.relocatable
1433d8817e4Smiod && sec->owner != NULL
1443d8817e4Smiod && bfd_is_group_section (sec->owner, sec))
1453d8817e4Smiod return TRUE;
1463d8817e4Smiod
1473d8817e4Smiod secnam = sec->name;
1483d8817e4Smiod for (unam = unique_section_list; unam; unam = unam->next)
1493d8817e4Smiod if (wildcardp (unam->name)
1503d8817e4Smiod ? fnmatch (unam->name, secnam, 0) == 0
1513d8817e4Smiod : strcmp (unam->name, secnam) == 0)
1523d8817e4Smiod {
1533d8817e4Smiod return TRUE;
1543d8817e4Smiod }
1553d8817e4Smiod
1563d8817e4Smiod return FALSE;
1573d8817e4Smiod }
1583d8817e4Smiod
1593d8817e4Smiod /* Generic traversal routines for finding matching sections. */
1603d8817e4Smiod
1613d8817e4Smiod /* Try processing a section against a wildcard. This just calls
1623d8817e4Smiod the callback unless the filename exclusion list is present
1633d8817e4Smiod and excludes the file. It's hardly ever present so this
1643d8817e4Smiod function is very fast. */
1653d8817e4Smiod
1663d8817e4Smiod static void
walk_wild_consider_section(lang_wild_statement_type * ptr,lang_input_statement_type * file,asection * s,struct wildcard_list * sec,callback_t callback,void * data)1673d8817e4Smiod walk_wild_consider_section (lang_wild_statement_type *ptr,
1683d8817e4Smiod lang_input_statement_type *file,
1693d8817e4Smiod asection *s,
1703d8817e4Smiod struct wildcard_list *sec,
1713d8817e4Smiod callback_t callback,
1723d8817e4Smiod void *data)
1733d8817e4Smiod {
1743d8817e4Smiod bfd_boolean skip = FALSE;
1753d8817e4Smiod struct name_list *list_tmp;
1763d8817e4Smiod
1773d8817e4Smiod /* Don't process sections from files which were
1783d8817e4Smiod excluded. */
1793d8817e4Smiod for (list_tmp = sec->spec.exclude_name_list;
1803d8817e4Smiod list_tmp;
1813d8817e4Smiod list_tmp = list_tmp->next)
1823d8817e4Smiod {
1833d8817e4Smiod bfd_boolean is_wildcard = wildcardp (list_tmp->name);
1843d8817e4Smiod if (is_wildcard)
1853d8817e4Smiod skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
1863d8817e4Smiod else
1873d8817e4Smiod skip = strcmp (list_tmp->name, file->filename) == 0;
1883d8817e4Smiod
1893d8817e4Smiod /* If this file is part of an archive, and the archive is
1903d8817e4Smiod excluded, exclude this file. */
1913d8817e4Smiod if (! skip && file->the_bfd != NULL
1923d8817e4Smiod && file->the_bfd->my_archive != NULL
1933d8817e4Smiod && file->the_bfd->my_archive->filename != NULL)
1943d8817e4Smiod {
1953d8817e4Smiod if (is_wildcard)
1963d8817e4Smiod skip = fnmatch (list_tmp->name,
1973d8817e4Smiod file->the_bfd->my_archive->filename,
1983d8817e4Smiod 0) == 0;
1993d8817e4Smiod else
2003d8817e4Smiod skip = strcmp (list_tmp->name,
2013d8817e4Smiod file->the_bfd->my_archive->filename) == 0;
2023d8817e4Smiod }
2033d8817e4Smiod
2043d8817e4Smiod if (skip)
2053d8817e4Smiod break;
2063d8817e4Smiod }
2073d8817e4Smiod
2083d8817e4Smiod if (!skip)
2093d8817e4Smiod (*callback) (ptr, sec, s, file, data);
2103d8817e4Smiod }
2113d8817e4Smiod
2123d8817e4Smiod /* Lowest common denominator routine that can handle everything correctly,
2133d8817e4Smiod but slowly. */
2143d8817e4Smiod
2153d8817e4Smiod static void
walk_wild_section_general(lang_wild_statement_type * ptr,lang_input_statement_type * file,callback_t callback,void * data)2163d8817e4Smiod walk_wild_section_general (lang_wild_statement_type *ptr,
2173d8817e4Smiod lang_input_statement_type *file,
2183d8817e4Smiod callback_t callback,
2193d8817e4Smiod void *data)
2203d8817e4Smiod {
2213d8817e4Smiod asection *s;
2223d8817e4Smiod struct wildcard_list *sec;
2233d8817e4Smiod
2243d8817e4Smiod for (s = file->the_bfd->sections; s != NULL; s = s->next)
2253d8817e4Smiod {
2263d8817e4Smiod sec = ptr->section_list;
2273d8817e4Smiod if (sec == NULL)
2283d8817e4Smiod (*callback) (ptr, sec, s, file, data);
2293d8817e4Smiod
2303d8817e4Smiod while (sec != NULL)
2313d8817e4Smiod {
2323d8817e4Smiod bfd_boolean skip = FALSE;
2333d8817e4Smiod
2343d8817e4Smiod if (sec->spec.name != NULL)
2353d8817e4Smiod {
2363d8817e4Smiod const char *sname = bfd_get_section_name (file->the_bfd, s);
2373d8817e4Smiod
2383d8817e4Smiod if (wildcardp (sec->spec.name))
2393d8817e4Smiod skip = fnmatch (sec->spec.name, sname, 0) != 0;
2403d8817e4Smiod else
2413d8817e4Smiod skip = strcmp (sec->spec.name, sname) != 0;
2423d8817e4Smiod }
2433d8817e4Smiod
2443d8817e4Smiod if (!skip)
2453d8817e4Smiod walk_wild_consider_section (ptr, file, s, sec, callback, data);
2463d8817e4Smiod
2473d8817e4Smiod sec = sec->next;
2483d8817e4Smiod }
2493d8817e4Smiod }
2503d8817e4Smiod }
2513d8817e4Smiod
2523d8817e4Smiod /* Routines to find a single section given its name. If there's more
2533d8817e4Smiod than one section with that name, we report that. */
2543d8817e4Smiod
2553d8817e4Smiod typedef struct
2563d8817e4Smiod {
2573d8817e4Smiod asection *found_section;
2583d8817e4Smiod bfd_boolean multiple_sections_found;
2593d8817e4Smiod } section_iterator_callback_data;
2603d8817e4Smiod
2613d8817e4Smiod static bfd_boolean
section_iterator_callback(bfd * bfd ATTRIBUTE_UNUSED,asection * s,void * data)2623d8817e4Smiod section_iterator_callback (bfd *bfd ATTRIBUTE_UNUSED, asection *s, void *data)
2633d8817e4Smiod {
2643d8817e4Smiod section_iterator_callback_data *d = data;
2653d8817e4Smiod
2663d8817e4Smiod if (d->found_section != NULL)
2673d8817e4Smiod {
2683d8817e4Smiod d->multiple_sections_found = TRUE;
2693d8817e4Smiod return TRUE;
2703d8817e4Smiod }
2713d8817e4Smiod
2723d8817e4Smiod d->found_section = s;
2733d8817e4Smiod return FALSE;
2743d8817e4Smiod }
2753d8817e4Smiod
2763d8817e4Smiod static asection *
find_section(lang_input_statement_type * file,struct wildcard_list * sec,bfd_boolean * multiple_sections_found)2773d8817e4Smiod find_section (lang_input_statement_type *file,
2783d8817e4Smiod struct wildcard_list *sec,
2793d8817e4Smiod bfd_boolean *multiple_sections_found)
2803d8817e4Smiod {
2813d8817e4Smiod section_iterator_callback_data cb_data = { NULL, FALSE };
2823d8817e4Smiod
2833d8817e4Smiod bfd_get_section_by_name_if (file->the_bfd, sec->spec.name,
2843d8817e4Smiod section_iterator_callback, &cb_data);
2853d8817e4Smiod *multiple_sections_found = cb_data.multiple_sections_found;
2863d8817e4Smiod return cb_data.found_section;
2873d8817e4Smiod }
2883d8817e4Smiod
2893d8817e4Smiod /* Code for handling simple wildcards without going through fnmatch,
2903d8817e4Smiod which can be expensive because of charset translations etc. */
2913d8817e4Smiod
2923d8817e4Smiod /* A simple wild is a literal string followed by a single '*',
2933d8817e4Smiod where the literal part is at least 4 characters long. */
2943d8817e4Smiod
2953d8817e4Smiod static bfd_boolean
is_simple_wild(const char * name)2963d8817e4Smiod is_simple_wild (const char *name)
2973d8817e4Smiod {
2983d8817e4Smiod size_t len = strcspn (name, "*?[");
2993d8817e4Smiod return len >= 4 && name[len] == '*' && name[len + 1] == '\0';
3003d8817e4Smiod }
3013d8817e4Smiod
3023d8817e4Smiod static bfd_boolean
match_simple_wild(const char * pattern,const char * name)3033d8817e4Smiod match_simple_wild (const char *pattern, const char *name)
3043d8817e4Smiod {
3053d8817e4Smiod /* The first four characters of the pattern are guaranteed valid
3063d8817e4Smiod non-wildcard characters. So we can go faster. */
3073d8817e4Smiod if (pattern[0] != name[0] || pattern[1] != name[1]
3083d8817e4Smiod || pattern[2] != name[2] || pattern[3] != name[3])
3093d8817e4Smiod return FALSE;
3103d8817e4Smiod
3113d8817e4Smiod pattern += 4;
3123d8817e4Smiod name += 4;
3133d8817e4Smiod while (*pattern != '*')
3143d8817e4Smiod if (*name++ != *pattern++)
3153d8817e4Smiod return FALSE;
3163d8817e4Smiod
3173d8817e4Smiod return TRUE;
3183d8817e4Smiod }
3193d8817e4Smiod
3203d8817e4Smiod /* Specialized, optimized routines for handling different kinds of
3213d8817e4Smiod wildcards */
3223d8817e4Smiod
3233d8817e4Smiod static void
walk_wild_section_specs1_wild0(lang_wild_statement_type * ptr,lang_input_statement_type * file,callback_t callback,void * data)3243d8817e4Smiod walk_wild_section_specs1_wild0 (lang_wild_statement_type *ptr,
3253d8817e4Smiod lang_input_statement_type *file,
3263d8817e4Smiod callback_t callback,
3273d8817e4Smiod void *data)
3283d8817e4Smiod {
3293d8817e4Smiod /* We can just do a hash lookup for the section with the right name.
3303d8817e4Smiod But if that lookup discovers more than one section with the name
3313d8817e4Smiod (should be rare), we fall back to the general algorithm because
3323d8817e4Smiod we would otherwise have to sort the sections to make sure they
3333d8817e4Smiod get processed in the bfd's order. */
3343d8817e4Smiod bfd_boolean multiple_sections_found;
3353d8817e4Smiod struct wildcard_list *sec0 = ptr->handler_data[0];
3363d8817e4Smiod asection *s0 = find_section (file, sec0, &multiple_sections_found);
3373d8817e4Smiod
3383d8817e4Smiod if (multiple_sections_found)
3393d8817e4Smiod walk_wild_section_general (ptr, file, callback, data);
3403d8817e4Smiod else if (s0)
3413d8817e4Smiod walk_wild_consider_section (ptr, file, s0, sec0, callback, data);
3423d8817e4Smiod }
3433d8817e4Smiod
3443d8817e4Smiod static void
walk_wild_section_specs1_wild1(lang_wild_statement_type * ptr,lang_input_statement_type * file,callback_t callback,void * data)3453d8817e4Smiod walk_wild_section_specs1_wild1 (lang_wild_statement_type *ptr,
3463d8817e4Smiod lang_input_statement_type *file,
3473d8817e4Smiod callback_t callback,
3483d8817e4Smiod void *data)
3493d8817e4Smiod {
3503d8817e4Smiod asection *s;
3513d8817e4Smiod struct wildcard_list *wildsec0 = ptr->handler_data[0];
3523d8817e4Smiod
3533d8817e4Smiod for (s = file->the_bfd->sections; s != NULL; s = s->next)
3543d8817e4Smiod {
3553d8817e4Smiod const char *sname = bfd_get_section_name (file->the_bfd, s);
3563d8817e4Smiod bfd_boolean skip = !match_simple_wild (wildsec0->spec.name, sname);
3573d8817e4Smiod
3583d8817e4Smiod if (!skip)
3593d8817e4Smiod walk_wild_consider_section (ptr, file, s, wildsec0, callback, data);
3603d8817e4Smiod }
3613d8817e4Smiod }
3623d8817e4Smiod
3633d8817e4Smiod static void
walk_wild_section_specs2_wild1(lang_wild_statement_type * ptr,lang_input_statement_type * file,callback_t callback,void * data)3643d8817e4Smiod walk_wild_section_specs2_wild1 (lang_wild_statement_type *ptr,
3653d8817e4Smiod lang_input_statement_type *file,
3663d8817e4Smiod callback_t callback,
3673d8817e4Smiod void *data)
3683d8817e4Smiod {
3693d8817e4Smiod asection *s;
3703d8817e4Smiod struct wildcard_list *sec0 = ptr->handler_data[0];
3713d8817e4Smiod struct wildcard_list *wildsec1 = ptr->handler_data[1];
3723d8817e4Smiod bfd_boolean multiple_sections_found;
3733d8817e4Smiod asection *s0 = find_section (file, sec0, &multiple_sections_found);
3743d8817e4Smiod
3753d8817e4Smiod if (multiple_sections_found)
3763d8817e4Smiod {
3773d8817e4Smiod walk_wild_section_general (ptr, file, callback, data);
3783d8817e4Smiod return;
3793d8817e4Smiod }
3803d8817e4Smiod
3813d8817e4Smiod /* Note that if the section was not found, s0 is NULL and
3823d8817e4Smiod we'll simply never succeed the s == s0 test below. */
3833d8817e4Smiod for (s = file->the_bfd->sections; s != NULL; s = s->next)
3843d8817e4Smiod {
3853d8817e4Smiod /* Recall that in this code path, a section cannot satisfy more
3863d8817e4Smiod than one spec, so if s == s0 then it cannot match
3873d8817e4Smiod wildspec1. */
3883d8817e4Smiod if (s == s0)
3893d8817e4Smiod walk_wild_consider_section (ptr, file, s, sec0, callback, data);
3903d8817e4Smiod else
3913d8817e4Smiod {
3923d8817e4Smiod const char *sname = bfd_get_section_name (file->the_bfd, s);
3933d8817e4Smiod bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname);
3943d8817e4Smiod
3953d8817e4Smiod if (!skip)
3963d8817e4Smiod walk_wild_consider_section (ptr, file, s, wildsec1, callback,
3973d8817e4Smiod data);
3983d8817e4Smiod }
3993d8817e4Smiod }
4003d8817e4Smiod }
4013d8817e4Smiod
4023d8817e4Smiod static void
walk_wild_section_specs3_wild2(lang_wild_statement_type * ptr,lang_input_statement_type * file,callback_t callback,void * data)4033d8817e4Smiod walk_wild_section_specs3_wild2 (lang_wild_statement_type *ptr,
4043d8817e4Smiod lang_input_statement_type *file,
4053d8817e4Smiod callback_t callback,
4063d8817e4Smiod void *data)
4073d8817e4Smiod {
4083d8817e4Smiod asection *s;
4093d8817e4Smiod struct wildcard_list *sec0 = ptr->handler_data[0];
4103d8817e4Smiod struct wildcard_list *wildsec1 = ptr->handler_data[1];
4113d8817e4Smiod struct wildcard_list *wildsec2 = ptr->handler_data[2];
4123d8817e4Smiod bfd_boolean multiple_sections_found;
4133d8817e4Smiod asection *s0 = find_section (file, sec0, &multiple_sections_found);
4143d8817e4Smiod
4153d8817e4Smiod if (multiple_sections_found)
4163d8817e4Smiod {
4173d8817e4Smiod walk_wild_section_general (ptr, file, callback, data);
4183d8817e4Smiod return;
4193d8817e4Smiod }
4203d8817e4Smiod
4213d8817e4Smiod for (s = file->the_bfd->sections; s != NULL; s = s->next)
4223d8817e4Smiod {
4233d8817e4Smiod if (s == s0)
4243d8817e4Smiod walk_wild_consider_section (ptr, file, s, sec0, callback, data);
4253d8817e4Smiod else
4263d8817e4Smiod {
4273d8817e4Smiod const char *sname = bfd_get_section_name (file->the_bfd, s);
4283d8817e4Smiod bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname);
4293d8817e4Smiod
4303d8817e4Smiod if (!skip)
4313d8817e4Smiod walk_wild_consider_section (ptr, file, s, wildsec1, callback, data);
4323d8817e4Smiod else
4333d8817e4Smiod {
4343d8817e4Smiod skip = !match_simple_wild (wildsec2->spec.name, sname);
4353d8817e4Smiod if (!skip)
4363d8817e4Smiod walk_wild_consider_section (ptr, file, s, wildsec2, callback,
4373d8817e4Smiod data);
4383d8817e4Smiod }
4393d8817e4Smiod }
4403d8817e4Smiod }
4413d8817e4Smiod }
4423d8817e4Smiod
4433d8817e4Smiod static void
walk_wild_section_specs4_wild2(lang_wild_statement_type * ptr,lang_input_statement_type * file,callback_t callback,void * data)4443d8817e4Smiod walk_wild_section_specs4_wild2 (lang_wild_statement_type *ptr,
4453d8817e4Smiod lang_input_statement_type *file,
4463d8817e4Smiod callback_t callback,
4473d8817e4Smiod void *data)
4483d8817e4Smiod {
4493d8817e4Smiod asection *s;
4503d8817e4Smiod struct wildcard_list *sec0 = ptr->handler_data[0];
4513d8817e4Smiod struct wildcard_list *sec1 = ptr->handler_data[1];
4523d8817e4Smiod struct wildcard_list *wildsec2 = ptr->handler_data[2];
4533d8817e4Smiod struct wildcard_list *wildsec3 = ptr->handler_data[3];
4543d8817e4Smiod bfd_boolean multiple_sections_found;
4553d8817e4Smiod asection *s0 = find_section (file, sec0, &multiple_sections_found), *s1;
4563d8817e4Smiod
4573d8817e4Smiod if (multiple_sections_found)
4583d8817e4Smiod {
4593d8817e4Smiod walk_wild_section_general (ptr, file, callback, data);
4603d8817e4Smiod return;
4613d8817e4Smiod }
4623d8817e4Smiod
4633d8817e4Smiod s1 = find_section (file, sec1, &multiple_sections_found);
4643d8817e4Smiod if (multiple_sections_found)
4653d8817e4Smiod {
4663d8817e4Smiod walk_wild_section_general (ptr, file, callback, data);
4673d8817e4Smiod return;
4683d8817e4Smiod }
4693d8817e4Smiod
4703d8817e4Smiod for (s = file->the_bfd->sections; s != NULL; s = s->next)
4713d8817e4Smiod {
4723d8817e4Smiod if (s == s0)
4733d8817e4Smiod walk_wild_consider_section (ptr, file, s, sec0, callback, data);
4743d8817e4Smiod else
4753d8817e4Smiod if (s == s1)
4763d8817e4Smiod walk_wild_consider_section (ptr, file, s, sec1, callback, data);
4773d8817e4Smiod else
4783d8817e4Smiod {
4793d8817e4Smiod const char *sname = bfd_get_section_name (file->the_bfd, s);
4803d8817e4Smiod bfd_boolean skip = !match_simple_wild (wildsec2->spec.name,
4813d8817e4Smiod sname);
4823d8817e4Smiod
4833d8817e4Smiod if (!skip)
4843d8817e4Smiod walk_wild_consider_section (ptr, file, s, wildsec2, callback,
4853d8817e4Smiod data);
4863d8817e4Smiod else
4873d8817e4Smiod {
4883d8817e4Smiod skip = !match_simple_wild (wildsec3->spec.name, sname);
4893d8817e4Smiod if (!skip)
4903d8817e4Smiod walk_wild_consider_section (ptr, file, s, wildsec3,
4913d8817e4Smiod callback, data);
4923d8817e4Smiod }
4933d8817e4Smiod }
4943d8817e4Smiod }
4953d8817e4Smiod }
4963d8817e4Smiod
4973d8817e4Smiod static void
walk_wild_section(lang_wild_statement_type * ptr,lang_input_statement_type * file,callback_t callback,void * data)4983d8817e4Smiod walk_wild_section (lang_wild_statement_type *ptr,
4993d8817e4Smiod lang_input_statement_type *file,
5003d8817e4Smiod callback_t callback,
5013d8817e4Smiod void *data)
5023d8817e4Smiod {
5033d8817e4Smiod if (file->just_syms_flag)
5043d8817e4Smiod return;
5053d8817e4Smiod
5063d8817e4Smiod (*ptr->walk_wild_section_handler) (ptr, file, callback, data);
5073d8817e4Smiod }
5083d8817e4Smiod
5093d8817e4Smiod /* Returns TRUE when name1 is a wildcard spec that might match
5103d8817e4Smiod something name2 can match. We're conservative: we return FALSE
5113d8817e4Smiod only if the prefixes of name1 and name2 are different up to the
5123d8817e4Smiod first wildcard character. */
5133d8817e4Smiod
5143d8817e4Smiod static bfd_boolean
wild_spec_can_overlap(const char * name1,const char * name2)5153d8817e4Smiod wild_spec_can_overlap (const char *name1, const char *name2)
5163d8817e4Smiod {
5173d8817e4Smiod size_t prefix1_len = strcspn (name1, "?*[");
5183d8817e4Smiod size_t prefix2_len = strcspn (name2, "?*[");
5193d8817e4Smiod size_t min_prefix_len;
5203d8817e4Smiod
5213d8817e4Smiod /* Note that if there is no wildcard character, then we treat the
5223d8817e4Smiod terminating 0 as part of the prefix. Thus ".text" won't match
5233d8817e4Smiod ".text." or ".text.*", for example. */
5243d8817e4Smiod if (name1[prefix1_len] == '\0')
5253d8817e4Smiod prefix1_len++;
5263d8817e4Smiod if (name2[prefix2_len] == '\0')
5273d8817e4Smiod prefix2_len++;
5283d8817e4Smiod
5293d8817e4Smiod min_prefix_len = prefix1_len < prefix2_len ? prefix1_len : prefix2_len;
5303d8817e4Smiod
5313d8817e4Smiod return memcmp (name1, name2, min_prefix_len) == 0;
5323d8817e4Smiod }
5333d8817e4Smiod
5343d8817e4Smiod /* Select specialized code to handle various kinds of wildcard
5353d8817e4Smiod statements. */
5363d8817e4Smiod
5373d8817e4Smiod static void
analyze_walk_wild_section_handler(lang_wild_statement_type * ptr)5383d8817e4Smiod analyze_walk_wild_section_handler (lang_wild_statement_type *ptr)
5393d8817e4Smiod {
5403d8817e4Smiod int sec_count = 0;
5413d8817e4Smiod int wild_name_count = 0;
5423d8817e4Smiod struct wildcard_list *sec;
5433d8817e4Smiod int signature;
5443d8817e4Smiod int data_counter;
5453d8817e4Smiod
5463d8817e4Smiod ptr->walk_wild_section_handler = walk_wild_section_general;
5473d8817e4Smiod
5483d8817e4Smiod /* Count how many wildcard_specs there are, and how many of those
5493d8817e4Smiod actually use wildcards in the name. Also, bail out if any of the
5503d8817e4Smiod wildcard names are NULL. (Can this actually happen?
5513d8817e4Smiod walk_wild_section used to test for it.) And bail out if any
5523d8817e4Smiod of the wildcards are more complex than a simple string
5533d8817e4Smiod ending in a single '*'. */
5543d8817e4Smiod for (sec = ptr->section_list; sec != NULL; sec = sec->next)
5553d8817e4Smiod {
5563d8817e4Smiod ++sec_count;
5573d8817e4Smiod if (sec->spec.name == NULL)
5583d8817e4Smiod return;
5593d8817e4Smiod if (wildcardp (sec->spec.name))
5603d8817e4Smiod {
5613d8817e4Smiod ++wild_name_count;
5623d8817e4Smiod if (!is_simple_wild (sec->spec.name))
5633d8817e4Smiod return;
5643d8817e4Smiod }
5653d8817e4Smiod }
5663d8817e4Smiod
5673d8817e4Smiod /* The zero-spec case would be easy to optimize but it doesn't
5683d8817e4Smiod happen in practice. Likewise, more than 4 specs doesn't
5693d8817e4Smiod happen in practice. */
5703d8817e4Smiod if (sec_count == 0 || sec_count > 4)
5713d8817e4Smiod return;
5723d8817e4Smiod
5733d8817e4Smiod /* Check that no two specs can match the same section. */
5743d8817e4Smiod for (sec = ptr->section_list; sec != NULL; sec = sec->next)
5753d8817e4Smiod {
5763d8817e4Smiod struct wildcard_list *sec2;
5773d8817e4Smiod for (sec2 = sec->next; sec2 != NULL; sec2 = sec2->next)
5783d8817e4Smiod {
5793d8817e4Smiod if (wild_spec_can_overlap (sec->spec.name, sec2->spec.name))
5803d8817e4Smiod return;
5813d8817e4Smiod }
5823d8817e4Smiod }
5833d8817e4Smiod
5843d8817e4Smiod signature = (sec_count << 8) + wild_name_count;
5853d8817e4Smiod switch (signature)
5863d8817e4Smiod {
5873d8817e4Smiod case 0x0100:
5883d8817e4Smiod ptr->walk_wild_section_handler = walk_wild_section_specs1_wild0;
5893d8817e4Smiod break;
5903d8817e4Smiod case 0x0101:
5913d8817e4Smiod ptr->walk_wild_section_handler = walk_wild_section_specs1_wild1;
5923d8817e4Smiod break;
5933d8817e4Smiod case 0x0201:
5943d8817e4Smiod ptr->walk_wild_section_handler = walk_wild_section_specs2_wild1;
5953d8817e4Smiod break;
5963d8817e4Smiod case 0x0302:
5973d8817e4Smiod ptr->walk_wild_section_handler = walk_wild_section_specs3_wild2;
5983d8817e4Smiod break;
5993d8817e4Smiod case 0x0402:
6003d8817e4Smiod ptr->walk_wild_section_handler = walk_wild_section_specs4_wild2;
6013d8817e4Smiod break;
6023d8817e4Smiod default:
6033d8817e4Smiod return;
6043d8817e4Smiod }
6053d8817e4Smiod
6063d8817e4Smiod /* Now fill the data array with pointers to the specs, first the
6073d8817e4Smiod specs with non-wildcard names, then the specs with wildcard
6083d8817e4Smiod names. It's OK to process the specs in different order from the
6093d8817e4Smiod given order, because we've already determined that no section
6103d8817e4Smiod will match more than one spec. */
6113d8817e4Smiod data_counter = 0;
6123d8817e4Smiod for (sec = ptr->section_list; sec != NULL; sec = sec->next)
6133d8817e4Smiod if (!wildcardp (sec->spec.name))
6143d8817e4Smiod ptr->handler_data[data_counter++] = sec;
6153d8817e4Smiod for (sec = ptr->section_list; sec != NULL; sec = sec->next)
6163d8817e4Smiod if (wildcardp (sec->spec.name))
6173d8817e4Smiod ptr->handler_data[data_counter++] = sec;
6183d8817e4Smiod }
6193d8817e4Smiod
6203d8817e4Smiod /* Handle a wild statement for a single file F. */
6213d8817e4Smiod
6223d8817e4Smiod static void
walk_wild_file(lang_wild_statement_type * s,lang_input_statement_type * f,callback_t callback,void * data)6233d8817e4Smiod walk_wild_file (lang_wild_statement_type *s,
6243d8817e4Smiod lang_input_statement_type *f,
6253d8817e4Smiod callback_t callback,
6263d8817e4Smiod void *data)
6273d8817e4Smiod {
6283d8817e4Smiod if (f->the_bfd == NULL
6293d8817e4Smiod || ! bfd_check_format (f->the_bfd, bfd_archive))
6303d8817e4Smiod walk_wild_section (s, f, callback, data);
6313d8817e4Smiod else
6323d8817e4Smiod {
6333d8817e4Smiod bfd *member;
6343d8817e4Smiod
6353d8817e4Smiod /* This is an archive file. We must map each member of the
6363d8817e4Smiod archive separately. */
6373d8817e4Smiod member = bfd_openr_next_archived_file (f->the_bfd, NULL);
6383d8817e4Smiod while (member != NULL)
6393d8817e4Smiod {
6403d8817e4Smiod /* When lookup_name is called, it will call the add_symbols
6413d8817e4Smiod entry point for the archive. For each element of the
6423d8817e4Smiod archive which is included, BFD will call ldlang_add_file,
6433d8817e4Smiod which will set the usrdata field of the member to the
6443d8817e4Smiod lang_input_statement. */
6453d8817e4Smiod if (member->usrdata != NULL)
6463d8817e4Smiod {
6473d8817e4Smiod walk_wild_section (s, member->usrdata, callback, data);
6483d8817e4Smiod }
6493d8817e4Smiod
6503d8817e4Smiod member = bfd_openr_next_archived_file (f->the_bfd, member);
6513d8817e4Smiod }
6523d8817e4Smiod }
6533d8817e4Smiod }
6543d8817e4Smiod
6553d8817e4Smiod static void
walk_wild(lang_wild_statement_type * s,callback_t callback,void * data)6563d8817e4Smiod walk_wild (lang_wild_statement_type *s, callback_t callback, void *data)
6573d8817e4Smiod {
6583d8817e4Smiod const char *file_spec = s->filename;
6593d8817e4Smiod
6603d8817e4Smiod if (file_spec == NULL)
6613d8817e4Smiod {
6623d8817e4Smiod /* Perform the iteration over all files in the list. */
6633d8817e4Smiod LANG_FOR_EACH_INPUT_STATEMENT (f)
6643d8817e4Smiod {
6653d8817e4Smiod walk_wild_file (s, f, callback, data);
6663d8817e4Smiod }
6673d8817e4Smiod }
6683d8817e4Smiod else if (wildcardp (file_spec))
6693d8817e4Smiod {
6703d8817e4Smiod LANG_FOR_EACH_INPUT_STATEMENT (f)
6713d8817e4Smiod {
6723d8817e4Smiod if (fnmatch (file_spec, f->filename, FNM_FILE_NAME) == 0)
6733d8817e4Smiod walk_wild_file (s, f, callback, data);
6743d8817e4Smiod }
6753d8817e4Smiod }
6763d8817e4Smiod else
6773d8817e4Smiod {
6783d8817e4Smiod lang_input_statement_type *f;
6793d8817e4Smiod
6803d8817e4Smiod /* Perform the iteration over a single file. */
6813d8817e4Smiod f = lookup_name (file_spec);
6823d8817e4Smiod if (f)
6833d8817e4Smiod walk_wild_file (s, f, callback, data);
6843d8817e4Smiod }
6853d8817e4Smiod }
6863d8817e4Smiod
6873d8817e4Smiod /* lang_for_each_statement walks the parse tree and calls the provided
6883d8817e4Smiod function for each node. */
6893d8817e4Smiod
6903d8817e4Smiod static void
lang_for_each_statement_worker(void (* func)(lang_statement_union_type *),lang_statement_union_type * s)6913d8817e4Smiod lang_for_each_statement_worker (void (*func) (lang_statement_union_type *),
6923d8817e4Smiod lang_statement_union_type *s)
6933d8817e4Smiod {
6943d8817e4Smiod for (; s != NULL; s = s->header.next)
6953d8817e4Smiod {
6963d8817e4Smiod func (s);
6973d8817e4Smiod
6983d8817e4Smiod switch (s->header.type)
6993d8817e4Smiod {
7003d8817e4Smiod case lang_constructors_statement_enum:
7013d8817e4Smiod lang_for_each_statement_worker (func, constructor_list.head);
7023d8817e4Smiod break;
7033d8817e4Smiod case lang_output_section_statement_enum:
7043d8817e4Smiod lang_for_each_statement_worker
7053d8817e4Smiod (func, s->output_section_statement.children.head);
7063d8817e4Smiod break;
7073d8817e4Smiod case lang_wild_statement_enum:
7083d8817e4Smiod lang_for_each_statement_worker (func,
7093d8817e4Smiod s->wild_statement.children.head);
7103d8817e4Smiod break;
7113d8817e4Smiod case lang_group_statement_enum:
7123d8817e4Smiod lang_for_each_statement_worker (func,
7133d8817e4Smiod s->group_statement.children.head);
7143d8817e4Smiod break;
7153d8817e4Smiod case lang_data_statement_enum:
7163d8817e4Smiod case lang_reloc_statement_enum:
7173d8817e4Smiod case lang_object_symbols_statement_enum:
7183d8817e4Smiod case lang_output_statement_enum:
7193d8817e4Smiod case lang_target_statement_enum:
7203d8817e4Smiod case lang_input_section_enum:
7213d8817e4Smiod case lang_input_statement_enum:
7223d8817e4Smiod case lang_assignment_statement_enum:
7233d8817e4Smiod case lang_padding_statement_enum:
7243d8817e4Smiod case lang_address_statement_enum:
7253d8817e4Smiod case lang_fill_statement_enum:
7263d8817e4Smiod break;
7273d8817e4Smiod default:
7283d8817e4Smiod FAIL ();
7293d8817e4Smiod break;
7303d8817e4Smiod }
7313d8817e4Smiod }
7323d8817e4Smiod }
7333d8817e4Smiod
7343d8817e4Smiod void
lang_for_each_statement(void (* func)(lang_statement_union_type *))7353d8817e4Smiod lang_for_each_statement (void (*func) (lang_statement_union_type *))
7363d8817e4Smiod {
7373d8817e4Smiod lang_for_each_statement_worker (func, statement_list.head);
7383d8817e4Smiod }
7393d8817e4Smiod
7403d8817e4Smiod /*----------------------------------------------------------------------*/
7413d8817e4Smiod
7423d8817e4Smiod void
lang_list_init(lang_statement_list_type * list)7433d8817e4Smiod lang_list_init (lang_statement_list_type *list)
7443d8817e4Smiod {
7453d8817e4Smiod list->head = NULL;
7463d8817e4Smiod list->tail = &list->head;
7473d8817e4Smiod }
7483d8817e4Smiod
7493d8817e4Smiod /* Build a new statement node for the parse tree. */
7503d8817e4Smiod
7513d8817e4Smiod static lang_statement_union_type *
new_statement(enum statement_enum type,size_t size,lang_statement_list_type * list)7523d8817e4Smiod new_statement (enum statement_enum type,
7533d8817e4Smiod size_t size,
7543d8817e4Smiod lang_statement_list_type *list)
7553d8817e4Smiod {
7563d8817e4Smiod lang_statement_union_type *new;
7573d8817e4Smiod
7583d8817e4Smiod new = stat_alloc (size);
7593d8817e4Smiod new->header.type = type;
7603d8817e4Smiod new->header.next = NULL;
7613d8817e4Smiod lang_statement_append (list, new, &new->header.next);
7623d8817e4Smiod return new;
7633d8817e4Smiod }
7643d8817e4Smiod
7653d8817e4Smiod /* Build a new input file node for the language. There are several
7663d8817e4Smiod ways in which we treat an input file, eg, we only look at symbols,
7673d8817e4Smiod or prefix it with a -l etc.
7683d8817e4Smiod
7693d8817e4Smiod We can be supplied with requests for input files more than once;
7703d8817e4Smiod they may, for example be split over several lines like foo.o(.text)
7713d8817e4Smiod foo.o(.data) etc, so when asked for a file we check that we haven't
7723d8817e4Smiod got it already so we don't duplicate the bfd. */
7733d8817e4Smiod
7743d8817e4Smiod 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)7753d8817e4Smiod new_afile (const char *name,
7763d8817e4Smiod lang_input_file_enum_type file_type,
7773d8817e4Smiod const char *target,
7783d8817e4Smiod bfd_boolean add_to_list)
7793d8817e4Smiod {
7803d8817e4Smiod lang_input_statement_type *p;
7813d8817e4Smiod
7823d8817e4Smiod if (add_to_list)
7833d8817e4Smiod p = new_stat (lang_input_statement, stat_ptr);
7843d8817e4Smiod else
7853d8817e4Smiod {
7863d8817e4Smiod p = stat_alloc (sizeof (lang_input_statement_type));
7873d8817e4Smiod p->header.type = lang_input_statement_enum;
7883d8817e4Smiod p->header.next = NULL;
7893d8817e4Smiod }
7903d8817e4Smiod
7913d8817e4Smiod lang_has_input_file = TRUE;
7923d8817e4Smiod p->target = target;
7933d8817e4Smiod p->sysrooted = FALSE;
7943d8817e4Smiod switch (file_type)
7953d8817e4Smiod {
7963d8817e4Smiod case lang_input_file_is_symbols_only_enum:
7973d8817e4Smiod p->filename = name;
7983d8817e4Smiod p->is_archive = FALSE;
7993d8817e4Smiod p->real = TRUE;
8003d8817e4Smiod p->local_sym_name = name;
8013d8817e4Smiod p->just_syms_flag = TRUE;
8023d8817e4Smiod p->search_dirs_flag = FALSE;
8033d8817e4Smiod break;
8043d8817e4Smiod case lang_input_file_is_fake_enum:
8053d8817e4Smiod p->filename = name;
8063d8817e4Smiod p->is_archive = FALSE;
8073d8817e4Smiod p->real = FALSE;
8083d8817e4Smiod p->local_sym_name = name;
8093d8817e4Smiod p->just_syms_flag = FALSE;
8103d8817e4Smiod p->search_dirs_flag = FALSE;
8113d8817e4Smiod break;
8123d8817e4Smiod case lang_input_file_is_l_enum:
8133d8817e4Smiod p->is_archive = TRUE;
8143d8817e4Smiod p->filename = name;
8153d8817e4Smiod p->real = TRUE;
8163d8817e4Smiod p->local_sym_name = concat ("-l", name, NULL);
8173d8817e4Smiod p->just_syms_flag = FALSE;
8183d8817e4Smiod p->search_dirs_flag = TRUE;
8193d8817e4Smiod break;
8203d8817e4Smiod case lang_input_file_is_marker_enum:
8213d8817e4Smiod p->filename = name;
8223d8817e4Smiod p->is_archive = FALSE;
8233d8817e4Smiod p->real = FALSE;
8243d8817e4Smiod p->local_sym_name = name;
8253d8817e4Smiod p->just_syms_flag = FALSE;
8263d8817e4Smiod p->search_dirs_flag = TRUE;
8273d8817e4Smiod break;
8283d8817e4Smiod case lang_input_file_is_search_file_enum:
8293d8817e4Smiod p->sysrooted = ldlang_sysrooted_script;
8303d8817e4Smiod p->filename = name;
8313d8817e4Smiod p->is_archive = FALSE;
8323d8817e4Smiod p->real = TRUE;
8333d8817e4Smiod p->local_sym_name = name;
8343d8817e4Smiod p->just_syms_flag = FALSE;
8353d8817e4Smiod p->search_dirs_flag = TRUE;
8363d8817e4Smiod break;
8373d8817e4Smiod case lang_input_file_is_file_enum:
8383d8817e4Smiod p->filename = name;
8393d8817e4Smiod p->is_archive = FALSE;
8403d8817e4Smiod p->real = TRUE;
8413d8817e4Smiod p->local_sym_name = name;
8423d8817e4Smiod p->just_syms_flag = FALSE;
8433d8817e4Smiod p->search_dirs_flag = FALSE;
8443d8817e4Smiod break;
8453d8817e4Smiod default:
8463d8817e4Smiod FAIL ();
8473d8817e4Smiod }
8483d8817e4Smiod p->the_bfd = NULL;
8493d8817e4Smiod p->asymbols = NULL;
8503d8817e4Smiod p->next_real_file = NULL;
8513d8817e4Smiod p->next = NULL;
8523d8817e4Smiod p->symbol_count = 0;
8533d8817e4Smiod p->dynamic = config.dynamic_link;
8543d8817e4Smiod p->add_needed = add_needed;
8553d8817e4Smiod p->as_needed = as_needed;
8563d8817e4Smiod p->whole_archive = whole_archive;
8573d8817e4Smiod p->loaded = FALSE;
8583d8817e4Smiod lang_statement_append (&input_file_chain,
8593d8817e4Smiod (lang_statement_union_type *) p,
8603d8817e4Smiod &p->next_real_file);
8613d8817e4Smiod return p;
8623d8817e4Smiod }
8633d8817e4Smiod
8643d8817e4Smiod lang_input_statement_type *
lang_add_input_file(const char * name,lang_input_file_enum_type file_type,const char * target)8653d8817e4Smiod lang_add_input_file (const char *name,
8663d8817e4Smiod lang_input_file_enum_type file_type,
8673d8817e4Smiod const char *target)
8683d8817e4Smiod {
8693d8817e4Smiod lang_has_input_file = TRUE;
8703d8817e4Smiod return new_afile (name, file_type, target, TRUE);
8713d8817e4Smiod }
8723d8817e4Smiod
8733d8817e4Smiod struct out_section_hash_entry
8743d8817e4Smiod {
8753d8817e4Smiod struct bfd_hash_entry root;
8763d8817e4Smiod lang_statement_union_type s;
8773d8817e4Smiod };
8783d8817e4Smiod
8793d8817e4Smiod /* The hash table. */
8803d8817e4Smiod
8813d8817e4Smiod static struct bfd_hash_table output_section_statement_table;
8823d8817e4Smiod
8833d8817e4Smiod /* Support routines for the hash table used by lang_output_section_find,
8843d8817e4Smiod initialize the table, fill in an entry and remove the table. */
8853d8817e4Smiod
8863d8817e4Smiod static struct bfd_hash_entry *
output_section_statement_newfunc(struct bfd_hash_entry * entry,struct bfd_hash_table * table,const char * string)8873d8817e4Smiod output_section_statement_newfunc (struct bfd_hash_entry *entry,
8883d8817e4Smiod struct bfd_hash_table *table,
8893d8817e4Smiod const char *string)
8903d8817e4Smiod {
8913d8817e4Smiod lang_output_section_statement_type **nextp;
8923d8817e4Smiod struct out_section_hash_entry *ret;
8933d8817e4Smiod
8943d8817e4Smiod if (entry == NULL)
8953d8817e4Smiod {
8963d8817e4Smiod entry = bfd_hash_allocate (table, sizeof (*ret));
8973d8817e4Smiod if (entry == NULL)
8983d8817e4Smiod return entry;
8993d8817e4Smiod }
9003d8817e4Smiod
9013d8817e4Smiod entry = bfd_hash_newfunc (entry, table, string);
9023d8817e4Smiod if (entry == NULL)
9033d8817e4Smiod return entry;
9043d8817e4Smiod
9053d8817e4Smiod ret = (struct out_section_hash_entry *) entry;
9063d8817e4Smiod memset (&ret->s, 0, sizeof (ret->s));
9073d8817e4Smiod ret->s.header.type = lang_output_section_statement_enum;
9083d8817e4Smiod ret->s.output_section_statement.subsection_alignment = -1;
9093d8817e4Smiod ret->s.output_section_statement.section_alignment = -1;
9103d8817e4Smiod ret->s.output_section_statement.block_value = 1;
9113d8817e4Smiod lang_list_init (&ret->s.output_section_statement.children);
9123d8817e4Smiod lang_statement_append (stat_ptr, &ret->s, &ret->s.header.next);
9133d8817e4Smiod
9143d8817e4Smiod /* For every output section statement added to the list, except the
9153d8817e4Smiod first one, lang_output_section_statement.tail points to the "next"
9163d8817e4Smiod field of the last element of the list. */
9173d8817e4Smiod if (lang_output_section_statement.head != NULL)
9183d8817e4Smiod ret->s.output_section_statement.prev
9193d8817e4Smiod = ((lang_output_section_statement_type *)
9203d8817e4Smiod ((char *) lang_output_section_statement.tail
9213d8817e4Smiod - offsetof (lang_output_section_statement_type, next)));
9223d8817e4Smiod
9233d8817e4Smiod /* GCC's strict aliasing rules prevent us from just casting the
9243d8817e4Smiod address, so we store the pointer in a variable and cast that
9253d8817e4Smiod instead. */
9263d8817e4Smiod nextp = &ret->s.output_section_statement.next;
9273d8817e4Smiod lang_statement_append (&lang_output_section_statement,
9283d8817e4Smiod &ret->s,
9293d8817e4Smiod (lang_statement_union_type **) nextp);
9303d8817e4Smiod return &ret->root;
9313d8817e4Smiod }
9323d8817e4Smiod
9333d8817e4Smiod static void
output_section_statement_table_init(void)9343d8817e4Smiod output_section_statement_table_init (void)
9353d8817e4Smiod {
9363d8817e4Smiod if (!bfd_hash_table_init_n (&output_section_statement_table,
9373d8817e4Smiod output_section_statement_newfunc,
9383d8817e4Smiod sizeof (struct out_section_hash_entry),
9393d8817e4Smiod 61))
9403d8817e4Smiod einfo (_("%P%F: can not create hash table: %E\n"));
9413d8817e4Smiod }
9423d8817e4Smiod
9433d8817e4Smiod static void
output_section_statement_table_free(void)9443d8817e4Smiod output_section_statement_table_free (void)
9453d8817e4Smiod {
9463d8817e4Smiod bfd_hash_table_free (&output_section_statement_table);
9473d8817e4Smiod }
9483d8817e4Smiod
9493d8817e4Smiod /* Build enough state so that the parser can build its tree. */
9503d8817e4Smiod
9513d8817e4Smiod void
lang_init(void)9523d8817e4Smiod lang_init (void)
9533d8817e4Smiod {
9543d8817e4Smiod obstack_begin (&stat_obstack, 1000);
9553d8817e4Smiod
9563d8817e4Smiod stat_ptr = &statement_list;
9573d8817e4Smiod
9583d8817e4Smiod output_section_statement_table_init ();
9593d8817e4Smiod
9603d8817e4Smiod lang_list_init (stat_ptr);
9613d8817e4Smiod
9623d8817e4Smiod lang_list_init (&input_file_chain);
9633d8817e4Smiod lang_list_init (&lang_output_section_statement);
9643d8817e4Smiod lang_list_init (&file_chain);
9653d8817e4Smiod first_file = lang_add_input_file (NULL, lang_input_file_is_marker_enum,
9663d8817e4Smiod NULL);
9673d8817e4Smiod abs_output_section =
9683d8817e4Smiod lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME);
9693d8817e4Smiod
9703d8817e4Smiod abs_output_section->bfd_section = bfd_abs_section_ptr;
9713d8817e4Smiod
9723d8817e4Smiod /* The value "3" is ad-hoc, somewhat related to the expected number of
9733d8817e4Smiod DEFINED expressions in a linker script. For most default linker
9743d8817e4Smiod scripts, there are none. Why a hash table then? Well, it's somewhat
9753d8817e4Smiod simpler to re-use working machinery than using a linked list in terms
9763d8817e4Smiod of code-complexity here in ld, besides the initialization which just
9773d8817e4Smiod looks like other code here. */
9783d8817e4Smiod if (!bfd_hash_table_init_n (&lang_definedness_table,
9793d8817e4Smiod lang_definedness_newfunc,
9803d8817e4Smiod sizeof (struct lang_definedness_hash_entry),
9813d8817e4Smiod 3))
9823d8817e4Smiod einfo (_("%P%F: can not create hash table: %E\n"));
9833d8817e4Smiod }
9843d8817e4Smiod
9853d8817e4Smiod void
lang_finish(void)9863d8817e4Smiod lang_finish (void)
9873d8817e4Smiod {
9883d8817e4Smiod output_section_statement_table_free ();
9893d8817e4Smiod }
9903d8817e4Smiod
9913d8817e4Smiod /*----------------------------------------------------------------------
9923d8817e4Smiod A region is an area of memory declared with the
9933d8817e4Smiod MEMORY { name:org=exp, len=exp ... }
9943d8817e4Smiod syntax.
9953d8817e4Smiod
9963d8817e4Smiod We maintain a list of all the regions here.
9973d8817e4Smiod
9983d8817e4Smiod If no regions are specified in the script, then the default is used
9993d8817e4Smiod which is created when looked up to be the entire data space.
10003d8817e4Smiod
10013d8817e4Smiod If create is true we are creating a region inside a MEMORY block.
10023d8817e4Smiod In this case it is probably an error to create a region that has
10033d8817e4Smiod already been created. If we are not inside a MEMORY block it is
10043d8817e4Smiod dubious to use an undeclared region name (except DEFAULT_MEMORY_REGION)
10053d8817e4Smiod and so we issue a warning. */
10063d8817e4Smiod
10073d8817e4Smiod static lang_memory_region_type *lang_memory_region_list;
10083d8817e4Smiod static lang_memory_region_type **lang_memory_region_list_tail
10093d8817e4Smiod = &lang_memory_region_list;
10103d8817e4Smiod
10113d8817e4Smiod lang_memory_region_type *
lang_memory_region_lookup(const char * const name,bfd_boolean create)10123d8817e4Smiod lang_memory_region_lookup (const char *const name, bfd_boolean create)
10133d8817e4Smiod {
10143d8817e4Smiod lang_memory_region_type *p;
10153d8817e4Smiod lang_memory_region_type *new;
10163d8817e4Smiod
10173d8817e4Smiod /* NAME is NULL for LMA memspecs if no region was specified. */
10183d8817e4Smiod if (name == NULL)
10193d8817e4Smiod return NULL;
10203d8817e4Smiod
10213d8817e4Smiod for (p = lang_memory_region_list; p != NULL; p = p->next)
10223d8817e4Smiod if (strcmp (p->name, name) == 0)
10233d8817e4Smiod {
10243d8817e4Smiod if (create)
10253d8817e4Smiod einfo (_("%P:%S: warning: redeclaration of memory region '%s'\n"),
10263d8817e4Smiod name);
10273d8817e4Smiod return p;
10283d8817e4Smiod }
10293d8817e4Smiod
10303d8817e4Smiod if (!create && strcmp (name, DEFAULT_MEMORY_REGION))
10313d8817e4Smiod einfo (_("%P:%S: warning: memory region %s not declared\n"), name);
10323d8817e4Smiod
10333d8817e4Smiod new = stat_alloc (sizeof (lang_memory_region_type));
10343d8817e4Smiod
10353d8817e4Smiod new->name = xstrdup (name);
10363d8817e4Smiod new->next = NULL;
10373d8817e4Smiod
10383d8817e4Smiod *lang_memory_region_list_tail = new;
10393d8817e4Smiod lang_memory_region_list_tail = &new->next;
10403d8817e4Smiod new->origin = 0;
10413d8817e4Smiod new->flags = 0;
10423d8817e4Smiod new->not_flags = 0;
10433d8817e4Smiod new->length = ~(bfd_size_type) 0;
10443d8817e4Smiod new->current = 0;
10453d8817e4Smiod new->had_full_message = FALSE;
10463d8817e4Smiod
10473d8817e4Smiod return new;
10483d8817e4Smiod }
10493d8817e4Smiod
10503d8817e4Smiod static lang_memory_region_type *
lang_memory_default(asection * section)10513d8817e4Smiod lang_memory_default (asection *section)
10523d8817e4Smiod {
10533d8817e4Smiod lang_memory_region_type *p;
10543d8817e4Smiod
10553d8817e4Smiod flagword sec_flags = section->flags;
10563d8817e4Smiod
10573d8817e4Smiod /* Override SEC_DATA to mean a writable section. */
10583d8817e4Smiod if ((sec_flags & (SEC_ALLOC | SEC_READONLY | SEC_CODE)) == SEC_ALLOC)
10593d8817e4Smiod sec_flags |= SEC_DATA;
10603d8817e4Smiod
10613d8817e4Smiod for (p = lang_memory_region_list; p != NULL; p = p->next)
10623d8817e4Smiod {
10633d8817e4Smiod if ((p->flags & sec_flags) != 0
10643d8817e4Smiod && (p->not_flags & sec_flags) == 0)
10653d8817e4Smiod {
10663d8817e4Smiod return p;
10673d8817e4Smiod }
10683d8817e4Smiod }
10693d8817e4Smiod return lang_memory_region_lookup (DEFAULT_MEMORY_REGION, FALSE);
10703d8817e4Smiod }
10713d8817e4Smiod
10723d8817e4Smiod lang_output_section_statement_type *
lang_output_section_find(const char * const name)10733d8817e4Smiod lang_output_section_find (const char *const name)
10743d8817e4Smiod {
10753d8817e4Smiod struct out_section_hash_entry *entry;
10763d8817e4Smiod unsigned long hash;
10773d8817e4Smiod
10783d8817e4Smiod entry = ((struct out_section_hash_entry *)
10793d8817e4Smiod bfd_hash_lookup (&output_section_statement_table, name,
10803d8817e4Smiod FALSE, FALSE));
10813d8817e4Smiod if (entry == NULL)
10823d8817e4Smiod return NULL;
10833d8817e4Smiod
10843d8817e4Smiod hash = entry->root.hash;
10853d8817e4Smiod do
10863d8817e4Smiod {
10873d8817e4Smiod if (entry->s.output_section_statement.constraint != -1)
10883d8817e4Smiod return &entry->s.output_section_statement;
10893d8817e4Smiod entry = (struct out_section_hash_entry *) entry->root.next;
10903d8817e4Smiod }
10913d8817e4Smiod while (entry != NULL
10923d8817e4Smiod && entry->root.hash == hash
10933d8817e4Smiod && strcmp (name, entry->s.output_section_statement.name) == 0);
10943d8817e4Smiod
10953d8817e4Smiod return NULL;
10963d8817e4Smiod }
10973d8817e4Smiod
10983d8817e4Smiod static lang_output_section_statement_type *
lang_output_section_statement_lookup_1(const char * const name,int constraint)10993d8817e4Smiod lang_output_section_statement_lookup_1 (const char *const name, int constraint)
11003d8817e4Smiod {
11013d8817e4Smiod struct out_section_hash_entry *entry;
11023d8817e4Smiod struct out_section_hash_entry *last_ent;
11033d8817e4Smiod unsigned long hash;
11043d8817e4Smiod
11053d8817e4Smiod entry = ((struct out_section_hash_entry *)
11063d8817e4Smiod bfd_hash_lookup (&output_section_statement_table, name,
11073d8817e4Smiod TRUE, FALSE));
11083d8817e4Smiod if (entry == NULL)
11093d8817e4Smiod {
11103d8817e4Smiod einfo (_("%P%F: failed creating section `%s': %E\n"), name);
11113d8817e4Smiod return NULL;
11123d8817e4Smiod }
11133d8817e4Smiod
11143d8817e4Smiod if (entry->s.output_section_statement.name != NULL)
11153d8817e4Smiod {
11163d8817e4Smiod /* We have a section of this name, but it might not have the correct
11173d8817e4Smiod constraint. */
11183d8817e4Smiod hash = entry->root.hash;
11193d8817e4Smiod do
11203d8817e4Smiod {
11213d8817e4Smiod if (entry->s.output_section_statement.constraint != -1
11223d8817e4Smiod && (constraint == 0
11233d8817e4Smiod || (constraint == entry->s.output_section_statement.constraint
11243d8817e4Smiod && constraint != SPECIAL)))
11253d8817e4Smiod return &entry->s.output_section_statement;
11263d8817e4Smiod last_ent = entry;
11273d8817e4Smiod entry = (struct out_section_hash_entry *) entry->root.next;
11283d8817e4Smiod }
11293d8817e4Smiod while (entry != NULL
11303d8817e4Smiod && entry->root.hash == hash
11313d8817e4Smiod && strcmp (name, entry->s.output_section_statement.name) == 0);
11323d8817e4Smiod
11333d8817e4Smiod entry
11343d8817e4Smiod = ((struct out_section_hash_entry *)
11353d8817e4Smiod output_section_statement_newfunc (NULL,
11363d8817e4Smiod &output_section_statement_table,
11373d8817e4Smiod name));
11383d8817e4Smiod if (entry == NULL)
11393d8817e4Smiod {
11403d8817e4Smiod einfo (_("%P%F: failed creating section `%s': %E\n"), name);
11413d8817e4Smiod return NULL;
11423d8817e4Smiod }
11433d8817e4Smiod entry->root = last_ent->root;
11443d8817e4Smiod last_ent->root.next = &entry->root;
11453d8817e4Smiod }
11463d8817e4Smiod
11473d8817e4Smiod entry->s.output_section_statement.name = name;
11483d8817e4Smiod entry->s.output_section_statement.constraint = constraint;
11493d8817e4Smiod return &entry->s.output_section_statement;
11503d8817e4Smiod }
11513d8817e4Smiod
11523d8817e4Smiod lang_output_section_statement_type *
lang_output_section_statement_lookup(const char * const name)11533d8817e4Smiod lang_output_section_statement_lookup (const char *const name)
11543d8817e4Smiod {
11553d8817e4Smiod return lang_output_section_statement_lookup_1 (name, 0);
11563d8817e4Smiod }
11573d8817e4Smiod
11583d8817e4Smiod /* A variant of lang_output_section_find used by place_orphan.
11593d8817e4Smiod Returns the output statement that should precede a new output
11603d8817e4Smiod statement for SEC. If an exact match is found on certain flags,
11613d8817e4Smiod sets *EXACT too. */
11623d8817e4Smiod
11633d8817e4Smiod lang_output_section_statement_type *
lang_output_section_find_by_flags(const asection * sec,lang_output_section_statement_type ** exact,lang_match_sec_type_func match_type)11643d8817e4Smiod lang_output_section_find_by_flags (const asection *sec,
11653d8817e4Smiod lang_output_section_statement_type **exact,
11663d8817e4Smiod lang_match_sec_type_func match_type)
11673d8817e4Smiod {
11683d8817e4Smiod lang_output_section_statement_type *first, *look, *found;
11693d8817e4Smiod flagword flags;
11703d8817e4Smiod
11713d8817e4Smiod /* We know the first statement on this list is *ABS*. May as well
11723d8817e4Smiod skip it. */
11733d8817e4Smiod first = &lang_output_section_statement.head->output_section_statement;
11743d8817e4Smiod first = first->next;
11753d8817e4Smiod
11763d8817e4Smiod /* First try for an exact match. */
11773d8817e4Smiod found = NULL;
11783d8817e4Smiod for (look = first; look; look = look->next)
11793d8817e4Smiod {
11803d8817e4Smiod flags = look->flags;
11813d8817e4Smiod if (look->bfd_section != NULL)
11823d8817e4Smiod {
11833d8817e4Smiod flags = look->bfd_section->flags;
11843d8817e4Smiod if (match_type && !match_type (output_bfd, look->bfd_section,
11853d8817e4Smiod sec->owner, sec))
11863d8817e4Smiod continue;
11873d8817e4Smiod }
11883d8817e4Smiod flags ^= sec->flags;
11893d8817e4Smiod if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY
11903d8817e4Smiod | SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
11913d8817e4Smiod found = look;
11923d8817e4Smiod }
11933d8817e4Smiod if (found != NULL)
11943d8817e4Smiod {
11953d8817e4Smiod if (exact != NULL)
11963d8817e4Smiod *exact = found;
11973d8817e4Smiod return found;
11983d8817e4Smiod }
11993d8817e4Smiod
12003d8817e4Smiod if (sec->flags & SEC_CODE)
12013d8817e4Smiod {
12023d8817e4Smiod /* Try for a rw code section. */
12033d8817e4Smiod for (look = first; look; look = look->next)
12043d8817e4Smiod {
12053d8817e4Smiod flags = look->flags;
12063d8817e4Smiod if (look->bfd_section != NULL)
12073d8817e4Smiod {
12083d8817e4Smiod flags = look->bfd_section->flags;
12093d8817e4Smiod if (match_type && !match_type (output_bfd, look->bfd_section,
12103d8817e4Smiod sec->owner, sec))
12113d8817e4Smiod continue;
12123d8817e4Smiod }
12133d8817e4Smiod flags ^= sec->flags;
12143d8817e4Smiod if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
12153d8817e4Smiod | SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
12163d8817e4Smiod found = look;
12173d8817e4Smiod }
12183d8817e4Smiod }
12193d8817e4Smiod else if (sec->flags & (SEC_READONLY | SEC_THREAD_LOCAL))
12203d8817e4Smiod {
12213d8817e4Smiod /* .rodata can go after .text, .sdata2 after .rodata. */
12223d8817e4Smiod for (look = first; look; look = look->next)
12233d8817e4Smiod {
12243d8817e4Smiod flags = look->flags;
12253d8817e4Smiod if (look->bfd_section != NULL)
12263d8817e4Smiod {
12273d8817e4Smiod flags = look->bfd_section->flags;
12283d8817e4Smiod if (match_type && !match_type (output_bfd, look->bfd_section,
12293d8817e4Smiod sec->owner, sec))
12303d8817e4Smiod continue;
12313d8817e4Smiod }
12323d8817e4Smiod flags ^= sec->flags;
12333d8817e4Smiod if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
12343d8817e4Smiod | SEC_READONLY))
12353d8817e4Smiod && !(look->flags & (SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
12363d8817e4Smiod found = look;
12373d8817e4Smiod }
12383d8817e4Smiod }
12393d8817e4Smiod else if (sec->flags & SEC_SMALL_DATA)
12403d8817e4Smiod {
12413d8817e4Smiod /* .sdata goes after .data, .sbss after .sdata. */
12423d8817e4Smiod for (look = first; look; look = look->next)
12433d8817e4Smiod {
12443d8817e4Smiod flags = look->flags;
12453d8817e4Smiod if (look->bfd_section != NULL)
12463d8817e4Smiod {
12473d8817e4Smiod flags = look->bfd_section->flags;
12483d8817e4Smiod if (match_type && !match_type (output_bfd, look->bfd_section,
12493d8817e4Smiod sec->owner, sec))
12503d8817e4Smiod continue;
12513d8817e4Smiod }
12523d8817e4Smiod flags ^= sec->flags;
12533d8817e4Smiod if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
12543d8817e4Smiod | SEC_THREAD_LOCAL))
12553d8817e4Smiod || ((look->flags & SEC_SMALL_DATA)
12563d8817e4Smiod && !(sec->flags & SEC_HAS_CONTENTS)))
12573d8817e4Smiod found = look;
12583d8817e4Smiod }
12593d8817e4Smiod }
12603d8817e4Smiod else if (sec->flags & SEC_HAS_CONTENTS)
12613d8817e4Smiod {
12623d8817e4Smiod /* .data goes after .rodata. */
12633d8817e4Smiod for (look = first; look; look = look->next)
12643d8817e4Smiod {
12653d8817e4Smiod flags = look->flags;
12663d8817e4Smiod if (look->bfd_section != NULL)
12673d8817e4Smiod {
12683d8817e4Smiod flags = look->bfd_section->flags;
12693d8817e4Smiod if (match_type && !match_type (output_bfd, look->bfd_section,
12703d8817e4Smiod sec->owner, sec))
12713d8817e4Smiod continue;
12723d8817e4Smiod }
12733d8817e4Smiod flags ^= sec->flags;
12743d8817e4Smiod if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
12753d8817e4Smiod | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
12763d8817e4Smiod found = look;
12773d8817e4Smiod }
12783d8817e4Smiod }
12793d8817e4Smiod else
12803d8817e4Smiod {
12813d8817e4Smiod /* .bss goes last. */
12823d8817e4Smiod for (look = first; look; look = look->next)
12833d8817e4Smiod {
12843d8817e4Smiod flags = look->flags;
12853d8817e4Smiod if (look->bfd_section != NULL)
12863d8817e4Smiod {
12873d8817e4Smiod flags = look->bfd_section->flags;
12883d8817e4Smiod if (match_type && !match_type (output_bfd, look->bfd_section,
12893d8817e4Smiod sec->owner, sec))
12903d8817e4Smiod continue;
12913d8817e4Smiod }
12923d8817e4Smiod flags ^= sec->flags;
12933d8817e4Smiod if (!(flags & SEC_ALLOC))
12943d8817e4Smiod found = look;
12953d8817e4Smiod }
12963d8817e4Smiod }
12973d8817e4Smiod
12983d8817e4Smiod if (found || !match_type)
12993d8817e4Smiod return found;
13003d8817e4Smiod
13013d8817e4Smiod return lang_output_section_find_by_flags (sec, NULL, NULL);
13023d8817e4Smiod }
13033d8817e4Smiod
13043d8817e4Smiod /* Find the last output section before given output statement.
13053d8817e4Smiod Used by place_orphan. */
13063d8817e4Smiod
13073d8817e4Smiod static asection *
output_prev_sec_find(lang_output_section_statement_type * os)13083d8817e4Smiod output_prev_sec_find (lang_output_section_statement_type *os)
13093d8817e4Smiod {
13103d8817e4Smiod lang_output_section_statement_type *lookup;
13113d8817e4Smiod
13123d8817e4Smiod for (lookup = os->prev; lookup != NULL; lookup = lookup->prev)
13133d8817e4Smiod {
13143d8817e4Smiod if (lookup->constraint == -1)
13153d8817e4Smiod continue;
13163d8817e4Smiod
13173d8817e4Smiod if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
13183d8817e4Smiod return lookup->bfd_section;
13193d8817e4Smiod }
13203d8817e4Smiod
13213d8817e4Smiod return NULL;
13223d8817e4Smiod }
13233d8817e4Smiod
13243d8817e4Smiod lang_output_section_statement_type *
lang_insert_orphan(asection * s,const char * secname,lang_output_section_statement_type * after,struct orphan_save * place,etree_type * address,lang_statement_list_type * add_child)13253d8817e4Smiod lang_insert_orphan (asection *s,
13263d8817e4Smiod const char *secname,
13273d8817e4Smiod lang_output_section_statement_type *after,
13283d8817e4Smiod struct orphan_save *place,
13293d8817e4Smiod etree_type *address,
13303d8817e4Smiod lang_statement_list_type *add_child)
13313d8817e4Smiod {
13323d8817e4Smiod lang_statement_list_type *old;
13333d8817e4Smiod lang_statement_list_type add;
13343d8817e4Smiod const char *ps;
13353d8817e4Smiod etree_type *load_base;
13363d8817e4Smiod lang_output_section_statement_type *os;
13373d8817e4Smiod lang_output_section_statement_type **os_tail;
13383d8817e4Smiod
13393d8817e4Smiod /* Start building a list of statements for this section.
13403d8817e4Smiod First save the current statement pointer. */
13413d8817e4Smiod old = stat_ptr;
13423d8817e4Smiod
13433d8817e4Smiod /* If we have found an appropriate place for the output section
13443d8817e4Smiod statements for this orphan, add them to our own private list,
13453d8817e4Smiod inserting them later into the global statement list. */
13463d8817e4Smiod if (after != NULL)
13473d8817e4Smiod {
13483d8817e4Smiod stat_ptr = &add;
13493d8817e4Smiod lang_list_init (stat_ptr);
13503d8817e4Smiod }
13513d8817e4Smiod
13523d8817e4Smiod ps = NULL;
13533d8817e4Smiod if (config.build_constructors)
13543d8817e4Smiod {
13553d8817e4Smiod /* If the name of the section is representable in C, then create
13563d8817e4Smiod symbols to mark the start and the end of the section. */
13573d8817e4Smiod for (ps = secname; *ps != '\0'; ps++)
13583d8817e4Smiod if (! ISALNUM ((unsigned char) *ps) && *ps != '_')
13593d8817e4Smiod break;
13603d8817e4Smiod if (*ps == '\0')
13613d8817e4Smiod {
13623d8817e4Smiod char *symname;
13633d8817e4Smiod etree_type *e_align;
13643d8817e4Smiod
13653d8817e4Smiod symname = (char *) xmalloc (ps - secname + sizeof "__start_" + 1);
13663d8817e4Smiod symname[0] = bfd_get_symbol_leading_char (output_bfd);
13673d8817e4Smiod sprintf (symname + (symname[0] != 0), "__start_%s", secname);
13683d8817e4Smiod e_align = exp_unop (ALIGN_K,
13693d8817e4Smiod exp_intop ((bfd_vma) 1 << s->alignment_power));
13703d8817e4Smiod lang_add_assignment (exp_assop ('=', ".", e_align));
13713d8817e4Smiod lang_add_assignment (exp_assop ('=', symname,
13723d8817e4Smiod exp_nameop (NAME, ".")));
13733d8817e4Smiod }
13743d8817e4Smiod }
13753d8817e4Smiod
13763d8817e4Smiod if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
13773d8817e4Smiod address = exp_intop (0);
13783d8817e4Smiod
13793d8817e4Smiod load_base = NULL;
13803d8817e4Smiod if (after != NULL && after->load_base != NULL)
13813d8817e4Smiod {
13823d8817e4Smiod etree_type *lma_from_vma;
13833d8817e4Smiod lma_from_vma = exp_binop ('-', after->load_base,
13843d8817e4Smiod exp_nameop (ADDR, after->name));
13853d8817e4Smiod load_base = exp_binop ('+', lma_from_vma,
13863d8817e4Smiod exp_nameop (ADDR, secname));
13873d8817e4Smiod }
13883d8817e4Smiod
13893d8817e4Smiod os_tail = ((lang_output_section_statement_type **)
13903d8817e4Smiod lang_output_section_statement.tail);
13913d8817e4Smiod os = lang_enter_output_section_statement (secname, address, 0, NULL, NULL,
13923d8817e4Smiod load_base, 0);
13933d8817e4Smiod
13943d8817e4Smiod if (add_child == NULL)
13953d8817e4Smiod add_child = &os->children;
13963d8817e4Smiod lang_add_section (add_child, s, os);
13973d8817e4Smiod
13983d8817e4Smiod lang_leave_output_section_statement (0, "*default*", NULL, NULL);
13993d8817e4Smiod
14003d8817e4Smiod if (config.build_constructors && *ps == '\0')
14013d8817e4Smiod {
14023d8817e4Smiod char *symname;
14033d8817e4Smiod
14043d8817e4Smiod /* lang_leave_ouput_section_statement resets stat_ptr.
14053d8817e4Smiod Put stat_ptr back where we want it. */
14063d8817e4Smiod if (after != NULL)
14073d8817e4Smiod stat_ptr = &add;
14083d8817e4Smiod
14093d8817e4Smiod symname = (char *) xmalloc (ps - secname + sizeof "__stop_" + 1);
14103d8817e4Smiod symname[0] = bfd_get_symbol_leading_char (output_bfd);
14113d8817e4Smiod sprintf (symname + (symname[0] != 0), "__stop_%s", secname);
14123d8817e4Smiod lang_add_assignment (exp_assop ('=', symname,
14133d8817e4Smiod exp_nameop (NAME, ".")));
14143d8817e4Smiod }
14153d8817e4Smiod
14163d8817e4Smiod /* Restore the global list pointer. */
14173d8817e4Smiod if (after != NULL)
14183d8817e4Smiod stat_ptr = old;
14193d8817e4Smiod
14203d8817e4Smiod if (after != NULL && os->bfd_section != NULL)
14213d8817e4Smiod {
14223d8817e4Smiod asection *snew, *as;
14233d8817e4Smiod
14243d8817e4Smiod snew = os->bfd_section;
14253d8817e4Smiod
14263d8817e4Smiod /* Shuffle the bfd section list to make the output file look
14273d8817e4Smiod neater. This is really only cosmetic. */
14283d8817e4Smiod if (place->section == NULL
14293d8817e4Smiod && after != (&lang_output_section_statement.head
14303d8817e4Smiod ->output_section_statement))
14313d8817e4Smiod {
14323d8817e4Smiod asection *bfd_section = after->bfd_section;
14333d8817e4Smiod
14343d8817e4Smiod /* If the output statement hasn't been used to place any input
14353d8817e4Smiod sections (and thus doesn't have an output bfd_section),
14363d8817e4Smiod look for the closest prior output statement having an
14373d8817e4Smiod output section. */
14383d8817e4Smiod if (bfd_section == NULL)
14393d8817e4Smiod bfd_section = output_prev_sec_find (after);
14403d8817e4Smiod
14413d8817e4Smiod if (bfd_section != NULL && bfd_section != snew)
14423d8817e4Smiod place->section = &bfd_section->next;
14433d8817e4Smiod }
14443d8817e4Smiod
14453d8817e4Smiod if (place->section == NULL)
14463d8817e4Smiod place->section = &output_bfd->sections;
14473d8817e4Smiod
14483d8817e4Smiod as = *place->section;
14493d8817e4Smiod if (as != snew && as->prev != snew)
14503d8817e4Smiod {
14513d8817e4Smiod /* Unlink the section. */
14523d8817e4Smiod bfd_section_list_remove (output_bfd, snew);
14533d8817e4Smiod
14543d8817e4Smiod /* Now tack it back on in the right place. */
14553d8817e4Smiod bfd_section_list_insert_before (output_bfd, as, snew);
14563d8817e4Smiod }
14573d8817e4Smiod
14583d8817e4Smiod /* Save the end of this list. Further ophans of this type will
14593d8817e4Smiod follow the one we've just added. */
14603d8817e4Smiod place->section = &snew->next;
14613d8817e4Smiod
14623d8817e4Smiod /* The following is non-cosmetic. We try to put the output
14633d8817e4Smiod statements in some sort of reasonable order here, because they
14643d8817e4Smiod determine the final load addresses of the orphan sections.
14653d8817e4Smiod In addition, placing output statements in the wrong order may
14663d8817e4Smiod require extra segments. For instance, given a typical
14673d8817e4Smiod situation of all read-only sections placed in one segment and
14683d8817e4Smiod following that a segment containing all the read-write
14693d8817e4Smiod sections, we wouldn't want to place an orphan read/write
14703d8817e4Smiod section before or amongst the read-only ones. */
14713d8817e4Smiod if (add.head != NULL)
14723d8817e4Smiod {
14733d8817e4Smiod lang_output_section_statement_type *newly_added_os;
14743d8817e4Smiod
14753d8817e4Smiod if (place->stmt == NULL)
14763d8817e4Smiod {
14773d8817e4Smiod lang_statement_union_type **where;
14783d8817e4Smiod lang_statement_union_type **assign = NULL;
14793d8817e4Smiod bfd_boolean ignore_first;
14803d8817e4Smiod
14813d8817e4Smiod /* Look for a suitable place for the new statement list.
14823d8817e4Smiod The idea is to skip over anything that might be inside
14833d8817e4Smiod a SECTIONS {} statement in a script, before we find
14843d8817e4Smiod another output_section_statement. Assignments to "dot"
14853d8817e4Smiod before an output section statement are assumed to
14863d8817e4Smiod belong to it. An exception to this rule is made for
14873d8817e4Smiod the first assignment to dot, otherwise we might put an
14883d8817e4Smiod orphan before . = . + SIZEOF_HEADERS or similar
14893d8817e4Smiod assignments that set the initial address. */
14903d8817e4Smiod
14913d8817e4Smiod ignore_first = after == (&lang_output_section_statement.head
14923d8817e4Smiod ->output_section_statement);
14933d8817e4Smiod for (where = &after->header.next;
14943d8817e4Smiod *where != NULL;
14953d8817e4Smiod where = &(*where)->header.next)
14963d8817e4Smiod {
14973d8817e4Smiod switch ((*where)->header.type)
14983d8817e4Smiod {
14993d8817e4Smiod case lang_assignment_statement_enum:
15003d8817e4Smiod if (assign == NULL)
15013d8817e4Smiod {
15023d8817e4Smiod lang_assignment_statement_type *ass;
15033d8817e4Smiod ass = &(*where)->assignment_statement;
15043d8817e4Smiod if (ass->exp->type.node_class != etree_assert
15053d8817e4Smiod && ass->exp->assign.dst[0] == '.'
15063d8817e4Smiod && ass->exp->assign.dst[1] == 0
15073d8817e4Smiod && !ignore_first)
15083d8817e4Smiod assign = where;
15093d8817e4Smiod }
15103d8817e4Smiod ignore_first = FALSE;
15113d8817e4Smiod continue;
15123d8817e4Smiod case lang_wild_statement_enum:
15133d8817e4Smiod case lang_input_section_enum:
15143d8817e4Smiod case lang_object_symbols_statement_enum:
15153d8817e4Smiod case lang_fill_statement_enum:
15163d8817e4Smiod case lang_data_statement_enum:
15173d8817e4Smiod case lang_reloc_statement_enum:
15183d8817e4Smiod case lang_padding_statement_enum:
15193d8817e4Smiod case lang_constructors_statement_enum:
15203d8817e4Smiod assign = NULL;
15213d8817e4Smiod continue;
15223d8817e4Smiod case lang_output_section_statement_enum:
15233d8817e4Smiod if (assign != NULL)
15243d8817e4Smiod where = assign;
15253d8817e4Smiod case lang_input_statement_enum:
15263d8817e4Smiod case lang_address_statement_enum:
15273d8817e4Smiod case lang_target_statement_enum:
15283d8817e4Smiod case lang_output_statement_enum:
15293d8817e4Smiod case lang_group_statement_enum:
15303d8817e4Smiod case lang_afile_asection_pair_statement_enum:
15313d8817e4Smiod break;
15323d8817e4Smiod }
15333d8817e4Smiod break;
15343d8817e4Smiod }
15353d8817e4Smiod
15363d8817e4Smiod *add.tail = *where;
15373d8817e4Smiod *where = add.head;
15383d8817e4Smiod
15393d8817e4Smiod place->os_tail = &after->next;
15403d8817e4Smiod }
15413d8817e4Smiod else
15423d8817e4Smiod {
15433d8817e4Smiod /* Put it after the last orphan statement we added. */
15443d8817e4Smiod *add.tail = *place->stmt;
15453d8817e4Smiod *place->stmt = add.head;
15463d8817e4Smiod }
15473d8817e4Smiod
15483d8817e4Smiod /* Fix the global list pointer if we happened to tack our
15493d8817e4Smiod new list at the tail. */
15503d8817e4Smiod if (*old->tail == add.head)
15513d8817e4Smiod old->tail = add.tail;
15523d8817e4Smiod
15533d8817e4Smiod /* Save the end of this list. */
15543d8817e4Smiod place->stmt = add.tail;
15553d8817e4Smiod
15563d8817e4Smiod /* Do the same for the list of output section statements. */
15573d8817e4Smiod newly_added_os = *os_tail;
15583d8817e4Smiod *os_tail = NULL;
15593d8817e4Smiod newly_added_os->prev = (lang_output_section_statement_type *)
15603d8817e4Smiod ((char *) place->os_tail
15613d8817e4Smiod - offsetof (lang_output_section_statement_type, next));
15623d8817e4Smiod newly_added_os->next = *place->os_tail;
15633d8817e4Smiod if (newly_added_os->next != NULL)
15643d8817e4Smiod newly_added_os->next->prev = newly_added_os;
15653d8817e4Smiod *place->os_tail = newly_added_os;
15663d8817e4Smiod place->os_tail = &newly_added_os->next;
15673d8817e4Smiod
15683d8817e4Smiod /* Fixing the global list pointer here is a little different.
15693d8817e4Smiod We added to the list in lang_enter_output_section_statement,
15703d8817e4Smiod trimmed off the new output_section_statment above when
15713d8817e4Smiod assigning *os_tail = NULL, but possibly added it back in
15723d8817e4Smiod the same place when assigning *place->os_tail. */
15733d8817e4Smiod if (*os_tail == NULL)
15743d8817e4Smiod lang_output_section_statement.tail
15753d8817e4Smiod = (lang_statement_union_type **) os_tail;
15763d8817e4Smiod }
15773d8817e4Smiod }
15783d8817e4Smiod return os;
15793d8817e4Smiod }
15803d8817e4Smiod
15813d8817e4Smiod static void
lang_map_flags(flagword flag)15823d8817e4Smiod lang_map_flags (flagword flag)
15833d8817e4Smiod {
15843d8817e4Smiod if (flag & SEC_ALLOC)
15853d8817e4Smiod minfo ("a");
15863d8817e4Smiod
15873d8817e4Smiod if (flag & SEC_CODE)
15883d8817e4Smiod minfo ("x");
15893d8817e4Smiod
15903d8817e4Smiod if (flag & SEC_READONLY)
15913d8817e4Smiod minfo ("r");
15923d8817e4Smiod
15933d8817e4Smiod if (flag & SEC_DATA)
15943d8817e4Smiod minfo ("w");
15953d8817e4Smiod
15963d8817e4Smiod if (flag & SEC_LOAD)
15973d8817e4Smiod minfo ("l");
15983d8817e4Smiod }
15993d8817e4Smiod
16003d8817e4Smiod void
lang_map(void)16013d8817e4Smiod lang_map (void)
16023d8817e4Smiod {
16033d8817e4Smiod lang_memory_region_type *m;
16043d8817e4Smiod bfd_boolean dis_header_printed = FALSE;
16053d8817e4Smiod bfd *p;
16063d8817e4Smiod
16073d8817e4Smiod LANG_FOR_EACH_INPUT_STATEMENT (file)
16083d8817e4Smiod {
16093d8817e4Smiod asection *s;
16103d8817e4Smiod
16113d8817e4Smiod if ((file->the_bfd->flags & (BFD_LINKER_CREATED | DYNAMIC)) != 0
16123d8817e4Smiod || file->just_syms_flag)
16133d8817e4Smiod continue;
16143d8817e4Smiod
16153d8817e4Smiod for (s = file->the_bfd->sections; s != NULL; s = s->next)
16163d8817e4Smiod if (s->output_section == NULL
16173d8817e4Smiod || s->output_section->owner != output_bfd)
16183d8817e4Smiod {
16193d8817e4Smiod if (! dis_header_printed)
16203d8817e4Smiod {
16213d8817e4Smiod fprintf (config.map_file, _("\nDiscarded input sections\n\n"));
16223d8817e4Smiod dis_header_printed = TRUE;
16233d8817e4Smiod }
16243d8817e4Smiod
16253d8817e4Smiod print_input_section (s);
16263d8817e4Smiod }
16273d8817e4Smiod }
16283d8817e4Smiod
16293d8817e4Smiod minfo (_("\nMemory Configuration\n\n"));
16303d8817e4Smiod fprintf (config.map_file, "%-16s %-18s %-18s %s\n",
16313d8817e4Smiod _("Name"), _("Origin"), _("Length"), _("Attributes"));
16323d8817e4Smiod
16333d8817e4Smiod for (m = lang_memory_region_list; m != NULL; m = m->next)
16343d8817e4Smiod {
16353d8817e4Smiod char buf[100];
16363d8817e4Smiod int len;
16373d8817e4Smiod
16383d8817e4Smiod fprintf (config.map_file, "%-16s ", m->name);
16393d8817e4Smiod
16403d8817e4Smiod sprintf_vma (buf, m->origin);
16413d8817e4Smiod minfo ("0x%s ", buf);
16423d8817e4Smiod len = strlen (buf);
16433d8817e4Smiod while (len < 16)
16443d8817e4Smiod {
16453d8817e4Smiod print_space ();
16463d8817e4Smiod ++len;
16473d8817e4Smiod }
16483d8817e4Smiod
16493d8817e4Smiod minfo ("0x%V", m->length);
16503d8817e4Smiod if (m->flags || m->not_flags)
16513d8817e4Smiod {
16523d8817e4Smiod #ifndef BFD64
16533d8817e4Smiod minfo (" ");
16543d8817e4Smiod #endif
16553d8817e4Smiod if (m->flags)
16563d8817e4Smiod {
16573d8817e4Smiod print_space ();
16583d8817e4Smiod lang_map_flags (m->flags);
16593d8817e4Smiod }
16603d8817e4Smiod
16613d8817e4Smiod if (m->not_flags)
16623d8817e4Smiod {
16633d8817e4Smiod minfo (" !");
16643d8817e4Smiod lang_map_flags (m->not_flags);
16653d8817e4Smiod }
16663d8817e4Smiod }
16673d8817e4Smiod
16683d8817e4Smiod print_nl ();
16693d8817e4Smiod }
16703d8817e4Smiod
16713d8817e4Smiod fprintf (config.map_file, _("\nLinker script and memory map\n\n"));
16723d8817e4Smiod
1673b8417449Sstefan if (! link_info.reduce_memory_overheads)
16743d8817e4Smiod {
16753d8817e4Smiod obstack_begin (&map_obstack, 1000);
16763d8817e4Smiod for (p = link_info.input_bfds; p != (bfd *) NULL; p = p->link_next)
16773d8817e4Smiod bfd_map_over_sections (p, init_map_userdata, 0);
16783d8817e4Smiod bfd_link_hash_traverse (link_info.hash, sort_def_symbol, 0);
16793d8817e4Smiod }
16803d8817e4Smiod print_statements ();
16813d8817e4Smiod }
16823d8817e4Smiod
16833d8817e4Smiod static void
init_map_userdata(abfd,sec,data)16843d8817e4Smiod init_map_userdata (abfd, sec, data)
16853d8817e4Smiod bfd *abfd ATTRIBUTE_UNUSED;
16863d8817e4Smiod asection *sec;
16873d8817e4Smiod void *data ATTRIBUTE_UNUSED;
16883d8817e4Smiod {
16893d8817e4Smiod fat_section_userdata_type *new_data
16903d8817e4Smiod = ((fat_section_userdata_type *) (stat_alloc
16913d8817e4Smiod (sizeof (fat_section_userdata_type))));
16923d8817e4Smiod
16933d8817e4Smiod ASSERT (get_userdata (sec) == NULL);
16943d8817e4Smiod get_userdata (sec) = new_data;
16953d8817e4Smiod new_data->map_symbol_def_tail = &new_data->map_symbol_def_head;
16963d8817e4Smiod }
16973d8817e4Smiod
16983d8817e4Smiod static bfd_boolean
sort_def_symbol(hash_entry,info)16993d8817e4Smiod sort_def_symbol (hash_entry, info)
17003d8817e4Smiod struct bfd_link_hash_entry *hash_entry;
17013d8817e4Smiod void *info ATTRIBUTE_UNUSED;
17023d8817e4Smiod {
17033d8817e4Smiod if (hash_entry->type == bfd_link_hash_defined
17043d8817e4Smiod || hash_entry->type == bfd_link_hash_defweak)
17053d8817e4Smiod {
17063d8817e4Smiod struct fat_user_section_struct *ud;
17073d8817e4Smiod struct map_symbol_def *def;
17083d8817e4Smiod
17093d8817e4Smiod ud = get_userdata (hash_entry->u.def.section);
17103d8817e4Smiod if (! ud)
17113d8817e4Smiod {
17123d8817e4Smiod /* ??? What do we have to do to initialize this beforehand? */
17133d8817e4Smiod /* The first time we get here is bfd_abs_section... */
17143d8817e4Smiod init_map_userdata (0, hash_entry->u.def.section, 0);
17153d8817e4Smiod ud = get_userdata (hash_entry->u.def.section);
17163d8817e4Smiod }
17173d8817e4Smiod else if (!ud->map_symbol_def_tail)
17183d8817e4Smiod ud->map_symbol_def_tail = &ud->map_symbol_def_head;
17193d8817e4Smiod
17203d8817e4Smiod def = obstack_alloc (&map_obstack, sizeof *def);
17213d8817e4Smiod def->entry = hash_entry;
17223d8817e4Smiod *(ud->map_symbol_def_tail) = def;
17233d8817e4Smiod ud->map_symbol_def_tail = &def->next;
17243d8817e4Smiod }
17253d8817e4Smiod return TRUE;
17263d8817e4Smiod }
17273d8817e4Smiod
17283d8817e4Smiod /* Initialize an output section. */
17293d8817e4Smiod
17303d8817e4Smiod static void
init_os(lang_output_section_statement_type * s,asection * isec)17313d8817e4Smiod init_os (lang_output_section_statement_type *s, asection *isec)
17323d8817e4Smiod {
17333d8817e4Smiod if (s->bfd_section != NULL)
17343d8817e4Smiod return;
17353d8817e4Smiod
17363d8817e4Smiod if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
17373d8817e4Smiod einfo (_("%P%F: Illegal use of `%s' section\n"), DISCARD_SECTION_NAME);
17383d8817e4Smiod
17393d8817e4Smiod s->bfd_section = bfd_get_section_by_name (output_bfd, s->name);
17403d8817e4Smiod if (s->bfd_section == NULL)
17413d8817e4Smiod s->bfd_section = bfd_make_section (output_bfd, s->name);
17423d8817e4Smiod if (s->bfd_section == NULL)
17433d8817e4Smiod {
17443d8817e4Smiod einfo (_("%P%F: output format %s cannot represent section called %s\n"),
17453d8817e4Smiod output_bfd->xvec->name, s->name);
17463d8817e4Smiod }
17473d8817e4Smiod s->bfd_section->output_section = s->bfd_section;
17483d8817e4Smiod s->bfd_section->output_offset = 0;
1749b8417449Sstefan if (!link_info.reduce_memory_overheads)
17503d8817e4Smiod {
17513d8817e4Smiod fat_section_userdata_type *new
17523d8817e4Smiod = stat_alloc (sizeof (fat_section_userdata_type));
17533d8817e4Smiod memset (new, 0, sizeof (fat_section_userdata_type));
17543d8817e4Smiod get_userdata (s->bfd_section) = new;
17553d8817e4Smiod }
17563d8817e4Smiod
17573d8817e4Smiod
17583d8817e4Smiod /* If there is a base address, make sure that any sections it might
17593d8817e4Smiod mention are initialized. */
17603d8817e4Smiod if (s->addr_tree != NULL)
17613d8817e4Smiod exp_init_os (s->addr_tree);
17623d8817e4Smiod
17633d8817e4Smiod if (s->load_base != NULL)
17643d8817e4Smiod exp_init_os (s->load_base);
17653d8817e4Smiod
17663d8817e4Smiod /* If supplied an alignment, set it. */
17673d8817e4Smiod if (s->section_alignment != -1)
17683d8817e4Smiod s->bfd_section->alignment_power = s->section_alignment;
17693d8817e4Smiod
17703d8817e4Smiod if (isec)
17713d8817e4Smiod bfd_init_private_section_data (isec->owner, isec,
17723d8817e4Smiod output_bfd, s->bfd_section,
17733d8817e4Smiod &link_info);
17743d8817e4Smiod }
17753d8817e4Smiod
17763d8817e4Smiod /* Make sure that all output sections mentioned in an expression are
17773d8817e4Smiod initialized. */
17783d8817e4Smiod
17793d8817e4Smiod static void
exp_init_os(etree_type * exp)17803d8817e4Smiod exp_init_os (etree_type *exp)
17813d8817e4Smiod {
17823d8817e4Smiod switch (exp->type.node_class)
17833d8817e4Smiod {
17843d8817e4Smiod case etree_assign:
17853d8817e4Smiod case etree_provide:
17863d8817e4Smiod exp_init_os (exp->assign.src);
17873d8817e4Smiod break;
17883d8817e4Smiod
17893d8817e4Smiod case etree_binary:
17903d8817e4Smiod exp_init_os (exp->binary.lhs);
17913d8817e4Smiod exp_init_os (exp->binary.rhs);
17923d8817e4Smiod break;
17933d8817e4Smiod
17943d8817e4Smiod case etree_trinary:
17953d8817e4Smiod exp_init_os (exp->trinary.cond);
17963d8817e4Smiod exp_init_os (exp->trinary.lhs);
17973d8817e4Smiod exp_init_os (exp->trinary.rhs);
17983d8817e4Smiod break;
17993d8817e4Smiod
18003d8817e4Smiod case etree_assert:
18013d8817e4Smiod exp_init_os (exp->assert_s.child);
18023d8817e4Smiod break;
18033d8817e4Smiod
18043d8817e4Smiod case etree_unary:
18053d8817e4Smiod exp_init_os (exp->unary.child);
18063d8817e4Smiod break;
18073d8817e4Smiod
18083d8817e4Smiod case etree_name:
18093d8817e4Smiod switch (exp->type.node_code)
18103d8817e4Smiod {
18113d8817e4Smiod case ADDR:
18123d8817e4Smiod case LOADADDR:
18133d8817e4Smiod case SIZEOF:
18143d8817e4Smiod {
18153d8817e4Smiod lang_output_section_statement_type *os;
18163d8817e4Smiod
18173d8817e4Smiod os = lang_output_section_find (exp->name.name);
18183d8817e4Smiod if (os != NULL && os->bfd_section == NULL)
18193d8817e4Smiod init_os (os, NULL);
18203d8817e4Smiod }
18213d8817e4Smiod }
18223d8817e4Smiod break;
18233d8817e4Smiod
18243d8817e4Smiod default:
18253d8817e4Smiod break;
18263d8817e4Smiod }
18273d8817e4Smiod }
18283d8817e4Smiod
18293d8817e4Smiod static void
section_already_linked(bfd * abfd,asection * sec,void * data)18303d8817e4Smiod section_already_linked (bfd *abfd, asection *sec, void *data)
18313d8817e4Smiod {
18323d8817e4Smiod lang_input_statement_type *entry = data;
18333d8817e4Smiod
18343d8817e4Smiod /* If we are only reading symbols from this object, then we want to
18353d8817e4Smiod discard all sections. */
18363d8817e4Smiod if (entry->just_syms_flag)
18373d8817e4Smiod {
18383d8817e4Smiod bfd_link_just_syms (abfd, sec, &link_info);
18393d8817e4Smiod return;
18403d8817e4Smiod }
18413d8817e4Smiod
18423d8817e4Smiod if (!(abfd->flags & DYNAMIC))
1843b8417449Sstefan bfd_section_already_linked (abfd, sec, &link_info);
18443d8817e4Smiod }
18453d8817e4Smiod
18463d8817e4Smiod /* The wild routines.
18473d8817e4Smiod
18483d8817e4Smiod These expand statements like *(.text) and foo.o to a list of
18493d8817e4Smiod explicit actions, like foo.o(.text), bar.o(.text) and
18503d8817e4Smiod foo.o(.text, .data). */
18513d8817e4Smiod
18523d8817e4Smiod /* Add SECTION to the output section OUTPUT. Do this by creating a
18533d8817e4Smiod lang_input_section statement which is placed at PTR. FILE is the
18543d8817e4Smiod input file which holds SECTION. */
18553d8817e4Smiod
18563d8817e4Smiod void
lang_add_section(lang_statement_list_type * ptr,asection * section,lang_output_section_statement_type * output)18573d8817e4Smiod lang_add_section (lang_statement_list_type *ptr,
18583d8817e4Smiod asection *section,
18593d8817e4Smiod lang_output_section_statement_type *output)
18603d8817e4Smiod {
18613d8817e4Smiod flagword flags = section->flags;
18623d8817e4Smiod bfd_boolean discard;
18633d8817e4Smiod
18643d8817e4Smiod /* Discard sections marked with SEC_EXCLUDE. */
18653d8817e4Smiod discard = (flags & SEC_EXCLUDE) != 0;
18663d8817e4Smiod
18673d8817e4Smiod /* Discard input sections which are assigned to a section named
18683d8817e4Smiod DISCARD_SECTION_NAME. */
18693d8817e4Smiod if (strcmp (output->name, DISCARD_SECTION_NAME) == 0)
18703d8817e4Smiod discard = TRUE;
18713d8817e4Smiod
18723d8817e4Smiod /* Discard debugging sections if we are stripping debugging
18733d8817e4Smiod information. */
18743d8817e4Smiod if ((link_info.strip == strip_debugger || link_info.strip == strip_all)
18753d8817e4Smiod && (flags & SEC_DEBUGGING) != 0)
18763d8817e4Smiod discard = TRUE;
18773d8817e4Smiod
18783d8817e4Smiod if (discard)
18793d8817e4Smiod {
18803d8817e4Smiod if (section->output_section == NULL)
18813d8817e4Smiod {
18823d8817e4Smiod /* This prevents future calls from assigning this section. */
18833d8817e4Smiod section->output_section = bfd_abs_section_ptr;
18843d8817e4Smiod }
18853d8817e4Smiod return;
18863d8817e4Smiod }
18873d8817e4Smiod
18883d8817e4Smiod if (section->output_section == NULL)
18893d8817e4Smiod {
18903d8817e4Smiod bfd_boolean first;
18913d8817e4Smiod lang_input_section_type *new;
18923d8817e4Smiod flagword flags;
18933d8817e4Smiod
18943d8817e4Smiod if (output->bfd_section == NULL)
18953d8817e4Smiod init_os (output, section);
18963d8817e4Smiod
18973d8817e4Smiod first = ! output->bfd_section->linker_has_input;
18983d8817e4Smiod output->bfd_section->linker_has_input = 1;
18993d8817e4Smiod
19003d8817e4Smiod if (!link_info.relocatable
19013d8817e4Smiod && !stripped_excluded_sections)
19023d8817e4Smiod {
19033d8817e4Smiod asection *s = output->bfd_section->map_tail.s;
19043d8817e4Smiod output->bfd_section->map_tail.s = section;
19053d8817e4Smiod section->map_head.s = NULL;
19063d8817e4Smiod section->map_tail.s = s;
19073d8817e4Smiod if (s != NULL)
19083d8817e4Smiod s->map_head.s = section;
19093d8817e4Smiod else
19103d8817e4Smiod output->bfd_section->map_head.s = section;
19113d8817e4Smiod }
19123d8817e4Smiod
19133d8817e4Smiod /* Add a section reference to the list. */
19143d8817e4Smiod new = new_stat (lang_input_section, ptr);
19153d8817e4Smiod
19163d8817e4Smiod new->section = section;
19173d8817e4Smiod section->output_section = output->bfd_section;
19183d8817e4Smiod
19193d8817e4Smiod flags = section->flags;
19203d8817e4Smiod
19213d8817e4Smiod /* We don't copy the SEC_NEVER_LOAD flag from an input section
19223d8817e4Smiod to an output section, because we want to be able to include a
19233d8817e4Smiod SEC_NEVER_LOAD section in the middle of an otherwise loaded
19243d8817e4Smiod section (I don't know why we want to do this, but we do).
19253d8817e4Smiod build_link_order in ldwrite.c handles this case by turning
19263d8817e4Smiod the embedded SEC_NEVER_LOAD section into a fill. */
19273d8817e4Smiod
19283d8817e4Smiod flags &= ~ SEC_NEVER_LOAD;
19293d8817e4Smiod
19303d8817e4Smiod /* If final link, don't copy the SEC_LINK_ONCE flags, they've
19313d8817e4Smiod already been processed. One reason to do this is that on pe
19323d8817e4Smiod format targets, .text$foo sections go into .text and it's odd
19333d8817e4Smiod to see .text with SEC_LINK_ONCE set. */
19343d8817e4Smiod
19353d8817e4Smiod if (! link_info.relocatable)
19363d8817e4Smiod flags &= ~ (SEC_LINK_ONCE | SEC_LINK_DUPLICATES);
19373d8817e4Smiod
19383d8817e4Smiod /* If this is not the first input section, and the SEC_READONLY
19393d8817e4Smiod flag is not currently set, then don't set it just because the
19403d8817e4Smiod input section has it set. */
19413d8817e4Smiod
19423d8817e4Smiod if (! first && (output->bfd_section->flags & SEC_READONLY) == 0)
19433d8817e4Smiod flags &= ~ SEC_READONLY;
19443d8817e4Smiod
19453d8817e4Smiod /* Keep SEC_MERGE and SEC_STRINGS only if they are the same. */
19463d8817e4Smiod if (! first
19473d8817e4Smiod && ((output->bfd_section->flags & (SEC_MERGE | SEC_STRINGS))
19483d8817e4Smiod != (flags & (SEC_MERGE | SEC_STRINGS))
19493d8817e4Smiod || ((flags & SEC_MERGE)
19503d8817e4Smiod && output->bfd_section->entsize != section->entsize)))
19513d8817e4Smiod {
19523d8817e4Smiod output->bfd_section->flags &= ~ (SEC_MERGE | SEC_STRINGS);
19533d8817e4Smiod flags &= ~ (SEC_MERGE | SEC_STRINGS);
19543d8817e4Smiod }
19553d8817e4Smiod
19563d8817e4Smiod output->bfd_section->flags |= flags;
19573d8817e4Smiod
19583d8817e4Smiod if (flags & SEC_MERGE)
19593d8817e4Smiod output->bfd_section->entsize = section->entsize;
19603d8817e4Smiod
19613d8817e4Smiod /* If SEC_READONLY is not set in the input section, then clear
19623d8817e4Smiod it from the output section. */
19633d8817e4Smiod if ((section->flags & SEC_READONLY) == 0)
19643d8817e4Smiod output->bfd_section->flags &= ~SEC_READONLY;
19653d8817e4Smiod
19663d8817e4Smiod switch (output->sectype)
19673d8817e4Smiod {
19683d8817e4Smiod case normal_section:
19693d8817e4Smiod break;
19703d8817e4Smiod case dsect_section:
19713d8817e4Smiod case copy_section:
19723d8817e4Smiod case info_section:
19733d8817e4Smiod case overlay_section:
19743d8817e4Smiod output->bfd_section->flags &= ~SEC_ALLOC;
19753d8817e4Smiod break;
19763d8817e4Smiod case noload_section:
19773d8817e4Smiod output->bfd_section->flags &= ~SEC_LOAD;
19783d8817e4Smiod output->bfd_section->flags |= SEC_NEVER_LOAD;
19793d8817e4Smiod break;
19803d8817e4Smiod }
19813d8817e4Smiod
19823d8817e4Smiod /* Copy over SEC_SMALL_DATA. */
19833d8817e4Smiod if (section->flags & SEC_SMALL_DATA)
19843d8817e4Smiod output->bfd_section->flags |= SEC_SMALL_DATA;
19853d8817e4Smiod
19863d8817e4Smiod if (section->alignment_power > output->bfd_section->alignment_power)
19873d8817e4Smiod output->bfd_section->alignment_power = section->alignment_power;
19883d8817e4Smiod
19893d8817e4Smiod if (bfd_get_arch (section->owner) == bfd_arch_tic54x
19903d8817e4Smiod && (section->flags & SEC_TIC54X_BLOCK) != 0)
19913d8817e4Smiod {
19923d8817e4Smiod output->bfd_section->flags |= SEC_TIC54X_BLOCK;
19933d8817e4Smiod /* FIXME: This value should really be obtained from the bfd... */
19943d8817e4Smiod output->block_value = 128;
19953d8817e4Smiod }
19963d8817e4Smiod }
19973d8817e4Smiod }
19983d8817e4Smiod
19993d8817e4Smiod /* Compare sections ASEC and BSEC according to SORT. */
20003d8817e4Smiod
20013d8817e4Smiod static int
compare_section(sort_type sort,asection * asec,asection * bsec)20023d8817e4Smiod compare_section (sort_type sort, asection *asec, asection *bsec)
20033d8817e4Smiod {
20043d8817e4Smiod int ret;
20053d8817e4Smiod
20063d8817e4Smiod switch (sort)
20073d8817e4Smiod {
20083d8817e4Smiod default:
20093d8817e4Smiod abort ();
20103d8817e4Smiod
20113d8817e4Smiod case by_alignment_name:
20123d8817e4Smiod ret = (bfd_section_alignment (bsec->owner, bsec)
20133d8817e4Smiod - bfd_section_alignment (asec->owner, asec));
20143d8817e4Smiod if (ret)
20153d8817e4Smiod break;
20163d8817e4Smiod /* Fall through. */
20173d8817e4Smiod
20183d8817e4Smiod case by_name:
20193d8817e4Smiod ret = strcmp (bfd_get_section_name (asec->owner, asec),
20203d8817e4Smiod bfd_get_section_name (bsec->owner, bsec));
20213d8817e4Smiod break;
20223d8817e4Smiod
20233d8817e4Smiod case by_name_alignment:
20243d8817e4Smiod ret = strcmp (bfd_get_section_name (asec->owner, asec),
20253d8817e4Smiod bfd_get_section_name (bsec->owner, bsec));
20263d8817e4Smiod if (ret)
20273d8817e4Smiod break;
20283d8817e4Smiod /* Fall through. */
20293d8817e4Smiod
20303d8817e4Smiod case by_alignment:
20313d8817e4Smiod ret = (bfd_section_alignment (bsec->owner, bsec)
20323d8817e4Smiod - bfd_section_alignment (asec->owner, asec));
20333d8817e4Smiod break;
20343d8817e4Smiod }
20353d8817e4Smiod
20363d8817e4Smiod return ret;
20373d8817e4Smiod }
20383d8817e4Smiod
20393d8817e4Smiod /* Handle wildcard sorting. This returns the lang_input_section which
20403d8817e4Smiod should follow the one we are going to create for SECTION and FILE,
20413d8817e4Smiod based on the sorting requirements of WILD. It returns NULL if the
20423d8817e4Smiod new section should just go at the end of the current list. */
20433d8817e4Smiod
20443d8817e4Smiod static lang_statement_union_type *
wild_sort(lang_wild_statement_type * wild,struct wildcard_list * sec,lang_input_statement_type * file,asection * section)20453d8817e4Smiod wild_sort (lang_wild_statement_type *wild,
20463d8817e4Smiod struct wildcard_list *sec,
20473d8817e4Smiod lang_input_statement_type *file,
20483d8817e4Smiod asection *section)
20493d8817e4Smiod {
20503d8817e4Smiod const char *section_name;
20513d8817e4Smiod lang_statement_union_type *l;
20523d8817e4Smiod
20533d8817e4Smiod if (!wild->filenames_sorted
20543d8817e4Smiod && (sec == NULL || sec->spec.sorted == none))
20553d8817e4Smiod return NULL;
20563d8817e4Smiod
20573d8817e4Smiod section_name = bfd_get_section_name (file->the_bfd, section);
20583d8817e4Smiod for (l = wild->children.head; l != NULL; l = l->header.next)
20593d8817e4Smiod {
20603d8817e4Smiod lang_input_section_type *ls;
20613d8817e4Smiod
20623d8817e4Smiod if (l->header.type != lang_input_section_enum)
20633d8817e4Smiod continue;
20643d8817e4Smiod ls = &l->input_section;
20653d8817e4Smiod
20663d8817e4Smiod /* Sorting by filename takes precedence over sorting by section
20673d8817e4Smiod name. */
20683d8817e4Smiod
20693d8817e4Smiod if (wild->filenames_sorted)
20703d8817e4Smiod {
20713d8817e4Smiod const char *fn, *ln;
20723d8817e4Smiod bfd_boolean fa, la;
20733d8817e4Smiod int i;
20743d8817e4Smiod
20753d8817e4Smiod /* The PE support for the .idata section as generated by
20763d8817e4Smiod dlltool assumes that files will be sorted by the name of
20773d8817e4Smiod the archive and then the name of the file within the
20783d8817e4Smiod archive. */
20793d8817e4Smiod
20803d8817e4Smiod if (file->the_bfd != NULL
20813d8817e4Smiod && bfd_my_archive (file->the_bfd) != NULL)
20823d8817e4Smiod {
20833d8817e4Smiod fn = bfd_get_filename (bfd_my_archive (file->the_bfd));
20843d8817e4Smiod fa = TRUE;
20853d8817e4Smiod }
20863d8817e4Smiod else
20873d8817e4Smiod {
20883d8817e4Smiod fn = file->filename;
20893d8817e4Smiod fa = FALSE;
20903d8817e4Smiod }
20913d8817e4Smiod
20923d8817e4Smiod if (bfd_my_archive (ls->section->owner) != NULL)
20933d8817e4Smiod {
20943d8817e4Smiod ln = bfd_get_filename (bfd_my_archive (ls->section->owner));
20953d8817e4Smiod la = TRUE;
20963d8817e4Smiod }
20973d8817e4Smiod else
20983d8817e4Smiod {
20993d8817e4Smiod ln = ls->section->owner->filename;
21003d8817e4Smiod la = FALSE;
21013d8817e4Smiod }
21023d8817e4Smiod
21033d8817e4Smiod i = strcmp (fn, ln);
21043d8817e4Smiod if (i > 0)
21053d8817e4Smiod continue;
21063d8817e4Smiod else if (i < 0)
21073d8817e4Smiod break;
21083d8817e4Smiod
21093d8817e4Smiod if (fa || la)
21103d8817e4Smiod {
21113d8817e4Smiod if (fa)
21123d8817e4Smiod fn = file->filename;
21133d8817e4Smiod if (la)
21143d8817e4Smiod ln = ls->section->owner->filename;
21153d8817e4Smiod
21163d8817e4Smiod i = strcmp (fn, ln);
21173d8817e4Smiod if (i > 0)
21183d8817e4Smiod continue;
21193d8817e4Smiod else if (i < 0)
21203d8817e4Smiod break;
21213d8817e4Smiod }
21223d8817e4Smiod }
21233d8817e4Smiod
21243d8817e4Smiod /* Here either the files are not sorted by name, or we are
21253d8817e4Smiod looking at the sections for this file. */
21263d8817e4Smiod
21273d8817e4Smiod if (sec != NULL && sec->spec.sorted != none)
21283d8817e4Smiod if (compare_section (sec->spec.sorted, section, ls->section) < 0)
21293d8817e4Smiod break;
21303d8817e4Smiod }
21313d8817e4Smiod
21323d8817e4Smiod return l;
21333d8817e4Smiod }
21343d8817e4Smiod
21353d8817e4Smiod /* Expand a wild statement for a particular FILE. SECTION may be
21363d8817e4Smiod NULL, in which case it is a wild card. */
21373d8817e4Smiod
21383d8817e4Smiod static void
output_section_callback(lang_wild_statement_type * ptr,struct wildcard_list * sec,asection * section,lang_input_statement_type * file,void * output)21393d8817e4Smiod output_section_callback (lang_wild_statement_type *ptr,
21403d8817e4Smiod struct wildcard_list *sec,
21413d8817e4Smiod asection *section,
21423d8817e4Smiod lang_input_statement_type *file,
21433d8817e4Smiod void *output)
21443d8817e4Smiod {
21453d8817e4Smiod lang_statement_union_type *before;
21463d8817e4Smiod
21473d8817e4Smiod /* Exclude sections that match UNIQUE_SECTION_LIST. */
21483d8817e4Smiod if (unique_section_p (section))
21493d8817e4Smiod return;
21503d8817e4Smiod
21513d8817e4Smiod before = wild_sort (ptr, sec, file, section);
21523d8817e4Smiod
21533d8817e4Smiod /* Here BEFORE points to the lang_input_section which
21543d8817e4Smiod should follow the one we are about to add. If BEFORE
21553d8817e4Smiod is NULL, then the section should just go at the end
21563d8817e4Smiod of the current list. */
21573d8817e4Smiod
21583d8817e4Smiod if (before == NULL)
21593d8817e4Smiod lang_add_section (&ptr->children, section,
21603d8817e4Smiod (lang_output_section_statement_type *) output);
21613d8817e4Smiod else
21623d8817e4Smiod {
21633d8817e4Smiod lang_statement_list_type list;
21643d8817e4Smiod lang_statement_union_type **pp;
21653d8817e4Smiod
21663d8817e4Smiod lang_list_init (&list);
21673d8817e4Smiod lang_add_section (&list, section,
21683d8817e4Smiod (lang_output_section_statement_type *) output);
21693d8817e4Smiod
21703d8817e4Smiod /* If we are discarding the section, LIST.HEAD will
21713d8817e4Smiod be NULL. */
21723d8817e4Smiod if (list.head != NULL)
21733d8817e4Smiod {
21743d8817e4Smiod ASSERT (list.head->header.next == NULL);
21753d8817e4Smiod
21763d8817e4Smiod for (pp = &ptr->children.head;
21773d8817e4Smiod *pp != before;
21783d8817e4Smiod pp = &(*pp)->header.next)
21793d8817e4Smiod ASSERT (*pp != NULL);
21803d8817e4Smiod
21813d8817e4Smiod list.head->header.next = *pp;
21823d8817e4Smiod *pp = list.head;
21833d8817e4Smiod }
21843d8817e4Smiod }
21853d8817e4Smiod }
21863d8817e4Smiod
21873d8817e4Smiod /* Check if all sections in a wild statement for a particular FILE
21883d8817e4Smiod are readonly. */
21893d8817e4Smiod
21903d8817e4Smiod static void
check_section_callback(lang_wild_statement_type * ptr ATTRIBUTE_UNUSED,struct wildcard_list * sec ATTRIBUTE_UNUSED,asection * section,lang_input_statement_type * file ATTRIBUTE_UNUSED,void * data)21913d8817e4Smiod check_section_callback (lang_wild_statement_type *ptr ATTRIBUTE_UNUSED,
21923d8817e4Smiod struct wildcard_list *sec ATTRIBUTE_UNUSED,
21933d8817e4Smiod asection *section,
21943d8817e4Smiod lang_input_statement_type *file ATTRIBUTE_UNUSED,
21953d8817e4Smiod void *data)
21963d8817e4Smiod {
21973d8817e4Smiod /* Exclude sections that match UNIQUE_SECTION_LIST. */
21983d8817e4Smiod if (unique_section_p (section))
21993d8817e4Smiod return;
22003d8817e4Smiod
22013d8817e4Smiod if (section->output_section == NULL && (section->flags & SEC_READONLY) == 0)
22023d8817e4Smiod ((lang_output_section_statement_type *) data)->all_input_readonly = FALSE;
22033d8817e4Smiod }
22043d8817e4Smiod
22053d8817e4Smiod /* This is passed a file name which must have been seen already and
22063d8817e4Smiod added to the statement tree. We will see if it has been opened
22073d8817e4Smiod already and had its symbols read. If not then we'll read it. */
22083d8817e4Smiod
22093d8817e4Smiod static lang_input_statement_type *
lookup_name(const char * name)22103d8817e4Smiod lookup_name (const char *name)
22113d8817e4Smiod {
22123d8817e4Smiod lang_input_statement_type *search;
22133d8817e4Smiod
22143d8817e4Smiod for (search = (lang_input_statement_type *) input_file_chain.head;
22153d8817e4Smiod search != NULL;
22163d8817e4Smiod search = (lang_input_statement_type *) search->next_real_file)
22173d8817e4Smiod {
22183d8817e4Smiod /* Use the local_sym_name as the name of the file that has
22193d8817e4Smiod already been loaded as filename might have been transformed
22203d8817e4Smiod via the search directory lookup mechanism. */
22213d8817e4Smiod const char * filename = search->local_sym_name;
22223d8817e4Smiod
22233d8817e4Smiod if (filename == NULL && name == NULL)
22243d8817e4Smiod return search;
22253d8817e4Smiod if (filename != NULL
22263d8817e4Smiod && name != NULL
22273d8817e4Smiod && strcmp (filename, name) == 0)
22283d8817e4Smiod break;
22293d8817e4Smiod }
22303d8817e4Smiod
22313d8817e4Smiod if (search == NULL)
22323d8817e4Smiod search = new_afile (name, lang_input_file_is_search_file_enum,
22333d8817e4Smiod default_target, FALSE);
22343d8817e4Smiod
22353d8817e4Smiod /* If we have already added this file, or this file is not real
22363d8817e4Smiod (FIXME: can that ever actually happen?) or the name is NULL
22373d8817e4Smiod (FIXME: can that ever actually happen?) don't add this file. */
22383d8817e4Smiod if (search->loaded
22393d8817e4Smiod || ! search->real
22403d8817e4Smiod || search->filename == NULL)
22413d8817e4Smiod return search;
22423d8817e4Smiod
22433d8817e4Smiod if (! load_symbols (search, NULL))
22443d8817e4Smiod return NULL;
22453d8817e4Smiod
22463d8817e4Smiod return search;
22473d8817e4Smiod }
22483d8817e4Smiod
22493d8817e4Smiod /* Save LIST as a list of libraries whose symbols should not be exported. */
22503d8817e4Smiod
22513d8817e4Smiod struct excluded_lib
22523d8817e4Smiod {
22533d8817e4Smiod char *name;
22543d8817e4Smiod struct excluded_lib *next;
22553d8817e4Smiod };
22563d8817e4Smiod static struct excluded_lib *excluded_libs;
22573d8817e4Smiod
22583d8817e4Smiod void
add_excluded_libs(const char * list)22593d8817e4Smiod add_excluded_libs (const char *list)
22603d8817e4Smiod {
22613d8817e4Smiod const char *p = list, *end;
22623d8817e4Smiod
22633d8817e4Smiod while (*p != '\0')
22643d8817e4Smiod {
22653d8817e4Smiod struct excluded_lib *entry;
22663d8817e4Smiod end = strpbrk (p, ",:");
22673d8817e4Smiod if (end == NULL)
22683d8817e4Smiod end = p + strlen (p);
22693d8817e4Smiod entry = xmalloc (sizeof (*entry));
22703d8817e4Smiod entry->next = excluded_libs;
22713d8817e4Smiod entry->name = xmalloc (end - p + 1);
22723d8817e4Smiod memcpy (entry->name, p, end - p);
22733d8817e4Smiod entry->name[end - p] = '\0';
22743d8817e4Smiod excluded_libs = entry;
22753d8817e4Smiod if (*end == '\0')
22763d8817e4Smiod break;
22773d8817e4Smiod p = end + 1;
22783d8817e4Smiod }
22793d8817e4Smiod }
22803d8817e4Smiod
22813d8817e4Smiod static void
check_excluded_libs(bfd * abfd)22823d8817e4Smiod check_excluded_libs (bfd *abfd)
22833d8817e4Smiod {
22843d8817e4Smiod struct excluded_lib *lib = excluded_libs;
22853d8817e4Smiod
22863d8817e4Smiod while (lib)
22873d8817e4Smiod {
22883d8817e4Smiod int len = strlen (lib->name);
22893d8817e4Smiod const char *filename = lbasename (abfd->filename);
22903d8817e4Smiod
22913d8817e4Smiod if (strcmp (lib->name, "ALL") == 0)
22923d8817e4Smiod {
22933d8817e4Smiod abfd->no_export = TRUE;
22943d8817e4Smiod return;
22953d8817e4Smiod }
22963d8817e4Smiod
22973d8817e4Smiod if (strncmp (lib->name, filename, len) == 0
22983d8817e4Smiod && (filename[len] == '\0'
22993d8817e4Smiod || (filename[len] == '.' && filename[len + 1] == 'a'
23003d8817e4Smiod && filename[len + 2] == '\0')))
23013d8817e4Smiod {
23023d8817e4Smiod abfd->no_export = TRUE;
23033d8817e4Smiod return;
23043d8817e4Smiod }
23053d8817e4Smiod
23063d8817e4Smiod lib = lib->next;
23073d8817e4Smiod }
23083d8817e4Smiod }
23093d8817e4Smiod
23103d8817e4Smiod /* Get the symbols for an input file. */
23113d8817e4Smiod
23123d8817e4Smiod static bfd_boolean
load_symbols(lang_input_statement_type * entry,lang_statement_list_type * place)23133d8817e4Smiod load_symbols (lang_input_statement_type *entry,
23143d8817e4Smiod lang_statement_list_type *place)
23153d8817e4Smiod {
23163d8817e4Smiod char **matching;
23173d8817e4Smiod
23183d8817e4Smiod if (entry->loaded)
23193d8817e4Smiod return TRUE;
23203d8817e4Smiod
23213d8817e4Smiod ldfile_open_file (entry);
23223d8817e4Smiod
23233d8817e4Smiod if (! bfd_check_format (entry->the_bfd, bfd_archive)
23243d8817e4Smiod && ! bfd_check_format_matches (entry->the_bfd, bfd_object, &matching))
23253d8817e4Smiod {
23263d8817e4Smiod bfd_error_type err;
23273d8817e4Smiod lang_statement_list_type *hold;
23283d8817e4Smiod bfd_boolean bad_load = TRUE;
23293d8817e4Smiod bfd_boolean save_ldlang_sysrooted_script;
23303d8817e4Smiod bfd_boolean save_as_needed, save_add_needed;
23313d8817e4Smiod
23323d8817e4Smiod err = bfd_get_error ();
23333d8817e4Smiod
23343d8817e4Smiod /* See if the emulation has some special knowledge. */
23353d8817e4Smiod if (ldemul_unrecognized_file (entry))
23363d8817e4Smiod return TRUE;
23373d8817e4Smiod
23383d8817e4Smiod if (err == bfd_error_file_ambiguously_recognized)
23393d8817e4Smiod {
23403d8817e4Smiod char **p;
23413d8817e4Smiod
23423d8817e4Smiod einfo (_("%B: file not recognized: %E\n"), entry->the_bfd);
23433d8817e4Smiod einfo (_("%B: matching formats:"), entry->the_bfd);
23443d8817e4Smiod for (p = matching; *p != NULL; p++)
23453d8817e4Smiod einfo (" %s", *p);
23463d8817e4Smiod einfo ("%F\n");
23473d8817e4Smiod }
23483d8817e4Smiod else if (err != bfd_error_file_not_recognized
23493d8817e4Smiod || place == NULL)
23503d8817e4Smiod einfo (_("%F%B: file not recognized: %E\n"), entry->the_bfd);
23513d8817e4Smiod else
23523d8817e4Smiod bad_load = FALSE;
23533d8817e4Smiod
23543d8817e4Smiod bfd_close (entry->the_bfd);
23553d8817e4Smiod entry->the_bfd = NULL;
23563d8817e4Smiod
23573d8817e4Smiod /* Try to interpret the file as a linker script. */
23583d8817e4Smiod ldfile_open_command_file (entry->filename);
23593d8817e4Smiod
23603d8817e4Smiod hold = stat_ptr;
23613d8817e4Smiod stat_ptr = place;
23623d8817e4Smiod save_ldlang_sysrooted_script = ldlang_sysrooted_script;
23633d8817e4Smiod ldlang_sysrooted_script = entry->sysrooted;
23643d8817e4Smiod save_as_needed = as_needed;
23653d8817e4Smiod as_needed = entry->as_needed;
23663d8817e4Smiod save_add_needed = add_needed;
23673d8817e4Smiod add_needed = entry->add_needed;
23683d8817e4Smiod
23693d8817e4Smiod ldfile_assumed_script = TRUE;
23703d8817e4Smiod parser_input = input_script;
23713d8817e4Smiod /* We want to use the same -Bdynamic/-Bstatic as the one for
23723d8817e4Smiod ENTRY. */
23733d8817e4Smiod config.dynamic_link = entry->dynamic;
23743d8817e4Smiod yyparse ();
23753d8817e4Smiod ldfile_assumed_script = FALSE;
23763d8817e4Smiod
23773d8817e4Smiod ldlang_sysrooted_script = save_ldlang_sysrooted_script;
23783d8817e4Smiod as_needed = save_as_needed;
23793d8817e4Smiod add_needed = save_add_needed;
23803d8817e4Smiod stat_ptr = hold;
23813d8817e4Smiod
23823d8817e4Smiod return ! bad_load;
23833d8817e4Smiod }
23843d8817e4Smiod
23853d8817e4Smiod if (ldemul_recognized_file (entry))
23863d8817e4Smiod return TRUE;
23873d8817e4Smiod
23883d8817e4Smiod /* We don't call ldlang_add_file for an archive. Instead, the
23893d8817e4Smiod add_symbols entry point will call ldlang_add_file, via the
23903d8817e4Smiod add_archive_element callback, for each element of the archive
23913d8817e4Smiod which is used. */
23923d8817e4Smiod switch (bfd_get_format (entry->the_bfd))
23933d8817e4Smiod {
23943d8817e4Smiod default:
23953d8817e4Smiod break;
23963d8817e4Smiod
23973d8817e4Smiod case bfd_object:
23983d8817e4Smiod ldlang_add_file (entry);
23993d8817e4Smiod if (trace_files || trace_file_tries)
24003d8817e4Smiod info_msg ("%I\n", entry);
24013d8817e4Smiod break;
24023d8817e4Smiod
24033d8817e4Smiod case bfd_archive:
24043d8817e4Smiod check_excluded_libs (entry->the_bfd);
24053d8817e4Smiod
24063d8817e4Smiod if (entry->whole_archive)
24073d8817e4Smiod {
24083d8817e4Smiod bfd *member = NULL;
24093d8817e4Smiod bfd_boolean loaded = TRUE;
24103d8817e4Smiod
24113d8817e4Smiod for (;;)
24123d8817e4Smiod {
24133d8817e4Smiod member = bfd_openr_next_archived_file (entry->the_bfd, member);
24143d8817e4Smiod
24153d8817e4Smiod if (member == NULL)
24163d8817e4Smiod break;
24173d8817e4Smiod
24183d8817e4Smiod if (! bfd_check_format (member, bfd_object))
24193d8817e4Smiod {
24203d8817e4Smiod einfo (_("%F%B: member %B in archive is not an object\n"),
24213d8817e4Smiod entry->the_bfd, member);
24223d8817e4Smiod loaded = FALSE;
24233d8817e4Smiod }
24243d8817e4Smiod
24253d8817e4Smiod if (! ((*link_info.callbacks->add_archive_element)
24263d8817e4Smiod (&link_info, member, "--whole-archive")))
24273d8817e4Smiod abort ();
24283d8817e4Smiod
24293d8817e4Smiod if (! bfd_link_add_symbols (member, &link_info))
24303d8817e4Smiod {
24313d8817e4Smiod einfo (_("%F%B: could not read symbols: %E\n"), member);
24323d8817e4Smiod loaded = FALSE;
24333d8817e4Smiod }
24343d8817e4Smiod }
24353d8817e4Smiod
24363d8817e4Smiod entry->loaded = loaded;
24373d8817e4Smiod return loaded;
24383d8817e4Smiod }
24393d8817e4Smiod break;
24403d8817e4Smiod }
24413d8817e4Smiod
24423d8817e4Smiod if (bfd_link_add_symbols (entry->the_bfd, &link_info))
24433d8817e4Smiod entry->loaded = TRUE;
24443d8817e4Smiod else
24453d8817e4Smiod einfo (_("%F%B: could not read symbols: %E\n"), entry->the_bfd);
24463d8817e4Smiod
24473d8817e4Smiod return entry->loaded;
24483d8817e4Smiod }
24493d8817e4Smiod
24503d8817e4Smiod /* Handle a wild statement. S->FILENAME or S->SECTION_LIST or both
24513d8817e4Smiod may be NULL, indicating that it is a wildcard. Separate
24523d8817e4Smiod lang_input_section statements are created for each part of the
24533d8817e4Smiod expansion; they are added after the wild statement S. OUTPUT is
24543d8817e4Smiod the output section. */
24553d8817e4Smiod
24563d8817e4Smiod static void
wild(lang_wild_statement_type * s,const char * target ATTRIBUTE_UNUSED,lang_output_section_statement_type * output)24573d8817e4Smiod wild (lang_wild_statement_type *s,
24583d8817e4Smiod const char *target ATTRIBUTE_UNUSED,
24593d8817e4Smiod lang_output_section_statement_type *output)
24603d8817e4Smiod {
24613d8817e4Smiod struct wildcard_list *sec;
24623d8817e4Smiod
24633d8817e4Smiod walk_wild (s, output_section_callback, output);
24643d8817e4Smiod
24653d8817e4Smiod for (sec = s->section_list; sec != NULL; sec = sec->next)
24663d8817e4Smiod {
24673d8817e4Smiod if (default_common_section != NULL)
24683d8817e4Smiod break;
24693d8817e4Smiod if (sec->spec.name != NULL && strcmp (sec->spec.name, "COMMON") == 0)
24703d8817e4Smiod {
24713d8817e4Smiod /* Remember the section that common is going to in case we
24723d8817e4Smiod later get something which doesn't know where to put it. */
24733d8817e4Smiod default_common_section = output;
24743d8817e4Smiod }
24753d8817e4Smiod }
24763d8817e4Smiod }
24773d8817e4Smiod
24783d8817e4Smiod /* Return TRUE iff target is the sought target. */
24793d8817e4Smiod
24803d8817e4Smiod static int
get_target(const bfd_target * target,void * data)24813d8817e4Smiod get_target (const bfd_target *target, void *data)
24823d8817e4Smiod {
24833d8817e4Smiod const char *sought = data;
24843d8817e4Smiod
24853d8817e4Smiod return strcmp (target->name, sought) == 0;
24863d8817e4Smiod }
24873d8817e4Smiod
24883d8817e4Smiod /* Like strcpy() but convert to lower case as well. */
24893d8817e4Smiod
24903d8817e4Smiod static void
stricpy(char * dest,char * src)24913d8817e4Smiod stricpy (char *dest, char *src)
24923d8817e4Smiod {
24933d8817e4Smiod char c;
24943d8817e4Smiod
24953d8817e4Smiod while ((c = *src++) != 0)
24963d8817e4Smiod *dest++ = TOLOWER (c);
24973d8817e4Smiod
24983d8817e4Smiod *dest = 0;
24993d8817e4Smiod }
25003d8817e4Smiod
25013d8817e4Smiod /* Remove the first occurrence of needle (if any) in haystack
25023d8817e4Smiod from haystack. */
25033d8817e4Smiod
25043d8817e4Smiod static void
strcut(char * haystack,char * needle)25053d8817e4Smiod strcut (char *haystack, char *needle)
25063d8817e4Smiod {
25073d8817e4Smiod haystack = strstr (haystack, needle);
25083d8817e4Smiod
25093d8817e4Smiod if (haystack)
25103d8817e4Smiod {
25113d8817e4Smiod char *src;
25123d8817e4Smiod
25133d8817e4Smiod for (src = haystack + strlen (needle); *src;)
25143d8817e4Smiod *haystack++ = *src++;
25153d8817e4Smiod
25163d8817e4Smiod *haystack = 0;
25173d8817e4Smiod }
25183d8817e4Smiod }
25193d8817e4Smiod
25203d8817e4Smiod /* Compare two target format name strings.
25213d8817e4Smiod Return a value indicating how "similar" they are. */
25223d8817e4Smiod
25233d8817e4Smiod static int
name_compare(char * first,char * second)25243d8817e4Smiod name_compare (char *first, char *second)
25253d8817e4Smiod {
25263d8817e4Smiod char *copy1;
25273d8817e4Smiod char *copy2;
25283d8817e4Smiod int result;
25293d8817e4Smiod
25303d8817e4Smiod copy1 = xmalloc (strlen (first) + 1);
25313d8817e4Smiod copy2 = xmalloc (strlen (second) + 1);
25323d8817e4Smiod
25333d8817e4Smiod /* Convert the names to lower case. */
25343d8817e4Smiod stricpy (copy1, first);
25353d8817e4Smiod stricpy (copy2, second);
25363d8817e4Smiod
25373d8817e4Smiod /* Remove size and endian strings from the name. */
25383d8817e4Smiod strcut (copy1, "big");
25393d8817e4Smiod strcut (copy1, "little");
25403d8817e4Smiod strcut (copy2, "big");
25413d8817e4Smiod strcut (copy2, "little");
25423d8817e4Smiod
25433d8817e4Smiod /* Return a value based on how many characters match,
25443d8817e4Smiod starting from the beginning. If both strings are
25453d8817e4Smiod the same then return 10 * their length. */
25463d8817e4Smiod for (result = 0; copy1[result] == copy2[result]; result++)
25473d8817e4Smiod if (copy1[result] == 0)
25483d8817e4Smiod {
25493d8817e4Smiod result *= 10;
25503d8817e4Smiod break;
25513d8817e4Smiod }
25523d8817e4Smiod
25533d8817e4Smiod free (copy1);
25543d8817e4Smiod free (copy2);
25553d8817e4Smiod
25563d8817e4Smiod return result;
25573d8817e4Smiod }
25583d8817e4Smiod
25593d8817e4Smiod /* Set by closest_target_match() below. */
25603d8817e4Smiod static const bfd_target *winner;
25613d8817e4Smiod
25623d8817e4Smiod /* Scan all the valid bfd targets looking for one that has the endianness
25633d8817e4Smiod requirement that was specified on the command line, and is the nearest
25643d8817e4Smiod match to the original output target. */
25653d8817e4Smiod
25663d8817e4Smiod static int
closest_target_match(const bfd_target * target,void * data)25673d8817e4Smiod closest_target_match (const bfd_target *target, void *data)
25683d8817e4Smiod {
25693d8817e4Smiod const bfd_target *original = data;
25703d8817e4Smiod
25713d8817e4Smiod if (command_line.endian == ENDIAN_BIG
25723d8817e4Smiod && target->byteorder != BFD_ENDIAN_BIG)
25733d8817e4Smiod return 0;
25743d8817e4Smiod
25753d8817e4Smiod if (command_line.endian == ENDIAN_LITTLE
25763d8817e4Smiod && target->byteorder != BFD_ENDIAN_LITTLE)
25773d8817e4Smiod return 0;
25783d8817e4Smiod
25793d8817e4Smiod /* Must be the same flavour. */
25803d8817e4Smiod if (target->flavour != original->flavour)
25813d8817e4Smiod return 0;
25823d8817e4Smiod
25833d8817e4Smiod /* If we have not found a potential winner yet, then record this one. */
25843d8817e4Smiod if (winner == NULL)
25853d8817e4Smiod {
25863d8817e4Smiod winner = target;
25873d8817e4Smiod return 0;
25883d8817e4Smiod }
25893d8817e4Smiod
25903d8817e4Smiod /* Oh dear, we now have two potential candidates for a successful match.
25913d8817e4Smiod Compare their names and choose the better one. */
25923d8817e4Smiod if (name_compare (target->name, original->name)
25933d8817e4Smiod > name_compare (winner->name, original->name))
25943d8817e4Smiod winner = target;
25953d8817e4Smiod
25963d8817e4Smiod /* Keep on searching until wqe have checked them all. */
25973d8817e4Smiod return 0;
25983d8817e4Smiod }
25993d8817e4Smiod
26003d8817e4Smiod /* Return the BFD target format of the first input file. */
26013d8817e4Smiod
26023d8817e4Smiod static char *
get_first_input_target(void)26033d8817e4Smiod get_first_input_target (void)
26043d8817e4Smiod {
26053d8817e4Smiod char *target = NULL;
26063d8817e4Smiod
26073d8817e4Smiod LANG_FOR_EACH_INPUT_STATEMENT (s)
26083d8817e4Smiod {
26093d8817e4Smiod if (s->header.type == lang_input_statement_enum
26103d8817e4Smiod && s->real)
26113d8817e4Smiod {
26123d8817e4Smiod ldfile_open_file (s);
26133d8817e4Smiod
26143d8817e4Smiod if (s->the_bfd != NULL
26153d8817e4Smiod && bfd_check_format (s->the_bfd, bfd_object))
26163d8817e4Smiod {
26173d8817e4Smiod target = bfd_get_target (s->the_bfd);
26183d8817e4Smiod
26193d8817e4Smiod if (target != NULL)
26203d8817e4Smiod break;
26213d8817e4Smiod }
26223d8817e4Smiod }
26233d8817e4Smiod }
26243d8817e4Smiod
26253d8817e4Smiod return target;
26263d8817e4Smiod }
26273d8817e4Smiod
26283d8817e4Smiod const char *
lang_get_output_target(void)26293d8817e4Smiod lang_get_output_target (void)
26303d8817e4Smiod {
26313d8817e4Smiod const char *target;
26323d8817e4Smiod
26333d8817e4Smiod /* Has the user told us which output format to use? */
26343d8817e4Smiod if (output_target != NULL)
26353d8817e4Smiod return output_target;
26363d8817e4Smiod
26373d8817e4Smiod /* No - has the current target been set to something other than
26383d8817e4Smiod the default? */
26393d8817e4Smiod if (current_target != default_target)
26403d8817e4Smiod return current_target;
26413d8817e4Smiod
26423d8817e4Smiod /* No - can we determine the format of the first input file? */
26433d8817e4Smiod target = get_first_input_target ();
26443d8817e4Smiod if (target != NULL)
26453d8817e4Smiod return target;
26463d8817e4Smiod
26473d8817e4Smiod /* Failed - use the default output target. */
26483d8817e4Smiod return default_target;
26493d8817e4Smiod }
26503d8817e4Smiod
26513d8817e4Smiod /* Open the output file. */
26523d8817e4Smiod
26533d8817e4Smiod static bfd *
open_output(const char * name)26543d8817e4Smiod open_output (const char *name)
26553d8817e4Smiod {
26563d8817e4Smiod bfd *output;
26573d8817e4Smiod
26583d8817e4Smiod output_target = lang_get_output_target ();
26593d8817e4Smiod
26603d8817e4Smiod /* Has the user requested a particular endianness on the command
26613d8817e4Smiod line? */
26623d8817e4Smiod if (command_line.endian != ENDIAN_UNSET)
26633d8817e4Smiod {
26643d8817e4Smiod const bfd_target *target;
26653d8817e4Smiod enum bfd_endian desired_endian;
26663d8817e4Smiod
26673d8817e4Smiod /* Get the chosen target. */
26683d8817e4Smiod target = bfd_search_for_target (get_target, (void *) output_target);
26693d8817e4Smiod
26703d8817e4Smiod /* If the target is not supported, we cannot do anything. */
26713d8817e4Smiod if (target != NULL)
26723d8817e4Smiod {
26733d8817e4Smiod if (command_line.endian == ENDIAN_BIG)
26743d8817e4Smiod desired_endian = BFD_ENDIAN_BIG;
26753d8817e4Smiod else
26763d8817e4Smiod desired_endian = BFD_ENDIAN_LITTLE;
26773d8817e4Smiod
26783d8817e4Smiod /* See if the target has the wrong endianness. This should
26793d8817e4Smiod not happen if the linker script has provided big and
26803d8817e4Smiod little endian alternatives, but some scrips don't do
26813d8817e4Smiod this. */
26823d8817e4Smiod if (target->byteorder != desired_endian)
26833d8817e4Smiod {
26843d8817e4Smiod /* If it does, then see if the target provides
26853d8817e4Smiod an alternative with the correct endianness. */
26863d8817e4Smiod if (target->alternative_target != NULL
26873d8817e4Smiod && (target->alternative_target->byteorder == desired_endian))
26883d8817e4Smiod output_target = target->alternative_target->name;
26893d8817e4Smiod else
26903d8817e4Smiod {
26913d8817e4Smiod /* Try to find a target as similar as possible to
26923d8817e4Smiod the default target, but which has the desired
26933d8817e4Smiod endian characteristic. */
26943d8817e4Smiod bfd_search_for_target (closest_target_match,
26953d8817e4Smiod (void *) target);
26963d8817e4Smiod
26973d8817e4Smiod /* Oh dear - we could not find any targets that
26983d8817e4Smiod satisfy our requirements. */
26993d8817e4Smiod if (winner == NULL)
27003d8817e4Smiod einfo (_("%P: warning: could not find any targets"
27013d8817e4Smiod " that match endianness requirement\n"));
27023d8817e4Smiod else
27033d8817e4Smiod output_target = winner->name;
27043d8817e4Smiod }
27053d8817e4Smiod }
27063d8817e4Smiod }
27073d8817e4Smiod }
27083d8817e4Smiod
27093d8817e4Smiod output = bfd_openw (name, output_target);
27103d8817e4Smiod
27113d8817e4Smiod if (output == NULL)
27123d8817e4Smiod {
27133d8817e4Smiod if (bfd_get_error () == bfd_error_invalid_target)
27143d8817e4Smiod einfo (_("%P%F: target %s not found\n"), output_target);
27153d8817e4Smiod
27163d8817e4Smiod einfo (_("%P%F: cannot open output file %s: %E\n"), name);
27173d8817e4Smiod }
27183d8817e4Smiod
27193d8817e4Smiod delete_output_file_on_failure = TRUE;
27203d8817e4Smiod
27213d8817e4Smiod if (! bfd_set_format (output, bfd_object))
27223d8817e4Smiod einfo (_("%P%F:%s: can not make object file: %E\n"), name);
27233d8817e4Smiod if (! bfd_set_arch_mach (output,
27243d8817e4Smiod ldfile_output_architecture,
27253d8817e4Smiod ldfile_output_machine))
27263d8817e4Smiod einfo (_("%P%F:%s: can not set architecture: %E\n"), name);
27273d8817e4Smiod
27283d8817e4Smiod link_info.hash = bfd_link_hash_table_create (output);
27293d8817e4Smiod if (link_info.hash == NULL)
27303d8817e4Smiod einfo (_("%P%F: can not create hash table: %E\n"));
27313d8817e4Smiod
27323d8817e4Smiod bfd_set_gp_size (output, g_switch_value);
27333d8817e4Smiod return output;
27343d8817e4Smiod }
27353d8817e4Smiod
27363d8817e4Smiod static void
ldlang_open_output(lang_statement_union_type * statement)27373d8817e4Smiod ldlang_open_output (lang_statement_union_type *statement)
27383d8817e4Smiod {
27393d8817e4Smiod switch (statement->header.type)
27403d8817e4Smiod {
27413d8817e4Smiod case lang_output_statement_enum:
27423d8817e4Smiod ASSERT (output_bfd == NULL);
27433d8817e4Smiod output_bfd = open_output (statement->output_statement.name);
27443d8817e4Smiod ldemul_set_output_arch ();
27453d8817e4Smiod if (config.magic_demand_paged && !link_info.relocatable)
27463d8817e4Smiod output_bfd->flags |= D_PAGED;
27473d8817e4Smiod else
27483d8817e4Smiod output_bfd->flags &= ~D_PAGED;
27493d8817e4Smiod if (config.text_read_only)
27503d8817e4Smiod output_bfd->flags |= WP_TEXT;
27513d8817e4Smiod else
27523d8817e4Smiod output_bfd->flags &= ~WP_TEXT;
27533d8817e4Smiod if (link_info.traditional_format)
27543d8817e4Smiod output_bfd->flags |= BFD_TRADITIONAL_FORMAT;
27553d8817e4Smiod else
27563d8817e4Smiod output_bfd->flags &= ~BFD_TRADITIONAL_FORMAT;
27573d8817e4Smiod break;
27583d8817e4Smiod
27593d8817e4Smiod case lang_target_statement_enum:
27603d8817e4Smiod current_target = statement->target_statement.target;
27613d8817e4Smiod break;
27623d8817e4Smiod default:
27633d8817e4Smiod break;
27643d8817e4Smiod }
27653d8817e4Smiod }
27663d8817e4Smiod
27673d8817e4Smiod /* Convert between addresses in bytes and sizes in octets.
27683d8817e4Smiod For currently supported targets, octets_per_byte is always a power
27693d8817e4Smiod of two, so we can use shifts. */
27703d8817e4Smiod #define TO_ADDR(X) ((X) >> opb_shift)
27713d8817e4Smiod #define TO_SIZE(X) ((X) << opb_shift)
27723d8817e4Smiod
27733d8817e4Smiod /* Support the above. */
27743d8817e4Smiod static unsigned int opb_shift = 0;
27753d8817e4Smiod
27763d8817e4Smiod static void
init_opb(void)27773d8817e4Smiod init_opb (void)
27783d8817e4Smiod {
27793d8817e4Smiod unsigned x = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
27803d8817e4Smiod ldfile_output_machine);
27813d8817e4Smiod opb_shift = 0;
27823d8817e4Smiod if (x > 1)
27833d8817e4Smiod while ((x & 1) == 0)
27843d8817e4Smiod {
27853d8817e4Smiod x >>= 1;
27863d8817e4Smiod ++opb_shift;
27873d8817e4Smiod }
27883d8817e4Smiod ASSERT (x == 1);
27893d8817e4Smiod }
27903d8817e4Smiod
27913d8817e4Smiod /* Open all the input files. */
27923d8817e4Smiod
27933d8817e4Smiod static void
open_input_bfds(lang_statement_union_type * s,bfd_boolean force)27943d8817e4Smiod open_input_bfds (lang_statement_union_type *s, bfd_boolean force)
27953d8817e4Smiod {
27963d8817e4Smiod for (; s != NULL; s = s->header.next)
27973d8817e4Smiod {
27983d8817e4Smiod switch (s->header.type)
27993d8817e4Smiod {
28003d8817e4Smiod case lang_constructors_statement_enum:
28013d8817e4Smiod open_input_bfds (constructor_list.head, force);
28023d8817e4Smiod break;
28033d8817e4Smiod case lang_output_section_statement_enum:
28043d8817e4Smiod open_input_bfds (s->output_section_statement.children.head, force);
28053d8817e4Smiod break;
28063d8817e4Smiod case lang_wild_statement_enum:
28073d8817e4Smiod /* Maybe we should load the file's symbols. */
28083d8817e4Smiod if (s->wild_statement.filename
28093d8817e4Smiod && ! wildcardp (s->wild_statement.filename))
28103d8817e4Smiod lookup_name (s->wild_statement.filename);
28113d8817e4Smiod open_input_bfds (s->wild_statement.children.head, force);
28123d8817e4Smiod break;
28133d8817e4Smiod case lang_group_statement_enum:
28143d8817e4Smiod {
28153d8817e4Smiod struct bfd_link_hash_entry *undefs;
28163d8817e4Smiod
28173d8817e4Smiod /* We must continually search the entries in the group
28183d8817e4Smiod until no new symbols are added to the list of undefined
28193d8817e4Smiod symbols. */
28203d8817e4Smiod
28213d8817e4Smiod do
28223d8817e4Smiod {
28233d8817e4Smiod undefs = link_info.hash->undefs_tail;
28243d8817e4Smiod open_input_bfds (s->group_statement.children.head, TRUE);
28253d8817e4Smiod }
28263d8817e4Smiod while (undefs != link_info.hash->undefs_tail);
28273d8817e4Smiod }
28283d8817e4Smiod break;
28293d8817e4Smiod case lang_target_statement_enum:
28303d8817e4Smiod current_target = s->target_statement.target;
28313d8817e4Smiod break;
28323d8817e4Smiod case lang_input_statement_enum:
28333d8817e4Smiod if (s->input_statement.real)
28343d8817e4Smiod {
28353d8817e4Smiod lang_statement_list_type add;
28363d8817e4Smiod
28373d8817e4Smiod s->input_statement.target = current_target;
28383d8817e4Smiod
28393d8817e4Smiod /* If we are being called from within a group, and this
28403d8817e4Smiod is an archive which has already been searched, then
28413d8817e4Smiod force it to be researched unless the whole archive
28423d8817e4Smiod has been loaded already. */
28433d8817e4Smiod if (force
28443d8817e4Smiod && !s->input_statement.whole_archive
28453d8817e4Smiod && s->input_statement.loaded
28463d8817e4Smiod && bfd_check_format (s->input_statement.the_bfd,
28473d8817e4Smiod bfd_archive))
28483d8817e4Smiod s->input_statement.loaded = FALSE;
28493d8817e4Smiod
28503d8817e4Smiod lang_list_init (&add);
28513d8817e4Smiod
28523d8817e4Smiod if (! load_symbols (&s->input_statement, &add))
28533d8817e4Smiod config.make_executable = FALSE;
28543d8817e4Smiod
28553d8817e4Smiod if (add.head != NULL)
28563d8817e4Smiod {
28573d8817e4Smiod *add.tail = s->header.next;
28583d8817e4Smiod s->header.next = add.head;
28593d8817e4Smiod }
28603d8817e4Smiod }
28613d8817e4Smiod break;
28623d8817e4Smiod default:
28633d8817e4Smiod break;
28643d8817e4Smiod }
28653d8817e4Smiod }
28663d8817e4Smiod }
28673d8817e4Smiod
28683d8817e4Smiod /* Add a symbol to a hash of symbols used in DEFINED (NAME) expressions. */
28693d8817e4Smiod
28703d8817e4Smiod void
lang_track_definedness(const char * name)28713d8817e4Smiod lang_track_definedness (const char *name)
28723d8817e4Smiod {
28733d8817e4Smiod if (bfd_hash_lookup (&lang_definedness_table, name, TRUE, FALSE) == NULL)
28743d8817e4Smiod einfo (_("%P%F: bfd_hash_lookup failed creating symbol %s\n"), name);
28753d8817e4Smiod }
28763d8817e4Smiod
28773d8817e4Smiod /* New-function for the definedness hash table. */
28783d8817e4Smiod
28793d8817e4Smiod static struct bfd_hash_entry *
lang_definedness_newfunc(struct bfd_hash_entry * entry,struct bfd_hash_table * table ATTRIBUTE_UNUSED,const char * name ATTRIBUTE_UNUSED)28803d8817e4Smiod lang_definedness_newfunc (struct bfd_hash_entry *entry,
28813d8817e4Smiod struct bfd_hash_table *table ATTRIBUTE_UNUSED,
28823d8817e4Smiod const char *name ATTRIBUTE_UNUSED)
28833d8817e4Smiod {
28843d8817e4Smiod struct lang_definedness_hash_entry *ret
28853d8817e4Smiod = (struct lang_definedness_hash_entry *) entry;
28863d8817e4Smiod
28873d8817e4Smiod if (ret == NULL)
28883d8817e4Smiod ret = (struct lang_definedness_hash_entry *)
28893d8817e4Smiod bfd_hash_allocate (table, sizeof (struct lang_definedness_hash_entry));
28903d8817e4Smiod
28913d8817e4Smiod if (ret == NULL)
28923d8817e4Smiod einfo (_("%P%F: bfd_hash_allocate failed creating symbol %s\n"), name);
28933d8817e4Smiod
28943d8817e4Smiod ret->iteration = -1;
28953d8817e4Smiod return &ret->root;
28963d8817e4Smiod }
28973d8817e4Smiod
28983d8817e4Smiod /* Return the iteration when the definition of NAME was last updated. A
28993d8817e4Smiod value of -1 means that the symbol is not defined in the linker script
29003d8817e4Smiod or the command line, but may be defined in the linker symbol table. */
29013d8817e4Smiod
29023d8817e4Smiod int
lang_symbol_definition_iteration(const char * name)29033d8817e4Smiod lang_symbol_definition_iteration (const char *name)
29043d8817e4Smiod {
29053d8817e4Smiod struct lang_definedness_hash_entry *defentry
29063d8817e4Smiod = (struct lang_definedness_hash_entry *)
29073d8817e4Smiod bfd_hash_lookup (&lang_definedness_table, name, FALSE, FALSE);
29083d8817e4Smiod
29093d8817e4Smiod /* We've already created this one on the presence of DEFINED in the
29103d8817e4Smiod script, so it can't be NULL unless something is borked elsewhere in
29113d8817e4Smiod the code. */
29123d8817e4Smiod if (defentry == NULL)
29133d8817e4Smiod FAIL ();
29143d8817e4Smiod
29153d8817e4Smiod return defentry->iteration;
29163d8817e4Smiod }
29173d8817e4Smiod
29183d8817e4Smiod /* Update the definedness state of NAME. */
29193d8817e4Smiod
29203d8817e4Smiod void
lang_update_definedness(const char * name,struct bfd_link_hash_entry * h)29213d8817e4Smiod lang_update_definedness (const char *name, struct bfd_link_hash_entry *h)
29223d8817e4Smiod {
29233d8817e4Smiod struct lang_definedness_hash_entry *defentry
29243d8817e4Smiod = (struct lang_definedness_hash_entry *)
29253d8817e4Smiod bfd_hash_lookup (&lang_definedness_table, name, FALSE, FALSE);
29263d8817e4Smiod
29273d8817e4Smiod /* We don't keep track of symbols not tested with DEFINED. */
29283d8817e4Smiod if (defentry == NULL)
29293d8817e4Smiod return;
29303d8817e4Smiod
29313d8817e4Smiod /* If the symbol was already defined, and not from an earlier statement
29323d8817e4Smiod iteration, don't update the definedness iteration, because that'd
29333d8817e4Smiod make the symbol seem defined in the linker script at this point, and
29343d8817e4Smiod it wasn't; it was defined in some object. If we do anyway, DEFINED
29353d8817e4Smiod would start to yield false before this point and the construct "sym =
29363d8817e4Smiod DEFINED (sym) ? sym : X;" would change sym to X despite being defined
29373d8817e4Smiod in an object. */
29383d8817e4Smiod if (h->type != bfd_link_hash_undefined
29393d8817e4Smiod && h->type != bfd_link_hash_common
29403d8817e4Smiod && h->type != bfd_link_hash_new
29413d8817e4Smiod && defentry->iteration == -1)
29423d8817e4Smiod return;
29433d8817e4Smiod
29443d8817e4Smiod defentry->iteration = lang_statement_iteration;
29453d8817e4Smiod }
29463d8817e4Smiod
29473d8817e4Smiod /* Add the supplied name to the symbol table as an undefined reference.
29483d8817e4Smiod This is a two step process as the symbol table doesn't even exist at
29493d8817e4Smiod the time the ld command line is processed. First we put the name
29503d8817e4Smiod on a list, then, once the output file has been opened, transfer the
29513d8817e4Smiod name to the symbol table. */
29523d8817e4Smiod
29533d8817e4Smiod typedef struct bfd_sym_chain ldlang_undef_chain_list_type;
29543d8817e4Smiod
29553d8817e4Smiod #define ldlang_undef_chain_list_head entry_symbol.next
29563d8817e4Smiod
29573d8817e4Smiod void
ldlang_add_undef(const char * const name)29583d8817e4Smiod ldlang_add_undef (const char *const name)
29593d8817e4Smiod {
29603d8817e4Smiod ldlang_undef_chain_list_type *new =
29613d8817e4Smiod stat_alloc (sizeof (ldlang_undef_chain_list_type));
29623d8817e4Smiod
29633d8817e4Smiod new->next = ldlang_undef_chain_list_head;
29643d8817e4Smiod ldlang_undef_chain_list_head = new;
29653d8817e4Smiod
29663d8817e4Smiod new->name = xstrdup (name);
29673d8817e4Smiod
29683d8817e4Smiod if (output_bfd != NULL)
29693d8817e4Smiod insert_undefined (new->name);
29703d8817e4Smiod }
29713d8817e4Smiod
29723d8817e4Smiod /* Insert NAME as undefined in the symbol table. */
29733d8817e4Smiod
29743d8817e4Smiod static void
insert_undefined(const char * name)29753d8817e4Smiod insert_undefined (const char *name)
29763d8817e4Smiod {
29773d8817e4Smiod struct bfd_link_hash_entry *h;
29783d8817e4Smiod
29793d8817e4Smiod h = bfd_link_hash_lookup (link_info.hash, name, TRUE, FALSE, TRUE);
29803d8817e4Smiod if (h == NULL)
29813d8817e4Smiod einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
29823d8817e4Smiod if (h->type == bfd_link_hash_new)
29833d8817e4Smiod {
29843d8817e4Smiod h->type = bfd_link_hash_undefined;
29853d8817e4Smiod h->u.undef.abfd = NULL;
29863d8817e4Smiod bfd_link_add_undef (link_info.hash, h);
29873d8817e4Smiod }
29883d8817e4Smiod }
29893d8817e4Smiod
29903d8817e4Smiod /* Run through the list of undefineds created above and place them
29913d8817e4Smiod into the linker hash table as undefined symbols belonging to the
29923d8817e4Smiod script file. */
29933d8817e4Smiod
29943d8817e4Smiod static void
lang_place_undefineds(void)29953d8817e4Smiod lang_place_undefineds (void)
29963d8817e4Smiod {
29973d8817e4Smiod ldlang_undef_chain_list_type *ptr;
29983d8817e4Smiod
29993d8817e4Smiod for (ptr = ldlang_undef_chain_list_head; ptr != NULL; ptr = ptr->next)
30003d8817e4Smiod insert_undefined (ptr->name);
30013d8817e4Smiod }
30023d8817e4Smiod
30033d8817e4Smiod /* Check for all readonly or some readwrite sections. */
30043d8817e4Smiod
30053d8817e4Smiod static void
check_input_sections(lang_statement_union_type * s,lang_output_section_statement_type * output_section_statement)30063d8817e4Smiod check_input_sections
30073d8817e4Smiod (lang_statement_union_type *s,
30083d8817e4Smiod lang_output_section_statement_type *output_section_statement)
30093d8817e4Smiod {
30103d8817e4Smiod for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
30113d8817e4Smiod {
30123d8817e4Smiod switch (s->header.type)
30133d8817e4Smiod {
30143d8817e4Smiod case lang_wild_statement_enum:
30153d8817e4Smiod walk_wild (&s->wild_statement, check_section_callback,
30163d8817e4Smiod output_section_statement);
30173d8817e4Smiod if (! output_section_statement->all_input_readonly)
30183d8817e4Smiod return;
30193d8817e4Smiod break;
30203d8817e4Smiod case lang_constructors_statement_enum:
30213d8817e4Smiod check_input_sections (constructor_list.head,
30223d8817e4Smiod output_section_statement);
30233d8817e4Smiod if (! output_section_statement->all_input_readonly)
30243d8817e4Smiod return;
30253d8817e4Smiod break;
30263d8817e4Smiod case lang_group_statement_enum:
30273d8817e4Smiod check_input_sections (s->group_statement.children.head,
30283d8817e4Smiod output_section_statement);
30293d8817e4Smiod if (! output_section_statement->all_input_readonly)
30303d8817e4Smiod return;
30313d8817e4Smiod break;
30323d8817e4Smiod default:
30333d8817e4Smiod break;
30343d8817e4Smiod }
30353d8817e4Smiod }
30363d8817e4Smiod }
30373d8817e4Smiod
30383d8817e4Smiod /* Update wildcard statements if needed. */
30393d8817e4Smiod
30403d8817e4Smiod static void
update_wild_statements(lang_statement_union_type * s)30413d8817e4Smiod update_wild_statements (lang_statement_union_type *s)
30423d8817e4Smiod {
30433d8817e4Smiod struct wildcard_list *sec;
30443d8817e4Smiod
30453d8817e4Smiod switch (sort_section)
30463d8817e4Smiod {
30473d8817e4Smiod default:
30483d8817e4Smiod FAIL ();
30493d8817e4Smiod
30503d8817e4Smiod case none:
30513d8817e4Smiod break;
30523d8817e4Smiod
30533d8817e4Smiod case by_name:
30543d8817e4Smiod case by_alignment:
30553d8817e4Smiod for (; s != NULL; s = s->header.next)
30563d8817e4Smiod {
30573d8817e4Smiod switch (s->header.type)
30583d8817e4Smiod {
30593d8817e4Smiod default:
30603d8817e4Smiod break;
30613d8817e4Smiod
30623d8817e4Smiod case lang_wild_statement_enum:
30633d8817e4Smiod sec = s->wild_statement.section_list;
30643d8817e4Smiod if (sec != NULL)
30653d8817e4Smiod {
30663d8817e4Smiod switch (sec->spec.sorted)
30673d8817e4Smiod {
30683d8817e4Smiod case none:
30693d8817e4Smiod sec->spec.sorted = sort_section;
30703d8817e4Smiod break;
30713d8817e4Smiod case by_name:
30723d8817e4Smiod if (sort_section == by_alignment)
30733d8817e4Smiod sec->spec.sorted = by_name_alignment;
30743d8817e4Smiod break;
30753d8817e4Smiod case by_alignment:
30763d8817e4Smiod if (sort_section == by_name)
30773d8817e4Smiod sec->spec.sorted = by_alignment_name;
30783d8817e4Smiod break;
30793d8817e4Smiod default:
30803d8817e4Smiod break;
30813d8817e4Smiod }
30823d8817e4Smiod }
30833d8817e4Smiod break;
30843d8817e4Smiod
30853d8817e4Smiod case lang_constructors_statement_enum:
30863d8817e4Smiod update_wild_statements (constructor_list.head);
30873d8817e4Smiod break;
30883d8817e4Smiod
30893d8817e4Smiod case lang_output_section_statement_enum:
30903d8817e4Smiod update_wild_statements
30913d8817e4Smiod (s->output_section_statement.children.head);
30923d8817e4Smiod break;
30933d8817e4Smiod
30943d8817e4Smiod case lang_group_statement_enum:
30953d8817e4Smiod update_wild_statements (s->group_statement.children.head);
30963d8817e4Smiod break;
30973d8817e4Smiod }
30983d8817e4Smiod }
30993d8817e4Smiod break;
31003d8817e4Smiod }
31013d8817e4Smiod }
31023d8817e4Smiod
31033d8817e4Smiod /* Open input files and attach to output sections. */
31043d8817e4Smiod
31053d8817e4Smiod static void
map_input_to_output_sections(lang_statement_union_type * s,const char * target,lang_output_section_statement_type * os)31063d8817e4Smiod map_input_to_output_sections
31073d8817e4Smiod (lang_statement_union_type *s, const char *target,
31083d8817e4Smiod lang_output_section_statement_type *os)
31093d8817e4Smiod {
31103d8817e4Smiod for (; s != NULL; s = s->header.next)
31113d8817e4Smiod {
31123d8817e4Smiod switch (s->header.type)
31133d8817e4Smiod {
31143d8817e4Smiod case lang_wild_statement_enum:
31153d8817e4Smiod wild (&s->wild_statement, target, os);
31163d8817e4Smiod break;
31173d8817e4Smiod case lang_constructors_statement_enum:
31183d8817e4Smiod map_input_to_output_sections (constructor_list.head,
31193d8817e4Smiod target,
31203d8817e4Smiod os);
31213d8817e4Smiod break;
31223d8817e4Smiod case lang_output_section_statement_enum:
31233d8817e4Smiod if (s->output_section_statement.constraint)
31243d8817e4Smiod {
31253d8817e4Smiod if (s->output_section_statement.constraint != ONLY_IF_RW
31263d8817e4Smiod && s->output_section_statement.constraint != ONLY_IF_RO)
31273d8817e4Smiod break;
31283d8817e4Smiod s->output_section_statement.all_input_readonly = TRUE;
31293d8817e4Smiod check_input_sections (s->output_section_statement.children.head,
31303d8817e4Smiod &s->output_section_statement);
31313d8817e4Smiod if ((s->output_section_statement.all_input_readonly
31323d8817e4Smiod && s->output_section_statement.constraint == ONLY_IF_RW)
31333d8817e4Smiod || (!s->output_section_statement.all_input_readonly
31343d8817e4Smiod && s->output_section_statement.constraint == ONLY_IF_RO))
31353d8817e4Smiod {
31363d8817e4Smiod s->output_section_statement.constraint = -1;
31373d8817e4Smiod break;
31383d8817e4Smiod }
31393d8817e4Smiod }
31403d8817e4Smiod
31413d8817e4Smiod map_input_to_output_sections (s->output_section_statement.children.head,
31423d8817e4Smiod target,
31433d8817e4Smiod &s->output_section_statement);
31443d8817e4Smiod break;
31453d8817e4Smiod case lang_output_statement_enum:
31463d8817e4Smiod break;
31473d8817e4Smiod case lang_target_statement_enum:
31483d8817e4Smiod target = s->target_statement.target;
31493d8817e4Smiod break;
31503d8817e4Smiod case lang_group_statement_enum:
31513d8817e4Smiod map_input_to_output_sections (s->group_statement.children.head,
31523d8817e4Smiod target,
31533d8817e4Smiod os);
31543d8817e4Smiod break;
31553d8817e4Smiod case lang_data_statement_enum:
31563d8817e4Smiod /* Make sure that any sections mentioned in the expression
31573d8817e4Smiod are initialized. */
31583d8817e4Smiod exp_init_os (s->data_statement.exp);
31593d8817e4Smiod if (os != NULL && os->bfd_section == NULL)
31603d8817e4Smiod init_os (os, NULL);
31613d8817e4Smiod /* The output section gets contents, and then we inspect for
31623d8817e4Smiod any flags set in the input script which override any ALLOC. */
31633d8817e4Smiod os->bfd_section->flags |= SEC_HAS_CONTENTS;
31643d8817e4Smiod if (!(os->flags & SEC_NEVER_LOAD))
31653d8817e4Smiod os->bfd_section->flags |= SEC_ALLOC | SEC_LOAD;
31663d8817e4Smiod break;
31673d8817e4Smiod case lang_fill_statement_enum:
31683d8817e4Smiod case lang_input_section_enum:
31693d8817e4Smiod case lang_object_symbols_statement_enum:
31703d8817e4Smiod case lang_reloc_statement_enum:
31713d8817e4Smiod case lang_padding_statement_enum:
31723d8817e4Smiod case lang_input_statement_enum:
31733d8817e4Smiod if (os != NULL && os->bfd_section == NULL)
31743d8817e4Smiod init_os (os, NULL);
31753d8817e4Smiod break;
31763d8817e4Smiod case lang_assignment_statement_enum:
31773d8817e4Smiod if (os != NULL && os->bfd_section == NULL)
31783d8817e4Smiod init_os (os, NULL);
31793d8817e4Smiod
31803d8817e4Smiod /* Make sure that any sections mentioned in the assignment
31813d8817e4Smiod are initialized. */
31823d8817e4Smiod exp_init_os (s->assignment_statement.exp);
31833d8817e4Smiod break;
31843d8817e4Smiod case lang_afile_asection_pair_statement_enum:
31853d8817e4Smiod FAIL ();
31863d8817e4Smiod break;
31873d8817e4Smiod case lang_address_statement_enum:
31883d8817e4Smiod /* Mark the specified section with the supplied address.
31893d8817e4Smiod
31903d8817e4Smiod If this section was actually a segment marker, then the
31913d8817e4Smiod directive is ignored if the linker script explicitly
31923d8817e4Smiod processed the segment marker. Originally, the linker
31933d8817e4Smiod treated segment directives (like -Ttext on the
31943d8817e4Smiod command-line) as section directives. We honor the
31953d8817e4Smiod section directive semantics for backwards compatibilty;
31963d8817e4Smiod linker scripts that do not specifically check for
31973d8817e4Smiod SEGMENT_START automatically get the old semantics. */
31983d8817e4Smiod if (!s->address_statement.segment
31993d8817e4Smiod || !s->address_statement.segment->used)
32003d8817e4Smiod {
32013d8817e4Smiod lang_output_section_statement_type *aos
32023d8817e4Smiod = (lang_output_section_statement_lookup
32033d8817e4Smiod (s->address_statement.section_name));
32043d8817e4Smiod
32053d8817e4Smiod if (aos->bfd_section == NULL)
32063d8817e4Smiod init_os (aos, NULL);
32073d8817e4Smiod aos->addr_tree = s->address_statement.address;
32083d8817e4Smiod }
32093d8817e4Smiod break;
32103d8817e4Smiod }
32113d8817e4Smiod }
32123d8817e4Smiod }
32133d8817e4Smiod
32143d8817e4Smiod /* An output section might have been removed after its statement was
32153d8817e4Smiod added. For example, ldemul_before_allocation can remove dynamic
32163d8817e4Smiod sections if they turn out to be not needed. Clean them up here. */
32173d8817e4Smiod
32183d8817e4Smiod void
strip_excluded_output_sections(void)32193d8817e4Smiod strip_excluded_output_sections (void)
32203d8817e4Smiod {
32213d8817e4Smiod lang_output_section_statement_type *os;
32223d8817e4Smiod
32233d8817e4Smiod /* Run lang_size_sections (if not already done). */
32243d8817e4Smiod if (expld.phase != lang_mark_phase_enum)
32253d8817e4Smiod {
32263d8817e4Smiod expld.phase = lang_mark_phase_enum;
32273d8817e4Smiod expld.dataseg.phase = exp_dataseg_none;
32283d8817e4Smiod one_lang_size_sections_pass (NULL, FALSE);
32293d8817e4Smiod lang_reset_memory_regions ();
32303d8817e4Smiod }
32313d8817e4Smiod
32323d8817e4Smiod for (os = &lang_output_section_statement.head->output_section_statement;
32333d8817e4Smiod os != NULL;
32343d8817e4Smiod os = os->next)
32353d8817e4Smiod {
32363d8817e4Smiod asection *output_section;
32373d8817e4Smiod bfd_boolean exclude;
32383d8817e4Smiod
32393d8817e4Smiod if (os->constraint == -1)
32403d8817e4Smiod continue;
32413d8817e4Smiod
32423d8817e4Smiod output_section = os->bfd_section;
32433d8817e4Smiod if (output_section == NULL)
32443d8817e4Smiod continue;
32453d8817e4Smiod
32463d8817e4Smiod exclude = (output_section->rawsize == 0
32473d8817e4Smiod && (output_section->flags & SEC_KEEP) == 0
32483d8817e4Smiod && !bfd_section_removed_from_list (output_bfd,
32493d8817e4Smiod output_section));
32503d8817e4Smiod
32513d8817e4Smiod /* Some sections have not yet been sized, notably .gnu.version,
32523d8817e4Smiod .dynsym, .dynstr and .hash. These all have SEC_LINKER_CREATED
32533d8817e4Smiod input sections, so don't drop output sections that have such
32543d8817e4Smiod input sections unless they are also marked SEC_EXCLUDE. */
32553d8817e4Smiod if (exclude && output_section->map_head.s != NULL)
32563d8817e4Smiod {
32573d8817e4Smiod asection *s;
32583d8817e4Smiod
32593d8817e4Smiod for (s = output_section->map_head.s; s != NULL; s = s->map_head.s)
32603d8817e4Smiod if ((s->flags & SEC_LINKER_CREATED) != 0
32613d8817e4Smiod && (s->flags & SEC_EXCLUDE) == 0)
32623d8817e4Smiod {
32633d8817e4Smiod exclude = FALSE;
32643d8817e4Smiod break;
32653d8817e4Smiod }
32663d8817e4Smiod }
32673d8817e4Smiod
32683d8817e4Smiod /* TODO: Don't just junk map_head.s, turn them into link_orders. */
32693d8817e4Smiod output_section->map_head.link_order = NULL;
32703d8817e4Smiod output_section->map_tail.link_order = NULL;
32713d8817e4Smiod
32723d8817e4Smiod if (exclude)
32733d8817e4Smiod {
32743d8817e4Smiod /* We don't set bfd_section to NULL since bfd_section of the
32753d8817e4Smiod removed output section statement may still be used. */
32763d8817e4Smiod os->ignored = TRUE;
32773d8817e4Smiod output_section->flags |= SEC_EXCLUDE;
32783d8817e4Smiod bfd_section_list_remove (output_bfd, output_section);
32793d8817e4Smiod output_bfd->section_count--;
32803d8817e4Smiod }
32813d8817e4Smiod }
32823d8817e4Smiod
32833d8817e4Smiod /* Stop future calls to lang_add_section from messing with map_head
32843d8817e4Smiod and map_tail link_order fields. */
32853d8817e4Smiod stripped_excluded_sections = TRUE;
32863d8817e4Smiod }
32873d8817e4Smiod
32883d8817e4Smiod static void
print_output_section_statement(lang_output_section_statement_type * output_section_statement)32893d8817e4Smiod print_output_section_statement
32903d8817e4Smiod (lang_output_section_statement_type *output_section_statement)
32913d8817e4Smiod {
32923d8817e4Smiod asection *section = output_section_statement->bfd_section;
32933d8817e4Smiod int len;
32943d8817e4Smiod
3295*80d8099eSguenther if (output_section_statement->constraint == -1)
3296*80d8099eSguenther return;
3297*80d8099eSguenther
32983d8817e4Smiod if (output_section_statement != abs_output_section)
32993d8817e4Smiod {
33003d8817e4Smiod minfo ("\n%s", output_section_statement->name);
33013d8817e4Smiod
33023d8817e4Smiod if (section != NULL)
33033d8817e4Smiod {
33043d8817e4Smiod print_dot = section->vma;
33053d8817e4Smiod
33063d8817e4Smiod len = strlen (output_section_statement->name);
33073d8817e4Smiod if (len >= SECTION_NAME_MAP_LENGTH - 1)
33083d8817e4Smiod {
33093d8817e4Smiod print_nl ();
33103d8817e4Smiod len = 0;
33113d8817e4Smiod }
33123d8817e4Smiod while (len < SECTION_NAME_MAP_LENGTH)
33133d8817e4Smiod {
33143d8817e4Smiod print_space ();
33153d8817e4Smiod ++len;
33163d8817e4Smiod }
33173d8817e4Smiod
33183d8817e4Smiod minfo ("0x%V %W", section->vma, section->size);
33193d8817e4Smiod
33203d8817e4Smiod if (output_section_statement->load_base != NULL)
33213d8817e4Smiod {
33223d8817e4Smiod bfd_vma addr;
33233d8817e4Smiod
33243d8817e4Smiod addr = exp_get_abs_int (output_section_statement->load_base, 0,
33253d8817e4Smiod "load base");
33263d8817e4Smiod minfo (_(" load address 0x%V"), addr);
33273d8817e4Smiod }
33283d8817e4Smiod }
33293d8817e4Smiod
33303d8817e4Smiod print_nl ();
33313d8817e4Smiod }
33323d8817e4Smiod
33333d8817e4Smiod print_statement_list (output_section_statement->children.head,
33343d8817e4Smiod output_section_statement);
33353d8817e4Smiod }
33363d8817e4Smiod
33373d8817e4Smiod /* Scan for the use of the destination in the right hand side
33383d8817e4Smiod of an expression. In such cases we will not compute the
33393d8817e4Smiod correct expression, since the value of DST that is used on
33403d8817e4Smiod the right hand side will be its final value, not its value
33413d8817e4Smiod just before this expression is evaluated. */
33423d8817e4Smiod
33433d8817e4Smiod static bfd_boolean
scan_for_self_assignment(const char * dst,etree_type * rhs)33443d8817e4Smiod scan_for_self_assignment (const char * dst, etree_type * rhs)
33453d8817e4Smiod {
33463d8817e4Smiod if (rhs == NULL || dst == NULL)
33473d8817e4Smiod return FALSE;
33483d8817e4Smiod
33493d8817e4Smiod switch (rhs->type.node_class)
33503d8817e4Smiod {
33513d8817e4Smiod case etree_binary:
33523d8817e4Smiod return scan_for_self_assignment (dst, rhs->binary.lhs)
33533d8817e4Smiod || scan_for_self_assignment (dst, rhs->binary.rhs);
33543d8817e4Smiod
33553d8817e4Smiod case etree_trinary:
33563d8817e4Smiod return scan_for_self_assignment (dst, rhs->trinary.lhs)
33573d8817e4Smiod || scan_for_self_assignment (dst, rhs->trinary.rhs);
33583d8817e4Smiod
33593d8817e4Smiod case etree_assign:
33603d8817e4Smiod case etree_provided:
33613d8817e4Smiod case etree_provide:
33623d8817e4Smiod if (strcmp (dst, rhs->assign.dst) == 0)
33633d8817e4Smiod return TRUE;
33643d8817e4Smiod return scan_for_self_assignment (dst, rhs->assign.src);
33653d8817e4Smiod
33663d8817e4Smiod case etree_unary:
33673d8817e4Smiod return scan_for_self_assignment (dst, rhs->unary.child);
33683d8817e4Smiod
33693d8817e4Smiod case etree_value:
33703d8817e4Smiod if (rhs->value.str)
33713d8817e4Smiod return strcmp (dst, rhs->value.str) == 0;
33723d8817e4Smiod return FALSE;
33733d8817e4Smiod
33743d8817e4Smiod case etree_name:
33753d8817e4Smiod if (rhs->name.name)
33763d8817e4Smiod return strcmp (dst, rhs->name.name) == 0;
33773d8817e4Smiod return FALSE;
33783d8817e4Smiod
33793d8817e4Smiod default:
33803d8817e4Smiod break;
33813d8817e4Smiod }
33823d8817e4Smiod
33833d8817e4Smiod return FALSE;
33843d8817e4Smiod }
33853d8817e4Smiod
33863d8817e4Smiod
33873d8817e4Smiod static void
print_assignment(lang_assignment_statement_type * assignment,lang_output_section_statement_type * output_section)33883d8817e4Smiod print_assignment (lang_assignment_statement_type *assignment,
33893d8817e4Smiod lang_output_section_statement_type *output_section)
33903d8817e4Smiod {
33913d8817e4Smiod unsigned int i;
33923d8817e4Smiod bfd_boolean is_dot;
33933d8817e4Smiod bfd_boolean computation_is_valid = TRUE;
33943d8817e4Smiod etree_type *tree;
33953d8817e4Smiod
33963d8817e4Smiod for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
33973d8817e4Smiod print_space ();
33983d8817e4Smiod
33993d8817e4Smiod if (assignment->exp->type.node_class == etree_assert)
34003d8817e4Smiod {
34013d8817e4Smiod is_dot = FALSE;
34023d8817e4Smiod tree = assignment->exp->assert_s.child;
34033d8817e4Smiod computation_is_valid = TRUE;
34043d8817e4Smiod }
34053d8817e4Smiod else
34063d8817e4Smiod {
34073d8817e4Smiod const char *dst = assignment->exp->assign.dst;
34083d8817e4Smiod
34093d8817e4Smiod is_dot = (dst[0] == '.' && dst[1] == 0);
34103d8817e4Smiod tree = assignment->exp->assign.src;
34113d8817e4Smiod computation_is_valid = is_dot || (scan_for_self_assignment (dst, tree) == FALSE);
34123d8817e4Smiod }
34133d8817e4Smiod
34143d8817e4Smiod exp_fold_tree (tree, output_section->bfd_section, &print_dot);
34153d8817e4Smiod if (expld.result.valid_p)
34163d8817e4Smiod {
34173d8817e4Smiod bfd_vma value;
34183d8817e4Smiod
34193d8817e4Smiod if (computation_is_valid)
34203d8817e4Smiod {
34213d8817e4Smiod value = expld.result.value;
34223d8817e4Smiod
34233d8817e4Smiod if (expld.result.section)
34243d8817e4Smiod value += expld.result.section->vma;
34253d8817e4Smiod
34263d8817e4Smiod minfo ("0x%V", value);
34273d8817e4Smiod if (is_dot)
34283d8817e4Smiod print_dot = value;
34293d8817e4Smiod }
34303d8817e4Smiod else
34313d8817e4Smiod {
34323d8817e4Smiod struct bfd_link_hash_entry *h;
34333d8817e4Smiod
34343d8817e4Smiod h = bfd_link_hash_lookup (link_info.hash, assignment->exp->assign.dst,
34353d8817e4Smiod FALSE, FALSE, TRUE);
34363d8817e4Smiod if (h)
34373d8817e4Smiod {
34383d8817e4Smiod value = h->u.def.value;
34393d8817e4Smiod
34403d8817e4Smiod if (expld.result.section)
34413d8817e4Smiod value += expld.result.section->vma;
34423d8817e4Smiod
34433d8817e4Smiod minfo ("[0x%V]", value);
34443d8817e4Smiod }
34453d8817e4Smiod else
34463d8817e4Smiod minfo ("[unresolved]");
34473d8817e4Smiod }
34483d8817e4Smiod }
34493d8817e4Smiod else
34503d8817e4Smiod {
34513d8817e4Smiod minfo ("*undef* ");
34523d8817e4Smiod #ifdef BFD64
34533d8817e4Smiod minfo (" ");
34543d8817e4Smiod #endif
34553d8817e4Smiod }
34563d8817e4Smiod
34573d8817e4Smiod minfo (" ");
34583d8817e4Smiod exp_print_tree (assignment->exp);
34593d8817e4Smiod print_nl ();
34603d8817e4Smiod }
34613d8817e4Smiod
34623d8817e4Smiod static void
print_input_statement(lang_input_statement_type * statm)34633d8817e4Smiod print_input_statement (lang_input_statement_type *statm)
34643d8817e4Smiod {
34653d8817e4Smiod if (statm->filename != NULL)
34663d8817e4Smiod {
34673d8817e4Smiod fprintf (config.map_file, "LOAD %s\n", statm->filename);
34683d8817e4Smiod }
34693d8817e4Smiod }
34703d8817e4Smiod
34713d8817e4Smiod /* Print all symbols defined in a particular section. This is called
34723d8817e4Smiod via bfd_link_hash_traverse, or by print_all_symbols. */
34733d8817e4Smiod
34743d8817e4Smiod static bfd_boolean
print_one_symbol(struct bfd_link_hash_entry * hash_entry,void * ptr)34753d8817e4Smiod print_one_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr)
34763d8817e4Smiod {
34773d8817e4Smiod asection *sec = ptr;
34783d8817e4Smiod
34793d8817e4Smiod if ((hash_entry->type == bfd_link_hash_defined
34803d8817e4Smiod || hash_entry->type == bfd_link_hash_defweak)
34813d8817e4Smiod && sec == hash_entry->u.def.section)
34823d8817e4Smiod {
34833d8817e4Smiod int i;
34843d8817e4Smiod
34853d8817e4Smiod for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
34863d8817e4Smiod print_space ();
34873d8817e4Smiod minfo ("0x%V ",
34883d8817e4Smiod (hash_entry->u.def.value
34893d8817e4Smiod + hash_entry->u.def.section->output_offset
34903d8817e4Smiod + hash_entry->u.def.section->output_section->vma));
34913d8817e4Smiod
34923d8817e4Smiod minfo (" %T\n", hash_entry->root.string);
34933d8817e4Smiod }
34943d8817e4Smiod
34953d8817e4Smiod return TRUE;
34963d8817e4Smiod }
34973d8817e4Smiod
34983d8817e4Smiod static void
print_all_symbols(sec)34993d8817e4Smiod print_all_symbols (sec)
35003d8817e4Smiod asection *sec;
35013d8817e4Smiod {
35023d8817e4Smiod struct fat_user_section_struct *ud = get_userdata (sec);
35033d8817e4Smiod struct map_symbol_def *def;
35043d8817e4Smiod
35053d8817e4Smiod if (!ud)
35063d8817e4Smiod return;
35073d8817e4Smiod
35083d8817e4Smiod *ud->map_symbol_def_tail = 0;
35093d8817e4Smiod for (def = ud->map_symbol_def_head; def; def = def->next)
35103d8817e4Smiod print_one_symbol (def->entry, sec);
35113d8817e4Smiod }
35123d8817e4Smiod
35133d8817e4Smiod /* Print information about an input section to the map file. */
35143d8817e4Smiod
35153d8817e4Smiod static void
print_input_section(asection * i)35163d8817e4Smiod print_input_section (asection *i)
35173d8817e4Smiod {
35183d8817e4Smiod bfd_size_type size = i->size;
35193d8817e4Smiod
35203d8817e4Smiod init_opb ();
35213d8817e4Smiod
35223d8817e4Smiod {
35233d8817e4Smiod int len;
35243d8817e4Smiod bfd_vma addr;
35253d8817e4Smiod
35263d8817e4Smiod print_space ();
35273d8817e4Smiod minfo ("%s", i->name);
35283d8817e4Smiod
35293d8817e4Smiod len = 1 + strlen (i->name);
35303d8817e4Smiod if (len >= SECTION_NAME_MAP_LENGTH - 1)
35313d8817e4Smiod {
35323d8817e4Smiod print_nl ();
35333d8817e4Smiod len = 0;
35343d8817e4Smiod }
35353d8817e4Smiod while (len < SECTION_NAME_MAP_LENGTH)
35363d8817e4Smiod {
35373d8817e4Smiod print_space ();
35383d8817e4Smiod ++len;
35393d8817e4Smiod }
35403d8817e4Smiod
35413d8817e4Smiod if (i->output_section != NULL && i->output_section->owner == output_bfd)
35423d8817e4Smiod addr = i->output_section->vma + i->output_offset;
35433d8817e4Smiod else
35443d8817e4Smiod {
35453d8817e4Smiod addr = print_dot;
35463d8817e4Smiod size = 0;
35473d8817e4Smiod }
35483d8817e4Smiod
35493d8817e4Smiod minfo ("0x%V %W %B\n", addr, TO_ADDR (size), i->owner);
35503d8817e4Smiod
35513d8817e4Smiod if (size != i->rawsize && i->rawsize != 0)
35523d8817e4Smiod {
35533d8817e4Smiod len = SECTION_NAME_MAP_LENGTH + 3;
35543d8817e4Smiod #ifdef BFD64
35553d8817e4Smiod len += 16;
35563d8817e4Smiod #else
35573d8817e4Smiod len += 8;
35583d8817e4Smiod #endif
35593d8817e4Smiod while (len > 0)
35603d8817e4Smiod {
35613d8817e4Smiod print_space ();
35623d8817e4Smiod --len;
35633d8817e4Smiod }
35643d8817e4Smiod
35653d8817e4Smiod minfo (_("%W (size before relaxing)\n"), i->rawsize);
35663d8817e4Smiod }
35673d8817e4Smiod
35683d8817e4Smiod if (i->output_section != NULL && i->output_section->owner == output_bfd)
35693d8817e4Smiod {
3570b8417449Sstefan if (link_info.reduce_memory_overheads)
35713d8817e4Smiod bfd_link_hash_traverse (link_info.hash, print_one_symbol, i);
35723d8817e4Smiod else
35733d8817e4Smiod print_all_symbols (i);
35743d8817e4Smiod
35753d8817e4Smiod print_dot = addr + TO_ADDR (size);
35763d8817e4Smiod }
35773d8817e4Smiod }
35783d8817e4Smiod }
35793d8817e4Smiod
35803d8817e4Smiod static void
print_fill_statement(lang_fill_statement_type * fill)35813d8817e4Smiod print_fill_statement (lang_fill_statement_type *fill)
35823d8817e4Smiod {
35833d8817e4Smiod size_t size;
35843d8817e4Smiod unsigned char *p;
35853d8817e4Smiod fputs (" FILL mask 0x", config.map_file);
35863d8817e4Smiod for (p = fill->fill->data, size = fill->fill->size; size != 0; p++, size--)
35873d8817e4Smiod fprintf (config.map_file, "%02x", *p);
35883d8817e4Smiod fputs ("\n", config.map_file);
35893d8817e4Smiod }
35903d8817e4Smiod
35913d8817e4Smiod static void
print_data_statement(lang_data_statement_type * data)35923d8817e4Smiod print_data_statement (lang_data_statement_type *data)
35933d8817e4Smiod {
35943d8817e4Smiod int i;
35953d8817e4Smiod bfd_vma addr;
35963d8817e4Smiod bfd_size_type size;
35973d8817e4Smiod const char *name;
35983d8817e4Smiod
35993d8817e4Smiod init_opb ();
36003d8817e4Smiod for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
36013d8817e4Smiod print_space ();
36023d8817e4Smiod
36033d8817e4Smiod addr = data->output_offset;
36043d8817e4Smiod if (data->output_section != NULL)
36053d8817e4Smiod addr += data->output_section->vma;
36063d8817e4Smiod
36073d8817e4Smiod switch (data->type)
36083d8817e4Smiod {
36093d8817e4Smiod default:
36103d8817e4Smiod abort ();
36113d8817e4Smiod case BYTE:
36123d8817e4Smiod size = BYTE_SIZE;
36133d8817e4Smiod name = "BYTE";
36143d8817e4Smiod break;
36153d8817e4Smiod case SHORT:
36163d8817e4Smiod size = SHORT_SIZE;
36173d8817e4Smiod name = "SHORT";
36183d8817e4Smiod break;
36193d8817e4Smiod case LONG:
36203d8817e4Smiod size = LONG_SIZE;
36213d8817e4Smiod name = "LONG";
36223d8817e4Smiod break;
36233d8817e4Smiod case QUAD:
36243d8817e4Smiod size = QUAD_SIZE;
36253d8817e4Smiod name = "QUAD";
36263d8817e4Smiod break;
36273d8817e4Smiod case SQUAD:
36283d8817e4Smiod size = QUAD_SIZE;
36293d8817e4Smiod name = "SQUAD";
36303d8817e4Smiod break;
36313d8817e4Smiod }
36323d8817e4Smiod
36333d8817e4Smiod minfo ("0x%V %W %s 0x%v", addr, size, name, data->value);
36343d8817e4Smiod
36353d8817e4Smiod if (data->exp->type.node_class != etree_value)
36363d8817e4Smiod {
36373d8817e4Smiod print_space ();
36383d8817e4Smiod exp_print_tree (data->exp);
36393d8817e4Smiod }
36403d8817e4Smiod
36413d8817e4Smiod print_nl ();
36423d8817e4Smiod
36433d8817e4Smiod print_dot = addr + TO_ADDR (size);
36443d8817e4Smiod }
36453d8817e4Smiod
36463d8817e4Smiod /* Print an address statement. These are generated by options like
36473d8817e4Smiod -Ttext. */
36483d8817e4Smiod
36493d8817e4Smiod static void
print_address_statement(lang_address_statement_type * address)36503d8817e4Smiod print_address_statement (lang_address_statement_type *address)
36513d8817e4Smiod {
36523d8817e4Smiod minfo (_("Address of section %s set to "), address->section_name);
36533d8817e4Smiod exp_print_tree (address->address);
36543d8817e4Smiod print_nl ();
36553d8817e4Smiod }
36563d8817e4Smiod
36573d8817e4Smiod /* Print a reloc statement. */
36583d8817e4Smiod
36593d8817e4Smiod static void
print_reloc_statement(lang_reloc_statement_type * reloc)36603d8817e4Smiod print_reloc_statement (lang_reloc_statement_type *reloc)
36613d8817e4Smiod {
36623d8817e4Smiod int i;
36633d8817e4Smiod bfd_vma addr;
36643d8817e4Smiod bfd_size_type size;
36653d8817e4Smiod
36663d8817e4Smiod init_opb ();
36673d8817e4Smiod for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
36683d8817e4Smiod print_space ();
36693d8817e4Smiod
36703d8817e4Smiod addr = reloc->output_offset;
36713d8817e4Smiod if (reloc->output_section != NULL)
36723d8817e4Smiod addr += reloc->output_section->vma;
36733d8817e4Smiod
36743d8817e4Smiod size = bfd_get_reloc_size (reloc->howto);
36753d8817e4Smiod
36763d8817e4Smiod minfo ("0x%V %W RELOC %s ", addr, size, reloc->howto->name);
36773d8817e4Smiod
36783d8817e4Smiod if (reloc->name != NULL)
36793d8817e4Smiod minfo ("%s+", reloc->name);
36803d8817e4Smiod else
36813d8817e4Smiod minfo ("%s+", reloc->section->name);
36823d8817e4Smiod
36833d8817e4Smiod exp_print_tree (reloc->addend_exp);
36843d8817e4Smiod
36853d8817e4Smiod print_nl ();
36863d8817e4Smiod
36873d8817e4Smiod print_dot = addr + TO_ADDR (size);
36883d8817e4Smiod }
36893d8817e4Smiod
36903d8817e4Smiod static void
print_padding_statement(lang_padding_statement_type * s)36913d8817e4Smiod print_padding_statement (lang_padding_statement_type *s)
36923d8817e4Smiod {
36933d8817e4Smiod int len;
36943d8817e4Smiod bfd_vma addr;
36953d8817e4Smiod
36963d8817e4Smiod init_opb ();
36973d8817e4Smiod minfo (" *fill*");
36983d8817e4Smiod
36993d8817e4Smiod len = sizeof " *fill*" - 1;
37003d8817e4Smiod while (len < SECTION_NAME_MAP_LENGTH)
37013d8817e4Smiod {
37023d8817e4Smiod print_space ();
37033d8817e4Smiod ++len;
37043d8817e4Smiod }
37053d8817e4Smiod
37063d8817e4Smiod addr = s->output_offset;
37073d8817e4Smiod if (s->output_section != NULL)
37083d8817e4Smiod addr += s->output_section->vma;
37093d8817e4Smiod minfo ("0x%V %W ", addr, (bfd_vma) s->size);
37103d8817e4Smiod
37113d8817e4Smiod if (s->fill->size != 0)
37123d8817e4Smiod {
37133d8817e4Smiod size_t size;
37143d8817e4Smiod unsigned char *p;
37153d8817e4Smiod for (p = s->fill->data, size = s->fill->size; size != 0; p++, size--)
37163d8817e4Smiod fprintf (config.map_file, "%02x", *p);
37173d8817e4Smiod }
37183d8817e4Smiod
37193d8817e4Smiod print_nl ();
37203d8817e4Smiod
37213d8817e4Smiod print_dot = addr + TO_ADDR (s->size);
37223d8817e4Smiod }
37233d8817e4Smiod
37243d8817e4Smiod static void
print_wild_statement(lang_wild_statement_type * w,lang_output_section_statement_type * os)37253d8817e4Smiod print_wild_statement (lang_wild_statement_type *w,
37263d8817e4Smiod lang_output_section_statement_type *os)
37273d8817e4Smiod {
37283d8817e4Smiod struct wildcard_list *sec;
37293d8817e4Smiod
37303d8817e4Smiod print_space ();
37313d8817e4Smiod
37323d8817e4Smiod if (w->filenames_sorted)
37333d8817e4Smiod minfo ("SORT(");
37343d8817e4Smiod if (w->filename != NULL)
37353d8817e4Smiod minfo ("%s", w->filename);
37363d8817e4Smiod else
37373d8817e4Smiod minfo ("*");
37383d8817e4Smiod if (w->filenames_sorted)
37393d8817e4Smiod minfo (")");
37403d8817e4Smiod
37413d8817e4Smiod minfo ("(");
37423d8817e4Smiod for (sec = w->section_list; sec; sec = sec->next)
37433d8817e4Smiod {
37443d8817e4Smiod if (sec->spec.sorted)
37453d8817e4Smiod minfo ("SORT(");
37463d8817e4Smiod if (sec->spec.exclude_name_list != NULL)
37473d8817e4Smiod {
37483d8817e4Smiod name_list *tmp;
37493d8817e4Smiod minfo ("EXCLUDE_FILE(%s", sec->spec.exclude_name_list->name);
37503d8817e4Smiod for (tmp = sec->spec.exclude_name_list->next; tmp; tmp = tmp->next)
37513d8817e4Smiod minfo (" %s", tmp->name);
37523d8817e4Smiod minfo (") ");
37533d8817e4Smiod }
37543d8817e4Smiod if (sec->spec.name != NULL)
37553d8817e4Smiod minfo ("%s", sec->spec.name);
37563d8817e4Smiod else
37573d8817e4Smiod minfo ("*");
37583d8817e4Smiod if (sec->spec.sorted)
37593d8817e4Smiod minfo (")");
37603d8817e4Smiod if (sec->next)
37613d8817e4Smiod minfo (" ");
37623d8817e4Smiod }
37633d8817e4Smiod minfo (")");
37643d8817e4Smiod
37653d8817e4Smiod print_nl ();
37663d8817e4Smiod
37673d8817e4Smiod print_statement_list (w->children.head, os);
37683d8817e4Smiod }
37693d8817e4Smiod
37703d8817e4Smiod /* Print a group statement. */
37713d8817e4Smiod
37723d8817e4Smiod static void
print_group(lang_group_statement_type * s,lang_output_section_statement_type * os)37733d8817e4Smiod print_group (lang_group_statement_type *s,
37743d8817e4Smiod lang_output_section_statement_type *os)
37753d8817e4Smiod {
37763d8817e4Smiod fprintf (config.map_file, "START GROUP\n");
37773d8817e4Smiod print_statement_list (s->children.head, os);
37783d8817e4Smiod fprintf (config.map_file, "END GROUP\n");
37793d8817e4Smiod }
37803d8817e4Smiod
37813d8817e4Smiod /* Print the list of statements in S.
37823d8817e4Smiod This can be called for any statement type. */
37833d8817e4Smiod
37843d8817e4Smiod static void
print_statement_list(lang_statement_union_type * s,lang_output_section_statement_type * os)37853d8817e4Smiod print_statement_list (lang_statement_union_type *s,
37863d8817e4Smiod lang_output_section_statement_type *os)
37873d8817e4Smiod {
37883d8817e4Smiod while (s != NULL)
37893d8817e4Smiod {
37903d8817e4Smiod print_statement (s, os);
37913d8817e4Smiod s = s->header.next;
37923d8817e4Smiod }
37933d8817e4Smiod }
37943d8817e4Smiod
37953d8817e4Smiod /* Print the first statement in statement list S.
37963d8817e4Smiod This can be called for any statement type. */
37973d8817e4Smiod
37983d8817e4Smiod static void
print_statement(lang_statement_union_type * s,lang_output_section_statement_type * os)37993d8817e4Smiod print_statement (lang_statement_union_type *s,
38003d8817e4Smiod lang_output_section_statement_type *os)
38013d8817e4Smiod {
38023d8817e4Smiod switch (s->header.type)
38033d8817e4Smiod {
38043d8817e4Smiod default:
38053d8817e4Smiod fprintf (config.map_file, _("Fail with %d\n"), s->header.type);
38063d8817e4Smiod FAIL ();
38073d8817e4Smiod break;
38083d8817e4Smiod case lang_constructors_statement_enum:
38093d8817e4Smiod if (constructor_list.head != NULL)
38103d8817e4Smiod {
38113d8817e4Smiod if (constructors_sorted)
38123d8817e4Smiod minfo (" SORT (CONSTRUCTORS)\n");
38133d8817e4Smiod else
38143d8817e4Smiod minfo (" CONSTRUCTORS\n");
38153d8817e4Smiod print_statement_list (constructor_list.head, os);
38163d8817e4Smiod }
38173d8817e4Smiod break;
38183d8817e4Smiod case lang_wild_statement_enum:
38193d8817e4Smiod print_wild_statement (&s->wild_statement, os);
38203d8817e4Smiod break;
38213d8817e4Smiod case lang_address_statement_enum:
38223d8817e4Smiod print_address_statement (&s->address_statement);
38233d8817e4Smiod break;
38243d8817e4Smiod case lang_object_symbols_statement_enum:
38253d8817e4Smiod minfo (" CREATE_OBJECT_SYMBOLS\n");
38263d8817e4Smiod break;
38273d8817e4Smiod case lang_fill_statement_enum:
38283d8817e4Smiod print_fill_statement (&s->fill_statement);
38293d8817e4Smiod break;
38303d8817e4Smiod case lang_data_statement_enum:
38313d8817e4Smiod print_data_statement (&s->data_statement);
38323d8817e4Smiod break;
38333d8817e4Smiod case lang_reloc_statement_enum:
38343d8817e4Smiod print_reloc_statement (&s->reloc_statement);
38353d8817e4Smiod break;
38363d8817e4Smiod case lang_input_section_enum:
38373d8817e4Smiod print_input_section (s->input_section.section);
38383d8817e4Smiod break;
38393d8817e4Smiod case lang_padding_statement_enum:
38403d8817e4Smiod print_padding_statement (&s->padding_statement);
38413d8817e4Smiod break;
38423d8817e4Smiod case lang_output_section_statement_enum:
38433d8817e4Smiod print_output_section_statement (&s->output_section_statement);
38443d8817e4Smiod break;
38453d8817e4Smiod case lang_assignment_statement_enum:
38463d8817e4Smiod print_assignment (&s->assignment_statement, os);
38473d8817e4Smiod break;
38483d8817e4Smiod case lang_target_statement_enum:
38493d8817e4Smiod fprintf (config.map_file, "TARGET(%s)\n", s->target_statement.target);
38503d8817e4Smiod break;
38513d8817e4Smiod case lang_output_statement_enum:
38523d8817e4Smiod minfo ("OUTPUT(%s", s->output_statement.name);
38533d8817e4Smiod if (output_target != NULL)
38543d8817e4Smiod minfo (" %s", output_target);
38553d8817e4Smiod minfo (")\n");
38563d8817e4Smiod break;
38573d8817e4Smiod case lang_input_statement_enum:
38583d8817e4Smiod print_input_statement (&s->input_statement);
38593d8817e4Smiod break;
38603d8817e4Smiod case lang_group_statement_enum:
38613d8817e4Smiod print_group (&s->group_statement, os);
38623d8817e4Smiod break;
38633d8817e4Smiod case lang_afile_asection_pair_statement_enum:
38643d8817e4Smiod FAIL ();
38653d8817e4Smiod break;
38663d8817e4Smiod }
38673d8817e4Smiod }
38683d8817e4Smiod
38693d8817e4Smiod static void
print_statements(void)38703d8817e4Smiod print_statements (void)
38713d8817e4Smiod {
38723d8817e4Smiod print_statement_list (statement_list.head, abs_output_section);
38733d8817e4Smiod }
38743d8817e4Smiod
38753d8817e4Smiod /* Print the first N statements in statement list S to STDERR.
38763d8817e4Smiod If N == 0, nothing is printed.
38773d8817e4Smiod If N < 0, the entire list is printed.
38783d8817e4Smiod Intended to be called from GDB. */
38793d8817e4Smiod
38803d8817e4Smiod void
dprint_statement(lang_statement_union_type * s,int n)38813d8817e4Smiod dprint_statement (lang_statement_union_type *s, int n)
38823d8817e4Smiod {
38833d8817e4Smiod FILE *map_save = config.map_file;
38843d8817e4Smiod
38853d8817e4Smiod config.map_file = stderr;
38863d8817e4Smiod
38873d8817e4Smiod if (n < 0)
38883d8817e4Smiod print_statement_list (s, abs_output_section);
38893d8817e4Smiod else
38903d8817e4Smiod {
38913d8817e4Smiod while (s && --n >= 0)
38923d8817e4Smiod {
38933d8817e4Smiod print_statement (s, abs_output_section);
38943d8817e4Smiod s = s->header.next;
38953d8817e4Smiod }
38963d8817e4Smiod }
38973d8817e4Smiod
38983d8817e4Smiod config.map_file = map_save;
38993d8817e4Smiod }
39003d8817e4Smiod
39013d8817e4Smiod static void
insert_pad(lang_statement_union_type ** ptr,fill_type * fill,unsigned int alignment_needed,asection * output_section,bfd_vma dot)39023d8817e4Smiod insert_pad (lang_statement_union_type **ptr,
39033d8817e4Smiod fill_type *fill,
39043d8817e4Smiod unsigned int alignment_needed,
39053d8817e4Smiod asection *output_section,
39063d8817e4Smiod bfd_vma dot)
39073d8817e4Smiod {
39083d8817e4Smiod static fill_type zero_fill = { 1, { 0 } };
39093d8817e4Smiod lang_statement_union_type *pad = NULL;
39103d8817e4Smiod
39113d8817e4Smiod if (ptr != &statement_list.head)
39123d8817e4Smiod pad = ((lang_statement_union_type *)
39133d8817e4Smiod ((char *) ptr - offsetof (lang_statement_union_type, header.next)));
39143d8817e4Smiod if (pad != NULL
39153d8817e4Smiod && pad->header.type == lang_padding_statement_enum
39163d8817e4Smiod && pad->padding_statement.output_section == output_section)
39173d8817e4Smiod {
39183d8817e4Smiod /* Use the existing pad statement. */
39193d8817e4Smiod }
39203d8817e4Smiod else if ((pad = *ptr) != NULL
39213d8817e4Smiod && pad->header.type == lang_padding_statement_enum
39223d8817e4Smiod && pad->padding_statement.output_section == output_section)
39233d8817e4Smiod {
39243d8817e4Smiod /* Use the existing pad statement. */
39253d8817e4Smiod }
39263d8817e4Smiod else
39273d8817e4Smiod {
39283d8817e4Smiod /* Make a new padding statement, linked into existing chain. */
39293d8817e4Smiod pad = stat_alloc (sizeof (lang_padding_statement_type));
39303d8817e4Smiod pad->header.next = *ptr;
39313d8817e4Smiod *ptr = pad;
39323d8817e4Smiod pad->header.type = lang_padding_statement_enum;
39333d8817e4Smiod pad->padding_statement.output_section = output_section;
39343d8817e4Smiod if (fill == NULL)
39353d8817e4Smiod fill = &zero_fill;
39363d8817e4Smiod pad->padding_statement.fill = fill;
39373d8817e4Smiod }
39383d8817e4Smiod pad->padding_statement.output_offset = dot - output_section->vma;
39393d8817e4Smiod pad->padding_statement.size = alignment_needed;
39403d8817e4Smiod output_section->size += alignment_needed;
39413d8817e4Smiod }
39423d8817e4Smiod
39433d8817e4Smiod /* Work out how much this section will move the dot point. */
39443d8817e4Smiod
39453d8817e4Smiod static bfd_vma
size_input_section(lang_statement_union_type ** this_ptr,lang_output_section_statement_type * output_section_statement,fill_type * fill,bfd_vma dot)39463d8817e4Smiod size_input_section
39473d8817e4Smiod (lang_statement_union_type **this_ptr,
39483d8817e4Smiod lang_output_section_statement_type *output_section_statement,
39493d8817e4Smiod fill_type *fill,
39503d8817e4Smiod bfd_vma dot)
39513d8817e4Smiod {
39523d8817e4Smiod lang_input_section_type *is = &((*this_ptr)->input_section);
39533d8817e4Smiod asection *i = is->section;
39543d8817e4Smiod
39553d8817e4Smiod if (!((lang_input_statement_type *) i->owner->usrdata)->just_syms_flag
39563d8817e4Smiod && (i->flags & SEC_EXCLUDE) == 0)
39573d8817e4Smiod {
39583d8817e4Smiod unsigned int alignment_needed;
39593d8817e4Smiod asection *o;
39603d8817e4Smiod
39613d8817e4Smiod /* Align this section first to the input sections requirement,
39623d8817e4Smiod then to the output section's requirement. If this alignment
39633d8817e4Smiod is greater than any seen before, then record it too. Perform
39643d8817e4Smiod the alignment by inserting a magic 'padding' statement. */
39653d8817e4Smiod
39663d8817e4Smiod if (output_section_statement->subsection_alignment != -1)
39673d8817e4Smiod i->alignment_power = output_section_statement->subsection_alignment;
39683d8817e4Smiod
39693d8817e4Smiod o = output_section_statement->bfd_section;
39703d8817e4Smiod if (o->alignment_power < i->alignment_power)
39713d8817e4Smiod o->alignment_power = i->alignment_power;
39723d8817e4Smiod
39733d8817e4Smiod alignment_needed = align_power (dot, i->alignment_power) - dot;
39743d8817e4Smiod
39753d8817e4Smiod if (alignment_needed != 0)
39763d8817e4Smiod {
39773d8817e4Smiod insert_pad (this_ptr, fill, TO_SIZE (alignment_needed), o, dot);
39783d8817e4Smiod dot += alignment_needed;
39793d8817e4Smiod }
39803d8817e4Smiod
39813d8817e4Smiod /* Remember where in the output section this input section goes. */
39823d8817e4Smiod
39833d8817e4Smiod i->output_offset = dot - o->vma;
39843d8817e4Smiod
39853d8817e4Smiod /* Mark how big the output section must be to contain this now. */
39863d8817e4Smiod dot += TO_ADDR (i->size);
39873d8817e4Smiod o->size = TO_SIZE (dot - o->vma);
39883d8817e4Smiod }
39893d8817e4Smiod else
39903d8817e4Smiod {
39913d8817e4Smiod i->output_offset = i->vma - output_section_statement->bfd_section->vma;
39923d8817e4Smiod }
39933d8817e4Smiod
39943d8817e4Smiod return dot;
39953d8817e4Smiod }
39963d8817e4Smiod
39973d8817e4Smiod static int
sort_sections_by_lma(const void * arg1,const void * arg2)39983d8817e4Smiod sort_sections_by_lma (const void *arg1, const void *arg2)
39993d8817e4Smiod {
40003d8817e4Smiod const asection *sec1 = *(const asection **) arg1;
40013d8817e4Smiod const asection *sec2 = *(const asection **) arg2;
40023d8817e4Smiod
40033d8817e4Smiod if (bfd_section_lma (sec1->owner, sec1)
40043d8817e4Smiod < bfd_section_lma (sec2->owner, sec2))
40053d8817e4Smiod return -1;
40063d8817e4Smiod else if (bfd_section_lma (sec1->owner, sec1)
40073d8817e4Smiod > bfd_section_lma (sec2->owner, sec2))
40083d8817e4Smiod return 1;
40093d8817e4Smiod
40103d8817e4Smiod return 0;
40113d8817e4Smiod }
40123d8817e4Smiod
40133d8817e4Smiod #define IGNORE_SECTION(s) \
40143d8817e4Smiod ((s->flags & SEC_NEVER_LOAD) != 0 \
40153d8817e4Smiod || (s->flags & SEC_ALLOC) == 0 \
40163d8817e4Smiod || ((s->flags & SEC_THREAD_LOCAL) != 0 \
40173d8817e4Smiod && (s->flags & SEC_LOAD) == 0))
40183d8817e4Smiod
40193d8817e4Smiod /* Check to see if any allocated sections overlap with other allocated
40203d8817e4Smiod sections. This can happen if a linker script specifies the output
40213d8817e4Smiod section addresses of the two sections. */
40223d8817e4Smiod
40233d8817e4Smiod static void
lang_check_section_addresses(void)40243d8817e4Smiod lang_check_section_addresses (void)
40253d8817e4Smiod {
40263d8817e4Smiod asection *s, *os;
40273d8817e4Smiod asection **sections, **spp;
40283d8817e4Smiod unsigned int count;
40293d8817e4Smiod bfd_vma s_start;
40303d8817e4Smiod bfd_vma s_end;
40313d8817e4Smiod bfd_vma os_start;
40323d8817e4Smiod bfd_vma os_end;
40333d8817e4Smiod bfd_size_type amt;
40343d8817e4Smiod
40353d8817e4Smiod if (bfd_count_sections (output_bfd) <= 1)
40363d8817e4Smiod return;
40373d8817e4Smiod
40383d8817e4Smiod amt = bfd_count_sections (output_bfd) * sizeof (asection *);
40393d8817e4Smiod sections = xmalloc (amt);
40403d8817e4Smiod
40413d8817e4Smiod /* Scan all sections in the output list. */
40423d8817e4Smiod count = 0;
40433d8817e4Smiod for (s = output_bfd->sections; s != NULL; s = s->next)
40443d8817e4Smiod {
40453d8817e4Smiod /* Only consider loadable sections with real contents. */
40463d8817e4Smiod if (IGNORE_SECTION (s) || s->size == 0)
40473d8817e4Smiod continue;
40483d8817e4Smiod
40493d8817e4Smiod sections[count] = s;
40503d8817e4Smiod count++;
40513d8817e4Smiod }
40523d8817e4Smiod
40533d8817e4Smiod if (count <= 1)
40543d8817e4Smiod return;
40553d8817e4Smiod
40563d8817e4Smiod qsort (sections, (size_t) count, sizeof (asection *),
40573d8817e4Smiod sort_sections_by_lma);
40583d8817e4Smiod
40593d8817e4Smiod spp = sections;
40603d8817e4Smiod s = *spp++;
40613d8817e4Smiod s_start = bfd_section_lma (output_bfd, s);
40623d8817e4Smiod s_end = s_start + TO_ADDR (s->size) - 1;
40633d8817e4Smiod for (count--; count; count--)
40643d8817e4Smiod {
40653d8817e4Smiod /* We must check the sections' LMA addresses not their VMA
40663d8817e4Smiod addresses because overlay sections can have overlapping VMAs
40673d8817e4Smiod but they must have distinct LMAs. */
40683d8817e4Smiod os = s;
40693d8817e4Smiod os_start = s_start;
40703d8817e4Smiod os_end = s_end;
40713d8817e4Smiod s = *spp++;
40723d8817e4Smiod s_start = bfd_section_lma (output_bfd, s);
40733d8817e4Smiod s_end = s_start + TO_ADDR (s->size) - 1;
40743d8817e4Smiod
40753d8817e4Smiod /* Look for an overlap. */
40763d8817e4Smiod if (s_end >= os_start && s_start <= os_end)
40773d8817e4Smiod einfo (_("%X%P: section %s [%V -> %V] overlaps section %s [%V -> %V]\n"),
40783d8817e4Smiod s->name, s_start, s_end, os->name, os_start, os_end);
40793d8817e4Smiod }
40803d8817e4Smiod
40813d8817e4Smiod free (sections);
40823d8817e4Smiod }
40833d8817e4Smiod
40843d8817e4Smiod /* Make sure the new address is within the region. We explicitly permit the
40853d8817e4Smiod current address to be at the exact end of the region when the address is
40863d8817e4Smiod non-zero, in case the region is at the end of addressable memory and the
40873d8817e4Smiod calculation wraps around. */
40883d8817e4Smiod
40893d8817e4Smiod static void
os_region_check(lang_output_section_statement_type * os,lang_memory_region_type * region,etree_type * tree,bfd_vma base)40903d8817e4Smiod os_region_check (lang_output_section_statement_type *os,
40913d8817e4Smiod lang_memory_region_type *region,
40923d8817e4Smiod etree_type *tree,
40933d8817e4Smiod bfd_vma base)
40943d8817e4Smiod {
40953d8817e4Smiod if ((region->current < region->origin
40963d8817e4Smiod || (region->current - region->origin > region->length))
40973d8817e4Smiod && ((region->current != region->origin + region->length)
40983d8817e4Smiod || base == 0))
40993d8817e4Smiod {
41003d8817e4Smiod if (tree != NULL)
41013d8817e4Smiod {
41023d8817e4Smiod einfo (_("%X%P: address 0x%v of %B section %s"
41033d8817e4Smiod " is not within region %s\n"),
41043d8817e4Smiod region->current,
41053d8817e4Smiod os->bfd_section->owner,
41063d8817e4Smiod os->bfd_section->name,
41073d8817e4Smiod region->name);
41083d8817e4Smiod }
41093d8817e4Smiod else
41103d8817e4Smiod {
41113d8817e4Smiod einfo (_("%X%P: region %s is full (%B section %s)\n"),
41123d8817e4Smiod region->name,
41133d8817e4Smiod os->bfd_section->owner,
41143d8817e4Smiod os->bfd_section->name);
41153d8817e4Smiod }
41163d8817e4Smiod /* Reset the region pointer. */
41173d8817e4Smiod region->current = region->origin;
41183d8817e4Smiod }
41193d8817e4Smiod }
41203d8817e4Smiod
41213d8817e4Smiod /* Set the sizes for all the output sections. */
41223d8817e4Smiod
41233d8817e4Smiod static bfd_vma
lang_size_sections_1(lang_statement_union_type * s,lang_output_section_statement_type * output_section_statement,lang_statement_union_type ** prev,fill_type * fill,bfd_vma dot,bfd_boolean * relax,bfd_boolean check_regions)41243d8817e4Smiod lang_size_sections_1
41253d8817e4Smiod (lang_statement_union_type *s,
41263d8817e4Smiod lang_output_section_statement_type *output_section_statement,
41273d8817e4Smiod lang_statement_union_type **prev,
41283d8817e4Smiod fill_type *fill,
41293d8817e4Smiod bfd_vma dot,
41303d8817e4Smiod bfd_boolean *relax,
41313d8817e4Smiod bfd_boolean check_regions)
41323d8817e4Smiod {
41333d8817e4Smiod /* Size up the sections from their constituent parts. */
41343d8817e4Smiod for (; s != NULL; s = s->header.next)
41353d8817e4Smiod {
41363d8817e4Smiod switch (s->header.type)
41373d8817e4Smiod {
41383d8817e4Smiod case lang_output_section_statement_enum:
41393d8817e4Smiod {
41403d8817e4Smiod bfd_vma newdot, after;
41413d8817e4Smiod lang_output_section_statement_type *os;
41423d8817e4Smiod
41433d8817e4Smiod os = &s->output_section_statement;
41443d8817e4Smiod if (os->addr_tree != NULL)
41453d8817e4Smiod {
41463d8817e4Smiod os->processed = FALSE;
41473d8817e4Smiod exp_fold_tree (os->addr_tree, bfd_abs_section_ptr, &dot);
41483d8817e4Smiod
41493d8817e4Smiod if (!expld.result.valid_p
41503d8817e4Smiod && expld.phase != lang_mark_phase_enum)
41513d8817e4Smiod einfo (_("%F%S: non constant or forward reference"
41523d8817e4Smiod " address expression for section %s\n"),
41533d8817e4Smiod os->name);
41543d8817e4Smiod
41553d8817e4Smiod dot = expld.result.value + expld.result.section->vma;
41563d8817e4Smiod }
41573d8817e4Smiod
41583d8817e4Smiod if (os->bfd_section == NULL)
41593d8817e4Smiod /* This section was removed or never actually created. */
41603d8817e4Smiod break;
41613d8817e4Smiod
41623d8817e4Smiod /* If this is a COFF shared library section, use the size and
41633d8817e4Smiod address from the input section. FIXME: This is COFF
41643d8817e4Smiod specific; it would be cleaner if there were some other way
41653d8817e4Smiod to do this, but nothing simple comes to mind. */
41663d8817e4Smiod if ((bfd_get_flavour (output_bfd) == bfd_target_ecoff_flavour
41673d8817e4Smiod || bfd_get_flavour (output_bfd) == bfd_target_coff_flavour)
41683d8817e4Smiod && (os->bfd_section->flags & SEC_COFF_SHARED_LIBRARY) != 0)
41693d8817e4Smiod {
41703d8817e4Smiod asection *input;
41713d8817e4Smiod
41723d8817e4Smiod if (os->children.head == NULL
41733d8817e4Smiod || os->children.head->header.next != NULL
41743d8817e4Smiod || (os->children.head->header.type
41753d8817e4Smiod != lang_input_section_enum))
41763d8817e4Smiod einfo (_("%P%X: Internal error on COFF shared library"
41773d8817e4Smiod " section %s\n"), os->name);
41783d8817e4Smiod
41793d8817e4Smiod input = os->children.head->input_section.section;
41803d8817e4Smiod bfd_set_section_vma (os->bfd_section->owner,
41813d8817e4Smiod os->bfd_section,
41823d8817e4Smiod bfd_section_vma (input->owner, input));
41833d8817e4Smiod os->bfd_section->size = input->size;
41843d8817e4Smiod break;
41853d8817e4Smiod }
41863d8817e4Smiod
41873d8817e4Smiod newdot = dot;
41883d8817e4Smiod if (bfd_is_abs_section (os->bfd_section))
41893d8817e4Smiod {
41903d8817e4Smiod /* No matter what happens, an abs section starts at zero. */
41913d8817e4Smiod ASSERT (os->bfd_section->vma == 0);
41923d8817e4Smiod }
41933d8817e4Smiod else
41943d8817e4Smiod {
41953d8817e4Smiod int align;
41963d8817e4Smiod
41973d8817e4Smiod if (os->addr_tree == NULL)
41983d8817e4Smiod {
41993d8817e4Smiod /* No address specified for this section, get one
42003d8817e4Smiod from the region specification. */
42013d8817e4Smiod if (os->region == NULL
42023d8817e4Smiod || ((os->bfd_section->flags & (SEC_ALLOC | SEC_LOAD))
42033d8817e4Smiod && os->region->name[0] == '*'
42043d8817e4Smiod && strcmp (os->region->name,
42053d8817e4Smiod DEFAULT_MEMORY_REGION) == 0))
42063d8817e4Smiod {
42073d8817e4Smiod os->region = lang_memory_default (os->bfd_section);
42083d8817e4Smiod }
42093d8817e4Smiod
42103d8817e4Smiod /* If a loadable section is using the default memory
42113d8817e4Smiod region, and some non default memory regions were
42123d8817e4Smiod defined, issue an error message. */
42133d8817e4Smiod if (!IGNORE_SECTION (os->bfd_section)
42143d8817e4Smiod && ! link_info.relocatable
42153d8817e4Smiod && check_regions
42163d8817e4Smiod && strcmp (os->region->name,
42173d8817e4Smiod DEFAULT_MEMORY_REGION) == 0
42183d8817e4Smiod && lang_memory_region_list != NULL
42193d8817e4Smiod && (strcmp (lang_memory_region_list->name,
42203d8817e4Smiod DEFAULT_MEMORY_REGION) != 0
42213d8817e4Smiod || lang_memory_region_list->next != NULL)
42223d8817e4Smiod && expld.phase != lang_mark_phase_enum)
42233d8817e4Smiod {
42243d8817e4Smiod /* By default this is an error rather than just a
42253d8817e4Smiod warning because if we allocate the section to the
42263d8817e4Smiod default memory region we can end up creating an
42273d8817e4Smiod excessively large binary, or even seg faulting when
42283d8817e4Smiod attempting to perform a negative seek. See
42293d8817e4Smiod sources.redhat.com/ml/binutils/2003-04/msg00423.html
42303d8817e4Smiod for an example of this. This behaviour can be
42313d8817e4Smiod overridden by the using the --no-check-sections
42323d8817e4Smiod switch. */
42333d8817e4Smiod if (command_line.check_section_addresses)
42343d8817e4Smiod einfo (_("%P%F: error: no memory region specified"
42353d8817e4Smiod " for loadable section `%s'\n"),
42363d8817e4Smiod bfd_get_section_name (output_bfd,
42373d8817e4Smiod os->bfd_section));
42383d8817e4Smiod else
42393d8817e4Smiod einfo (_("%P: warning: no memory region specified"
42403d8817e4Smiod " for loadable section `%s'\n"),
42413d8817e4Smiod bfd_get_section_name (output_bfd,
42423d8817e4Smiod os->bfd_section));
42433d8817e4Smiod }
42443d8817e4Smiod
42453d8817e4Smiod newdot = os->region->current;
42463d8817e4Smiod align = os->bfd_section->alignment_power;
42473d8817e4Smiod }
42483d8817e4Smiod else
42493d8817e4Smiod align = os->section_alignment;
42503d8817e4Smiod
42513d8817e4Smiod /* Align to what the section needs. */
42523d8817e4Smiod if (align > 0)
42533d8817e4Smiod {
42543d8817e4Smiod bfd_vma savedot = newdot;
42553d8817e4Smiod newdot = align_power (newdot, align);
42563d8817e4Smiod
42573d8817e4Smiod if (newdot != savedot
42583d8817e4Smiod && (config.warn_section_align
42593d8817e4Smiod || os->addr_tree != NULL)
42603d8817e4Smiod && expld.phase != lang_mark_phase_enum)
42613d8817e4Smiod einfo (_("%P: warning: changing start of section"
42623d8817e4Smiod " %s by %lu bytes\n"),
42633d8817e4Smiod os->name, (unsigned long) (newdot - savedot));
42643d8817e4Smiod }
42653d8817e4Smiod
42663d8817e4Smiod bfd_set_section_vma (0, os->bfd_section, newdot);
42673d8817e4Smiod
42683d8817e4Smiod os->bfd_section->output_offset = 0;
42693d8817e4Smiod }
42703d8817e4Smiod
42713d8817e4Smiod lang_size_sections_1 (os->children.head, os, &os->children.head,
42723d8817e4Smiod os->fill, newdot, relax, check_regions);
42733d8817e4Smiod
42743d8817e4Smiod os->processed = TRUE;
42753d8817e4Smiod
42763d8817e4Smiod if (bfd_is_abs_section (os->bfd_section) || os->ignored)
42773d8817e4Smiod {
42783d8817e4Smiod ASSERT (os->bfd_section->size == 0);
42793d8817e4Smiod break;
42803d8817e4Smiod }
42813d8817e4Smiod
42823d8817e4Smiod dot = os->bfd_section->vma;
42833d8817e4Smiod
42843d8817e4Smiod /* Put the section within the requested block size, or
42853d8817e4Smiod align at the block boundary. */
42863d8817e4Smiod after = ((dot
42873d8817e4Smiod + TO_ADDR (os->bfd_section->size)
42883d8817e4Smiod + os->block_value - 1)
42893d8817e4Smiod & - (bfd_vma) os->block_value);
42903d8817e4Smiod
42913d8817e4Smiod os->bfd_section->size = TO_SIZE (after - os->bfd_section->vma);
42923d8817e4Smiod
42933d8817e4Smiod /* .tbss sections effectively have zero size. */
42943d8817e4Smiod if ((os->bfd_section->flags & SEC_HAS_CONTENTS) != 0
42953d8817e4Smiod || (os->bfd_section->flags & SEC_THREAD_LOCAL) == 0
42963d8817e4Smiod || link_info.relocatable)
42973d8817e4Smiod dot += TO_ADDR (os->bfd_section->size);
42983d8817e4Smiod
42993d8817e4Smiod if (os->update_dot_tree != 0)
43003d8817e4Smiod exp_fold_tree (os->update_dot_tree, bfd_abs_section_ptr, &dot);
43013d8817e4Smiod
43023d8817e4Smiod /* Update dot in the region ?
43033d8817e4Smiod We only do this if the section is going to be allocated,
43043d8817e4Smiod since unallocated sections do not contribute to the region's
43053d8817e4Smiod overall size in memory.
43063d8817e4Smiod
43073d8817e4Smiod If the SEC_NEVER_LOAD bit is not set, it will affect the
43083d8817e4Smiod addresses of sections after it. We have to update
43093d8817e4Smiod dot. */
43103d8817e4Smiod if (os->region != NULL
43113d8817e4Smiod && ((os->bfd_section->flags & SEC_NEVER_LOAD) == 0
43123d8817e4Smiod || (os->bfd_section->flags & (SEC_ALLOC | SEC_LOAD))))
43133d8817e4Smiod {
43143d8817e4Smiod os->region->current = dot;
43153d8817e4Smiod
43163d8817e4Smiod if (check_regions)
43173d8817e4Smiod /* Make sure the new address is within the region. */
43183d8817e4Smiod os_region_check (os, os->region, os->addr_tree,
43193d8817e4Smiod os->bfd_section->vma);
43203d8817e4Smiod
43213d8817e4Smiod /* If there's no load address specified, use the run
43223d8817e4Smiod region as the load region. */
43233d8817e4Smiod if (os->lma_region == NULL && os->load_base == NULL)
43243d8817e4Smiod os->lma_region = os->region;
43253d8817e4Smiod
43263d8817e4Smiod if (os->lma_region != NULL && os->lma_region != os->region)
43273d8817e4Smiod {
43283d8817e4Smiod /* Set load_base, which will be handled later. */
43293d8817e4Smiod os->load_base = exp_intop (os->lma_region->current);
43303d8817e4Smiod os->lma_region->current +=
43313d8817e4Smiod TO_ADDR (os->bfd_section->size);
43323d8817e4Smiod if (check_regions)
43333d8817e4Smiod os_region_check (os, os->lma_region, NULL,
43343d8817e4Smiod os->bfd_section->lma);
43353d8817e4Smiod }
43363d8817e4Smiod }
43373d8817e4Smiod }
43383d8817e4Smiod break;
43393d8817e4Smiod
43403d8817e4Smiod case lang_constructors_statement_enum:
43413d8817e4Smiod dot = lang_size_sections_1 (constructor_list.head,
43423d8817e4Smiod output_section_statement,
43433d8817e4Smiod &s->wild_statement.children.head,
43443d8817e4Smiod fill, dot, relax, check_regions);
43453d8817e4Smiod break;
43463d8817e4Smiod
43473d8817e4Smiod case lang_data_statement_enum:
43483d8817e4Smiod {
43493d8817e4Smiod unsigned int size = 0;
43503d8817e4Smiod
43513d8817e4Smiod s->data_statement.output_offset =
43523d8817e4Smiod dot - output_section_statement->bfd_section->vma;
43533d8817e4Smiod s->data_statement.output_section =
43543d8817e4Smiod output_section_statement->bfd_section;
43553d8817e4Smiod
43563d8817e4Smiod /* We might refer to provided symbols in the expression, and
43573d8817e4Smiod need to mark them as needed. */
43583d8817e4Smiod exp_fold_tree (s->data_statement.exp, bfd_abs_section_ptr, &dot);
43593d8817e4Smiod
43603d8817e4Smiod switch (s->data_statement.type)
43613d8817e4Smiod {
43623d8817e4Smiod default:
43633d8817e4Smiod abort ();
43643d8817e4Smiod case QUAD:
43653d8817e4Smiod case SQUAD:
43663d8817e4Smiod size = QUAD_SIZE;
43673d8817e4Smiod break;
43683d8817e4Smiod case LONG:
43693d8817e4Smiod size = LONG_SIZE;
43703d8817e4Smiod break;
43713d8817e4Smiod case SHORT:
43723d8817e4Smiod size = SHORT_SIZE;
43733d8817e4Smiod break;
43743d8817e4Smiod case BYTE:
43753d8817e4Smiod size = BYTE_SIZE;
43763d8817e4Smiod break;
43773d8817e4Smiod }
43783d8817e4Smiod if (size < TO_SIZE ((unsigned) 1))
43793d8817e4Smiod size = TO_SIZE ((unsigned) 1);
43803d8817e4Smiod dot += TO_ADDR (size);
43813d8817e4Smiod output_section_statement->bfd_section->size += size;
43823d8817e4Smiod }
43833d8817e4Smiod break;
43843d8817e4Smiod
43853d8817e4Smiod case lang_reloc_statement_enum:
43863d8817e4Smiod {
43873d8817e4Smiod int size;
43883d8817e4Smiod
43893d8817e4Smiod s->reloc_statement.output_offset =
43903d8817e4Smiod dot - output_section_statement->bfd_section->vma;
43913d8817e4Smiod s->reloc_statement.output_section =
43923d8817e4Smiod output_section_statement->bfd_section;
43933d8817e4Smiod size = bfd_get_reloc_size (s->reloc_statement.howto);
43943d8817e4Smiod dot += TO_ADDR (size);
43953d8817e4Smiod output_section_statement->bfd_section->size += size;
43963d8817e4Smiod }
43973d8817e4Smiod break;
43983d8817e4Smiod
43993d8817e4Smiod case lang_wild_statement_enum:
44003d8817e4Smiod dot = lang_size_sections_1 (s->wild_statement.children.head,
44013d8817e4Smiod output_section_statement,
44023d8817e4Smiod &s->wild_statement.children.head,
44033d8817e4Smiod fill, dot, relax, check_regions);
44043d8817e4Smiod break;
44053d8817e4Smiod
44063d8817e4Smiod case lang_object_symbols_statement_enum:
44073d8817e4Smiod link_info.create_object_symbols_section =
44083d8817e4Smiod output_section_statement->bfd_section;
44093d8817e4Smiod break;
44103d8817e4Smiod
44113d8817e4Smiod case lang_output_statement_enum:
44123d8817e4Smiod case lang_target_statement_enum:
44133d8817e4Smiod break;
44143d8817e4Smiod
44153d8817e4Smiod case lang_input_section_enum:
44163d8817e4Smiod {
44173d8817e4Smiod asection *i;
44183d8817e4Smiod
44193d8817e4Smiod i = (*prev)->input_section.section;
44203d8817e4Smiod if (relax)
44213d8817e4Smiod {
44223d8817e4Smiod bfd_boolean again;
44233d8817e4Smiod
44243d8817e4Smiod if (! bfd_relax_section (i->owner, i, &link_info, &again))
44253d8817e4Smiod einfo (_("%P%F: can't relax section: %E\n"));
44263d8817e4Smiod if (again)
44273d8817e4Smiod *relax = TRUE;
44283d8817e4Smiod }
44293d8817e4Smiod dot = size_input_section (prev, output_section_statement,
44303d8817e4Smiod output_section_statement->fill, dot);
44313d8817e4Smiod }
44323d8817e4Smiod break;
44333d8817e4Smiod
44343d8817e4Smiod case lang_input_statement_enum:
44353d8817e4Smiod break;
44363d8817e4Smiod
44373d8817e4Smiod case lang_fill_statement_enum:
44383d8817e4Smiod s->fill_statement.output_section =
44393d8817e4Smiod output_section_statement->bfd_section;
44403d8817e4Smiod
44413d8817e4Smiod fill = s->fill_statement.fill;
44423d8817e4Smiod break;
44433d8817e4Smiod
44443d8817e4Smiod case lang_assignment_statement_enum:
44453d8817e4Smiod {
44463d8817e4Smiod bfd_vma newdot = dot;
44473d8817e4Smiod
44483d8817e4Smiod exp_fold_tree (s->assignment_statement.exp,
44493d8817e4Smiod output_section_statement->bfd_section,
44503d8817e4Smiod &newdot);
44513d8817e4Smiod
44523d8817e4Smiod if (newdot != dot && !output_section_statement->ignored)
44533d8817e4Smiod {
44543d8817e4Smiod if (output_section_statement == abs_output_section)
44553d8817e4Smiod {
44563d8817e4Smiod /* If we don't have an output section, then just adjust
44573d8817e4Smiod the default memory address. */
44583d8817e4Smiod lang_memory_region_lookup (DEFAULT_MEMORY_REGION,
44593d8817e4Smiod FALSE)->current = newdot;
44603d8817e4Smiod }
44613d8817e4Smiod else
44623d8817e4Smiod {
44633d8817e4Smiod /* Insert a pad after this statement. We can't
44643d8817e4Smiod put the pad before when relaxing, in case the
44653d8817e4Smiod assignment references dot. */
44663d8817e4Smiod insert_pad (&s->header.next, fill, TO_SIZE (newdot - dot),
44673d8817e4Smiod output_section_statement->bfd_section, dot);
44683d8817e4Smiod
44693d8817e4Smiod /* Don't neuter the pad below when relaxing. */
44703d8817e4Smiod s = s->header.next;
44713d8817e4Smiod
44723d8817e4Smiod /* If dot is advanced, this implies that the section
44733d8817e4Smiod should have space allocated to it, unless the
44743d8817e4Smiod user has explicitly stated that the section
44753d8817e4Smiod should never be loaded. */
44763d8817e4Smiod if (!(output_section_statement->flags
44773d8817e4Smiod & (SEC_NEVER_LOAD | SEC_ALLOC)))
44783d8817e4Smiod output_section_statement->bfd_section->flags |= SEC_ALLOC;
44793d8817e4Smiod }
44803d8817e4Smiod dot = newdot;
44813d8817e4Smiod }
44823d8817e4Smiod }
44833d8817e4Smiod break;
44843d8817e4Smiod
44853d8817e4Smiod case lang_padding_statement_enum:
44863d8817e4Smiod /* If this is the first time lang_size_sections is called,
44873d8817e4Smiod we won't have any padding statements. If this is the
44883d8817e4Smiod second or later passes when relaxing, we should allow
44893d8817e4Smiod padding to shrink. If padding is needed on this pass, it
44903d8817e4Smiod will be added back in. */
44913d8817e4Smiod s->padding_statement.size = 0;
44923d8817e4Smiod
44933d8817e4Smiod /* Make sure output_offset is valid. If relaxation shrinks
44943d8817e4Smiod the section and this pad isn't needed, it's possible to
44953d8817e4Smiod have output_offset larger than the final size of the
44963d8817e4Smiod section. bfd_set_section_contents will complain even for
44973d8817e4Smiod a pad size of zero. */
44983d8817e4Smiod s->padding_statement.output_offset
44993d8817e4Smiod = dot - output_section_statement->bfd_section->vma;
45003d8817e4Smiod break;
45013d8817e4Smiod
45023d8817e4Smiod case lang_group_statement_enum:
45033d8817e4Smiod dot = lang_size_sections_1 (s->group_statement.children.head,
45043d8817e4Smiod output_section_statement,
45053d8817e4Smiod &s->group_statement.children.head,
45063d8817e4Smiod fill, dot, relax, check_regions);
45073d8817e4Smiod break;
45083d8817e4Smiod
45093d8817e4Smiod default:
45103d8817e4Smiod FAIL ();
45113d8817e4Smiod break;
45123d8817e4Smiod
45133d8817e4Smiod /* We can only get here when relaxing is turned on. */
45143d8817e4Smiod case lang_address_statement_enum:
45153d8817e4Smiod break;
45163d8817e4Smiod }
45173d8817e4Smiod prev = &s->header.next;
45183d8817e4Smiod }
45193d8817e4Smiod return dot;
45203d8817e4Smiod }
45213d8817e4Smiod
45223d8817e4Smiod void
one_lang_size_sections_pass(bfd_boolean * relax,bfd_boolean check_regions)45233d8817e4Smiod one_lang_size_sections_pass (bfd_boolean *relax, bfd_boolean check_regions)
45243d8817e4Smiod {
45253d8817e4Smiod lang_statement_iteration++;
45263d8817e4Smiod lang_size_sections_1 (statement_list.head, abs_output_section,
45273d8817e4Smiod &statement_list.head, 0, 0, relax, check_regions);
45283d8817e4Smiod }
45293d8817e4Smiod
45303d8817e4Smiod void
lang_size_sections(bfd_boolean * relax,bfd_boolean check_regions)45313d8817e4Smiod lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
45323d8817e4Smiod {
45333d8817e4Smiod expld.phase = lang_allocating_phase_enum;
45343d8817e4Smiod expld.dataseg.phase = exp_dataseg_none;
45353d8817e4Smiod
45363d8817e4Smiod one_lang_size_sections_pass (relax, check_regions);
45373d8817e4Smiod if (expld.dataseg.phase == exp_dataseg_end_seen
45383d8817e4Smiod && link_info.relro && expld.dataseg.relro_end)
45393d8817e4Smiod {
45403d8817e4Smiod /* If DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END pair was seen, try
45413d8817e4Smiod to put expld.dataseg.relro on a (common) page boundary. */
45423d8817e4Smiod bfd_vma old_min_base, relro_end, maxpage;
45433d8817e4Smiod
45443d8817e4Smiod expld.dataseg.phase = exp_dataseg_relro_adjust;
45453d8817e4Smiod old_min_base = expld.dataseg.min_base;
45463d8817e4Smiod maxpage = expld.dataseg.maxpagesize;
45473d8817e4Smiod expld.dataseg.base += (-expld.dataseg.relro_end
45483d8817e4Smiod & (expld.dataseg.pagesize - 1));
45493d8817e4Smiod /* Compute the expected PT_GNU_RELRO segment end. */
45503d8817e4Smiod relro_end = (expld.dataseg.relro_end + expld.dataseg.pagesize - 1)
45513d8817e4Smiod & ~(expld.dataseg.pagesize - 1);
45523d8817e4Smiod if (old_min_base + maxpage < expld.dataseg.base)
45533d8817e4Smiod {
45543d8817e4Smiod expld.dataseg.base -= maxpage;
45553d8817e4Smiod relro_end -= maxpage;
45563d8817e4Smiod }
45573d8817e4Smiod one_lang_size_sections_pass (relax, check_regions);
45583d8817e4Smiod if (expld.dataseg.relro_end > relro_end)
45593d8817e4Smiod {
45603d8817e4Smiod /* The alignment of sections between DATA_SEGMENT_ALIGN
45613d8817e4Smiod and DATA_SEGMENT_RELRO_END caused huge padding to be
45623d8817e4Smiod inserted at DATA_SEGMENT_RELRO_END. Try some other base. */
45633d8817e4Smiod asection *sec;
45643d8817e4Smiod unsigned int max_alignment_power = 0;
45653d8817e4Smiod
45663d8817e4Smiod /* Find maximum alignment power of sections between
45673d8817e4Smiod DATA_SEGMENT_ALIGN and DATA_SEGMENT_RELRO_END. */
45683d8817e4Smiod for (sec = output_bfd->sections; sec; sec = sec->next)
45693d8817e4Smiod if (sec->vma >= expld.dataseg.base
45703d8817e4Smiod && sec->vma < expld.dataseg.relro_end
45713d8817e4Smiod && sec->alignment_power > max_alignment_power)
45723d8817e4Smiod max_alignment_power = sec->alignment_power;
45733d8817e4Smiod
45743d8817e4Smiod if (((bfd_vma) 1 << max_alignment_power) < expld.dataseg.pagesize)
45753d8817e4Smiod {
45763d8817e4Smiod if (expld.dataseg.base - (1 << max_alignment_power)
45773d8817e4Smiod < old_min_base)
45783d8817e4Smiod expld.dataseg.base += expld.dataseg.pagesize;
45793d8817e4Smiod expld.dataseg.base -= (1 << max_alignment_power);
45803d8817e4Smiod one_lang_size_sections_pass (relax, check_regions);
45813d8817e4Smiod }
45823d8817e4Smiod }
45833d8817e4Smiod link_info.relro_start = expld.dataseg.base;
45843d8817e4Smiod link_info.relro_end = expld.dataseg.relro_end;
45853d8817e4Smiod }
45863d8817e4Smiod else if (expld.dataseg.phase == exp_dataseg_end_seen)
45873d8817e4Smiod {
45883d8817e4Smiod /* If DATA_SEGMENT_ALIGN DATA_SEGMENT_END pair was seen, check whether
45893d8817e4Smiod a page could be saved in the data segment. */
45903d8817e4Smiod bfd_vma first, last;
45913d8817e4Smiod
45923d8817e4Smiod first = -expld.dataseg.base & (expld.dataseg.pagesize - 1);
45933d8817e4Smiod last = expld.dataseg.end & (expld.dataseg.pagesize - 1);
45943d8817e4Smiod if (first && last
45953d8817e4Smiod && ((expld.dataseg.base & ~(expld.dataseg.pagesize - 1))
45963d8817e4Smiod != (expld.dataseg.end & ~(expld.dataseg.pagesize - 1)))
45973d8817e4Smiod && first + last <= expld.dataseg.pagesize)
45983d8817e4Smiod {
45993d8817e4Smiod expld.dataseg.phase = exp_dataseg_adjust;
46003d8817e4Smiod one_lang_size_sections_pass (relax, check_regions);
46013d8817e4Smiod }
46023d8817e4Smiod }
46033d8817e4Smiod
46043d8817e4Smiod expld.phase = lang_final_phase_enum;
46053d8817e4Smiod }
46063d8817e4Smiod
46073d8817e4Smiod /* Worker function for lang_do_assignments. Recursiveness goes here. */
46083d8817e4Smiod
46093d8817e4Smiod static bfd_vma
lang_do_assignments_1(lang_statement_union_type * s,lang_output_section_statement_type * output_section_statement,fill_type * fill,bfd_vma dot)46103d8817e4Smiod lang_do_assignments_1
46113d8817e4Smiod (lang_statement_union_type *s,
46123d8817e4Smiod lang_output_section_statement_type *output_section_statement,
46133d8817e4Smiod fill_type *fill,
46143d8817e4Smiod bfd_vma dot)
46153d8817e4Smiod {
46163d8817e4Smiod for (; s != NULL; s = s->header.next)
46173d8817e4Smiod {
46183d8817e4Smiod switch (s->header.type)
46193d8817e4Smiod {
46203d8817e4Smiod case lang_constructors_statement_enum:
46213d8817e4Smiod dot = lang_do_assignments_1 (constructor_list.head,
46223d8817e4Smiod output_section_statement,
46233d8817e4Smiod fill,
46243d8817e4Smiod dot);
46253d8817e4Smiod break;
46263d8817e4Smiod
46273d8817e4Smiod case lang_output_section_statement_enum:
46283d8817e4Smiod {
46293d8817e4Smiod lang_output_section_statement_type *os;
46303d8817e4Smiod
46313d8817e4Smiod os = &(s->output_section_statement);
46323d8817e4Smiod if (os->bfd_section != NULL && !os->ignored)
46333d8817e4Smiod {
46343d8817e4Smiod dot = os->bfd_section->vma;
46353d8817e4Smiod lang_do_assignments_1 (os->children.head, os, os->fill, dot);
46363d8817e4Smiod /* .tbss sections effectively have zero size. */
46373d8817e4Smiod if ((os->bfd_section->flags & SEC_HAS_CONTENTS) != 0
46383d8817e4Smiod || (os->bfd_section->flags & SEC_THREAD_LOCAL) == 0
46393d8817e4Smiod || link_info.relocatable)
46403d8817e4Smiod dot += TO_ADDR (os->bfd_section->size);
46413d8817e4Smiod }
46423d8817e4Smiod if (os->load_base)
46433d8817e4Smiod {
46443d8817e4Smiod /* If nothing has been placed into the output section then
46453d8817e4Smiod it won't have a bfd_section. */
46463d8817e4Smiod if (os->bfd_section && !os->ignored)
46473d8817e4Smiod {
46483d8817e4Smiod os->bfd_section->lma
46493d8817e4Smiod = exp_get_abs_int (os->load_base, 0, "load base");
46503d8817e4Smiod }
46513d8817e4Smiod }
46523d8817e4Smiod }
46533d8817e4Smiod break;
46543d8817e4Smiod
46553d8817e4Smiod case lang_wild_statement_enum:
46563d8817e4Smiod
46573d8817e4Smiod dot = lang_do_assignments_1 (s->wild_statement.children.head,
46583d8817e4Smiod output_section_statement,
46593d8817e4Smiod fill, dot);
46603d8817e4Smiod break;
46613d8817e4Smiod
46623d8817e4Smiod case lang_object_symbols_statement_enum:
46633d8817e4Smiod case lang_output_statement_enum:
46643d8817e4Smiod case lang_target_statement_enum:
46653d8817e4Smiod break;
46663d8817e4Smiod
46673d8817e4Smiod case lang_data_statement_enum:
46683d8817e4Smiod exp_fold_tree (s->data_statement.exp, bfd_abs_section_ptr, &dot);
46693d8817e4Smiod if (expld.result.valid_p)
46703d8817e4Smiod s->data_statement.value = (expld.result.value
46713d8817e4Smiod + expld.result.section->vma);
46723d8817e4Smiod else
46733d8817e4Smiod einfo (_("%F%P: invalid data statement\n"));
46743d8817e4Smiod {
46753d8817e4Smiod unsigned int size;
46763d8817e4Smiod switch (s->data_statement.type)
46773d8817e4Smiod {
46783d8817e4Smiod default:
46793d8817e4Smiod abort ();
46803d8817e4Smiod case QUAD:
46813d8817e4Smiod case SQUAD:
46823d8817e4Smiod size = QUAD_SIZE;
46833d8817e4Smiod break;
46843d8817e4Smiod case LONG:
46853d8817e4Smiod size = LONG_SIZE;
46863d8817e4Smiod break;
46873d8817e4Smiod case SHORT:
46883d8817e4Smiod size = SHORT_SIZE;
46893d8817e4Smiod break;
46903d8817e4Smiod case BYTE:
46913d8817e4Smiod size = BYTE_SIZE;
46923d8817e4Smiod break;
46933d8817e4Smiod }
46943d8817e4Smiod if (size < TO_SIZE ((unsigned) 1))
46953d8817e4Smiod size = TO_SIZE ((unsigned) 1);
46963d8817e4Smiod dot += TO_ADDR (size);
46973d8817e4Smiod }
46983d8817e4Smiod break;
46993d8817e4Smiod
47003d8817e4Smiod case lang_reloc_statement_enum:
47013d8817e4Smiod exp_fold_tree (s->reloc_statement.addend_exp,
47023d8817e4Smiod bfd_abs_section_ptr, &dot);
47033d8817e4Smiod if (expld.result.valid_p)
47043d8817e4Smiod s->reloc_statement.addend_value = expld.result.value;
47053d8817e4Smiod else
47063d8817e4Smiod einfo (_("%F%P: invalid reloc statement\n"));
47073d8817e4Smiod dot += TO_ADDR (bfd_get_reloc_size (s->reloc_statement.howto));
47083d8817e4Smiod break;
47093d8817e4Smiod
47103d8817e4Smiod case lang_input_section_enum:
47113d8817e4Smiod {
47123d8817e4Smiod asection *in = s->input_section.section;
47133d8817e4Smiod
47143d8817e4Smiod if ((in->flags & SEC_EXCLUDE) == 0)
47153d8817e4Smiod dot += TO_ADDR (in->size);
47163d8817e4Smiod }
47173d8817e4Smiod break;
47183d8817e4Smiod
47193d8817e4Smiod case lang_input_statement_enum:
47203d8817e4Smiod break;
47213d8817e4Smiod
47223d8817e4Smiod case lang_fill_statement_enum:
47233d8817e4Smiod fill = s->fill_statement.fill;
47243d8817e4Smiod break;
47253d8817e4Smiod
47263d8817e4Smiod case lang_assignment_statement_enum:
47273d8817e4Smiod exp_fold_tree (s->assignment_statement.exp,
47283d8817e4Smiod output_section_statement->bfd_section,
47293d8817e4Smiod &dot);
47303d8817e4Smiod break;
47313d8817e4Smiod
47323d8817e4Smiod case lang_padding_statement_enum:
47333d8817e4Smiod dot += TO_ADDR (s->padding_statement.size);
47343d8817e4Smiod break;
47353d8817e4Smiod
47363d8817e4Smiod case lang_group_statement_enum:
47373d8817e4Smiod dot = lang_do_assignments_1 (s->group_statement.children.head,
47383d8817e4Smiod output_section_statement,
47393d8817e4Smiod fill, dot);
47403d8817e4Smiod break;
47413d8817e4Smiod
47423d8817e4Smiod default:
47433d8817e4Smiod FAIL ();
47443d8817e4Smiod break;
47453d8817e4Smiod
47463d8817e4Smiod case lang_address_statement_enum:
47473d8817e4Smiod break;
47483d8817e4Smiod }
47493d8817e4Smiod }
47503d8817e4Smiod return dot;
47513d8817e4Smiod }
47523d8817e4Smiod
47533d8817e4Smiod void
lang_do_assignments(void)47543d8817e4Smiod lang_do_assignments (void)
47553d8817e4Smiod {
47563d8817e4Smiod lang_statement_iteration++;
47573d8817e4Smiod lang_do_assignments_1 (statement_list.head, abs_output_section, NULL, 0);
47583d8817e4Smiod }
47593d8817e4Smiod
47603d8817e4Smiod /* Fix any .startof. or .sizeof. symbols. When the assemblers see the
47613d8817e4Smiod operator .startof. (section_name), it produces an undefined symbol
47623d8817e4Smiod .startof.section_name. Similarly, when it sees
47633d8817e4Smiod .sizeof. (section_name), it produces an undefined symbol
47643d8817e4Smiod .sizeof.section_name. For all the output sections, we look for
47653d8817e4Smiod such symbols, and set them to the correct value. */
47663d8817e4Smiod
47673d8817e4Smiod static void
lang_set_startof(void)47683d8817e4Smiod lang_set_startof (void)
47693d8817e4Smiod {
47703d8817e4Smiod asection *s;
47713d8817e4Smiod
47723d8817e4Smiod if (link_info.relocatable)
47733d8817e4Smiod return;
47743d8817e4Smiod
47753d8817e4Smiod for (s = output_bfd->sections; s != NULL; s = s->next)
47763d8817e4Smiod {
47773d8817e4Smiod const char *secname;
47783d8817e4Smiod char *buf;
47793d8817e4Smiod struct bfd_link_hash_entry *h;
47803d8817e4Smiod
47813d8817e4Smiod secname = bfd_get_section_name (output_bfd, s);
47823d8817e4Smiod buf = xmalloc (10 + strlen (secname));
47833d8817e4Smiod
47843d8817e4Smiod sprintf (buf, ".startof.%s", secname);
47853d8817e4Smiod h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE, TRUE);
47863d8817e4Smiod if (h != NULL && h->type == bfd_link_hash_undefined)
47873d8817e4Smiod {
47883d8817e4Smiod h->type = bfd_link_hash_defined;
47893d8817e4Smiod h->u.def.value = bfd_get_section_vma (output_bfd, s);
47903d8817e4Smiod h->u.def.section = bfd_abs_section_ptr;
47913d8817e4Smiod }
47923d8817e4Smiod
47933d8817e4Smiod sprintf (buf, ".sizeof.%s", secname);
47943d8817e4Smiod h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE, TRUE);
47953d8817e4Smiod if (h != NULL && h->type == bfd_link_hash_undefined)
47963d8817e4Smiod {
47973d8817e4Smiod h->type = bfd_link_hash_defined;
47983d8817e4Smiod h->u.def.value = TO_ADDR (s->size);
47993d8817e4Smiod h->u.def.section = bfd_abs_section_ptr;
48003d8817e4Smiod }
48013d8817e4Smiod
48023d8817e4Smiod free (buf);
48033d8817e4Smiod }
48043d8817e4Smiod }
48053d8817e4Smiod
48063d8817e4Smiod static void
lang_end(void)48073d8817e4Smiod lang_end (void)
48083d8817e4Smiod {
48093d8817e4Smiod struct bfd_link_hash_entry *h;
48103d8817e4Smiod bfd_boolean warn;
48113d8817e4Smiod
48123d8817e4Smiod if (link_info.relocatable || link_info.shared)
48133d8817e4Smiod warn = FALSE;
48143d8817e4Smiod else
48153d8817e4Smiod warn = TRUE;
48163d8817e4Smiod
48173d8817e4Smiod if (entry_symbol.name == NULL)
48183d8817e4Smiod {
48193d8817e4Smiod /* No entry has been specified. Look for the default entry, but
48203d8817e4Smiod don't warn if we don't find it. */
48213d8817e4Smiod entry_symbol.name = entry_symbol_default;
48223d8817e4Smiod warn = FALSE;
48233d8817e4Smiod }
48243d8817e4Smiod
48253d8817e4Smiod h = bfd_link_hash_lookup (link_info.hash, entry_symbol.name,
48263d8817e4Smiod FALSE, FALSE, TRUE);
48273d8817e4Smiod if (h != NULL
48283d8817e4Smiod && (h->type == bfd_link_hash_defined
48293d8817e4Smiod || h->type == bfd_link_hash_defweak)
48303d8817e4Smiod && h->u.def.section->output_section != NULL)
48313d8817e4Smiod {
48323d8817e4Smiod bfd_vma val;
48333d8817e4Smiod
48343d8817e4Smiod val = (h->u.def.value
48353d8817e4Smiod + bfd_get_section_vma (output_bfd,
48363d8817e4Smiod h->u.def.section->output_section)
48373d8817e4Smiod + h->u.def.section->output_offset);
48383d8817e4Smiod if (! bfd_set_start_address (output_bfd, val))
48393d8817e4Smiod einfo (_("%P%F:%s: can't set start address\n"), entry_symbol.name);
48403d8817e4Smiod }
48413d8817e4Smiod else
48423d8817e4Smiod {
48433d8817e4Smiod bfd_vma val;
48443d8817e4Smiod const char *send;
48453d8817e4Smiod
48463d8817e4Smiod /* We couldn't find the entry symbol. Try parsing it as a
48473d8817e4Smiod number. */
48483d8817e4Smiod val = bfd_scan_vma (entry_symbol.name, &send, 0);
48493d8817e4Smiod if (*send == '\0')
48503d8817e4Smiod {
48513d8817e4Smiod if (! bfd_set_start_address (output_bfd, val))
48523d8817e4Smiod einfo (_("%P%F: can't set start address\n"));
48533d8817e4Smiod }
48543d8817e4Smiod else
48553d8817e4Smiod {
48563d8817e4Smiod asection *ts;
48573d8817e4Smiod
48583d8817e4Smiod /* Can't find the entry symbol, and it's not a number. Use
48593d8817e4Smiod the first address in the text section. */
48603d8817e4Smiod ts = bfd_get_section_by_name (output_bfd, entry_section);
48613d8817e4Smiod if (ts != NULL)
48623d8817e4Smiod {
48633d8817e4Smiod if (warn)
48643d8817e4Smiod einfo (_("%P: warning: cannot find entry symbol %s;"
48653d8817e4Smiod " defaulting to %V\n"),
48663d8817e4Smiod entry_symbol.name,
48673d8817e4Smiod bfd_get_section_vma (output_bfd, ts));
48683d8817e4Smiod if (! bfd_set_start_address (output_bfd,
48693d8817e4Smiod bfd_get_section_vma (output_bfd,
48703d8817e4Smiod ts)))
48713d8817e4Smiod einfo (_("%P%F: can't set start address\n"));
48723d8817e4Smiod }
48733d8817e4Smiod else
48743d8817e4Smiod {
48753d8817e4Smiod if (warn)
48763d8817e4Smiod einfo (_("%P: warning: cannot find entry symbol %s;"
48773d8817e4Smiod " not setting start address\n"),
48783d8817e4Smiod entry_symbol.name);
48793d8817e4Smiod }
48803d8817e4Smiod }
48813d8817e4Smiod }
48823d8817e4Smiod
48833d8817e4Smiod /* Don't bfd_hash_table_free (&lang_definedness_table);
48843d8817e4Smiod map file output may result in a call of lang_track_definedness. */
48853d8817e4Smiod }
48863d8817e4Smiod
48873d8817e4Smiod /* This is a small function used when we want to ignore errors from
48883d8817e4Smiod BFD. */
48893d8817e4Smiod
48903d8817e4Smiod static void
ignore_bfd_errors(const char * s ATTRIBUTE_UNUSED,...)48913d8817e4Smiod ignore_bfd_errors (const char *s ATTRIBUTE_UNUSED, ...)
48923d8817e4Smiod {
48933d8817e4Smiod /* Don't do anything. */
48943d8817e4Smiod }
48953d8817e4Smiod
48963d8817e4Smiod /* Check that the architecture of all the input files is compatible
48973d8817e4Smiod with the output file. Also call the backend to let it do any
48983d8817e4Smiod other checking that is needed. */
48993d8817e4Smiod
49003d8817e4Smiod static void
lang_check(void)49013d8817e4Smiod lang_check (void)
49023d8817e4Smiod {
49033d8817e4Smiod lang_statement_union_type *file;
49043d8817e4Smiod bfd *input_bfd;
49053d8817e4Smiod const bfd_arch_info_type *compatible;
49063d8817e4Smiod
49073d8817e4Smiod for (file = file_chain.head; file != NULL; file = file->input_statement.next)
49083d8817e4Smiod {
49093d8817e4Smiod input_bfd = file->input_statement.the_bfd;
49103d8817e4Smiod compatible
49113d8817e4Smiod = bfd_arch_get_compatible (input_bfd, output_bfd,
49123d8817e4Smiod command_line.accept_unknown_input_arch);
49133d8817e4Smiod
49143d8817e4Smiod /* In general it is not possible to perform a relocatable
49153d8817e4Smiod link between differing object formats when the input
49163d8817e4Smiod file has relocations, because the relocations in the
49173d8817e4Smiod input format may not have equivalent representations in
49183d8817e4Smiod the output format (and besides BFD does not translate
49193d8817e4Smiod relocs for other link purposes than a final link). */
49203d8817e4Smiod if ((link_info.relocatable || link_info.emitrelocations)
49213d8817e4Smiod && (compatible == NULL
49223d8817e4Smiod || bfd_get_flavour (input_bfd) != bfd_get_flavour (output_bfd))
49233d8817e4Smiod && (bfd_get_file_flags (input_bfd) & HAS_RELOC) != 0)
49243d8817e4Smiod {
49253d8817e4Smiod einfo (_("%P%F: Relocatable linking with relocations from"
49263d8817e4Smiod " format %s (%B) to format %s (%B) is not supported\n"),
49273d8817e4Smiod bfd_get_target (input_bfd), input_bfd,
49283d8817e4Smiod bfd_get_target (output_bfd), output_bfd);
49293d8817e4Smiod /* einfo with %F exits. */
49303d8817e4Smiod }
49313d8817e4Smiod
49323d8817e4Smiod if (compatible == NULL)
49333d8817e4Smiod {
49343d8817e4Smiod if (command_line.warn_mismatch)
49353d8817e4Smiod einfo (_("%P: warning: %s architecture of input file `%B'"
49363d8817e4Smiod " is incompatible with %s output\n"),
49373d8817e4Smiod bfd_printable_name (input_bfd), input_bfd,
49383d8817e4Smiod bfd_printable_name (output_bfd));
49393d8817e4Smiod }
49403d8817e4Smiod else if (bfd_count_sections (input_bfd))
49413d8817e4Smiod {
49423d8817e4Smiod /* If the input bfd has no contents, it shouldn't set the
49433d8817e4Smiod private data of the output bfd. */
49443d8817e4Smiod
49453d8817e4Smiod bfd_error_handler_type pfn = NULL;
49463d8817e4Smiod
49473d8817e4Smiod /* If we aren't supposed to warn about mismatched input
49483d8817e4Smiod files, temporarily set the BFD error handler to a
49493d8817e4Smiod function which will do nothing. We still want to call
49503d8817e4Smiod bfd_merge_private_bfd_data, since it may set up
49513d8817e4Smiod information which is needed in the output file. */
49523d8817e4Smiod if (! command_line.warn_mismatch)
49533d8817e4Smiod pfn = bfd_set_error_handler (ignore_bfd_errors);
49543d8817e4Smiod if (! bfd_merge_private_bfd_data (input_bfd, output_bfd))
49553d8817e4Smiod {
49563d8817e4Smiod if (command_line.warn_mismatch)
49573d8817e4Smiod einfo (_("%P%X: failed to merge target specific data"
49583d8817e4Smiod " of file %B\n"), input_bfd);
49593d8817e4Smiod }
49603d8817e4Smiod if (! command_line.warn_mismatch)
49613d8817e4Smiod bfd_set_error_handler (pfn);
49623d8817e4Smiod }
49633d8817e4Smiod }
49643d8817e4Smiod }
49653d8817e4Smiod
49663d8817e4Smiod /* Look through all the global common symbols and attach them to the
49673d8817e4Smiod correct section. The -sort-common command line switch may be used
49683d8817e4Smiod to roughly sort the entries by size. */
49693d8817e4Smiod
49703d8817e4Smiod static void
lang_common(void)49713d8817e4Smiod lang_common (void)
49723d8817e4Smiod {
49733d8817e4Smiod if (command_line.inhibit_common_definition)
49743d8817e4Smiod return;
49753d8817e4Smiod if (link_info.relocatable
49763d8817e4Smiod && ! command_line.force_common_definition)
49773d8817e4Smiod return;
49783d8817e4Smiod
49793d8817e4Smiod if (! config.sort_common)
49803d8817e4Smiod bfd_link_hash_traverse (link_info.hash, lang_one_common, NULL);
49813d8817e4Smiod else
49823d8817e4Smiod {
49833d8817e4Smiod int power;
49843d8817e4Smiod
49853d8817e4Smiod for (power = 4; power >= 0; power--)
49863d8817e4Smiod bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
49873d8817e4Smiod }
49883d8817e4Smiod }
49893d8817e4Smiod
49903d8817e4Smiod /* Place one common symbol in the correct section. */
49913d8817e4Smiod
49923d8817e4Smiod static bfd_boolean
lang_one_common(struct bfd_link_hash_entry * h,void * info)49933d8817e4Smiod lang_one_common (struct bfd_link_hash_entry *h, void *info)
49943d8817e4Smiod {
49953d8817e4Smiod unsigned int power_of_two;
49963d8817e4Smiod bfd_vma size;
49973d8817e4Smiod asection *section;
49983d8817e4Smiod
49993d8817e4Smiod if (h->type != bfd_link_hash_common)
50003d8817e4Smiod return TRUE;
50013d8817e4Smiod
50023d8817e4Smiod size = h->u.c.size;
50033d8817e4Smiod power_of_two = h->u.c.p->alignment_power;
50043d8817e4Smiod
50053d8817e4Smiod if (config.sort_common
50063d8817e4Smiod && power_of_two < (unsigned int) *(int *) info)
50073d8817e4Smiod return TRUE;
50083d8817e4Smiod
50093d8817e4Smiod section = h->u.c.p->section;
50103d8817e4Smiod
50113d8817e4Smiod /* Increase the size of the section to align the common sym. */
50123d8817e4Smiod section->size += ((bfd_vma) 1 << (power_of_two + opb_shift)) - 1;
50133d8817e4Smiod section->size &= (- (bfd_vma) 1 << (power_of_two + opb_shift));
50143d8817e4Smiod
50153d8817e4Smiod /* Adjust the alignment if necessary. */
50163d8817e4Smiod if (power_of_two > section->alignment_power)
50173d8817e4Smiod section->alignment_power = power_of_two;
50183d8817e4Smiod
50193d8817e4Smiod /* Change the symbol from common to defined. */
50203d8817e4Smiod h->type = bfd_link_hash_defined;
50213d8817e4Smiod h->u.def.section = section;
50223d8817e4Smiod h->u.def.value = section->size;
50233d8817e4Smiod
50243d8817e4Smiod /* Increase the size of the section. */
50253d8817e4Smiod section->size += size;
50263d8817e4Smiod
50273d8817e4Smiod /* Make sure the section is allocated in memory, and make sure that
50283d8817e4Smiod it is no longer a common section. */
50293d8817e4Smiod section->flags |= SEC_ALLOC;
50303d8817e4Smiod section->flags &= ~SEC_IS_COMMON;
50313d8817e4Smiod
50323d8817e4Smiod if (config.map_file != NULL)
50333d8817e4Smiod {
50343d8817e4Smiod static bfd_boolean header_printed;
50353d8817e4Smiod int len;
50363d8817e4Smiod char *name;
50373d8817e4Smiod char buf[50];
50383d8817e4Smiod
50393d8817e4Smiod if (! header_printed)
50403d8817e4Smiod {
50413d8817e4Smiod minfo (_("\nAllocating common symbols\n"));
50423d8817e4Smiod minfo (_("Common symbol size file\n\n"));
50433d8817e4Smiod header_printed = TRUE;
50443d8817e4Smiod }
50453d8817e4Smiod
50463d8817e4Smiod name = demangle (h->root.string);
50473d8817e4Smiod minfo ("%s", name);
50483d8817e4Smiod len = strlen (name);
50493d8817e4Smiod free (name);
50503d8817e4Smiod
50513d8817e4Smiod if (len >= 19)
50523d8817e4Smiod {
50533d8817e4Smiod print_nl ();
50543d8817e4Smiod len = 0;
50553d8817e4Smiod }
50563d8817e4Smiod while (len < 20)
50573d8817e4Smiod {
50583d8817e4Smiod print_space ();
50593d8817e4Smiod ++len;
50603d8817e4Smiod }
50613d8817e4Smiod
50623d8817e4Smiod minfo ("0x");
50633d8817e4Smiod if (size <= 0xffffffff)
50643d8817e4Smiod sprintf (buf, "%lx", (unsigned long) size);
50653d8817e4Smiod else
50663d8817e4Smiod sprintf_vma (buf, size);
50673d8817e4Smiod minfo ("%s", buf);
50683d8817e4Smiod len = strlen (buf);
50693d8817e4Smiod
50703d8817e4Smiod while (len < 16)
50713d8817e4Smiod {
50723d8817e4Smiod print_space ();
50733d8817e4Smiod ++len;
50743d8817e4Smiod }
50753d8817e4Smiod
50763d8817e4Smiod minfo ("%B\n", section->owner);
50773d8817e4Smiod }
50783d8817e4Smiod
50793d8817e4Smiod return TRUE;
50803d8817e4Smiod }
50813d8817e4Smiod
50823d8817e4Smiod /* Run through the input files and ensure that every input section has
50833d8817e4Smiod somewhere to go. If one is found without a destination then create
50843d8817e4Smiod an input request and place it into the statement tree. */
50853d8817e4Smiod
50863d8817e4Smiod static void
lang_place_orphans(void)50873d8817e4Smiod lang_place_orphans (void)
50883d8817e4Smiod {
50893d8817e4Smiod LANG_FOR_EACH_INPUT_STATEMENT (file)
50903d8817e4Smiod {
50913d8817e4Smiod asection *s;
50923d8817e4Smiod
50933d8817e4Smiod for (s = file->the_bfd->sections; s != NULL; s = s->next)
50943d8817e4Smiod {
50953d8817e4Smiod if (s->output_section == NULL)
50963d8817e4Smiod {
50973d8817e4Smiod /* This section of the file is not attached, root
50983d8817e4Smiod around for a sensible place for it to go. */
50993d8817e4Smiod
51003d8817e4Smiod if (file->just_syms_flag)
51013d8817e4Smiod bfd_link_just_syms (file->the_bfd, s, &link_info);
51023d8817e4Smiod else if ((s->flags & SEC_EXCLUDE) != 0)
51033d8817e4Smiod s->output_section = bfd_abs_section_ptr;
51043d8817e4Smiod else if (strcmp (s->name, "COMMON") == 0)
51053d8817e4Smiod {
51063d8817e4Smiod /* This is a lonely common section which must have
51073d8817e4Smiod come from an archive. We attach to the section
51083d8817e4Smiod with the wildcard. */
51093d8817e4Smiod if (! link_info.relocatable
51103d8817e4Smiod || command_line.force_common_definition)
51113d8817e4Smiod {
51123d8817e4Smiod if (default_common_section == NULL)
51133d8817e4Smiod {
51143d8817e4Smiod default_common_section =
51153d8817e4Smiod lang_output_section_statement_lookup (".bss");
51163d8817e4Smiod
51173d8817e4Smiod }
51183d8817e4Smiod lang_add_section (&default_common_section->children, s,
51193d8817e4Smiod default_common_section);
51203d8817e4Smiod }
51213d8817e4Smiod }
51223d8817e4Smiod else if (ldemul_place_orphan (s))
51233d8817e4Smiod ;
51243d8817e4Smiod else
51253d8817e4Smiod {
51263d8817e4Smiod lang_output_section_statement_type *os;
51273d8817e4Smiod
51283d8817e4Smiod os = lang_output_section_statement_lookup (s->name);
51293d8817e4Smiod lang_add_section (&os->children, s, os);
51303d8817e4Smiod }
51313d8817e4Smiod }
51323d8817e4Smiod }
51333d8817e4Smiod }
51343d8817e4Smiod }
51353d8817e4Smiod
51363d8817e4Smiod void
lang_set_flags(lang_memory_region_type * ptr,const char * flags,int invert)51373d8817e4Smiod lang_set_flags (lang_memory_region_type *ptr, const char *flags, int invert)
51383d8817e4Smiod {
51393d8817e4Smiod flagword *ptr_flags;
51403d8817e4Smiod
51413d8817e4Smiod ptr_flags = invert ? &ptr->not_flags : &ptr->flags;
51423d8817e4Smiod while (*flags)
51433d8817e4Smiod {
51443d8817e4Smiod switch (*flags)
51453d8817e4Smiod {
51463d8817e4Smiod case 'A': case 'a':
51473d8817e4Smiod *ptr_flags |= SEC_ALLOC;
51483d8817e4Smiod break;
51493d8817e4Smiod
51503d8817e4Smiod case 'R': case 'r':
51513d8817e4Smiod *ptr_flags |= SEC_READONLY;
51523d8817e4Smiod break;
51533d8817e4Smiod
51543d8817e4Smiod case 'W': case 'w':
51553d8817e4Smiod *ptr_flags |= SEC_DATA;
51563d8817e4Smiod break;
51573d8817e4Smiod
51583d8817e4Smiod case 'X': case 'x':
51593d8817e4Smiod *ptr_flags |= SEC_CODE;
51603d8817e4Smiod break;
51613d8817e4Smiod
51623d8817e4Smiod case 'L': case 'l':
51633d8817e4Smiod case 'I': case 'i':
51643d8817e4Smiod *ptr_flags |= SEC_LOAD;
51653d8817e4Smiod break;
51663d8817e4Smiod
51673d8817e4Smiod default:
51683d8817e4Smiod einfo (_("%P%F: invalid syntax in flags\n"));
51693d8817e4Smiod break;
51703d8817e4Smiod }
51713d8817e4Smiod flags++;
51723d8817e4Smiod }
51733d8817e4Smiod }
51743d8817e4Smiod
51753d8817e4Smiod /* Call a function on each input file. This function will be called
51763d8817e4Smiod on an archive, but not on the elements. */
51773d8817e4Smiod
51783d8817e4Smiod void
lang_for_each_input_file(void (* func)(lang_input_statement_type *))51793d8817e4Smiod lang_for_each_input_file (void (*func) (lang_input_statement_type *))
51803d8817e4Smiod {
51813d8817e4Smiod lang_input_statement_type *f;
51823d8817e4Smiod
51833d8817e4Smiod for (f = (lang_input_statement_type *) input_file_chain.head;
51843d8817e4Smiod f != NULL;
51853d8817e4Smiod f = (lang_input_statement_type *) f->next_real_file)
51863d8817e4Smiod func (f);
51873d8817e4Smiod }
51883d8817e4Smiod
51893d8817e4Smiod /* Call a function on each file. The function will be called on all
51903d8817e4Smiod the elements of an archive which are included in the link, but will
51913d8817e4Smiod not be called on the archive file itself. */
51923d8817e4Smiod
51933d8817e4Smiod void
lang_for_each_file(void (* func)(lang_input_statement_type *))51943d8817e4Smiod lang_for_each_file (void (*func) (lang_input_statement_type *))
51953d8817e4Smiod {
51963d8817e4Smiod LANG_FOR_EACH_INPUT_STATEMENT (f)
51973d8817e4Smiod {
51983d8817e4Smiod func (f);
51993d8817e4Smiod }
52003d8817e4Smiod }
52013d8817e4Smiod
52023d8817e4Smiod void
ldlang_add_file(lang_input_statement_type * entry)52033d8817e4Smiod ldlang_add_file (lang_input_statement_type *entry)
52043d8817e4Smiod {
52053d8817e4Smiod bfd **pp;
52063d8817e4Smiod
52073d8817e4Smiod lang_statement_append (&file_chain,
52083d8817e4Smiod (lang_statement_union_type *) entry,
52093d8817e4Smiod &entry->next);
52103d8817e4Smiod
52113d8817e4Smiod /* The BFD linker needs to have a list of all input BFDs involved in
52123d8817e4Smiod a link. */
52133d8817e4Smiod ASSERT (entry->the_bfd->link_next == NULL);
52143d8817e4Smiod ASSERT (entry->the_bfd != output_bfd);
52153d8817e4Smiod for (pp = &link_info.input_bfds; *pp != NULL; pp = &(*pp)->link_next)
52163d8817e4Smiod ;
52173d8817e4Smiod *pp = entry->the_bfd;
52183d8817e4Smiod entry->the_bfd->usrdata = entry;
52193d8817e4Smiod bfd_set_gp_size (entry->the_bfd, g_switch_value);
52203d8817e4Smiod
52213d8817e4Smiod /* Look through the sections and check for any which should not be
52223d8817e4Smiod included in the link. We need to do this now, so that we can
52233d8817e4Smiod notice when the backend linker tries to report multiple
52243d8817e4Smiod definition errors for symbols which are in sections we aren't
52253d8817e4Smiod going to link. FIXME: It might be better to entirely ignore
52263d8817e4Smiod symbols which are defined in sections which are going to be
52273d8817e4Smiod discarded. This would require modifying the backend linker for
52283d8817e4Smiod each backend which might set the SEC_LINK_ONCE flag. If we do
52293d8817e4Smiod this, we should probably handle SEC_EXCLUDE in the same way. */
52303d8817e4Smiod
52313d8817e4Smiod bfd_map_over_sections (entry->the_bfd, section_already_linked, entry);
52323d8817e4Smiod }
52333d8817e4Smiod
52343d8817e4Smiod void
lang_add_output(const char * name,int from_script)52353d8817e4Smiod lang_add_output (const char *name, int from_script)
52363d8817e4Smiod {
52373d8817e4Smiod /* Make -o on command line override OUTPUT in script. */
52383d8817e4Smiod if (!had_output_filename || !from_script)
52393d8817e4Smiod {
52403d8817e4Smiod output_filename = name;
52413d8817e4Smiod had_output_filename = TRUE;
52423d8817e4Smiod }
52433d8817e4Smiod }
52443d8817e4Smiod
52453d8817e4Smiod static lang_output_section_statement_type *current_section;
52463d8817e4Smiod
52473d8817e4Smiod static int
topower(int x)52483d8817e4Smiod topower (int x)
52493d8817e4Smiod {
52503d8817e4Smiod unsigned int i = 1;
52513d8817e4Smiod int l;
52523d8817e4Smiod
52533d8817e4Smiod if (x < 0)
52543d8817e4Smiod return -1;
52553d8817e4Smiod
52563d8817e4Smiod for (l = 0; l < 32; l++)
52573d8817e4Smiod {
52583d8817e4Smiod if (i >= (unsigned int) x)
52593d8817e4Smiod return l;
52603d8817e4Smiod i <<= 1;
52613d8817e4Smiod }
52623d8817e4Smiod
52633d8817e4Smiod return 0;
52643d8817e4Smiod }
52653d8817e4Smiod
52663d8817e4Smiod 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 * align,etree_type * subalign,etree_type * ebase,int constraint)52673d8817e4Smiod lang_enter_output_section_statement (const char *output_section_statement_name,
52683d8817e4Smiod etree_type *address_exp,
52693d8817e4Smiod enum section_type sectype,
52703d8817e4Smiod etree_type *align,
52713d8817e4Smiod etree_type *subalign,
52723d8817e4Smiod etree_type *ebase,
52733d8817e4Smiod int constraint)
52743d8817e4Smiod {
52753d8817e4Smiod lang_output_section_statement_type *os;
52763d8817e4Smiod
52773d8817e4Smiod os = lang_output_section_statement_lookup_1 (output_section_statement_name,
52783d8817e4Smiod constraint);
52793d8817e4Smiod current_section = os;
52803d8817e4Smiod
52813d8817e4Smiod /* Make next things chain into subchain of this. */
52823d8817e4Smiod
52833d8817e4Smiod if (os->addr_tree == NULL)
52843d8817e4Smiod {
52853d8817e4Smiod os->addr_tree = address_exp;
52863d8817e4Smiod }
52873d8817e4Smiod os->sectype = sectype;
52883d8817e4Smiod if (sectype != noload_section)
52893d8817e4Smiod os->flags = SEC_NO_FLAGS;
52903d8817e4Smiod else
52913d8817e4Smiod os->flags = SEC_NEVER_LOAD;
52923d8817e4Smiod os->block_value = 1;
52933d8817e4Smiod stat_ptr = &os->children;
52943d8817e4Smiod
52953d8817e4Smiod os->subsection_alignment =
52963d8817e4Smiod topower (exp_get_value_int (subalign, -1, "subsection alignment"));
52973d8817e4Smiod os->section_alignment =
52983d8817e4Smiod topower (exp_get_value_int (align, -1, "section alignment"));
52993d8817e4Smiod
53003d8817e4Smiod os->load_base = ebase;
53013d8817e4Smiod return os;
53023d8817e4Smiod }
53033d8817e4Smiod
53043d8817e4Smiod void
lang_final(void)53053d8817e4Smiod lang_final (void)
53063d8817e4Smiod {
53073d8817e4Smiod lang_output_statement_type *new;
53083d8817e4Smiod
53093d8817e4Smiod new = new_stat (lang_output_statement, stat_ptr);
53103d8817e4Smiod new->name = output_filename;
53113d8817e4Smiod }
53123d8817e4Smiod
53133d8817e4Smiod /* Reset the current counters in the regions. */
53143d8817e4Smiod
53153d8817e4Smiod void
lang_reset_memory_regions(void)53163d8817e4Smiod lang_reset_memory_regions (void)
53173d8817e4Smiod {
53183d8817e4Smiod lang_memory_region_type *p = lang_memory_region_list;
53193d8817e4Smiod asection *o;
53203d8817e4Smiod lang_output_section_statement_type *os;
53213d8817e4Smiod
53223d8817e4Smiod for (p = lang_memory_region_list; p != NULL; p = p->next)
53233d8817e4Smiod {
53243d8817e4Smiod p->old_length = (bfd_size_type) (p->current - p->origin);
53253d8817e4Smiod p->current = p->origin;
53263d8817e4Smiod }
53273d8817e4Smiod
53283d8817e4Smiod for (os = &lang_output_section_statement.head->output_section_statement;
53293d8817e4Smiod os != NULL;
53303d8817e4Smiod os = os->next)
53313d8817e4Smiod os->processed = FALSE;
53323d8817e4Smiod
53333d8817e4Smiod for (o = output_bfd->sections; o != NULL; o = o->next)
53343d8817e4Smiod {
53353d8817e4Smiod /* Save the last size for possible use by bfd_relax_section. */
53363d8817e4Smiod o->rawsize = o->size;
53373d8817e4Smiod o->size = 0;
53383d8817e4Smiod }
53393d8817e4Smiod }
53403d8817e4Smiod
53413d8817e4Smiod /* Worker for lang_gc_sections_1. */
53423d8817e4Smiod
53433d8817e4Smiod static void
gc_section_callback(lang_wild_statement_type * ptr,struct wildcard_list * sec ATTRIBUTE_UNUSED,asection * section,lang_input_statement_type * file ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)53443d8817e4Smiod gc_section_callback (lang_wild_statement_type *ptr,
53453d8817e4Smiod struct wildcard_list *sec ATTRIBUTE_UNUSED,
53463d8817e4Smiod asection *section,
53473d8817e4Smiod lang_input_statement_type *file ATTRIBUTE_UNUSED,
53483d8817e4Smiod void *data ATTRIBUTE_UNUSED)
53493d8817e4Smiod {
53503d8817e4Smiod /* If the wild pattern was marked KEEP, the member sections
53513d8817e4Smiod should be as well. */
53523d8817e4Smiod if (ptr->keep_sections)
53533d8817e4Smiod section->flags |= SEC_KEEP;
53543d8817e4Smiod }
53553d8817e4Smiod
53563d8817e4Smiod /* Iterate over sections marking them against GC. */
53573d8817e4Smiod
53583d8817e4Smiod static void
lang_gc_sections_1(lang_statement_union_type * s)53593d8817e4Smiod lang_gc_sections_1 (lang_statement_union_type *s)
53603d8817e4Smiod {
53613d8817e4Smiod for (; s != NULL; s = s->header.next)
53623d8817e4Smiod {
53633d8817e4Smiod switch (s->header.type)
53643d8817e4Smiod {
53653d8817e4Smiod case lang_wild_statement_enum:
53663d8817e4Smiod walk_wild (&s->wild_statement, gc_section_callback, NULL);
53673d8817e4Smiod break;
53683d8817e4Smiod case lang_constructors_statement_enum:
53693d8817e4Smiod lang_gc_sections_1 (constructor_list.head);
53703d8817e4Smiod break;
53713d8817e4Smiod case lang_output_section_statement_enum:
53723d8817e4Smiod lang_gc_sections_1 (s->output_section_statement.children.head);
53733d8817e4Smiod break;
53743d8817e4Smiod case lang_group_statement_enum:
53753d8817e4Smiod lang_gc_sections_1 (s->group_statement.children.head);
53763d8817e4Smiod break;
53773d8817e4Smiod default:
53783d8817e4Smiod break;
53793d8817e4Smiod }
53803d8817e4Smiod }
53813d8817e4Smiod }
53823d8817e4Smiod
53833d8817e4Smiod static void
lang_gc_sections(void)53843d8817e4Smiod lang_gc_sections (void)
53853d8817e4Smiod {
53863d8817e4Smiod struct bfd_link_hash_entry *h;
53873d8817e4Smiod ldlang_undef_chain_list_type *ulist;
53883d8817e4Smiod
53893d8817e4Smiod /* Keep all sections so marked in the link script. */
53903d8817e4Smiod
53913d8817e4Smiod lang_gc_sections_1 (statement_list.head);
53923d8817e4Smiod
53933d8817e4Smiod /* Keep all sections containing symbols undefined on the command-line,
53943d8817e4Smiod and the section containing the entry symbol. */
53953d8817e4Smiod
53963d8817e4Smiod for (ulist = link_info.gc_sym_list; ulist; ulist = ulist->next)
53973d8817e4Smiod {
53983d8817e4Smiod h = bfd_link_hash_lookup (link_info.hash, ulist->name,
53993d8817e4Smiod FALSE, FALSE, FALSE);
54003d8817e4Smiod
54013d8817e4Smiod if (h != NULL
54023d8817e4Smiod && (h->type == bfd_link_hash_defined
54033d8817e4Smiod || h->type == bfd_link_hash_defweak)
54043d8817e4Smiod && ! bfd_is_abs_section (h->u.def.section))
54053d8817e4Smiod {
54063d8817e4Smiod h->u.def.section->flags |= SEC_KEEP;
54073d8817e4Smiod }
54083d8817e4Smiod }
54093d8817e4Smiod
54103d8817e4Smiod /* SEC_EXCLUDE is ignored when doing a relocatable link, except in
54113d8817e4Smiod the special case of debug info. (See bfd/stabs.c)
54123d8817e4Smiod Twiddle the flag here, to simplify later linker code. */
54133d8817e4Smiod if (link_info.relocatable)
54143d8817e4Smiod {
54153d8817e4Smiod LANG_FOR_EACH_INPUT_STATEMENT (f)
54163d8817e4Smiod {
54173d8817e4Smiod asection *sec;
54183d8817e4Smiod for (sec = f->the_bfd->sections; sec != NULL; sec = sec->next)
54193d8817e4Smiod if ((sec->flags & SEC_DEBUGGING) == 0)
54203d8817e4Smiod sec->flags &= ~SEC_EXCLUDE;
54213d8817e4Smiod }
54223d8817e4Smiod }
54233d8817e4Smiod
54243d8817e4Smiod if (link_info.gc_sections)
54253d8817e4Smiod bfd_gc_sections (output_bfd, &link_info);
54263d8817e4Smiod }
54273d8817e4Smiod
54283d8817e4Smiod /* Relax all sections until bfd_relax_section gives up. */
54293d8817e4Smiod
54303d8817e4Smiod static void
relax_sections(void)54313d8817e4Smiod relax_sections (void)
54323d8817e4Smiod {
54333d8817e4Smiod /* Keep relaxing until bfd_relax_section gives up. */
54343d8817e4Smiod bfd_boolean relax_again;
54353d8817e4Smiod
54363d8817e4Smiod do
54373d8817e4Smiod {
54383d8817e4Smiod relax_again = FALSE;
54393d8817e4Smiod
54403d8817e4Smiod /* Note: pe-dll.c does something like this also. If you find
54413d8817e4Smiod you need to change this code, you probably need to change
54423d8817e4Smiod pe-dll.c also. DJ */
54433d8817e4Smiod
54443d8817e4Smiod /* Do all the assignments with our current guesses as to
54453d8817e4Smiod section sizes. */
54463d8817e4Smiod lang_do_assignments ();
54473d8817e4Smiod
54483d8817e4Smiod /* We must do this after lang_do_assignments, because it uses
54493d8817e4Smiod size. */
54503d8817e4Smiod lang_reset_memory_regions ();
54513d8817e4Smiod
54523d8817e4Smiod /* Perform another relax pass - this time we know where the
54533d8817e4Smiod globals are, so can make a better guess. */
54543d8817e4Smiod lang_size_sections (&relax_again, FALSE);
54553d8817e4Smiod }
54563d8817e4Smiod while (relax_again);
54573d8817e4Smiod }
54583d8817e4Smiod
54593d8817e4Smiod void
lang_process(void)54603d8817e4Smiod lang_process (void)
54613d8817e4Smiod {
54623d8817e4Smiod current_target = default_target;
54633d8817e4Smiod
54643d8817e4Smiod /* Open the output file. */
54653d8817e4Smiod lang_for_each_statement (ldlang_open_output);
54663d8817e4Smiod init_opb ();
54673d8817e4Smiod
54683d8817e4Smiod ldemul_create_output_section_statements ();
54693d8817e4Smiod
54703d8817e4Smiod /* Add to the hash table all undefineds on the command line. */
54713d8817e4Smiod lang_place_undefineds ();
54723d8817e4Smiod
54733d8817e4Smiod if (!bfd_section_already_linked_table_init ())
54743d8817e4Smiod einfo (_("%P%F: Failed to create hash table\n"));
54753d8817e4Smiod
54763d8817e4Smiod /* Create a bfd for each input file. */
54773d8817e4Smiod current_target = default_target;
54783d8817e4Smiod open_input_bfds (statement_list.head, FALSE);
54793d8817e4Smiod
54803d8817e4Smiod link_info.gc_sym_list = &entry_symbol;
54813d8817e4Smiod if (entry_symbol.name == NULL)
54823d8817e4Smiod link_info.gc_sym_list = ldlang_undef_chain_list_head;
54833d8817e4Smiod
54843d8817e4Smiod ldemul_after_open ();
54853d8817e4Smiod
54863d8817e4Smiod bfd_section_already_linked_table_free ();
54873d8817e4Smiod
54883d8817e4Smiod /* Make sure that we're not mixing architectures. We call this
54893d8817e4Smiod after all the input files have been opened, but before we do any
54903d8817e4Smiod other processing, so that any operations merge_private_bfd_data
54913d8817e4Smiod does on the output file will be known during the rest of the
54923d8817e4Smiod link. */
54933d8817e4Smiod lang_check ();
54943d8817e4Smiod
54953d8817e4Smiod /* Handle .exports instead of a version script if we're told to do so. */
54963d8817e4Smiod if (command_line.version_exports_section)
54973d8817e4Smiod lang_do_version_exports_section ();
54983d8817e4Smiod
54993d8817e4Smiod /* Build all sets based on the information gathered from the input
55003d8817e4Smiod files. */
55013d8817e4Smiod ldctor_build_sets ();
55023d8817e4Smiod
55033d8817e4Smiod /* Remove unreferenced sections if asked to. */
55043d8817e4Smiod lang_gc_sections ();
55053d8817e4Smiod
55063d8817e4Smiod /* Size up the common data. */
55073d8817e4Smiod lang_common ();
55083d8817e4Smiod
55093d8817e4Smiod /* Update wild statements. */
55103d8817e4Smiod update_wild_statements (statement_list.head);
55113d8817e4Smiod
55123d8817e4Smiod /* Run through the contours of the script and attach input sections
55133d8817e4Smiod to the correct output sections. */
55143d8817e4Smiod map_input_to_output_sections (statement_list.head, NULL, NULL);
55153d8817e4Smiod
55163d8817e4Smiod /* Find any sections not attached explicitly and handle them. */
55173d8817e4Smiod lang_place_orphans ();
55183d8817e4Smiod
55193d8817e4Smiod if (! link_info.relocatable)
55203d8817e4Smiod {
55213d8817e4Smiod asection *found;
55223d8817e4Smiod
55233d8817e4Smiod /* Merge SEC_MERGE sections. This has to be done after GC of
55243d8817e4Smiod sections, so that GCed sections are not merged, but before
55253d8817e4Smiod assigning dynamic symbols, since removing whole input sections
55263d8817e4Smiod is hard then. */
55273d8817e4Smiod bfd_merge_sections (output_bfd, &link_info);
55283d8817e4Smiod
55293d8817e4Smiod /* Look for a text section and set the readonly attribute in it. */
55303d8817e4Smiod found = bfd_get_section_by_name (output_bfd, ".text");
55313d8817e4Smiod
55323d8817e4Smiod if (found != NULL)
55333d8817e4Smiod {
55343d8817e4Smiod if (config.text_read_only)
55353d8817e4Smiod found->flags |= SEC_READONLY;
55363d8817e4Smiod else
55373d8817e4Smiod found->flags &= ~SEC_READONLY;
55383d8817e4Smiod }
55393d8817e4Smiod }
55403d8817e4Smiod
55413d8817e4Smiod /* Do anything special before sizing sections. This is where ELF
55423d8817e4Smiod and other back-ends size dynamic sections. */
55433d8817e4Smiod ldemul_before_allocation ();
55443d8817e4Smiod
55453d8817e4Smiod /* We must record the program headers before we try to fix the
55463d8817e4Smiod section positions, since they will affect SIZEOF_HEADERS. */
55473d8817e4Smiod lang_record_phdrs ();
55483d8817e4Smiod
55493d8817e4Smiod /* Size up the sections. */
55503d8817e4Smiod lang_size_sections (NULL, !command_line.relax);
55513d8817e4Smiod
55523d8817e4Smiod /* Now run around and relax if we can. */
55533d8817e4Smiod if (command_line.relax)
55543d8817e4Smiod {
55553d8817e4Smiod /* We may need more than one relaxation pass. */
55563d8817e4Smiod int i = link_info.relax_pass;
55573d8817e4Smiod
55583d8817e4Smiod /* The backend can use it to determine the current pass. */
55593d8817e4Smiod link_info.relax_pass = 0;
55603d8817e4Smiod
55613d8817e4Smiod while (i--)
55623d8817e4Smiod {
55633d8817e4Smiod relax_sections ();
55643d8817e4Smiod link_info.relax_pass++;
55653d8817e4Smiod }
55663d8817e4Smiod
55673d8817e4Smiod /* Final extra sizing to report errors. */
55683d8817e4Smiod lang_do_assignments ();
55693d8817e4Smiod lang_reset_memory_regions ();
55703d8817e4Smiod lang_size_sections (NULL, TRUE);
55713d8817e4Smiod }
55723d8817e4Smiod
55733d8817e4Smiod /* See if anything special should be done now we know how big
55743d8817e4Smiod everything is. */
55753d8817e4Smiod ldemul_after_allocation ();
55763d8817e4Smiod
55773d8817e4Smiod /* Fix any .startof. or .sizeof. symbols. */
55783d8817e4Smiod lang_set_startof ();
55793d8817e4Smiod
55803d8817e4Smiod /* Do all the assignments, now that we know the final resting places
55813d8817e4Smiod of all the symbols. */
55823d8817e4Smiod
55833d8817e4Smiod lang_do_assignments ();
55843d8817e4Smiod
55853d8817e4Smiod /* Make sure that the section addresses make sense. */
55863d8817e4Smiod if (! link_info.relocatable
55873d8817e4Smiod && command_line.check_section_addresses)
55883d8817e4Smiod lang_check_section_addresses ();
55893d8817e4Smiod
55903d8817e4Smiod /* Final stuffs. */
55913d8817e4Smiod ldemul_finish ();
55923d8817e4Smiod lang_end ();
55933d8817e4Smiod }
55943d8817e4Smiod
55953d8817e4Smiod /* EXPORTED TO YACC */
55963d8817e4Smiod
55973d8817e4Smiod void
lang_add_wild(struct wildcard_spec * filespec,struct wildcard_list * section_list,bfd_boolean keep_sections)55983d8817e4Smiod lang_add_wild (struct wildcard_spec *filespec,
55993d8817e4Smiod struct wildcard_list *section_list,
56003d8817e4Smiod bfd_boolean keep_sections)
56013d8817e4Smiod {
56023d8817e4Smiod struct wildcard_list *curr, *next;
56033d8817e4Smiod lang_wild_statement_type *new;
56043d8817e4Smiod
56053d8817e4Smiod /* Reverse the list as the parser puts it back to front. */
56063d8817e4Smiod for (curr = section_list, section_list = NULL;
56073d8817e4Smiod curr != NULL;
56083d8817e4Smiod section_list = curr, curr = next)
56093d8817e4Smiod {
56103d8817e4Smiod if (curr->spec.name != NULL && strcmp (curr->spec.name, "COMMON") == 0)
56113d8817e4Smiod placed_commons = TRUE;
56123d8817e4Smiod
56133d8817e4Smiod next = curr->next;
56143d8817e4Smiod curr->next = section_list;
56153d8817e4Smiod }
56163d8817e4Smiod
56173d8817e4Smiod if (filespec != NULL && filespec->name != NULL)
56183d8817e4Smiod {
56193d8817e4Smiod if (strcmp (filespec->name, "*") == 0)
56203d8817e4Smiod filespec->name = NULL;
56213d8817e4Smiod else if (! wildcardp (filespec->name))
56223d8817e4Smiod lang_has_input_file = TRUE;
56233d8817e4Smiod }
56243d8817e4Smiod
56253d8817e4Smiod new = new_stat (lang_wild_statement, stat_ptr);
56263d8817e4Smiod new->filename = NULL;
56273d8817e4Smiod new->filenames_sorted = FALSE;
56283d8817e4Smiod if (filespec != NULL)
56293d8817e4Smiod {
56303d8817e4Smiod new->filename = filespec->name;
56313d8817e4Smiod new->filenames_sorted = filespec->sorted == by_name;
56323d8817e4Smiod }
56333d8817e4Smiod new->section_list = section_list;
56343d8817e4Smiod new->keep_sections = keep_sections;
56353d8817e4Smiod lang_list_init (&new->children);
56363d8817e4Smiod analyze_walk_wild_section_handler (new);
56373d8817e4Smiod }
56383d8817e4Smiod
56393d8817e4Smiod void
lang_section_start(const char * name,etree_type * address,const segment_type * segment)56403d8817e4Smiod lang_section_start (const char *name, etree_type *address,
56413d8817e4Smiod const segment_type *segment)
56423d8817e4Smiod {
56433d8817e4Smiod lang_address_statement_type *ad;
56443d8817e4Smiod
56453d8817e4Smiod ad = new_stat (lang_address_statement, stat_ptr);
56463d8817e4Smiod ad->section_name = name;
56473d8817e4Smiod ad->address = address;
56483d8817e4Smiod ad->segment = segment;
56493d8817e4Smiod }
56503d8817e4Smiod
56513d8817e4Smiod /* Set the start symbol to NAME. CMDLINE is nonzero if this is called
56523d8817e4Smiod because of a -e argument on the command line, or zero if this is
56533d8817e4Smiod called by ENTRY in a linker script. Command line arguments take
56543d8817e4Smiod precedence. */
56553d8817e4Smiod
56563d8817e4Smiod void
lang_add_entry(const char * name,bfd_boolean cmdline)56573d8817e4Smiod lang_add_entry (const char *name, bfd_boolean cmdline)
56583d8817e4Smiod {
56593d8817e4Smiod if (entry_symbol.name == NULL
56603d8817e4Smiod || cmdline
56613d8817e4Smiod || ! entry_from_cmdline)
56623d8817e4Smiod {
56633d8817e4Smiod entry_symbol.name = name;
56643d8817e4Smiod entry_from_cmdline = cmdline;
56653d8817e4Smiod }
56663d8817e4Smiod }
56673d8817e4Smiod
56683d8817e4Smiod /* Set the default start symbol to NAME. .em files should use this,
56693d8817e4Smiod not lang_add_entry, to override the use of "start" if neither the
56703d8817e4Smiod linker script nor the command line specifies an entry point. NAME
56713d8817e4Smiod must be permanently allocated. */
56723d8817e4Smiod void
lang_default_entry(const char * name)56733d8817e4Smiod lang_default_entry (const char *name)
56743d8817e4Smiod {
56753d8817e4Smiod entry_symbol_default = name;
56763d8817e4Smiod }
56773d8817e4Smiod
56783d8817e4Smiod void
lang_add_target(const char * name)56793d8817e4Smiod lang_add_target (const char *name)
56803d8817e4Smiod {
56813d8817e4Smiod lang_target_statement_type *new;
56823d8817e4Smiod
56833d8817e4Smiod new = new_stat (lang_target_statement, stat_ptr);
56843d8817e4Smiod new->target = name;
56853d8817e4Smiod }
56863d8817e4Smiod
56873d8817e4Smiod void
lang_add_map(const char * name)56883d8817e4Smiod lang_add_map (const char *name)
56893d8817e4Smiod {
56903d8817e4Smiod while (*name)
56913d8817e4Smiod {
56923d8817e4Smiod switch (*name)
56933d8817e4Smiod {
56943d8817e4Smiod case 'F':
56953d8817e4Smiod map_option_f = TRUE;
56963d8817e4Smiod break;
56973d8817e4Smiod }
56983d8817e4Smiod name++;
56993d8817e4Smiod }
57003d8817e4Smiod }
57013d8817e4Smiod
57023d8817e4Smiod void
lang_add_fill(fill_type * fill)57033d8817e4Smiod lang_add_fill (fill_type *fill)
57043d8817e4Smiod {
57053d8817e4Smiod lang_fill_statement_type *new;
57063d8817e4Smiod
57073d8817e4Smiod new = new_stat (lang_fill_statement, stat_ptr);
57083d8817e4Smiod new->fill = fill;
57093d8817e4Smiod }
57103d8817e4Smiod
57113d8817e4Smiod void
lang_add_data(int type,union etree_union * exp)57123d8817e4Smiod lang_add_data (int type, union etree_union *exp)
57133d8817e4Smiod {
57143d8817e4Smiod lang_data_statement_type *new;
57153d8817e4Smiod
57163d8817e4Smiod new = new_stat (lang_data_statement, stat_ptr);
57173d8817e4Smiod new->exp = exp;
57183d8817e4Smiod new->type = type;
57193d8817e4Smiod }
57203d8817e4Smiod
57213d8817e4Smiod /* Create a new reloc statement. RELOC is the BFD relocation type to
57223d8817e4Smiod generate. HOWTO is the corresponding howto structure (we could
57233d8817e4Smiod look this up, but the caller has already done so). SECTION is the
57243d8817e4Smiod section to generate a reloc against, or NAME is the name of the
57253d8817e4Smiod symbol to generate a reloc against. Exactly one of SECTION and
57263d8817e4Smiod NAME must be NULL. ADDEND is an expression for the addend. */
57273d8817e4Smiod
57283d8817e4Smiod void
lang_add_reloc(bfd_reloc_code_real_type reloc,reloc_howto_type * howto,asection * section,const char * name,union etree_union * addend)57293d8817e4Smiod lang_add_reloc (bfd_reloc_code_real_type reloc,
57303d8817e4Smiod reloc_howto_type *howto,
57313d8817e4Smiod asection *section,
57323d8817e4Smiod const char *name,
57333d8817e4Smiod union etree_union *addend)
57343d8817e4Smiod {
57353d8817e4Smiod lang_reloc_statement_type *p = new_stat (lang_reloc_statement, stat_ptr);
57363d8817e4Smiod
57373d8817e4Smiod p->reloc = reloc;
57383d8817e4Smiod p->howto = howto;
57393d8817e4Smiod p->section = section;
57403d8817e4Smiod p->name = name;
57413d8817e4Smiod p->addend_exp = addend;
57423d8817e4Smiod
57433d8817e4Smiod p->addend_value = 0;
57443d8817e4Smiod p->output_section = NULL;
57453d8817e4Smiod p->output_offset = 0;
57463d8817e4Smiod }
57473d8817e4Smiod
57483d8817e4Smiod lang_assignment_statement_type *
lang_add_assignment(etree_type * exp)57493d8817e4Smiod lang_add_assignment (etree_type *exp)
57503d8817e4Smiod {
57513d8817e4Smiod lang_assignment_statement_type *new;
57523d8817e4Smiod
57533d8817e4Smiod new = new_stat (lang_assignment_statement, stat_ptr);
57543d8817e4Smiod new->exp = exp;
57553d8817e4Smiod return new;
57563d8817e4Smiod }
57573d8817e4Smiod
57583d8817e4Smiod void
lang_add_attribute(enum statement_enum attribute)57593d8817e4Smiod lang_add_attribute (enum statement_enum attribute)
57603d8817e4Smiod {
57613d8817e4Smiod new_statement (attribute, sizeof (lang_statement_header_type), stat_ptr);
57623d8817e4Smiod }
57633d8817e4Smiod
57643d8817e4Smiod void
lang_startup(const char * name)57653d8817e4Smiod lang_startup (const char *name)
57663d8817e4Smiod {
57673d8817e4Smiod if (startup_file != NULL)
57683d8817e4Smiod {
57693d8817e4Smiod einfo (_("%P%F: multiple STARTUP files\n"));
57703d8817e4Smiod }
57713d8817e4Smiod first_file->filename = name;
57723d8817e4Smiod first_file->local_sym_name = name;
57733d8817e4Smiod first_file->real = TRUE;
57743d8817e4Smiod
57753d8817e4Smiod startup_file = name;
57763d8817e4Smiod }
57773d8817e4Smiod
57783d8817e4Smiod void
lang_float(bfd_boolean maybe)57793d8817e4Smiod lang_float (bfd_boolean maybe)
57803d8817e4Smiod {
57813d8817e4Smiod lang_float_flag = maybe;
57823d8817e4Smiod }
57833d8817e4Smiod
57843d8817e4Smiod
57853d8817e4Smiod /* Work out the load- and run-time regions from a script statement, and
57863d8817e4Smiod store them in *LMA_REGION and *REGION respectively.
57873d8817e4Smiod
57883d8817e4Smiod MEMSPEC is the name of the run-time region, or the value of
57893d8817e4Smiod DEFAULT_MEMORY_REGION if the statement didn't specify one.
57903d8817e4Smiod LMA_MEMSPEC is the name of the load-time region, or null if the
57913d8817e4Smiod statement didn't specify one.HAVE_LMA_P is TRUE if the statement
57923d8817e4Smiod had an explicit load address.
57933d8817e4Smiod
57943d8817e4Smiod It is an error to specify both a load region and a load address. */
57953d8817e4Smiod
57963d8817e4Smiod static void
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)57973d8817e4Smiod lang_get_regions (lang_memory_region_type **region,
57983d8817e4Smiod lang_memory_region_type **lma_region,
57993d8817e4Smiod const char *memspec,
58003d8817e4Smiod const char *lma_memspec,
58013d8817e4Smiod bfd_boolean have_lma,
58023d8817e4Smiod bfd_boolean have_vma)
58033d8817e4Smiod {
58043d8817e4Smiod *lma_region = lang_memory_region_lookup (lma_memspec, FALSE);
58053d8817e4Smiod
58063d8817e4Smiod /* If no runtime region or VMA has been specified, but the load region
58073d8817e4Smiod has been specified, then use the load region for the runtime region
58083d8817e4Smiod as well. */
58093d8817e4Smiod if (lma_memspec != NULL
58103d8817e4Smiod && ! have_vma
58113d8817e4Smiod && strcmp (memspec, DEFAULT_MEMORY_REGION) == 0)
58123d8817e4Smiod *region = *lma_region;
58133d8817e4Smiod else
58143d8817e4Smiod *region = lang_memory_region_lookup (memspec, FALSE);
58153d8817e4Smiod
58163d8817e4Smiod if (have_lma && lma_memspec != 0)
58173d8817e4Smiod einfo (_("%X%P:%S: section has both a load address and a load region\n"));
58183d8817e4Smiod }
58193d8817e4Smiod
58203d8817e4Smiod void
lang_leave_output_section_statement(fill_type * fill,const char * memspec,lang_output_section_phdr_list * phdrs,const char * lma_memspec)58213d8817e4Smiod lang_leave_output_section_statement (fill_type *fill, const char *memspec,
58223d8817e4Smiod lang_output_section_phdr_list *phdrs,
58233d8817e4Smiod const char *lma_memspec)
58243d8817e4Smiod {
58253d8817e4Smiod lang_get_regions (¤t_section->region,
58263d8817e4Smiod ¤t_section->lma_region,
58273d8817e4Smiod memspec, lma_memspec,
58283d8817e4Smiod current_section->load_base != NULL,
58293d8817e4Smiod current_section->addr_tree != NULL);
58303d8817e4Smiod current_section->fill = fill;
58313d8817e4Smiod current_section->phdrs = phdrs;
58323d8817e4Smiod stat_ptr = &statement_list;
58333d8817e4Smiod }
58343d8817e4Smiod
58353d8817e4Smiod /* Create an absolute symbol with the given name with the value of the
58363d8817e4Smiod address of first byte of the section named.
58373d8817e4Smiod
58383d8817e4Smiod If the symbol already exists, then do nothing. */
58393d8817e4Smiod
58403d8817e4Smiod void
lang_abs_symbol_at_beginning_of(const char * secname,const char * name)58413d8817e4Smiod lang_abs_symbol_at_beginning_of (const char *secname, const char *name)
58423d8817e4Smiod {
58433d8817e4Smiod struct bfd_link_hash_entry *h;
58443d8817e4Smiod
58453d8817e4Smiod h = bfd_link_hash_lookup (link_info.hash, name, TRUE, TRUE, TRUE);
58463d8817e4Smiod if (h == NULL)
58473d8817e4Smiod einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
58483d8817e4Smiod
58493d8817e4Smiod if (h->type == bfd_link_hash_new
58503d8817e4Smiod || h->type == bfd_link_hash_undefined)
58513d8817e4Smiod {
58523d8817e4Smiod asection *sec;
58533d8817e4Smiod
58543d8817e4Smiod h->type = bfd_link_hash_defined;
58553d8817e4Smiod
58563d8817e4Smiod sec = bfd_get_section_by_name (output_bfd, secname);
58573d8817e4Smiod if (sec == NULL)
58583d8817e4Smiod h->u.def.value = 0;
58593d8817e4Smiod else
58603d8817e4Smiod h->u.def.value = bfd_get_section_vma (output_bfd, sec);
58613d8817e4Smiod
58623d8817e4Smiod h->u.def.section = bfd_abs_section_ptr;
58633d8817e4Smiod }
58643d8817e4Smiod }
58653d8817e4Smiod
58663d8817e4Smiod /* Create an absolute symbol with the given name with the value of the
58673d8817e4Smiod address of the first byte after the end of the section named.
58683d8817e4Smiod
58693d8817e4Smiod If the symbol already exists, then do nothing. */
58703d8817e4Smiod
58713d8817e4Smiod void
lang_abs_symbol_at_end_of(const char * secname,const char * name)58723d8817e4Smiod lang_abs_symbol_at_end_of (const char *secname, const char *name)
58733d8817e4Smiod {
58743d8817e4Smiod struct bfd_link_hash_entry *h;
58753d8817e4Smiod
58763d8817e4Smiod h = bfd_link_hash_lookup (link_info.hash, name, TRUE, TRUE, TRUE);
58773d8817e4Smiod if (h == NULL)
58783d8817e4Smiod einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
58793d8817e4Smiod
58803d8817e4Smiod if (h->type == bfd_link_hash_new
58813d8817e4Smiod || h->type == bfd_link_hash_undefined)
58823d8817e4Smiod {
58833d8817e4Smiod asection *sec;
58843d8817e4Smiod
58853d8817e4Smiod h->type = bfd_link_hash_defined;
58863d8817e4Smiod
58873d8817e4Smiod sec = bfd_get_section_by_name (output_bfd, secname);
58883d8817e4Smiod if (sec == NULL)
58893d8817e4Smiod h->u.def.value = 0;
58903d8817e4Smiod else
58913d8817e4Smiod h->u.def.value = (bfd_get_section_vma (output_bfd, sec)
58923d8817e4Smiod + TO_ADDR (sec->size));
58933d8817e4Smiod
58943d8817e4Smiod h->u.def.section = bfd_abs_section_ptr;
58953d8817e4Smiod }
58963d8817e4Smiod }
58973d8817e4Smiod
58983d8817e4Smiod void
lang_statement_append(lang_statement_list_type * list,lang_statement_union_type * element,lang_statement_union_type ** field)58993d8817e4Smiod lang_statement_append (lang_statement_list_type *list,
59003d8817e4Smiod lang_statement_union_type *element,
59013d8817e4Smiod lang_statement_union_type **field)
59023d8817e4Smiod {
59033d8817e4Smiod *(list->tail) = element;
59043d8817e4Smiod list->tail = field;
59053d8817e4Smiod }
59063d8817e4Smiod
59073d8817e4Smiod /* Set the output format type. -oformat overrides scripts. */
59083d8817e4Smiod
59093d8817e4Smiod void
lang_add_output_format(const char * format,const char * big,const char * little,int from_script)59103d8817e4Smiod lang_add_output_format (const char *format,
59113d8817e4Smiod const char *big,
59123d8817e4Smiod const char *little,
59133d8817e4Smiod int from_script)
59143d8817e4Smiod {
59153d8817e4Smiod if (output_target == NULL || !from_script)
59163d8817e4Smiod {
59173d8817e4Smiod if (command_line.endian == ENDIAN_BIG
59183d8817e4Smiod && big != NULL)
59193d8817e4Smiod format = big;
59203d8817e4Smiod else if (command_line.endian == ENDIAN_LITTLE
59213d8817e4Smiod && little != NULL)
59223d8817e4Smiod format = little;
59233d8817e4Smiod
59243d8817e4Smiod output_target = format;
59253d8817e4Smiod }
59263d8817e4Smiod }
59273d8817e4Smiod
59283d8817e4Smiod /* Enter a group. This creates a new lang_group_statement, and sets
59293d8817e4Smiod stat_ptr to build new statements within the group. */
59303d8817e4Smiod
59313d8817e4Smiod void
lang_enter_group(void)59323d8817e4Smiod lang_enter_group (void)
59333d8817e4Smiod {
59343d8817e4Smiod lang_group_statement_type *g;
59353d8817e4Smiod
59363d8817e4Smiod g = new_stat (lang_group_statement, stat_ptr);
59373d8817e4Smiod lang_list_init (&g->children);
59383d8817e4Smiod stat_ptr = &g->children;
59393d8817e4Smiod }
59403d8817e4Smiod
59413d8817e4Smiod /* Leave a group. This just resets stat_ptr to start writing to the
59423d8817e4Smiod regular list of statements again. Note that this will not work if
59433d8817e4Smiod groups can occur inside anything else which can adjust stat_ptr,
59443d8817e4Smiod but currently they can't. */
59453d8817e4Smiod
59463d8817e4Smiod void
lang_leave_group(void)59473d8817e4Smiod lang_leave_group (void)
59483d8817e4Smiod {
59493d8817e4Smiod stat_ptr = &statement_list;
59503d8817e4Smiod }
59513d8817e4Smiod
59523d8817e4Smiod /* Add a new program header. This is called for each entry in a PHDRS
59533d8817e4Smiod command in a linker script. */
59543d8817e4Smiod
59553d8817e4Smiod void
lang_new_phdr(const char * name,etree_type * type,bfd_boolean filehdr,bfd_boolean phdrs,etree_type * at,etree_type * flags)59563d8817e4Smiod lang_new_phdr (const char *name,
59573d8817e4Smiod etree_type *type,
59583d8817e4Smiod bfd_boolean filehdr,
59593d8817e4Smiod bfd_boolean phdrs,
59603d8817e4Smiod etree_type *at,
59613d8817e4Smiod etree_type *flags)
59623d8817e4Smiod {
59633d8817e4Smiod struct lang_phdr *n, **pp;
59643d8817e4Smiod
59653d8817e4Smiod n = stat_alloc (sizeof (struct lang_phdr));
59663d8817e4Smiod n->next = NULL;
59673d8817e4Smiod n->name = name;
59683d8817e4Smiod n->type = exp_get_value_int (type, 0, "program header type");
59693d8817e4Smiod n->filehdr = filehdr;
59703d8817e4Smiod n->phdrs = phdrs;
59713d8817e4Smiod n->at = at;
59723d8817e4Smiod n->flags = flags;
59733d8817e4Smiod
59743d8817e4Smiod for (pp = &lang_phdr_list; *pp != NULL; pp = &(*pp)->next)
59753d8817e4Smiod ;
59763d8817e4Smiod *pp = n;
59773d8817e4Smiod }
59783d8817e4Smiod
59793d8817e4Smiod /* Record the program header information in the output BFD. FIXME: We
59803d8817e4Smiod should not be calling an ELF specific function here. */
59813d8817e4Smiod
59823d8817e4Smiod static void
lang_record_phdrs(void)59833d8817e4Smiod lang_record_phdrs (void)
59843d8817e4Smiod {
59853d8817e4Smiod unsigned int alc;
59863d8817e4Smiod asection **secs;
59873d8817e4Smiod lang_output_section_phdr_list *last;
59883d8817e4Smiod struct lang_phdr *l;
59893d8817e4Smiod lang_output_section_statement_type *os;
59903d8817e4Smiod
59913d8817e4Smiod alc = 10;
59923d8817e4Smiod secs = xmalloc (alc * sizeof (asection *));
59933d8817e4Smiod last = NULL;
59943d8817e4Smiod for (l = lang_phdr_list; l != NULL; l = l->next)
59953d8817e4Smiod {
59963d8817e4Smiod unsigned int c;
59973d8817e4Smiod flagword flags;
59983d8817e4Smiod bfd_vma at;
59993d8817e4Smiod
60003d8817e4Smiod c = 0;
60013d8817e4Smiod for (os = &lang_output_section_statement.head->output_section_statement;
60023d8817e4Smiod os != NULL;
60033d8817e4Smiod os = os->next)
60043d8817e4Smiod {
60053d8817e4Smiod lang_output_section_phdr_list *pl;
60063d8817e4Smiod
60073d8817e4Smiod if (os->constraint == -1)
60083d8817e4Smiod continue;
60093d8817e4Smiod
60103d8817e4Smiod pl = os->phdrs;
60113d8817e4Smiod if (pl != NULL)
60123d8817e4Smiod last = pl;
60133d8817e4Smiod else
60143d8817e4Smiod {
60153d8817e4Smiod if (os->sectype == noload_section
60163d8817e4Smiod || os->bfd_section == NULL
60173d8817e4Smiod || (os->bfd_section->flags & SEC_ALLOC) == 0)
60183d8817e4Smiod continue;
60193d8817e4Smiod pl = last;
60203d8817e4Smiod }
60213d8817e4Smiod
60223d8817e4Smiod if (os->bfd_section == NULL)
60233d8817e4Smiod continue;
60243d8817e4Smiod
60253d8817e4Smiod for (; pl != NULL; pl = pl->next)
60263d8817e4Smiod {
60273d8817e4Smiod if (strcmp (pl->name, l->name) == 0)
60283d8817e4Smiod {
60293d8817e4Smiod if (c >= alc)
60303d8817e4Smiod {
60313d8817e4Smiod alc *= 2;
60323d8817e4Smiod secs = xrealloc (secs, alc * sizeof (asection *));
60333d8817e4Smiod }
60343d8817e4Smiod secs[c] = os->bfd_section;
60353d8817e4Smiod ++c;
60363d8817e4Smiod pl->used = TRUE;
60373d8817e4Smiod }
60383d8817e4Smiod }
60393d8817e4Smiod }
60403d8817e4Smiod
60413d8817e4Smiod if (l->flags == NULL)
60423d8817e4Smiod flags = 0;
60433d8817e4Smiod else
60443d8817e4Smiod flags = exp_get_vma (l->flags, 0, "phdr flags");
60453d8817e4Smiod
60463d8817e4Smiod if (l->at == NULL)
60473d8817e4Smiod at = 0;
60483d8817e4Smiod else
60493d8817e4Smiod at = exp_get_vma (l->at, 0, "phdr load address");
60503d8817e4Smiod
60513d8817e4Smiod if (! bfd_record_phdr (output_bfd, l->type,
60523d8817e4Smiod l->flags != NULL, flags, l->at != NULL,
60533d8817e4Smiod at, l->filehdr, l->phdrs, c, secs))
60543d8817e4Smiod einfo (_("%F%P: bfd_record_phdr failed: %E\n"));
60553d8817e4Smiod }
60563d8817e4Smiod
60573d8817e4Smiod free (secs);
60583d8817e4Smiod
60593d8817e4Smiod /* Make sure all the phdr assignments succeeded. */
60603d8817e4Smiod for (os = &lang_output_section_statement.head->output_section_statement;
60613d8817e4Smiod os != NULL;
60623d8817e4Smiod os = os->next)
60633d8817e4Smiod {
60643d8817e4Smiod lang_output_section_phdr_list *pl;
60653d8817e4Smiod
60663d8817e4Smiod if (os->constraint == -1
60673d8817e4Smiod || os->bfd_section == NULL)
60683d8817e4Smiod continue;
60693d8817e4Smiod
60703d8817e4Smiod for (pl = os->phdrs;
60713d8817e4Smiod pl != NULL;
60723d8817e4Smiod pl = pl->next)
60733d8817e4Smiod if (! pl->used && strcmp (pl->name, "NONE") != 0)
60743d8817e4Smiod einfo (_("%X%P: section `%s' assigned to non-existent phdr `%s'\n"),
60753d8817e4Smiod os->name, pl->name);
60763d8817e4Smiod }
60773d8817e4Smiod }
60783d8817e4Smiod
60793d8817e4Smiod /* Record a list of sections which may not be cross referenced. */
60803d8817e4Smiod
60813d8817e4Smiod void
lang_add_nocrossref(lang_nocrossref_type * l)60823d8817e4Smiod lang_add_nocrossref (lang_nocrossref_type *l)
60833d8817e4Smiod {
60843d8817e4Smiod struct lang_nocrossrefs *n;
60853d8817e4Smiod
60863d8817e4Smiod n = xmalloc (sizeof *n);
60873d8817e4Smiod n->next = nocrossref_list;
60883d8817e4Smiod n->list = l;
60893d8817e4Smiod nocrossref_list = n;
60903d8817e4Smiod
60913d8817e4Smiod /* Set notice_all so that we get informed about all symbols. */
60923d8817e4Smiod link_info.notice_all = TRUE;
60933d8817e4Smiod }
60943d8817e4Smiod
60953d8817e4Smiod /* Overlay handling. We handle overlays with some static variables. */
60963d8817e4Smiod
60973d8817e4Smiod /* The overlay virtual address. */
60983d8817e4Smiod static etree_type *overlay_vma;
60993d8817e4Smiod /* And subsection alignment. */
61003d8817e4Smiod static etree_type *overlay_subalign;
61013d8817e4Smiod
61023d8817e4Smiod /* An expression for the maximum section size seen so far. */
61033d8817e4Smiod static etree_type *overlay_max;
61043d8817e4Smiod
61053d8817e4Smiod /* A list of all the sections in this overlay. */
61063d8817e4Smiod
61073d8817e4Smiod struct overlay_list {
61083d8817e4Smiod struct overlay_list *next;
61093d8817e4Smiod lang_output_section_statement_type *os;
61103d8817e4Smiod };
61113d8817e4Smiod
61123d8817e4Smiod static struct overlay_list *overlay_list;
61133d8817e4Smiod
61143d8817e4Smiod /* Start handling an overlay. */
61153d8817e4Smiod
61163d8817e4Smiod void
lang_enter_overlay(etree_type * vma_expr,etree_type * subalign)61173d8817e4Smiod lang_enter_overlay (etree_type *vma_expr, etree_type *subalign)
61183d8817e4Smiod {
61193d8817e4Smiod /* The grammar should prevent nested overlays from occurring. */
61203d8817e4Smiod ASSERT (overlay_vma == NULL
61213d8817e4Smiod && overlay_subalign == NULL
61223d8817e4Smiod && overlay_max == NULL);
61233d8817e4Smiod
61243d8817e4Smiod overlay_vma = vma_expr;
61253d8817e4Smiod overlay_subalign = subalign;
61263d8817e4Smiod }
61273d8817e4Smiod
61283d8817e4Smiod /* Start a section in an overlay. We handle this by calling
61293d8817e4Smiod lang_enter_output_section_statement with the correct VMA.
61303d8817e4Smiod lang_leave_overlay sets up the LMA and memory regions. */
61313d8817e4Smiod
61323d8817e4Smiod void
lang_enter_overlay_section(const char * name)61333d8817e4Smiod lang_enter_overlay_section (const char *name)
61343d8817e4Smiod {
61353d8817e4Smiod struct overlay_list *n;
61363d8817e4Smiod etree_type *size;
61373d8817e4Smiod
61383d8817e4Smiod lang_enter_output_section_statement (name, overlay_vma, normal_section,
61393d8817e4Smiod 0, overlay_subalign, 0, 0);
61403d8817e4Smiod
61413d8817e4Smiod /* If this is the first section, then base the VMA of future
61423d8817e4Smiod sections on this one. This will work correctly even if `.' is
61433d8817e4Smiod used in the addresses. */
61443d8817e4Smiod if (overlay_list == NULL)
61453d8817e4Smiod overlay_vma = exp_nameop (ADDR, name);
61463d8817e4Smiod
61473d8817e4Smiod /* Remember the section. */
61483d8817e4Smiod n = xmalloc (sizeof *n);
61493d8817e4Smiod n->os = current_section;
61503d8817e4Smiod n->next = overlay_list;
61513d8817e4Smiod overlay_list = n;
61523d8817e4Smiod
61533d8817e4Smiod size = exp_nameop (SIZEOF, name);
61543d8817e4Smiod
61553d8817e4Smiod /* Arrange to work out the maximum section end address. */
61563d8817e4Smiod if (overlay_max == NULL)
61573d8817e4Smiod overlay_max = size;
61583d8817e4Smiod else
61593d8817e4Smiod overlay_max = exp_binop (MAX_K, overlay_max, size);
61603d8817e4Smiod }
61613d8817e4Smiod
61623d8817e4Smiod /* Finish a section in an overlay. There isn't any special to do
61633d8817e4Smiod here. */
61643d8817e4Smiod
61653d8817e4Smiod void
lang_leave_overlay_section(fill_type * fill,lang_output_section_phdr_list * phdrs)61663d8817e4Smiod lang_leave_overlay_section (fill_type *fill,
61673d8817e4Smiod lang_output_section_phdr_list *phdrs)
61683d8817e4Smiod {
61693d8817e4Smiod const char *name;
61703d8817e4Smiod char *clean, *s2;
61713d8817e4Smiod const char *s1;
61723d8817e4Smiod char *buf;
61733d8817e4Smiod
61743d8817e4Smiod name = current_section->name;
61753d8817e4Smiod
61763d8817e4Smiod /* For now, assume that DEFAULT_MEMORY_REGION is the run-time memory
61773d8817e4Smiod region and that no load-time region has been specified. It doesn't
61783d8817e4Smiod really matter what we say here, since lang_leave_overlay will
61793d8817e4Smiod override it. */
61803d8817e4Smiod lang_leave_output_section_statement (fill, DEFAULT_MEMORY_REGION, phdrs, 0);
61813d8817e4Smiod
61823d8817e4Smiod /* Define the magic symbols. */
61833d8817e4Smiod
61843d8817e4Smiod clean = xmalloc (strlen (name) + 1);
61853d8817e4Smiod s2 = clean;
61863d8817e4Smiod for (s1 = name; *s1 != '\0'; s1++)
61873d8817e4Smiod if (ISALNUM (*s1) || *s1 == '_')
61883d8817e4Smiod *s2++ = *s1;
61893d8817e4Smiod *s2 = '\0';
61903d8817e4Smiod
61913d8817e4Smiod buf = xmalloc (strlen (clean) + sizeof "__load_start_");
61923d8817e4Smiod sprintf (buf, "__load_start_%s", clean);
61933d8817e4Smiod lang_add_assignment (exp_assop ('=', buf,
61943d8817e4Smiod exp_nameop (LOADADDR, name)));
61953d8817e4Smiod
61963d8817e4Smiod buf = xmalloc (strlen (clean) + sizeof "__load_stop_");
61973d8817e4Smiod sprintf (buf, "__load_stop_%s", clean);
61983d8817e4Smiod lang_add_assignment (exp_assop ('=', buf,
61993d8817e4Smiod exp_binop ('+',
62003d8817e4Smiod exp_nameop (LOADADDR, name),
62013d8817e4Smiod exp_nameop (SIZEOF, name))));
62023d8817e4Smiod
62033d8817e4Smiod free (clean);
62043d8817e4Smiod }
62053d8817e4Smiod
62063d8817e4Smiod /* Finish an overlay. If there are any overlay wide settings, this
62073d8817e4Smiod looks through all the sections in the overlay and sets them. */
62083d8817e4Smiod
62093d8817e4Smiod void
lang_leave_overlay(etree_type * lma_expr,int nocrossrefs,fill_type * fill,const char * memspec,lang_output_section_phdr_list * phdrs,const char * lma_memspec)62103d8817e4Smiod lang_leave_overlay (etree_type *lma_expr,
62113d8817e4Smiod int nocrossrefs,
62123d8817e4Smiod fill_type *fill,
62133d8817e4Smiod const char *memspec,
62143d8817e4Smiod lang_output_section_phdr_list *phdrs,
62153d8817e4Smiod const char *lma_memspec)
62163d8817e4Smiod {
62173d8817e4Smiod lang_memory_region_type *region;
62183d8817e4Smiod lang_memory_region_type *lma_region;
62193d8817e4Smiod struct overlay_list *l;
62203d8817e4Smiod lang_nocrossref_type *nocrossref;
62213d8817e4Smiod
62223d8817e4Smiod lang_get_regions (®ion, &lma_region,
62233d8817e4Smiod memspec, lma_memspec,
62243d8817e4Smiod lma_expr != NULL, FALSE);
62253d8817e4Smiod
62263d8817e4Smiod nocrossref = NULL;
62273d8817e4Smiod
62283d8817e4Smiod /* After setting the size of the last section, set '.' to end of the
62293d8817e4Smiod overlay region. */
62303d8817e4Smiod if (overlay_list != NULL)
62313d8817e4Smiod overlay_list->os->update_dot_tree
62323d8817e4Smiod = exp_assop ('=', ".", exp_binop ('+', overlay_vma, overlay_max));
62333d8817e4Smiod
62343d8817e4Smiod l = overlay_list;
62353d8817e4Smiod while (l != NULL)
62363d8817e4Smiod {
62373d8817e4Smiod struct overlay_list *next;
62383d8817e4Smiod
62393d8817e4Smiod if (fill != NULL && l->os->fill == NULL)
62403d8817e4Smiod l->os->fill = fill;
62413d8817e4Smiod
62423d8817e4Smiod l->os->region = region;
62433d8817e4Smiod l->os->lma_region = lma_region;
62443d8817e4Smiod
62453d8817e4Smiod /* The first section has the load address specified in the
62463d8817e4Smiod OVERLAY statement. The rest are worked out from that.
62473d8817e4Smiod The base address is not needed (and should be null) if
62483d8817e4Smiod an LMA region was specified. */
62493d8817e4Smiod if (l->next == 0)
62503d8817e4Smiod l->os->load_base = lma_expr;
62513d8817e4Smiod else if (lma_region == 0)
62523d8817e4Smiod l->os->load_base = exp_binop ('+',
62533d8817e4Smiod exp_nameop (LOADADDR, l->next->os->name),
62543d8817e4Smiod exp_nameop (SIZEOF, l->next->os->name));
62553d8817e4Smiod
62563d8817e4Smiod if (phdrs != NULL && l->os->phdrs == NULL)
62573d8817e4Smiod l->os->phdrs = phdrs;
62583d8817e4Smiod
62593d8817e4Smiod if (nocrossrefs)
62603d8817e4Smiod {
62613d8817e4Smiod lang_nocrossref_type *nc;
62623d8817e4Smiod
62633d8817e4Smiod nc = xmalloc (sizeof *nc);
62643d8817e4Smiod nc->name = l->os->name;
62653d8817e4Smiod nc->next = nocrossref;
62663d8817e4Smiod nocrossref = nc;
62673d8817e4Smiod }
62683d8817e4Smiod
62693d8817e4Smiod next = l->next;
62703d8817e4Smiod free (l);
62713d8817e4Smiod l = next;
62723d8817e4Smiod }
62733d8817e4Smiod
62743d8817e4Smiod if (nocrossref != NULL)
62753d8817e4Smiod lang_add_nocrossref (nocrossref);
62763d8817e4Smiod
62773d8817e4Smiod overlay_vma = NULL;
62783d8817e4Smiod overlay_list = NULL;
62793d8817e4Smiod overlay_max = NULL;
62803d8817e4Smiod }
62813d8817e4Smiod
62823d8817e4Smiod /* Version handling. This is only useful for ELF. */
62833d8817e4Smiod
62843d8817e4Smiod /* This global variable holds the version tree that we build. */
62853d8817e4Smiod
62863d8817e4Smiod struct bfd_elf_version_tree *lang_elf_version_info;
62873d8817e4Smiod
62883d8817e4Smiod /* If PREV is NULL, return first version pattern matching particular symbol.
62893d8817e4Smiod If PREV is non-NULL, return first version pattern matching particular
62903d8817e4Smiod symbol after PREV (previously returned by lang_vers_match). */
62913d8817e4Smiod
62923d8817e4Smiod static struct bfd_elf_version_expr *
lang_vers_match(struct bfd_elf_version_expr_head * head,struct bfd_elf_version_expr * prev,const char * sym)62933d8817e4Smiod lang_vers_match (struct bfd_elf_version_expr_head *head,
62943d8817e4Smiod struct bfd_elf_version_expr *prev,
62953d8817e4Smiod const char *sym)
62963d8817e4Smiod {
62973d8817e4Smiod const char *cxx_sym = sym;
62983d8817e4Smiod const char *java_sym = sym;
62993d8817e4Smiod struct bfd_elf_version_expr *expr = NULL;
63003d8817e4Smiod
63013d8817e4Smiod if (head->mask & BFD_ELF_VERSION_CXX_TYPE)
63023d8817e4Smiod {
63033d8817e4Smiod cxx_sym = cplus_demangle (sym, DMGL_PARAMS | DMGL_ANSI);
63043d8817e4Smiod if (!cxx_sym)
63053d8817e4Smiod cxx_sym = sym;
63063d8817e4Smiod }
63073d8817e4Smiod if (head->mask & BFD_ELF_VERSION_JAVA_TYPE)
63083d8817e4Smiod {
63093d8817e4Smiod java_sym = cplus_demangle (sym, DMGL_JAVA);
63103d8817e4Smiod if (!java_sym)
63113d8817e4Smiod java_sym = sym;
63123d8817e4Smiod }
63133d8817e4Smiod
63143d8817e4Smiod if (head->htab && (prev == NULL || prev->symbol))
63153d8817e4Smiod {
63163d8817e4Smiod struct bfd_elf_version_expr e;
63173d8817e4Smiod
63183d8817e4Smiod switch (prev ? prev->mask : 0)
63193d8817e4Smiod {
63203d8817e4Smiod case 0:
63213d8817e4Smiod if (head->mask & BFD_ELF_VERSION_C_TYPE)
63223d8817e4Smiod {
63233d8817e4Smiod e.symbol = sym;
63243d8817e4Smiod expr = htab_find (head->htab, &e);
63253d8817e4Smiod while (expr && strcmp (expr->symbol, sym) == 0)
63263d8817e4Smiod if (expr->mask == BFD_ELF_VERSION_C_TYPE)
63273d8817e4Smiod goto out_ret;
63283d8817e4Smiod else
63293d8817e4Smiod expr = expr->next;
63303d8817e4Smiod }
63313d8817e4Smiod /* Fallthrough */
63323d8817e4Smiod case BFD_ELF_VERSION_C_TYPE:
63333d8817e4Smiod if (head->mask & BFD_ELF_VERSION_CXX_TYPE)
63343d8817e4Smiod {
63353d8817e4Smiod e.symbol = cxx_sym;
63363d8817e4Smiod expr = htab_find (head->htab, &e);
63373d8817e4Smiod while (expr && strcmp (expr->symbol, cxx_sym) == 0)
63383d8817e4Smiod if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
63393d8817e4Smiod goto out_ret;
63403d8817e4Smiod else
63413d8817e4Smiod expr = expr->next;
63423d8817e4Smiod }
63433d8817e4Smiod /* Fallthrough */
63443d8817e4Smiod case BFD_ELF_VERSION_CXX_TYPE:
63453d8817e4Smiod if (head->mask & BFD_ELF_VERSION_JAVA_TYPE)
63463d8817e4Smiod {
63473d8817e4Smiod e.symbol = java_sym;
63483d8817e4Smiod expr = htab_find (head->htab, &e);
63493d8817e4Smiod while (expr && strcmp (expr->symbol, java_sym) == 0)
63503d8817e4Smiod if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
63513d8817e4Smiod goto out_ret;
63523d8817e4Smiod else
63533d8817e4Smiod expr = expr->next;
63543d8817e4Smiod }
63553d8817e4Smiod /* Fallthrough */
63563d8817e4Smiod default:
63573d8817e4Smiod break;
63583d8817e4Smiod }
63593d8817e4Smiod }
63603d8817e4Smiod
63613d8817e4Smiod /* Finally, try the wildcards. */
63623d8817e4Smiod if (prev == NULL || prev->symbol)
63633d8817e4Smiod expr = head->remaining;
63643d8817e4Smiod else
63653d8817e4Smiod expr = prev->next;
63663d8817e4Smiod for (; expr; expr = expr->next)
63673d8817e4Smiod {
63683d8817e4Smiod const char *s;
63693d8817e4Smiod
63703d8817e4Smiod if (!expr->pattern)
63713d8817e4Smiod continue;
63723d8817e4Smiod
63733d8817e4Smiod if (expr->pattern[0] == '*' && expr->pattern[1] == '\0')
63743d8817e4Smiod break;
63753d8817e4Smiod
63763d8817e4Smiod if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
63773d8817e4Smiod s = java_sym;
63783d8817e4Smiod else if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
63793d8817e4Smiod s = cxx_sym;
63803d8817e4Smiod else
63813d8817e4Smiod s = sym;
63823d8817e4Smiod if (fnmatch (expr->pattern, s, 0) == 0)
63833d8817e4Smiod break;
63843d8817e4Smiod }
63853d8817e4Smiod
63863d8817e4Smiod out_ret:
63873d8817e4Smiod if (cxx_sym != sym)
63883d8817e4Smiod free ((char *) cxx_sym);
63893d8817e4Smiod if (java_sym != sym)
63903d8817e4Smiod free ((char *) java_sym);
63913d8817e4Smiod return expr;
63923d8817e4Smiod }
63933d8817e4Smiod
63943d8817e4Smiod /* Return NULL if the PATTERN argument is a glob pattern, otherwise,
63953d8817e4Smiod return a string pointing to the symbol name. */
63963d8817e4Smiod
63973d8817e4Smiod static const char *
realsymbol(const char * pattern)63983d8817e4Smiod realsymbol (const char *pattern)
63993d8817e4Smiod {
64003d8817e4Smiod const char *p;
64013d8817e4Smiod bfd_boolean changed = FALSE, backslash = FALSE;
64023d8817e4Smiod char *s, *symbol = xmalloc (strlen (pattern) + 1);
64033d8817e4Smiod
64043d8817e4Smiod for (p = pattern, s = symbol; *p != '\0'; ++p)
64053d8817e4Smiod {
64063d8817e4Smiod /* It is a glob pattern only if there is no preceding
64073d8817e4Smiod backslash. */
64083d8817e4Smiod if (! backslash && (*p == '?' || *p == '*' || *p == '['))
64093d8817e4Smiod {
64103d8817e4Smiod free (symbol);
64113d8817e4Smiod return NULL;
64123d8817e4Smiod }
64133d8817e4Smiod
64143d8817e4Smiod if (backslash)
64153d8817e4Smiod {
64163d8817e4Smiod /* Remove the preceding backslash. */
64173d8817e4Smiod *(s - 1) = *p;
64183d8817e4Smiod changed = TRUE;
64193d8817e4Smiod }
64203d8817e4Smiod else
64213d8817e4Smiod *s++ = *p;
64223d8817e4Smiod
64233d8817e4Smiod backslash = *p == '\\';
64243d8817e4Smiod }
64253d8817e4Smiod
64263d8817e4Smiod if (changed)
64273d8817e4Smiod {
64283d8817e4Smiod *s = '\0';
64293d8817e4Smiod return symbol;
64303d8817e4Smiod }
64313d8817e4Smiod else
64323d8817e4Smiod {
64333d8817e4Smiod free (symbol);
64343d8817e4Smiod return pattern;
64353d8817e4Smiod }
64363d8817e4Smiod }
64373d8817e4Smiod
64383d8817e4Smiod /* This is called for each variable name or match expression. NEW is
64393d8817e4Smiod the name of the symbol to match, or, if LITERAL_P is FALSE, a glob
64403d8817e4Smiod pattern to be matched against symbol names. */
64413d8817e4Smiod
64423d8817e4Smiod struct bfd_elf_version_expr *
lang_new_vers_pattern(struct bfd_elf_version_expr * orig,const char * new,const char * lang,bfd_boolean literal_p)64433d8817e4Smiod lang_new_vers_pattern (struct bfd_elf_version_expr *orig,
64443d8817e4Smiod const char *new,
64453d8817e4Smiod const char *lang,
64463d8817e4Smiod bfd_boolean literal_p)
64473d8817e4Smiod {
64483d8817e4Smiod struct bfd_elf_version_expr *ret;
64493d8817e4Smiod
64503d8817e4Smiod ret = xmalloc (sizeof *ret);
64513d8817e4Smiod ret->next = orig;
64523d8817e4Smiod ret->pattern = literal_p ? NULL : new;
64533d8817e4Smiod ret->symver = 0;
64543d8817e4Smiod ret->script = 0;
64553d8817e4Smiod ret->symbol = literal_p ? new : realsymbol (new);
64563d8817e4Smiod
64573d8817e4Smiod if (lang == NULL || strcasecmp (lang, "C") == 0)
64583d8817e4Smiod ret->mask = BFD_ELF_VERSION_C_TYPE;
64593d8817e4Smiod else if (strcasecmp (lang, "C++") == 0)
64603d8817e4Smiod ret->mask = BFD_ELF_VERSION_CXX_TYPE;
64613d8817e4Smiod else if (strcasecmp (lang, "Java") == 0)
64623d8817e4Smiod ret->mask = BFD_ELF_VERSION_JAVA_TYPE;
64633d8817e4Smiod else
64643d8817e4Smiod {
64653d8817e4Smiod einfo (_("%X%P: unknown language `%s' in version information\n"),
64663d8817e4Smiod lang);
64673d8817e4Smiod ret->mask = BFD_ELF_VERSION_C_TYPE;
64683d8817e4Smiod }
64693d8817e4Smiod
64703d8817e4Smiod return ldemul_new_vers_pattern (ret);
64713d8817e4Smiod }
64723d8817e4Smiod
64733d8817e4Smiod /* This is called for each set of variable names and match
64743d8817e4Smiod expressions. */
64753d8817e4Smiod
64763d8817e4Smiod struct bfd_elf_version_tree *
lang_new_vers_node(struct bfd_elf_version_expr * globals,struct bfd_elf_version_expr * locals)64773d8817e4Smiod lang_new_vers_node (struct bfd_elf_version_expr *globals,
64783d8817e4Smiod struct bfd_elf_version_expr *locals)
64793d8817e4Smiod {
64803d8817e4Smiod struct bfd_elf_version_tree *ret;
64813d8817e4Smiod
64823d8817e4Smiod ret = xcalloc (1, sizeof *ret);
64833d8817e4Smiod ret->globals.list = globals;
64843d8817e4Smiod ret->locals.list = locals;
64853d8817e4Smiod ret->match = lang_vers_match;
64863d8817e4Smiod ret->name_indx = (unsigned int) -1;
64873d8817e4Smiod return ret;
64883d8817e4Smiod }
64893d8817e4Smiod
64903d8817e4Smiod /* This static variable keeps track of version indices. */
64913d8817e4Smiod
64923d8817e4Smiod static int version_index;
64933d8817e4Smiod
64943d8817e4Smiod static hashval_t
version_expr_head_hash(const void * p)64953d8817e4Smiod version_expr_head_hash (const void *p)
64963d8817e4Smiod {
64973d8817e4Smiod const struct bfd_elf_version_expr *e = p;
64983d8817e4Smiod
64993d8817e4Smiod return htab_hash_string (e->symbol);
65003d8817e4Smiod }
65013d8817e4Smiod
65023d8817e4Smiod static int
version_expr_head_eq(const void * p1,const void * p2)65033d8817e4Smiod version_expr_head_eq (const void *p1, const void *p2)
65043d8817e4Smiod {
65053d8817e4Smiod const struct bfd_elf_version_expr *e1 = p1;
65063d8817e4Smiod const struct bfd_elf_version_expr *e2 = p2;
65073d8817e4Smiod
65083d8817e4Smiod return strcmp (e1->symbol, e2->symbol) == 0;
65093d8817e4Smiod }
65103d8817e4Smiod
65113d8817e4Smiod static void
lang_finalize_version_expr_head(struct bfd_elf_version_expr_head * head)65123d8817e4Smiod lang_finalize_version_expr_head (struct bfd_elf_version_expr_head *head)
65133d8817e4Smiod {
65143d8817e4Smiod size_t count = 0;
65153d8817e4Smiod struct bfd_elf_version_expr *e, *next;
65163d8817e4Smiod struct bfd_elf_version_expr **list_loc, **remaining_loc;
65173d8817e4Smiod
65183d8817e4Smiod for (e = head->list; e; e = e->next)
65193d8817e4Smiod {
65203d8817e4Smiod if (e->symbol)
65213d8817e4Smiod count++;
65223d8817e4Smiod head->mask |= e->mask;
65233d8817e4Smiod }
65243d8817e4Smiod
65253d8817e4Smiod if (count)
65263d8817e4Smiod {
65273d8817e4Smiod head->htab = htab_create (count * 2, version_expr_head_hash,
65283d8817e4Smiod version_expr_head_eq, NULL);
65293d8817e4Smiod list_loc = &head->list;
65303d8817e4Smiod remaining_loc = &head->remaining;
65313d8817e4Smiod for (e = head->list; e; e = next)
65323d8817e4Smiod {
65333d8817e4Smiod next = e->next;
65343d8817e4Smiod if (!e->symbol)
65353d8817e4Smiod {
65363d8817e4Smiod *remaining_loc = e;
65373d8817e4Smiod remaining_loc = &e->next;
65383d8817e4Smiod }
65393d8817e4Smiod else
65403d8817e4Smiod {
65413d8817e4Smiod void **loc = htab_find_slot (head->htab, e, INSERT);
65423d8817e4Smiod
65433d8817e4Smiod if (*loc)
65443d8817e4Smiod {
65453d8817e4Smiod struct bfd_elf_version_expr *e1, *last;
65463d8817e4Smiod
65473d8817e4Smiod e1 = *loc;
65483d8817e4Smiod last = NULL;
65493d8817e4Smiod do
65503d8817e4Smiod {
65513d8817e4Smiod if (e1->mask == e->mask)
65523d8817e4Smiod {
65533d8817e4Smiod last = NULL;
65543d8817e4Smiod break;
65553d8817e4Smiod }
65563d8817e4Smiod last = e1;
65573d8817e4Smiod e1 = e1->next;
65583d8817e4Smiod }
65593d8817e4Smiod while (e1 && strcmp (e1->symbol, e->symbol) == 0);
65603d8817e4Smiod
65613d8817e4Smiod if (last == NULL)
65623d8817e4Smiod {
65633d8817e4Smiod /* This is a duplicate. */
65643d8817e4Smiod /* FIXME: Memory leak. Sometimes pattern is not
65653d8817e4Smiod xmalloced alone, but in larger chunk of memory. */
65663d8817e4Smiod /* free (e->symbol); */
65673d8817e4Smiod free (e);
65683d8817e4Smiod }
65693d8817e4Smiod else
65703d8817e4Smiod {
65713d8817e4Smiod e->next = last->next;
65723d8817e4Smiod last->next = e;
65733d8817e4Smiod }
65743d8817e4Smiod }
65753d8817e4Smiod else
65763d8817e4Smiod {
65773d8817e4Smiod *loc = e;
65783d8817e4Smiod *list_loc = e;
65793d8817e4Smiod list_loc = &e->next;
65803d8817e4Smiod }
65813d8817e4Smiod }
65823d8817e4Smiod }
65833d8817e4Smiod *remaining_loc = NULL;
65843d8817e4Smiod *list_loc = head->remaining;
65853d8817e4Smiod }
65863d8817e4Smiod else
65873d8817e4Smiod head->remaining = head->list;
65883d8817e4Smiod }
65893d8817e4Smiod
65903d8817e4Smiod /* This is called when we know the name and dependencies of the
65913d8817e4Smiod version. */
65923d8817e4Smiod
65933d8817e4Smiod void
lang_register_vers_node(const char * name,struct bfd_elf_version_tree * version,struct bfd_elf_version_deps * deps)65943d8817e4Smiod lang_register_vers_node (const char *name,
65953d8817e4Smiod struct bfd_elf_version_tree *version,
65963d8817e4Smiod struct bfd_elf_version_deps *deps)
65973d8817e4Smiod {
65983d8817e4Smiod struct bfd_elf_version_tree *t, **pp;
65993d8817e4Smiod struct bfd_elf_version_expr *e1;
66003d8817e4Smiod
66013d8817e4Smiod if (name == NULL)
66023d8817e4Smiod name = "";
66033d8817e4Smiod
66043d8817e4Smiod if ((name[0] == '\0' && lang_elf_version_info != NULL)
66053d8817e4Smiod || (lang_elf_version_info && lang_elf_version_info->name[0] == '\0'))
66063d8817e4Smiod {
66073d8817e4Smiod einfo (_("%X%P: anonymous version tag cannot be combined"
66083d8817e4Smiod " with other version tags\n"));
66093d8817e4Smiod free (version);
66103d8817e4Smiod return;
66113d8817e4Smiod }
66123d8817e4Smiod
66133d8817e4Smiod /* Make sure this node has a unique name. */
66143d8817e4Smiod for (t = lang_elf_version_info; t != NULL; t = t->next)
66153d8817e4Smiod if (strcmp (t->name, name) == 0)
66163d8817e4Smiod einfo (_("%X%P: duplicate version tag `%s'\n"), name);
66173d8817e4Smiod
66183d8817e4Smiod lang_finalize_version_expr_head (&version->globals);
66193d8817e4Smiod lang_finalize_version_expr_head (&version->locals);
66203d8817e4Smiod
66213d8817e4Smiod /* Check the global and local match names, and make sure there
66223d8817e4Smiod aren't any duplicates. */
66233d8817e4Smiod
66243d8817e4Smiod for (e1 = version->globals.list; e1 != NULL; e1 = e1->next)
66253d8817e4Smiod {
66263d8817e4Smiod for (t = lang_elf_version_info; t != NULL; t = t->next)
66273d8817e4Smiod {
66283d8817e4Smiod struct bfd_elf_version_expr *e2;
66293d8817e4Smiod
66303d8817e4Smiod if (t->locals.htab && e1->symbol)
66313d8817e4Smiod {
66323d8817e4Smiod e2 = htab_find (t->locals.htab, e1);
66333d8817e4Smiod while (e2 && strcmp (e1->symbol, e2->symbol) == 0)
66343d8817e4Smiod {
66353d8817e4Smiod if (e1->mask == e2->mask)
66363d8817e4Smiod einfo (_("%X%P: duplicate expression `%s'"
66373d8817e4Smiod " in version information\n"), e1->symbol);
66383d8817e4Smiod e2 = e2->next;
66393d8817e4Smiod }
66403d8817e4Smiod }
66413d8817e4Smiod else if (!e1->symbol)
66423d8817e4Smiod for (e2 = t->locals.remaining; e2 != NULL; e2 = e2->next)
66433d8817e4Smiod if (strcmp (e1->pattern, e2->pattern) == 0
66443d8817e4Smiod && e1->mask == e2->mask)
66453d8817e4Smiod einfo (_("%X%P: duplicate expression `%s'"
66463d8817e4Smiod " in version information\n"), e1->pattern);
66473d8817e4Smiod }
66483d8817e4Smiod }
66493d8817e4Smiod
66503d8817e4Smiod for (e1 = version->locals.list; e1 != NULL; e1 = e1->next)
66513d8817e4Smiod {
66523d8817e4Smiod for (t = lang_elf_version_info; t != NULL; t = t->next)
66533d8817e4Smiod {
66543d8817e4Smiod struct bfd_elf_version_expr *e2;
66553d8817e4Smiod
66563d8817e4Smiod if (t->globals.htab && e1->symbol)
66573d8817e4Smiod {
66583d8817e4Smiod e2 = htab_find (t->globals.htab, e1);
66593d8817e4Smiod while (e2 && strcmp (e1->symbol, e2->symbol) == 0)
66603d8817e4Smiod {
66613d8817e4Smiod if (e1->mask == e2->mask)
66623d8817e4Smiod einfo (_("%X%P: duplicate expression `%s'"
66633d8817e4Smiod " in version information\n"),
66643d8817e4Smiod e1->symbol);
66653d8817e4Smiod e2 = e2->next;
66663d8817e4Smiod }
66673d8817e4Smiod }
66683d8817e4Smiod else if (!e1->symbol)
66693d8817e4Smiod for (e2 = t->globals.remaining; e2 != NULL; e2 = e2->next)
66703d8817e4Smiod if (strcmp (e1->pattern, e2->pattern) == 0
66713d8817e4Smiod && e1->mask == e2->mask)
66723d8817e4Smiod einfo (_("%X%P: duplicate expression `%s'"
66733d8817e4Smiod " in version information\n"), e1->pattern);
66743d8817e4Smiod }
66753d8817e4Smiod }
66763d8817e4Smiod
66773d8817e4Smiod version->deps = deps;
66783d8817e4Smiod version->name = name;
66793d8817e4Smiod if (name[0] != '\0')
66803d8817e4Smiod {
66813d8817e4Smiod ++version_index;
66823d8817e4Smiod version->vernum = version_index;
66833d8817e4Smiod }
66843d8817e4Smiod else
66853d8817e4Smiod version->vernum = 0;
66863d8817e4Smiod
66873d8817e4Smiod for (pp = &lang_elf_version_info; *pp != NULL; pp = &(*pp)->next)
66883d8817e4Smiod ;
66893d8817e4Smiod *pp = version;
66903d8817e4Smiod }
66913d8817e4Smiod
66923d8817e4Smiod /* This is called when we see a version dependency. */
66933d8817e4Smiod
66943d8817e4Smiod struct bfd_elf_version_deps *
lang_add_vers_depend(struct bfd_elf_version_deps * list,const char * name)66953d8817e4Smiod lang_add_vers_depend (struct bfd_elf_version_deps *list, const char *name)
66963d8817e4Smiod {
66973d8817e4Smiod struct bfd_elf_version_deps *ret;
66983d8817e4Smiod struct bfd_elf_version_tree *t;
66993d8817e4Smiod
67003d8817e4Smiod ret = xmalloc (sizeof *ret);
67013d8817e4Smiod ret->next = list;
67023d8817e4Smiod
67033d8817e4Smiod for (t = lang_elf_version_info; t != NULL; t = t->next)
67043d8817e4Smiod {
67053d8817e4Smiod if (strcmp (t->name, name) == 0)
67063d8817e4Smiod {
67073d8817e4Smiod ret->version_needed = t;
67083d8817e4Smiod return ret;
67093d8817e4Smiod }
67103d8817e4Smiod }
67113d8817e4Smiod
67123d8817e4Smiod einfo (_("%X%P: unable to find version dependency `%s'\n"), name);
67133d8817e4Smiod
67143d8817e4Smiod return ret;
67153d8817e4Smiod }
67163d8817e4Smiod
67173d8817e4Smiod static void
lang_do_version_exports_section(void)67183d8817e4Smiod lang_do_version_exports_section (void)
67193d8817e4Smiod {
67203d8817e4Smiod struct bfd_elf_version_expr *greg = NULL, *lreg;
67213d8817e4Smiod
67223d8817e4Smiod LANG_FOR_EACH_INPUT_STATEMENT (is)
67233d8817e4Smiod {
67243d8817e4Smiod asection *sec = bfd_get_section_by_name (is->the_bfd, ".exports");
67253d8817e4Smiod char *contents, *p;
67263d8817e4Smiod bfd_size_type len;
67273d8817e4Smiod
67283d8817e4Smiod if (sec == NULL)
67293d8817e4Smiod continue;
67303d8817e4Smiod
67313d8817e4Smiod len = sec->size;
67323d8817e4Smiod contents = xmalloc (len);
67333d8817e4Smiod if (!bfd_get_section_contents (is->the_bfd, sec, contents, 0, len))
67343d8817e4Smiod einfo (_("%X%P: unable to read .exports section contents\n"), sec);
67353d8817e4Smiod
67363d8817e4Smiod p = contents;
67373d8817e4Smiod while (p < contents + len)
67383d8817e4Smiod {
67393d8817e4Smiod greg = lang_new_vers_pattern (greg, p, NULL, FALSE);
67403d8817e4Smiod p = strchr (p, '\0') + 1;
67413d8817e4Smiod }
67423d8817e4Smiod
67433d8817e4Smiod /* Do not free the contents, as we used them creating the regex. */
67443d8817e4Smiod
67453d8817e4Smiod /* Do not include this section in the link. */
67463d8817e4Smiod sec->flags |= SEC_EXCLUDE;
67473d8817e4Smiod }
67483d8817e4Smiod
67493d8817e4Smiod lreg = lang_new_vers_pattern (NULL, "*", NULL, FALSE);
67503d8817e4Smiod lang_register_vers_node (command_line.version_exports_section,
67513d8817e4Smiod lang_new_vers_node (greg, lreg), NULL);
67523d8817e4Smiod }
67533d8817e4Smiod
67543d8817e4Smiod void
lang_add_unique(const char * name)67553d8817e4Smiod lang_add_unique (const char *name)
67563d8817e4Smiod {
67573d8817e4Smiod struct unique_sections *ent;
67583d8817e4Smiod
67593d8817e4Smiod for (ent = unique_section_list; ent; ent = ent->next)
67603d8817e4Smiod if (strcmp (ent->name, name) == 0)
67613d8817e4Smiod return;
67623d8817e4Smiod
67633d8817e4Smiod ent = xmalloc (sizeof *ent);
67643d8817e4Smiod ent->name = xstrdup (name);
67653d8817e4Smiod ent->next = unique_section_list;
67663d8817e4Smiod unique_section_list = ent;
67673d8817e4Smiod }
6768