xref: /openbsd-src/gnu/usr.bin/binutils-2.17/ld/ldlang.c (revision 80d8099e91b15068a54945a7c2ba251802ca9154)
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 (&current_section->region,
58263d8817e4Smiod 		    &current_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 (&region, &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