diff options
Diffstat (limited to 'contrib/binutils/ld/ldlang.c')
| -rw-r--r-- | contrib/binutils/ld/ldlang.c | 5470 | 
1 files changed, 0 insertions, 5470 deletions
diff --git a/contrib/binutils/ld/ldlang.c b/contrib/binutils/ld/ldlang.c deleted file mode 100644 index 0c086014e2a0c..0000000000000 --- a/contrib/binutils/ld/ldlang.c +++ /dev/null @@ -1,5470 +0,0 @@ -/* Linker command language support. -   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -   2001, 2002, 2003, 2004 -   Free Software Foundation, Inc. - -   This file is part of GLD, the Gnu Linker. - -   GLD is free software; you can redistribute it and/or modify -   it under the terms of the GNU General Public License as published by -   the Free Software Foundation; either version 2, or (at your option) -   any later version. - -   GLD is distributed in the hope that it will be useful, -   but WITHOUT ANY WARRANTY; without even the implied warranty of -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -   GNU General Public License for more details. - -   You should have received a copy of the GNU General Public License -   along with GLD; see the file COPYING.  If not, write to the Free -   Software Foundation, 59 Temple Place - Suite 330, Boston, MA -   02111-1307, USA.  */ - -#include "bfd.h" -#include "sysdep.h" -#include "libiberty.h" -#include "safe-ctype.h" -#include "obstack.h" -#include "bfdlink.h" - -#include "ld.h" -#include "ldmain.h" -#include "ldexp.h" -#include "ldlang.h" -#include <ldgram.h> -#include "ldlex.h" -#include "ldmisc.h" -#include "ldctor.h" -#include "ldfile.h" -#include "ldemul.h" -#include "fnmatch.h" -#include "demangle.h" -#include "hashtab.h" - -#ifndef offsetof -#define offsetof(TYPE, MEMBER) ((size_t) & (((TYPE*) 0)->MEMBER)) -#endif - -/* Locals variables.  */ -static struct obstack stat_obstack; - -#define obstack_chunk_alloc xmalloc -#define obstack_chunk_free free -static const char *startup_file; -static lang_statement_list_type input_file_chain; -static bfd_boolean placed_commons = FALSE; -static lang_output_section_statement_type *default_common_section; -static bfd_boolean map_option_f; -static bfd_vma print_dot; -static lang_input_statement_type *first_file; -static const char *current_target; -static const char *output_target; -static lang_statement_list_type statement_list; -static struct lang_phdr *lang_phdr_list; -static struct bfd_hash_table lang_definedness_table; - -/* Forward declarations.  */ -static void exp_init_os (etree_type *); -static bfd_boolean wildcardp (const char *); -static lang_input_statement_type *lookup_name (const char *); -static bfd_boolean load_symbols (lang_input_statement_type *, -				 lang_statement_list_type *); -static struct bfd_hash_entry *lang_definedness_newfunc - (struct bfd_hash_entry *, struct bfd_hash_table *, const char *); -static void insert_undefined (const char *); -static void print_statement (lang_statement_union_type *, -			     lang_output_section_statement_type *); -static void print_statement_list (lang_statement_union_type *, -				  lang_output_section_statement_type *); -static void print_statements (void); -static bfd_boolean lang_one_common (struct bfd_link_hash_entry *, void *); -static void lang_record_phdrs (void); -static void lang_do_version_exports_section (void); - -typedef void (*callback_t) (lang_wild_statement_type *, struct wildcard_list *, -			    asection *, lang_input_statement_type *, void *); - -/* Exported variables.  */ -lang_output_section_statement_type *abs_output_section; -lang_statement_list_type lang_output_section_statement; -lang_statement_list_type *stat_ptr = &statement_list; -lang_statement_list_type file_chain = { NULL, NULL }; -struct bfd_sym_chain entry_symbol = { NULL, NULL }; -const char *entry_section = ".text"; -bfd_boolean entry_from_cmdline; -bfd_boolean lang_has_input_file = FALSE; -bfd_boolean had_output_filename = FALSE; -bfd_boolean lang_float_flag = FALSE; -bfd_boolean delete_output_file_on_failure = FALSE; -struct lang_nocrossrefs *nocrossref_list; -struct unique_sections *unique_section_list; -static bfd_boolean ldlang_sysrooted_script = FALSE; -int lang_statement_iteration = 0; - -etree_type *base; /* Relocation base - or null */ - -#define new_stat(x, y) \ -  (x##_type *) new_statement (x##_enum, sizeof (x##_type), y) - -#define outside_section_address(q) \ -  ((q)->output_offset + (q)->output_section->vma) - -#define outside_symbol_address(q) \ -  ((q)->value + outside_section_address (q->section)) - -#define SECTION_NAME_MAP_LENGTH (16) - -void * -stat_alloc (size_t size) -{ -  return obstack_alloc (&stat_obstack, size); -} - -bfd_boolean -unique_section_p (const char *secnam) -{ -  struct unique_sections *unam; - -  for (unam = unique_section_list; unam; unam = unam->next) -    if (wildcardp (unam->name) -	? fnmatch (unam->name, secnam, 0) == 0 -	: strcmp (unam->name, secnam) == 0) -      { -	return TRUE; -      } - -  return FALSE; -} - -/* Generic traversal routines for finding matching sections.  */ - -static void -walk_wild_section (lang_wild_statement_type *ptr, -		   lang_input_statement_type *file, -		   callback_t callback, -		   void *data) -{ -  asection *s; - -  if (file->just_syms_flag) -    return; - -  for (s = file->the_bfd->sections; s != NULL; s = s->next) -    { -      struct wildcard_list *sec; - -      sec = ptr->section_list; -      if (sec == NULL) -	(*callback) (ptr, sec, s, file, data); - -      while (sec != NULL) -	{ -	  bfd_boolean skip = FALSE; -	  struct name_list *list_tmp; - -	  /* Don't process sections from files which were -	     excluded.  */ -	  for (list_tmp = sec->spec.exclude_name_list; -	       list_tmp; -	       list_tmp = list_tmp->next) -	    { -	      if (wildcardp (list_tmp->name)) -		skip = fnmatch (list_tmp->name, file->filename, 0) == 0; -	      else -		skip = strcmp (list_tmp->name, file->filename) == 0; - -	      /* If this file is part of an archive, and the archive is -		 excluded, exclude this file.  */ -	      if (! skip && file->the_bfd != NULL -		  && file->the_bfd->my_archive != NULL -		  && file->the_bfd->my_archive->filename != NULL) -		{ -		  if (wildcardp (list_tmp->name)) -		    skip = fnmatch (list_tmp->name, -				    file->the_bfd->my_archive->filename, -				    0) == 0; -		  else -		    skip = strcmp (list_tmp->name, -				   file->the_bfd->my_archive->filename) == 0; -		} - -	      if (skip) -		break; -	    } - -	  if (!skip && sec->spec.name != NULL) -	    { -	      const char *sname = bfd_get_section_name (file->the_bfd, s); - -	      if (wildcardp (sec->spec.name)) -		skip = fnmatch (sec->spec.name, sname, 0) != 0; -	      else -		skip = strcmp (sec->spec.name, sname) != 0; -	    } - -	  if (!skip) -	    (*callback) (ptr, sec, s, file, data); - -	  sec = sec->next; -	} -    } -} - -/* Handle a wild statement for a single file F.  */ - -static void -walk_wild_file (lang_wild_statement_type *s, -		lang_input_statement_type *f, -		callback_t callback, -		void *data) -{ -  if (f->the_bfd == NULL -      || ! bfd_check_format (f->the_bfd, bfd_archive)) -    walk_wild_section (s, f, callback, data); -  else -    { -      bfd *member; - -      /* This is an archive file.  We must map each member of the -	 archive separately.  */ -      member = bfd_openr_next_archived_file (f->the_bfd, NULL); -      while (member != NULL) -	{ -	  /* When lookup_name is called, it will call the add_symbols -	     entry point for the archive.  For each element of the -	     archive which is included, BFD will call ldlang_add_file, -	     which will set the usrdata field of the member to the -	     lang_input_statement.  */ -	  if (member->usrdata != NULL) -	    { -	      walk_wild_section (s, member->usrdata, callback, data); -	    } - -	  member = bfd_openr_next_archived_file (f->the_bfd, member); -	} -    } -} - -static void -walk_wild (lang_wild_statement_type *s, callback_t callback, void *data) -{ -  const char *file_spec = s->filename; - -  if (file_spec == NULL) -    { -      /* Perform the iteration over all files in the list.  */ -      LANG_FOR_EACH_INPUT_STATEMENT (f) -	{ -	  walk_wild_file (s, f, callback, data); -	} -    } -  else if (wildcardp (file_spec)) -    { -      LANG_FOR_EACH_INPUT_STATEMENT (f) -	{ -	  if (fnmatch (file_spec, f->filename, FNM_FILE_NAME) == 0) -	    walk_wild_file (s, f, callback, data); -	} -    } -  else -    { -      lang_input_statement_type *f; - -      /* Perform the iteration over a single file.  */ -      f = lookup_name (file_spec); -      if (f) -	walk_wild_file (s, f, callback, data); -    } -} - -/* lang_for_each_statement walks the parse tree and calls the provided -   function for each node.  */ - -static void -lang_for_each_statement_worker (void (*func) (lang_statement_union_type *), -				lang_statement_union_type *s) -{ -  for (; s != NULL; s = s->header.next) -    { -      func (s); - -      switch (s->header.type) -	{ -	case lang_constructors_statement_enum: -	  lang_for_each_statement_worker (func, constructor_list.head); -	  break; -	case lang_output_section_statement_enum: -	  lang_for_each_statement_worker -	    (func, -	     s->output_section_statement.children.head); -	  break; -	case lang_wild_statement_enum: -	  lang_for_each_statement_worker -	    (func, -	     s->wild_statement.children.head); -	  break; -	case lang_group_statement_enum: -	  lang_for_each_statement_worker (func, -					  s->group_statement.children.head); -	  break; -	case lang_data_statement_enum: -	case lang_reloc_statement_enum: -	case lang_object_symbols_statement_enum: -	case lang_output_statement_enum: -	case lang_target_statement_enum: -	case lang_input_section_enum: -	case lang_input_statement_enum: -	case lang_assignment_statement_enum: -	case lang_padding_statement_enum: -	case lang_address_statement_enum: -	case lang_fill_statement_enum: -	  break; -	default: -	  FAIL (); -	  break; -	} -    } -} - -void -lang_for_each_statement (void (*func) (lang_statement_union_type *)) -{ -  lang_for_each_statement_worker (func, statement_list.head); -} - -/*----------------------------------------------------------------------*/ - -void -lang_list_init (lang_statement_list_type *list) -{ -  list->head = NULL; -  list->tail = &list->head; -} - -/* Build a new statement node for the parse tree.  */ - -static lang_statement_union_type * -new_statement (enum statement_enum type, -	       size_t size, -	       lang_statement_list_type *list) -{ -  lang_statement_union_type *new; - -  new = stat_alloc (size); -  new->header.type = type; -  new->header.next = NULL; -  lang_statement_append (list, new, &new->header.next); -  return new; -} - -/* Build a new input file node for the language.  There are several -   ways in which we treat an input file, eg, we only look at symbols, -   or prefix it with a -l etc. - -   We can be supplied with requests for input files more than once; -   they may, for example be split over several lines like foo.o(.text) -   foo.o(.data) etc, so when asked for a file we check that we haven't -   got it already so we don't duplicate the bfd.  */ - -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) -{ -  lang_input_statement_type *p; - -  if (add_to_list) -    p = new_stat (lang_input_statement, stat_ptr); -  else -    { -      p = stat_alloc (sizeof (lang_input_statement_type)); -      p->header.next = NULL; -    } - -  lang_has_input_file = TRUE; -  p->target = target; -  p->sysrooted = FALSE; -  switch (file_type) -    { -    case lang_input_file_is_symbols_only_enum: -      p->filename = name; -      p->is_archive = FALSE; -      p->real = TRUE; -      p->local_sym_name = name; -      p->just_syms_flag = TRUE; -      p->search_dirs_flag = FALSE; -      break; -    case lang_input_file_is_fake_enum: -      p->filename = name; -      p->is_archive = FALSE; -      p->real = FALSE; -      p->local_sym_name = name; -      p->just_syms_flag = FALSE; -      p->search_dirs_flag = FALSE; -      break; -    case lang_input_file_is_l_enum: -      p->is_archive = TRUE; -      p->filename = name; -      p->real = TRUE; -      p->local_sym_name = concat ("-l", name, NULL); -      p->just_syms_flag = FALSE; -      p->search_dirs_flag = TRUE; -      break; -    case lang_input_file_is_marker_enum: -      p->filename = name; -      p->is_archive = FALSE; -      p->real = FALSE; -      p->local_sym_name = name; -      p->just_syms_flag = FALSE; -      p->search_dirs_flag = TRUE; -      break; -    case lang_input_file_is_search_file_enum: -      p->sysrooted = ldlang_sysrooted_script; -      p->filename = name; -      p->is_archive = FALSE; -      p->real = TRUE; -      p->local_sym_name = name; -      p->just_syms_flag = FALSE; -      p->search_dirs_flag = TRUE; -      break; -    case lang_input_file_is_file_enum: -      p->filename = name; -      p->is_archive = FALSE; -      p->real = TRUE; -      p->local_sym_name = name; -      p->just_syms_flag = FALSE; -      p->search_dirs_flag = FALSE; -      break; -    default: -      FAIL (); -    } -  p->the_bfd = NULL; -  p->asymbols = NULL; -  p->next_real_file = NULL; -  p->next = NULL; -  p->symbol_count = 0; -  p->dynamic = config.dynamic_link; -  p->as_needed = as_needed; -  p->whole_archive = whole_archive; -  p->loaded = FALSE; -  lang_statement_append (&input_file_chain, -			 (lang_statement_union_type *) p, -			 &p->next_real_file); -  return p; -} - -lang_input_statement_type * -lang_add_input_file (const char *name, -		     lang_input_file_enum_type file_type, -		     const char *target) -{ -  lang_has_input_file = TRUE; -  return new_afile (name, file_type, target, TRUE); -} - -/* Build enough state so that the parser can build its tree.  */ - -void -lang_init (void) -{ -  obstack_begin (&stat_obstack, 1000); - -  stat_ptr = &statement_list; - -  lang_list_init (stat_ptr); - -  lang_list_init (&input_file_chain); -  lang_list_init (&lang_output_section_statement); -  lang_list_init (&file_chain); -  first_file = lang_add_input_file (NULL, lang_input_file_is_marker_enum, -				    NULL); -  abs_output_section = -    lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME); - -  abs_output_section->bfd_section = bfd_abs_section_ptr; - -  /* The value "3" is ad-hoc, somewhat related to the expected number of -     DEFINED expressions in a linker script.  For most default linker -     scripts, there are none.  Why a hash table then?  Well, it's somewhat -     simpler to re-use working machinery than using a linked list in terms -     of code-complexity here in ld, besides the initialization which just -     looks like other code here.  */ -  if (bfd_hash_table_init_n (&lang_definedness_table, -			     lang_definedness_newfunc, 3) != TRUE) -    einfo (_("%P%F: out of memory during initialization")); - -  /* Callers of exp_fold_tree need to increment this.  */ -  lang_statement_iteration = 0; -} - -/*---------------------------------------------------------------------- -  A region is an area of memory declared with the -  MEMORY {  name:org=exp, len=exp ... } -  syntax. - -  We maintain a list of all the regions here. - -  If no regions are specified in the script, then the default is used -  which is created when looked up to be the entire data space. - -  If create is true we are creating a region inside a MEMORY block. -  In this case it is probably an error to create a region that has -  already been created.  If we are not inside a MEMORY block it is -  dubious to use an undeclared region name (except DEFAULT_MEMORY_REGION) -  and so we issue a warning.  */ - -static lang_memory_region_type *lang_memory_region_list; -static lang_memory_region_type **lang_memory_region_list_tail = &lang_memory_region_list; - -lang_memory_region_type * -lang_memory_region_lookup (const char *const name, bfd_boolean create) -{ -  lang_memory_region_type *p; -  lang_memory_region_type *new; - -  /* NAME is NULL for LMA memspecs if no region was specified.  */ -  if (name == NULL) -    return NULL; - -  for (p = lang_memory_region_list; p != NULL; p = p->next) -    if (strcmp (p->name, name) == 0) -      { -	if (create) -	  einfo (_("%P:%S: warning: redeclaration of memory region '%s'\n"), name); -	return p; -      } - -#if 0 -  /* This code used to always use the first region in the list as the -     default region.  I changed it to instead use a region -     encompassing all of memory as the default region.  This permits -     NOLOAD sections to work reasonably without requiring a region. -     People should specify what region they mean, if they really want -     a region.  */ -  if (strcmp (name, DEFAULT_MEMORY_REGION) == 0) -    { -      if (lang_memory_region_list != NULL) -	return lang_memory_region_list; -    } -#endif - -  if (!create && strcmp (name, DEFAULT_MEMORY_REGION)) -    einfo (_("%P:%S: warning: memory region %s not declared\n"), name); - -  new = stat_alloc (sizeof (lang_memory_region_type)); - -  new->name = xstrdup (name); -  new->next = NULL; - -  *lang_memory_region_list_tail = new; -  lang_memory_region_list_tail = &new->next; -  new->origin = 0; -  new->flags = 0; -  new->not_flags = 0; -  new->length = ~(bfd_size_type) 0; -  new->current = 0; -  new->had_full_message = FALSE; - -  return new; -} - -static lang_memory_region_type * -lang_memory_default (asection *section) -{ -  lang_memory_region_type *p; - -  flagword sec_flags = section->flags; - -  /* Override SEC_DATA to mean a writable section.  */ -  if ((sec_flags & (SEC_ALLOC | SEC_READONLY | SEC_CODE)) == SEC_ALLOC) -    sec_flags |= SEC_DATA; - -  for (p = lang_memory_region_list; p != NULL; p = p->next) -    { -      if ((p->flags & sec_flags) != 0 -	  && (p->not_flags & sec_flags) == 0) -	{ -	  return p; -	} -    } -  return lang_memory_region_lookup (DEFAULT_MEMORY_REGION, FALSE); -} - -lang_output_section_statement_type * -lang_output_section_find (const char *const name) -{ -  lang_statement_union_type *u; -  lang_output_section_statement_type *lookup; - -  for (u = lang_output_section_statement.head; u != NULL; u = lookup->next) -    { -      lookup = &u->output_section_statement; -      if (strcmp (name, lookup->name) == 0) -	return lookup; -    } -  return NULL; -} - -lang_output_section_statement_type * -lang_output_section_statement_lookup (const char *const name) -{ -  lang_output_section_statement_type *lookup; - -  lookup = lang_output_section_find (name); -  if (lookup == NULL) -    { -      lookup = new_stat (lang_output_section_statement, stat_ptr); -      lookup->region = NULL; -      lookup->lma_region = NULL; -      lookup->fill = 0; -      lookup->block_value = 1; -      lookup->name = name; - -      lookup->next = NULL; -      lookup->bfd_section = NULL; -      lookup->processed = 0; -      lookup->sectype = normal_section; -      lookup->addr_tree = NULL; -      lang_list_init (&lookup->children); - -      lookup->memspec = NULL; -      lookup->flags = 0; -      lookup->subsection_alignment = -1; -      lookup->section_alignment = -1; -      lookup->load_base = NULL; -      lookup->update_dot_tree = NULL; -      lookup->phdrs = NULL; - -      lang_statement_append (&lang_output_section_statement, -			     (lang_statement_union_type *) lookup, -			     &lookup->next); -    } -  return lookup; -} - -static void -lang_map_flags (flagword flag) -{ -  if (flag & SEC_ALLOC) -    minfo ("a"); - -  if (flag & SEC_CODE) -    minfo ("x"); - -  if (flag & SEC_READONLY) -    minfo ("r"); - -  if (flag & SEC_DATA) -    minfo ("w"); - -  if (flag & SEC_LOAD) -    minfo ("l"); -} - -void -lang_map (void) -{ -  lang_memory_region_type *m; - -  minfo (_("\nMemory Configuration\n\n")); -  fprintf (config.map_file, "%-16s %-18s %-18s %s\n", -	   _("Name"), _("Origin"), _("Length"), _("Attributes")); - -  for (m = lang_memory_region_list; m != NULL; m = m->next) -    { -      char buf[100]; -      int len; - -      fprintf (config.map_file, "%-16s ", m->name); - -      sprintf_vma (buf, m->origin); -      minfo ("0x%s ", buf); -      len = strlen (buf); -      while (len < 16) -	{ -	  print_space (); -	  ++len; -	} - -      minfo ("0x%V", m->length); -      if (m->flags || m->not_flags) -	{ -#ifndef BFD64 -	  minfo ("        "); -#endif -	  if (m->flags) -	    { -	      print_space (); -	      lang_map_flags (m->flags); -	    } - -	  if (m->not_flags) -	    { -	      minfo (" !"); -	      lang_map_flags (m->not_flags); -	    } -	} - -      print_nl (); -    } - -  fprintf (config.map_file, _("\nLinker script and memory map\n\n")); - -  print_statements (); -} - -/* Initialize an output section.  */ - -static void -init_os (lang_output_section_statement_type *s) -{ -  section_userdata_type *new; - -  if (s->bfd_section != NULL) -    return; - -  if (strcmp (s->name, DISCARD_SECTION_NAME) == 0) -    einfo (_("%P%F: Illegal use of `%s' section\n"), DISCARD_SECTION_NAME); - -  new = stat_alloc (sizeof (section_userdata_type)); - -  s->bfd_section = bfd_get_section_by_name (output_bfd, s->name); -  if (s->bfd_section == NULL) -    s->bfd_section = bfd_make_section (output_bfd, s->name); -  if (s->bfd_section == NULL) -    { -      einfo (_("%P%F: output format %s cannot represent section called %s\n"), -	     output_bfd->xvec->name, s->name); -    } -  s->bfd_section->output_section = s->bfd_section; - -  /* We initialize an output sections output offset to minus its own -     vma to allow us to output a section through itself.  */ -  s->bfd_section->output_offset = 0; -  get_userdata (s->bfd_section) = new; - -  /* If there is a base address, make sure that any sections it might -     mention are initialized.  */ -  if (s->addr_tree != NULL) -    exp_init_os (s->addr_tree); - -  if (s->load_base != NULL) -    exp_init_os (s->load_base); -} - -/* Make sure that all output sections mentioned in an expression are -   initialized.  */ - -static void -exp_init_os (etree_type *exp) -{ -  switch (exp->type.node_class) -    { -    case etree_assign: -      exp_init_os (exp->assign.src); -      break; - -    case etree_binary: -      exp_init_os (exp->binary.lhs); -      exp_init_os (exp->binary.rhs); -      break; - -    case etree_trinary: -      exp_init_os (exp->trinary.cond); -      exp_init_os (exp->trinary.lhs); -      exp_init_os (exp->trinary.rhs); -      break; - -    case etree_assert: -      exp_init_os (exp->assert_s.child); -      break; -       -    case etree_unary: -      exp_init_os (exp->unary.child); -      break; - -    case etree_name: -      switch (exp->type.node_code) -	{ -	case ADDR: -	case LOADADDR: -	case SIZEOF: -	  { -	    lang_output_section_statement_type *os; - -	    os = lang_output_section_find (exp->name.name); -	    if (os != NULL && os->bfd_section == NULL) -	      init_os (os); -	  } -	} -      break; - -    default: -      break; -    } -} - -/* Sections marked with the SEC_LINK_ONCE flag should only be linked -   once into the output.  This routine checks each section, and -   arrange to discard it if a section of the same name has already -   been linked.  If the section has COMDAT information, then it uses -   that to decide whether the section should be included.  This code -   assumes that all relevant sections have the SEC_LINK_ONCE flag set; -   that is, it does not depend solely upon the section name. -   section_already_linked is called via bfd_map_over_sections.  */ - -/* This is the shape of the elements inside the already_linked hash -   table. It maps a name onto a list of already_linked elements with -   the same name.  It's possible to get more than one element in a -   list if the COMDAT sections have different names.  */ - -struct already_linked_hash_entry -{ -  struct bfd_hash_entry root; -  struct already_linked *entry; -}; - -struct already_linked -{ -  struct already_linked *next; -  asection *sec; -}; - -/* The hash table.  */ - -static struct bfd_hash_table already_linked_table; - -static void -section_already_linked (bfd *abfd, asection *sec, void *data) -{ -  lang_input_statement_type *entry = data; -  flagword flags; -  const char *name; -  struct already_linked *l; -  struct already_linked_hash_entry *already_linked_list; - -  /* If we are only reading symbols from this object, then we want to -     discard all sections.  */ -  if (entry->just_syms_flag) -    { -      bfd_link_just_syms (sec, &link_info); -      return; -    } - -  flags = bfd_get_section_flags (abfd, sec); - -  if ((flags & SEC_LINK_ONCE) == 0) -    return; - -  /* FIXME: When doing a relocatable link, we may have trouble -     copying relocations in other sections that refer to local symbols -     in the section being discarded.  Those relocations will have to -     be converted somehow; as of this writing I'm not sure that any of -     the backends handle that correctly. - -     It is tempting to instead not discard link once sections when -     doing a relocatable link (technically, they should be discarded -     whenever we are building constructors).  However, that fails, -     because the linker winds up combining all the link once sections -     into a single large link once section, which defeats the purpose -     of having link once sections in the first place. - -     Also, not merging link once sections in a relocatable link -     causes trouble for MIPS ELF, which relies on link once semantics -     to handle the .reginfo section correctly.  */ - -  name = bfd_get_section_name (abfd, sec); - -  already_linked_list = -    ((struct already_linked_hash_entry *) -     bfd_hash_lookup (&already_linked_table, name, TRUE, FALSE)); - -  for (l = already_linked_list->entry; l != NULL; l = l->next) -    { -      if (sec->comdat == NULL -	  || l->sec->comdat == NULL -	  || strcmp (sec->comdat->name, l->sec->comdat->name) == 0) -	{ -	  /* The section has already been linked.  See if we should -             issue a warning.  */ -	  switch (flags & SEC_LINK_DUPLICATES) -	    { -	    default: -	      abort (); - -	    case SEC_LINK_DUPLICATES_DISCARD: -	      break; - -	    case SEC_LINK_DUPLICATES_ONE_ONLY: -	      if (sec->comdat == NULL) -		einfo (_("%P: %B: warning: ignoring duplicate section `%s'\n"), -		       abfd, name); -	      else -		einfo (_("%P: %B: warning: ignoring duplicate `%s' section symbol `%s'\n"), -		       abfd, name, sec->comdat->name); -	      break; - -	    case SEC_LINK_DUPLICATES_SAME_CONTENTS: -	      /* FIXME: We should really dig out the contents of both -                 sections and memcmp them.  The COFF/PE spec says that -                 the Microsoft linker does not implement this -                 correctly, so I'm not going to bother doing it -                 either.  */ -	      /* Fall through.  */ -	    case SEC_LINK_DUPLICATES_SAME_SIZE: -	      if (bfd_section_size (abfd, sec) -		  != bfd_section_size (l->sec->owner, l->sec)) -		einfo (_("%P: %B: warning: duplicate section `%s' has different size\n"), -		       abfd, name); -	      break; -	    } - -	  /* Set the output_section field so that lang_add_section -	     does not create a lang_input_section structure for this -	     section.  Since there might be a symbol in the section -	     being discarded, we must retain a pointer to the section -	     which we are really going to use.  */ -	  sec->output_section = bfd_abs_section_ptr; -	  sec->kept_section = l->sec; - -	  if (flags & SEC_GROUP) -	    bfd_discard_group (abfd, sec); - -	  return; -	} -    } - -  /* This is the first section with this name.  Record it.  Allocate -     the memory from the same obstack as the hash table is kept in.  */ - -  l = bfd_hash_allocate (&already_linked_table, sizeof *l); - -  l->sec = sec; -  l->next = already_linked_list->entry; -  already_linked_list->entry = l; -} - -/* Support routines for the hash table used by section_already_linked, -   initialize the table, fill in an entry and remove the table.  */ - -static struct bfd_hash_entry * -already_linked_newfunc (struct bfd_hash_entry *entry ATTRIBUTE_UNUSED, -			struct bfd_hash_table *table, -			const char *string ATTRIBUTE_UNUSED) -{ -  struct already_linked_hash_entry *ret = -    bfd_hash_allocate (table, sizeof (struct already_linked_hash_entry)); - -  ret->entry = NULL; - -  return &ret->root; -} - -static void -already_linked_table_init (void) -{ -  if (! bfd_hash_table_init_n (&already_linked_table, -			       already_linked_newfunc, -			       42)) -    einfo (_("%P%F: Failed to create hash table\n")); -} - -static void -already_linked_table_free (void) -{ -  bfd_hash_table_free (&already_linked_table); -} - -/* The wild routines. - -   These expand statements like *(.text) and foo.o to a list of -   explicit actions, like foo.o(.text), bar.o(.text) and -   foo.o(.text, .data).  */ - -/* Return TRUE if the PATTERN argument is a wildcard pattern. -   Although backslashes are treated specially if a pattern contains -   wildcards, we do not consider the mere presence of a backslash to -   be enough to cause the pattern to be treated as a wildcard. -   That lets us handle DOS filenames more naturally.  */ - -static bfd_boolean -wildcardp (const char *pattern) -{ -  const char *s; - -  for (s = pattern; *s != '\0'; ++s) -    if (*s == '?' -	|| *s == '*' -	|| *s == '[') -      return TRUE; -  return FALSE; -} - -/* Add SECTION to the output section OUTPUT.  Do this by creating a -   lang_input_section statement which is placed at PTR.  FILE is the -   input file which holds SECTION.  */ - -void -lang_add_section (lang_statement_list_type *ptr, -		  asection *section, -		  lang_output_section_statement_type *output, -		  lang_input_statement_type *file) -{ -  flagword flags; -  bfd_boolean discard; - -  flags = bfd_get_section_flags (section->owner, section); - -  discard = FALSE; - -  /* Discard sections marked with SEC_EXCLUDE if we are doing a final -     link.  Discard debugging sections marked with SEC_EXCLUDE on a -     relocatable link too.  */ -  if ((flags & SEC_EXCLUDE) != 0 -      && ((flags & SEC_DEBUGGING) != 0 || !link_info.relocatable)) -    discard = TRUE; - -  /* Discard input sections which are assigned to a section named -     DISCARD_SECTION_NAME.  */ -  if (strcmp (output->name, DISCARD_SECTION_NAME) == 0) -    discard = TRUE; - -  /* Discard debugging sections if we are stripping debugging -     information.  */ -  if ((link_info.strip == strip_debugger || link_info.strip == strip_all) -      && (flags & SEC_DEBUGGING) != 0) -    discard = TRUE; - -  if (discard) -    { -      if (section->output_section == NULL) -	{ -	  /* This prevents future calls from assigning this section.  */ -	  section->output_section = bfd_abs_section_ptr; -	} -      return; -    } - -  if (section->output_section == NULL) -    { -      bfd_boolean first; -      lang_input_section_type *new; -      flagword flags; - -      if (output->bfd_section == NULL) -	init_os (output); - -      first = ! output->bfd_section->linker_has_input; -      output->bfd_section->linker_has_input = 1; - -      /* Add a section reference to the list.  */ -      new = new_stat (lang_input_section, ptr); - -      new->section = section; -      new->ifile = file; -      section->output_section = output->bfd_section; - -      flags = section->flags; - -      /* We don't copy the SEC_NEVER_LOAD flag from an input section -	 to an output section, because we want to be able to include a -	 SEC_NEVER_LOAD section in the middle of an otherwise loaded -	 section (I don't know why we want to do this, but we do). -	 build_link_order in ldwrite.c handles this case by turning -	 the embedded SEC_NEVER_LOAD section into a fill.  */ - -      flags &= ~ SEC_NEVER_LOAD; - -      /* If final link, don't copy the SEC_LINK_ONCE flags, they've -	 already been processed.  One reason to do this is that on pe -	 format targets, .text$foo sections go into .text and it's odd -	 to see .text with SEC_LINK_ONCE set.  */ - -      if (! link_info.relocatable) -	flags &= ~ (SEC_LINK_ONCE | SEC_LINK_DUPLICATES); - -      /* If this is not the first input section, and the SEC_READONLY -         flag is not currently set, then don't set it just because the -         input section has it set.  */ - -      if (! first && (section->output_section->flags & SEC_READONLY) == 0) -	flags &= ~ SEC_READONLY; - -      /* Keep SEC_MERGE and SEC_STRINGS only if they are the same.  */ -      if (! first -	  && ((section->output_section->flags & (SEC_MERGE | SEC_STRINGS)) -	      != (flags & (SEC_MERGE | SEC_STRINGS)) -	      || ((flags & SEC_MERGE) -		  && section->output_section->entsize != section->entsize))) -	{ -	  section->output_section->flags &= ~ (SEC_MERGE | SEC_STRINGS); -	  flags &= ~ (SEC_MERGE | SEC_STRINGS); -	} - -      section->output_section->flags |= flags; - -      if (flags & SEC_MERGE) -	section->output_section->entsize = section->entsize; - -      /* If SEC_READONLY is not set in the input section, then clear -         it from the output section.  */ -      if ((section->flags & SEC_READONLY) == 0) -	section->output_section->flags &= ~SEC_READONLY; - -      switch (output->sectype) -	{ -	case normal_section: -	  break; -	case dsect_section: -	case copy_section: -	case info_section: -	case overlay_section: -	  output->bfd_section->flags &= ~SEC_ALLOC; -	  break; -	case noload_section: -	  output->bfd_section->flags &= ~SEC_LOAD; -	  output->bfd_section->flags |= SEC_NEVER_LOAD; -	  break; -	} - -      /* Copy over SEC_SMALL_DATA.  */ -      if (section->flags & SEC_SMALL_DATA) -	section->output_section->flags |= SEC_SMALL_DATA; - -      if (section->alignment_power > output->bfd_section->alignment_power) -	output->bfd_section->alignment_power = section->alignment_power; - -      /* If supplied an alignment, then force it.  */ -      if (output->section_alignment != -1) -	output->bfd_section->alignment_power = output->section_alignment; - -      if (section->flags & SEC_BLOCK) -	{ -	  section->output_section->flags |= SEC_BLOCK; -	  /* FIXME: This value should really be obtained from the bfd...  */ -	  output->block_value = 128; -	} -    } -} - -/* Handle wildcard sorting.  This returns the lang_input_section which -   should follow the one we are going to create for SECTION and FILE, -   based on the sorting requirements of WILD.  It returns NULL if the -   new section should just go at the end of the current list.  */ - -static lang_statement_union_type * -wild_sort (lang_wild_statement_type *wild, -	   struct wildcard_list *sec, -	   lang_input_statement_type *file, -	   asection *section) -{ -  const char *section_name; -  lang_statement_union_type *l; - -  if (!wild->filenames_sorted && (sec == NULL || !sec->spec.sorted)) -    return NULL; - -  section_name = bfd_get_section_name (file->the_bfd, section); -  for (l = wild->children.head; l != NULL; l = l->header.next) -    { -      lang_input_section_type *ls; - -      if (l->header.type != lang_input_section_enum) -	continue; -      ls = &l->input_section; - -      /* Sorting by filename takes precedence over sorting by section -         name.  */ - -      if (wild->filenames_sorted) -	{ -	  const char *fn, *ln; -	  bfd_boolean fa, la; -	  int i; - -	  /* The PE support for the .idata section as generated by -             dlltool assumes that files will be sorted by the name of -             the archive and then the name of the file within the -             archive.  */ - -	  if (file->the_bfd != NULL -	      && bfd_my_archive (file->the_bfd) != NULL) -	    { -	      fn = bfd_get_filename (bfd_my_archive (file->the_bfd)); -	      fa = TRUE; -	    } -	  else -	    { -	      fn = file->filename; -	      fa = FALSE; -	    } - -	  if (ls->ifile->the_bfd != NULL -	      && bfd_my_archive (ls->ifile->the_bfd) != NULL) -	    { -	      ln = bfd_get_filename (bfd_my_archive (ls->ifile->the_bfd)); -	      la = TRUE; -	    } -	  else -	    { -	      ln = ls->ifile->filename; -	      la = FALSE; -	    } - -	  i = strcmp (fn, ln); -	  if (i > 0) -	    continue; -	  else if (i < 0) -	    break; - -	  if (fa || la) -	    { -	      if (fa) -		fn = file->filename; -	      if (la) -		ln = ls->ifile->filename; - -	      i = strcmp (fn, ln); -	      if (i > 0) -		continue; -	      else if (i < 0) -		break; -	    } -	} - -      /* Here either the files are not sorted by name, or we are -         looking at the sections for this file.  */ - -      if (sec != NULL && sec->spec.sorted) -	{ -	  if (strcmp (section_name, -		      bfd_get_section_name (ls->ifile->the_bfd, -					    ls->section)) -	      < 0) -	    break; -	} -    } - -  return l; -} - -/* Expand a wild statement for a particular FILE.  SECTION may be -   NULL, in which case it is a wild card.  */ - -static void -output_section_callback (lang_wild_statement_type *ptr, -			 struct wildcard_list *sec, -			 asection *section, -			 lang_input_statement_type *file, -			 void *output) -{ -  lang_statement_union_type *before; - -  /* Exclude sections that match UNIQUE_SECTION_LIST.  */ -  if (unique_section_p (bfd_get_section_name (file->the_bfd, section))) -    return; - -  /* If the wild pattern was marked KEEP, the member sections -     should be as well.  */ -  if (ptr->keep_sections) -    section->flags |= SEC_KEEP; - -  before = wild_sort (ptr, sec, file, section); - -  /* Here BEFORE points to the lang_input_section which -     should follow the one we are about to add.  If BEFORE -     is NULL, then the section should just go at the end -     of the current list.  */ - -  if (before == NULL) -    lang_add_section (&ptr->children, section, -		      (lang_output_section_statement_type *) output, -		      file); -  else -    { -      lang_statement_list_type list; -      lang_statement_union_type **pp; - -      lang_list_init (&list); -      lang_add_section (&list, section, -			(lang_output_section_statement_type *) output, -			file); - -      /* If we are discarding the section, LIST.HEAD will -	 be NULL.  */ -      if (list.head != NULL) -	{ -	  ASSERT (list.head->header.next == NULL); - -	  for (pp = &ptr->children.head; -	       *pp != before; -	       pp = &(*pp)->header.next) -	    ASSERT (*pp != NULL); - -	  list.head->header.next = *pp; -	  *pp = list.head; -	} -    } -} - -/* This is passed a file name which must have been seen already and -   added to the statement tree.  We will see if it has been opened -   already and had its symbols read.  If not then we'll read it.  */ - -static lang_input_statement_type * -lookup_name (const char *name) -{ -  lang_input_statement_type *search; - -  for (search = (lang_input_statement_type *) input_file_chain.head; -       search != NULL; -       search = (lang_input_statement_type *) search->next_real_file) -    { -      /* Use the local_sym_name as the name of the file that has -	 already been loaded as filename might have been transformed -	 via the search directory lookup mechanism.  */ -      const char * filename = search->local_sym_name; - -      if (filename == NULL && name == NULL) -	return search; -      if (filename != NULL -	  && name != NULL -	  && strcmp (filename, name) == 0) -	break; -    } - -  if (search == NULL) -    search = new_afile (name, lang_input_file_is_search_file_enum, default_target, -			FALSE); - -  /* If we have already added this file, or this file is not real -     (FIXME: can that ever actually happen?) or the name is NULL -     (FIXME: can that ever actually happen?) don't add this file.  */ -  if (search->loaded -      || ! search->real -      || search->filename == NULL) -    return search; - -  if (! load_symbols (search, NULL)) -    return NULL; - -  return search; -} - -/* Get the symbols for an input file.  */ - -static bfd_boolean -load_symbols (lang_input_statement_type *entry, -	      lang_statement_list_type *place) -{ -  char **matching; - -  if (entry->loaded) -    return TRUE; - -  ldfile_open_file (entry); - -  if (! bfd_check_format (entry->the_bfd, bfd_archive) -      && ! bfd_check_format_matches (entry->the_bfd, bfd_object, &matching)) -    { -      bfd_error_type err; -      lang_statement_list_type *hold; -      bfd_boolean bad_load = TRUE; -      bfd_boolean save_ldlang_sysrooted_script; - -      err = bfd_get_error (); - -      /* See if the emulation has some special knowledge.  */ -      if (ldemul_unrecognized_file (entry)) -	return TRUE; - -      if (err == bfd_error_file_ambiguously_recognized) -	{ -	  char **p; - -	  einfo (_("%B: file not recognized: %E\n"), entry->the_bfd); -	  einfo (_("%B: matching formats:"), entry->the_bfd); -	  for (p = matching; *p != NULL; p++) -	    einfo (" %s", *p); -	  einfo ("%F\n"); -	} -      else if (err != bfd_error_file_not_recognized -	       || place == NULL) -	  einfo (_("%F%B: file not recognized: %E\n"), entry->the_bfd); -      else -	bad_load = FALSE; - -      bfd_close (entry->the_bfd); -      entry->the_bfd = NULL; - -      /* Try to interpret the file as a linker script.  */ -      ldfile_open_command_file (entry->filename); - -      hold = stat_ptr; -      stat_ptr = place; -      save_ldlang_sysrooted_script = ldlang_sysrooted_script; -      ldlang_sysrooted_script = entry->sysrooted; - -      ldfile_assumed_script = TRUE; -      parser_input = input_script; -      yyparse (); -      ldfile_assumed_script = FALSE; - -      ldlang_sysrooted_script = save_ldlang_sysrooted_script; -      stat_ptr = hold; - -      return ! bad_load; -    } - -  if (ldemul_recognized_file (entry)) -    return TRUE; - -  /* We don't call ldlang_add_file for an archive.  Instead, the -     add_symbols entry point will call ldlang_add_file, via the -     add_archive_element callback, for each element of the archive -     which is used.  */ -  switch (bfd_get_format (entry->the_bfd)) -    { -    default: -      break; - -    case bfd_object: -      ldlang_add_file (entry); -      if (trace_files || trace_file_tries) -	info_msg ("%I\n", entry); -      break; - -    case bfd_archive: -      if (entry->whole_archive) -	{ -	  bfd *member = NULL; -	  bfd_boolean loaded = TRUE; - -	  for (;;) -	    { -	      member = bfd_openr_next_archived_file (entry->the_bfd, member); - -	      if (member == NULL) -		break; - -	      if (! bfd_check_format (member, bfd_object)) -		{ -		  einfo (_("%F%B: member %B in archive is not an object\n"), -			 entry->the_bfd, member); -		  loaded = FALSE; -		} - -	      if (! ((*link_info.callbacks->add_archive_element) -		     (&link_info, member, "--whole-archive"))) -		abort (); - -	      if (! bfd_link_add_symbols (member, &link_info)) -		{ -		  einfo (_("%F%B: could not read symbols: %E\n"), member); -		  loaded = FALSE; -		} -	    } - -	  entry->loaded = loaded; -	  return loaded; -	} -      break; -    } - -  if (bfd_link_add_symbols (entry->the_bfd, &link_info)) -    entry->loaded = TRUE; -  else -    einfo (_("%F%B: could not read symbols: %E\n"), entry->the_bfd); - -  return entry->loaded; -} - -/* Handle a wild statement.  S->FILENAME or S->SECTION_LIST or both -   may be NULL, indicating that it is a wildcard.  Separate -   lang_input_section statements are created for each part of the -   expansion; they are added after the wild statement S.  OUTPUT is -   the output section.  */ - -static void -wild (lang_wild_statement_type *s, -      const char *target ATTRIBUTE_UNUSED, -      lang_output_section_statement_type *output) -{ -  struct wildcard_list *sec; - -  walk_wild (s, output_section_callback, output); - -  for (sec = s->section_list; sec != NULL; sec = sec->next) -    { -      if (default_common_section != NULL) -	break; -      if (sec->spec.name != NULL && strcmp (sec->spec.name, "COMMON") == 0) -	{ -	  /* Remember the section that common is going to in case we -	     later get something which doesn't know where to put it.  */ -	  default_common_section = output; -	} -    } -} - -/* Return TRUE iff target is the sought target.  */ - -static int -get_target (const bfd_target *target, void *data) -{ -  const char *sought = data; - -  return strcmp (target->name, sought) == 0; -} - -/* Like strcpy() but convert to lower case as well.  */ - -static void -stricpy (char *dest, char *src) -{ -  char c; - -  while ((c = *src++) != 0) -    *dest++ = TOLOWER (c); - -  *dest = 0; -} - -/* Remove the first occurrence of needle (if any) in haystack -   from haystack.  */ - -static void -strcut (char *haystack, char *needle) -{ -  haystack = strstr (haystack, needle); - -  if (haystack) -    { -      char *src; - -      for (src = haystack + strlen (needle); *src;) -	*haystack++ = *src++; - -      *haystack = 0; -    } -} - -/* Compare two target format name strings. -   Return a value indicating how "similar" they are.  */ - -static int -name_compare (char *first, char *second) -{ -  char *copy1; -  char *copy2; -  int result; - -  copy1 = xmalloc (strlen (first) + 1); -  copy2 = xmalloc (strlen (second) + 1); - -  /* Convert the names to lower case.  */ -  stricpy (copy1, first); -  stricpy (copy2, second); - -  /* Remove size and endian strings from the name.  */ -  strcut (copy1, "big"); -  strcut (copy1, "little"); -  strcut (copy2, "big"); -  strcut (copy2, "little"); - -  /* Return a value based on how many characters match, -     starting from the beginning.   If both strings are -     the same then return 10 * their length.  */ -  for (result = 0; copy1[result] == copy2[result]; result++) -    if (copy1[result] == 0) -      { -	result *= 10; -	break; -      } - -  free (copy1); -  free (copy2); - -  return result; -} - -/* Set by closest_target_match() below.  */ -static const bfd_target *winner; - -/* Scan all the valid bfd targets looking for one that has the endianness -   requirement that was specified on the command line, and is the nearest -   match to the original output target.  */ - -static int -closest_target_match (const bfd_target *target, void *data) -{ -  const bfd_target *original = data; - -  if (command_line.endian == ENDIAN_BIG -      && target->byteorder != BFD_ENDIAN_BIG) -    return 0; - -  if (command_line.endian == ENDIAN_LITTLE -      && target->byteorder != BFD_ENDIAN_LITTLE) -    return 0; - -  /* Must be the same flavour.  */ -  if (target->flavour != original->flavour) -    return 0; - -  /* If we have not found a potential winner yet, then record this one.  */ -  if (winner == NULL) -    { -      winner = target; -      return 0; -    } - -  /* Oh dear, we now have two potential candidates for a successful match. -     Compare their names and choose the better one.  */ -  if (name_compare (target->name, original->name) -      > name_compare (winner->name, original->name)) -    winner = target; - -  /* Keep on searching until wqe have checked them all.  */ -  return 0; -} - -/* Return the BFD target format of the first input file.  */ - -static char * -get_first_input_target (void) -{ -  char *target = NULL; - -  LANG_FOR_EACH_INPUT_STATEMENT (s) -    { -      if (s->header.type == lang_input_statement_enum -	  && s->real) -	{ -	  ldfile_open_file (s); - -	  if (s->the_bfd != NULL -	      && bfd_check_format (s->the_bfd, bfd_object)) -	    { -	      target = bfd_get_target (s->the_bfd); - -	      if (target != NULL) -		break; -	    } -	} -    } - -  return target; -} - -const char * -lang_get_output_target (void) -{ -  const char *target; - -  /* Has the user told us which output format to use?  */ -  if (output_target != NULL) -    return output_target; - -  /* No - has the current target been set to something other than -     the default?  */ -  if (current_target != default_target) -    return current_target; - -  /* No - can we determine the format of the first input file?  */ -  target = get_first_input_target (); -  if (target != NULL) -    return target; - -  /* Failed - use the default output target.  */ -  return default_target; -} - -/* Open the output file.  */ - -static bfd * -open_output (const char *name) -{ -  bfd *output; - -  output_target = lang_get_output_target (); - -  /* Has the user requested a particular endianness on the command -     line?  */ -  if (command_line.endian != ENDIAN_UNSET) -    { -      const bfd_target *target; -      enum bfd_endian desired_endian; - -      /* Get the chosen target.  */ -      target = bfd_search_for_target (get_target, (void *) output_target); - -      /* If the target is not supported, we cannot do anything.  */ -      if (target != NULL) -	{ -	  if (command_line.endian == ENDIAN_BIG) -	    desired_endian = BFD_ENDIAN_BIG; -	  else -	    desired_endian = BFD_ENDIAN_LITTLE; - -	  /* See if the target has the wrong endianness.  This should -	     not happen if the linker script has provided big and -	     little endian alternatives, but some scrips don't do -	     this.  */ -	  if (target->byteorder != desired_endian) -	    { -	      /* If it does, then see if the target provides -		 an alternative with the correct endianness.  */ -	      if (target->alternative_target != NULL -		  && (target->alternative_target->byteorder == desired_endian)) -		output_target = target->alternative_target->name; -	      else -		{ -		  /* Try to find a target as similar as possible to -		     the default target, but which has the desired -		     endian characteristic.  */ -		  bfd_search_for_target (closest_target_match, -					 (void *) target); - -		  /* Oh dear - we could not find any targets that -		     satisfy our requirements.  */ -		  if (winner == NULL) -		    einfo (_("%P: warning: could not find any targets that match endianness requirement\n")); -		  else -		    output_target = winner->name; -		} -	    } -	} -    } - -  output = bfd_openw (name, output_target); - -  if (output == NULL) -    { -      if (bfd_get_error () == bfd_error_invalid_target) -	einfo (_("%P%F: target %s not found\n"), output_target); - -      einfo (_("%P%F: cannot open output file %s: %E\n"), name); -    } - -  delete_output_file_on_failure = TRUE; - -#if 0 -  output->flags |= D_PAGED; -#endif - -  if (! bfd_set_format (output, bfd_object)) -    einfo (_("%P%F:%s: can not make object file: %E\n"), name); -  if (! bfd_set_arch_mach (output, -			   ldfile_output_architecture, -			   ldfile_output_machine)) -    einfo (_("%P%F:%s: can not set architecture: %E\n"), name); - -  link_info.hash = bfd_link_hash_table_create (output); -  if (link_info.hash == NULL) -    einfo (_("%P%F: can not create link hash table: %E\n")); - -  bfd_set_gp_size (output, g_switch_value); -  return output; -} - -static void -ldlang_open_output (lang_statement_union_type *statement) -{ -  switch (statement->header.type) -    { -    case lang_output_statement_enum: -      ASSERT (output_bfd == NULL); -      output_bfd = open_output (statement->output_statement.name); -      ldemul_set_output_arch (); -      if (config.magic_demand_paged && !link_info.relocatable) -	output_bfd->flags |= D_PAGED; -      else -	output_bfd->flags &= ~D_PAGED; -      if (config.text_read_only) -	output_bfd->flags |= WP_TEXT; -      else -	output_bfd->flags &= ~WP_TEXT; -      if (link_info.traditional_format) -	output_bfd->flags |= BFD_TRADITIONAL_FORMAT; -      else -	output_bfd->flags &= ~BFD_TRADITIONAL_FORMAT; -      break; - -    case lang_target_statement_enum: -      current_target = statement->target_statement.target; -      break; -    default: -      break; -    } -} - -/* Convert between addresses in bytes and sizes in octets. -   For currently supported targets, octets_per_byte is always a power -   of two, so we can use shifts.  */ -#define TO_ADDR(X) ((X) >> opb_shift) -#define TO_SIZE(X) ((X) << opb_shift) - -/* Support the above.  */ -static unsigned int opb_shift = 0; - -static void -init_opb (void) -{ -  unsigned x = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, -					      ldfile_output_machine); -  opb_shift = 0; -  if (x > 1) -    while ((x & 1) == 0) -      { -	x >>= 1; -	++opb_shift; -      } -  ASSERT (x == 1); -} - -/* Open all the input files.  */ - -static void -open_input_bfds (lang_statement_union_type *s, bfd_boolean force) -{ -  for (; s != NULL; s = s->header.next) -    { -      switch (s->header.type) -	{ -	case lang_constructors_statement_enum: -	  open_input_bfds (constructor_list.head, force); -	  break; -	case lang_output_section_statement_enum: -	  open_input_bfds (s->output_section_statement.children.head, force); -	  break; -	case lang_wild_statement_enum: -	  /* Maybe we should load the file's symbols.  */ -	  if (s->wild_statement.filename -	      && ! wildcardp (s->wild_statement.filename)) -	    lookup_name (s->wild_statement.filename); -	  open_input_bfds (s->wild_statement.children.head, force); -	  break; -	case lang_group_statement_enum: -	  { -	    struct bfd_link_hash_entry *undefs; - -	    /* We must continually search the entries in the group -	       until no new symbols are added to the list of undefined -	       symbols.  */ - -	    do -	      { -		undefs = link_info.hash->undefs_tail; -		open_input_bfds (s->group_statement.children.head, TRUE); -	      } -	    while (undefs != link_info.hash->undefs_tail); -	  } -	  break; -	case lang_target_statement_enum: -	  current_target = s->target_statement.target; -	  break; -	case lang_input_statement_enum: -	  if (s->input_statement.real) -	    { -	      lang_statement_list_type add; - -	      s->input_statement.target = current_target; - -	      /* If we are being called from within a group, and this -                 is an archive which has already been searched, then -                 force it to be researched unless the whole archive -		 has been loaded already.  */ -	      if (force -		  && !s->input_statement.whole_archive -		  && s->input_statement.loaded -		  && bfd_check_format (s->input_statement.the_bfd, -				       bfd_archive)) -		s->input_statement.loaded = FALSE; - -	      lang_list_init (&add); - -	      if (! load_symbols (&s->input_statement, &add)) -		config.make_executable = FALSE; - -	      if (add.head != NULL) -		{ -		  *add.tail = s->header.next; -		  s->header.next = add.head; -		} -	    } -	  break; -	default: -	  break; -	} -    } -} - -/* If there are [COMMONS] statements, put a wild one into the bss -   section.  */ - -static void -lang_reasonable_defaults (void) -{ -#if 0 -  lang_output_section_statement_lookup (".text"); -  lang_output_section_statement_lookup (".data"); - -  default_common_section = lang_output_section_statement_lookup (".bss"); - -  if (!placed_commons) -    { -      lang_wild_statement_type *new = -      new_stat (lang_wild_statement, -		&default_common_section->children); - -      new->section_name = "COMMON"; -      new->filename = NULL; -      lang_list_init (&new->children); -    } -#endif -} - -/* Add a symbol to a hash of symbols used in DEFINED (NAME) expressions.  */ - -void -lang_track_definedness (const char *name) -{ -  if (bfd_hash_lookup (&lang_definedness_table, name, TRUE, FALSE) == NULL) -    einfo (_("%P%F: bfd_hash_lookup failed creating symbol %s\n"), name); -} - -/* New-function for the definedness hash table.  */ - -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) -{ -  struct lang_definedness_hash_entry *ret -    = (struct lang_definedness_hash_entry *) entry; - -  if (ret == NULL) -    ret = (struct lang_definedness_hash_entry *) -      bfd_hash_allocate (table, sizeof (struct lang_definedness_hash_entry)); - -  if (ret == NULL) -    einfo (_("%P%F: bfd_hash_allocate failed creating symbol %s\n"), name); - -  ret->iteration = -1; -  return &ret->root; -} - -/* Return the iteration when the definition of NAME was last updated.  A -   value of -1 means that the symbol is not defined in the linker script -   or the command line, but may be defined in the linker symbol table.  */ - -int -lang_symbol_definition_iteration (const char *name) -{ -  struct lang_definedness_hash_entry *defentry -    = (struct lang_definedness_hash_entry *) -    bfd_hash_lookup (&lang_definedness_table, name, FALSE, FALSE); - -  /* We've already created this one on the presence of DEFINED in the -     script, so it can't be NULL unless something is borked elsewhere in -     the code.  */ -  if (defentry == NULL) -    FAIL (); - -  return defentry->iteration; -} - -/* Update the definedness state of NAME.  */ - -void -lang_update_definedness (const char *name, struct bfd_link_hash_entry *h) -{ -  struct lang_definedness_hash_entry *defentry -    = (struct lang_definedness_hash_entry *) -    bfd_hash_lookup (&lang_definedness_table, name, FALSE, FALSE); - -  /* We don't keep track of symbols not tested with DEFINED.  */ -  if (defentry == NULL) -    return; - -  /* If the symbol was already defined, and not from an earlier statement -     iteration, don't update the definedness iteration, because that'd -     make the symbol seem defined in the linker script at this point, and -     it wasn't; it was defined in some object.  If we do anyway, DEFINED -     would start to yield false before this point and the construct "sym = -     DEFINED (sym) ? sym : X;" would change sym to X despite being defined -     in an object.  */ -  if (h->type != bfd_link_hash_undefined -      && h->type != bfd_link_hash_common -      && h->type != bfd_link_hash_new -      && defentry->iteration == -1) -    return; - -  defentry->iteration = lang_statement_iteration; -} - -/* Add the supplied name to the symbol table as an undefined reference. -   This is a two step process as the symbol table doesn't even exist at -   the time the ld command line is processed.  First we put the name -   on a list, then, once the output file has been opened, transfer the -   name to the symbol table.  */ - -typedef struct bfd_sym_chain ldlang_undef_chain_list_type; - -#define ldlang_undef_chain_list_head entry_symbol.next - -void -ldlang_add_undef (const char *const name) -{ -  ldlang_undef_chain_list_type *new = -    stat_alloc (sizeof (ldlang_undef_chain_list_type)); - -  new->next = ldlang_undef_chain_list_head; -  ldlang_undef_chain_list_head = new; - -  new->name = xstrdup (name); - -  if (output_bfd != NULL) -    insert_undefined (new->name); -} - -/* Insert NAME as undefined in the symbol table.  */ - -static void -insert_undefined (const char *name) -{ -  struct bfd_link_hash_entry *h; - -  h = bfd_link_hash_lookup (link_info.hash, name, TRUE, FALSE, TRUE); -  if (h == NULL) -    einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n")); -  if (h->type == bfd_link_hash_new) -    { -      h->type = bfd_link_hash_undefined; -      h->u.undef.abfd = NULL; -      bfd_link_add_undef (link_info.hash, h); -    } -} - -/* Run through the list of undefineds created above and place them -   into the linker hash table as undefined symbols belonging to the -   script file.  */ - -static void -lang_place_undefineds (void) -{ -  ldlang_undef_chain_list_type *ptr; - -  for (ptr = ldlang_undef_chain_list_head; ptr != NULL; ptr = ptr->next) -    insert_undefined (ptr->name); -} - -/* Open input files and attach to output sections.  */ - -static void -map_input_to_output_sections -  (lang_statement_union_type *s, const char *target, -   lang_output_section_statement_type *output_section_statement) -{ -  for (; s != NULL; s = s->header.next) -    { -      switch (s->header.type) -	{ -	case lang_wild_statement_enum: -	  wild (&s->wild_statement, target, output_section_statement); -	  break; -	case lang_constructors_statement_enum: -	  map_input_to_output_sections (constructor_list.head, -					target, -					output_section_statement); -	  break; -	case lang_output_section_statement_enum: -	  map_input_to_output_sections (s->output_section_statement.children.head, -					target, -					&s->output_section_statement); -	  break; -	case lang_output_statement_enum: -	  break; -	case lang_target_statement_enum: -	  target = s->target_statement.target; -	  break; -	case lang_group_statement_enum: -	  map_input_to_output_sections (s->group_statement.children.head, -					target, -					output_section_statement); -	  break; -	case lang_data_statement_enum: -	  /* Make sure that any sections mentioned in the expression -	     are initialized.  */ -	  exp_init_os (s->data_statement.exp); -	  /* FALLTHROUGH */ -	case lang_fill_statement_enum: -	case lang_input_section_enum: -	case lang_object_symbols_statement_enum: -	case lang_reloc_statement_enum: -	case lang_padding_statement_enum: -	case lang_input_statement_enum: -	  if (output_section_statement != NULL -	      && output_section_statement->bfd_section == NULL) -	    init_os (output_section_statement); -	  break; -	case lang_assignment_statement_enum: -	  if (output_section_statement != NULL -	      && output_section_statement->bfd_section == NULL) -	    init_os (output_section_statement); - -	  /* Make sure that any sections mentioned in the assignment -	     are initialized.  */ -	  exp_init_os (s->assignment_statement.exp); -	  break; -	case lang_afile_asection_pair_statement_enum: -	  FAIL (); -	  break; -	case lang_address_statement_enum: -	  /* Mark the specified section with the supplied address.  */ -	  { -	    lang_output_section_statement_type *os = -	      lang_output_section_statement_lookup -		(s->address_statement.section_name); - -	    if (os->bfd_section == NULL) -	      init_os (os); -	    os->addr_tree = s->address_statement.address; -	  } -	  break; -	} -    } -} - -/* An output section might have been removed after its statement was -   added.  For example, ldemul_before_allocation can remove dynamic -   sections if they turn out to be not needed.  Clean them up here.  */ - -static void -strip_excluded_output_sections (void) -{ -  lang_statement_union_type *u; - -  for (u = lang_output_section_statement.head; -       u != NULL; -       u = u->output_section_statement.next) -    { -      lang_output_section_statement_type *os; -      asection *s; - -      os = &u->output_section_statement; -      s = os->bfd_section; -      if (s != NULL && (s->flags & SEC_EXCLUDE) != 0) -	{ -	  asection **p; - -	  os->bfd_section = NULL; - -	  for (p = &output_bfd->sections; *p; p = &(*p)->next) -	    if (*p == s) -	      { -		bfd_section_list_remove (output_bfd, p); -		output_bfd->section_count--; -		break; -	      } -	} -    } -} - -static void -print_output_section_statement -  (lang_output_section_statement_type *output_section_statement) -{ -  asection *section = output_section_statement->bfd_section; -  int len; - -  if (output_section_statement != abs_output_section) -    { -      minfo ("\n%s", output_section_statement->name); - -      if (section != NULL) -	{ -	  print_dot = section->vma; - -	  len = strlen (output_section_statement->name); -	  if (len >= SECTION_NAME_MAP_LENGTH - 1) -	    { -	      print_nl (); -	      len = 0; -	    } -	  while (len < SECTION_NAME_MAP_LENGTH) -	    { -	      print_space (); -	      ++len; -	    } - -	  minfo ("0x%V %W", section->vma, section->_raw_size); - -	  if (output_section_statement->load_base != NULL) -	    { -	      bfd_vma addr; - -	      addr = exp_get_abs_int (output_section_statement->load_base, 0, -				      "load base", lang_final_phase_enum); -	      minfo (_(" load address 0x%V"), addr); -	    } -	} - -      print_nl (); -    } - -  print_statement_list (output_section_statement->children.head, -			output_section_statement); -} - -static void -print_assignment (lang_assignment_statement_type *assignment, -		  lang_output_section_statement_type *output_section) -{ -  int i; -  etree_value_type result; - -  for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++) -    print_space (); - -  result = exp_fold_tree (assignment->exp->assign.src, output_section, -			  lang_final_phase_enum, print_dot, &print_dot); -  if (result.valid_p) -    { -      const char *dst; -      bfd_vma value; - -      value = result.value + result.section->bfd_section->vma; -      dst = assignment->exp->assign.dst; - -      minfo ("0x%V", value); -      if (dst[0] == '.' && dst[1] == 0) -	print_dot = value; -    } -  else -    { -      minfo ("*undef*   "); -#ifdef BFD64 -      minfo ("        "); -#endif -    } - -  minfo ("                "); - -  exp_print_tree (assignment->exp); - -  print_nl (); -} - -static void -print_input_statement (lang_input_statement_type *statm) -{ -  if (statm->filename != NULL) -    { -      fprintf (config.map_file, "LOAD %s\n", statm->filename); -    } -} - -/* Print all symbols defined in a particular section.  This is called -   via bfd_link_hash_traverse.  */ - -static bfd_boolean -print_one_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr) -{ -  asection *sec = ptr; - -  if ((hash_entry->type == bfd_link_hash_defined -       || hash_entry->type == bfd_link_hash_defweak) -      && sec == hash_entry->u.def.section) -    { -      int i; - -      for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++) -	print_space (); -      minfo ("0x%V   ", -	     (hash_entry->u.def.value -	      + hash_entry->u.def.section->output_offset -	      + hash_entry->u.def.section->output_section->vma)); - -      minfo ("             %T\n", hash_entry->root.string); -    } - -  return TRUE; -} - -/* Print information about an input section to the map file.  */ - -static void -print_input_section (lang_input_section_type *in) -{ -  asection *i = in->section; -  bfd_size_type size = i->_cooked_size != 0 ? i->_cooked_size : i->_raw_size; - -  init_opb (); -  if (size != 0) -    { -      print_space (); - -      minfo ("%s", i->name); - -      if (i->output_section != NULL) -	{ -	  int len; - -	  len = 1 + strlen (i->name); -	  if (len >= SECTION_NAME_MAP_LENGTH - 1) -	    { -	      print_nl (); -	      len = 0; -	    } -	  while (len < SECTION_NAME_MAP_LENGTH) -	    { -	      print_space (); -	      ++len; -	    } - -	  minfo ("0x%V %W %B\n", -		 i->output_section->vma + i->output_offset, TO_ADDR (size), -		 i->owner); - -	  if (i->_cooked_size != 0 && i->_cooked_size != i->_raw_size) -	    { -	      len = SECTION_NAME_MAP_LENGTH + 3; -#ifdef BFD64 -	      len += 16; -#else -	      len += 8; -#endif -	      while (len > 0) -		{ -		  print_space (); -		  --len; -		} - -	      minfo (_("%W (size before relaxing)\n"), i->_raw_size); -	    } - -	  bfd_link_hash_traverse (link_info.hash, print_one_symbol, i); - -	  print_dot = (i->output_section->vma + i->output_offset -		       + TO_ADDR (size)); -	} -    } -} - -static void -print_fill_statement (lang_fill_statement_type *fill) -{ -  size_t size; -  unsigned char *p; -  fputs (" FILL mask 0x", config.map_file); -  for (p = fill->fill->data, size = fill->fill->size; size != 0; p++, size--) -    fprintf (config.map_file, "%02x", *p); -  fputs ("\n", config.map_file); -} - -static void -print_data_statement (lang_data_statement_type *data) -{ -  int i; -  bfd_vma addr; -  bfd_size_type size; -  const char *name; - -  init_opb (); -  for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++) -    print_space (); - -  addr = data->output_vma; -  if (data->output_section != NULL) -    addr += data->output_section->vma; - -  switch (data->type) -    { -    default: -      abort (); -    case BYTE: -      size = BYTE_SIZE; -      name = "BYTE"; -      break; -    case SHORT: -      size = SHORT_SIZE; -      name = "SHORT"; -      break; -    case LONG: -      size = LONG_SIZE; -      name = "LONG"; -      break; -    case QUAD: -      size = QUAD_SIZE; -      name = "QUAD"; -      break; -    case SQUAD: -      size = QUAD_SIZE; -      name = "SQUAD"; -      break; -    } - -  minfo ("0x%V %W %s 0x%v", addr, size, name, data->value); - -  if (data->exp->type.node_class != etree_value) -    { -      print_space (); -      exp_print_tree (data->exp); -    } - -  print_nl (); - -  print_dot = addr + TO_ADDR (size); -} - -/* Print an address statement.  These are generated by options like -   -Ttext.  */ - -static void -print_address_statement (lang_address_statement_type *address) -{ -  minfo (_("Address of section %s set to "), address->section_name); -  exp_print_tree (address->address); -  print_nl (); -} - -/* Print a reloc statement.  */ - -static void -print_reloc_statement (lang_reloc_statement_type *reloc) -{ -  int i; -  bfd_vma addr; -  bfd_size_type size; - -  init_opb (); -  for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++) -    print_space (); - -  addr = reloc->output_vma; -  if (reloc->output_section != NULL) -    addr += reloc->output_section->vma; - -  size = bfd_get_reloc_size (reloc->howto); - -  minfo ("0x%V %W RELOC %s ", addr, size, reloc->howto->name); - -  if (reloc->name != NULL) -    minfo ("%s+", reloc->name); -  else -    minfo ("%s+", reloc->section->name); - -  exp_print_tree (reloc->addend_exp); - -  print_nl (); - -  print_dot = addr + TO_ADDR (size); -} - -static void -print_padding_statement (lang_padding_statement_type *s) -{ -  int len; -  bfd_vma addr; - -  init_opb (); -  minfo (" *fill*"); - -  len = sizeof " *fill*" - 1; -  while (len < SECTION_NAME_MAP_LENGTH) -    { -      print_space (); -      ++len; -    } - -  addr = s->output_offset; -  if (s->output_section != NULL) -    addr += s->output_section->vma; -  minfo ("0x%V %W ", addr, s->size); - -  if (s->fill->size != 0) -    { -      size_t size; -      unsigned char *p; -      for (p = s->fill->data, size = s->fill->size; size != 0; p++, size--) -	fprintf (config.map_file, "%02x", *p); -    } - -  print_nl (); - -  print_dot = addr + TO_ADDR (s->size); -} - -static void -print_wild_statement (lang_wild_statement_type *w, -		      lang_output_section_statement_type *os) -{ -  struct wildcard_list *sec; - -  print_space (); - -  if (w->filenames_sorted) -    minfo ("SORT("); -  if (w->filename != NULL) -    minfo ("%s", w->filename); -  else -    minfo ("*"); -  if (w->filenames_sorted) -    minfo (")"); - -  minfo ("("); -  for (sec = w->section_list; sec; sec = sec->next) -    { -      if (sec->spec.sorted) -	minfo ("SORT("); -      if (sec->spec.exclude_name_list != NULL) -	{ -	  name_list *tmp; -	  minfo ("EXCLUDE_FILE(%s", sec->spec.exclude_name_list->name); -	  for (tmp = sec->spec.exclude_name_list->next; tmp; tmp = tmp->next) -	    minfo (" %s", tmp->name); -	  minfo (") "); -	} -      if (sec->spec.name != NULL) -	minfo ("%s", sec->spec.name); -      else -	minfo ("*"); -      if (sec->spec.sorted) -	minfo (")"); -      if (sec->next) -	minfo (" "); -    } -  minfo (")"); - -  print_nl (); - -  print_statement_list (w->children.head, os); -} - -/* Print a group statement.  */ - -static void -print_group (lang_group_statement_type *s, -	     lang_output_section_statement_type *os) -{ -  fprintf (config.map_file, "START GROUP\n"); -  print_statement_list (s->children.head, os); -  fprintf (config.map_file, "END GROUP\n"); -} - -/* Print the list of statements in S. -   This can be called for any statement type.  */ - -static void -print_statement_list (lang_statement_union_type *s, -		      lang_output_section_statement_type *os) -{ -  while (s != NULL) -    { -      print_statement (s, os); -      s = s->header.next; -    } -} - -/* Print the first statement in statement list S. -   This can be called for any statement type.  */ - -static void -print_statement (lang_statement_union_type *s, -		 lang_output_section_statement_type *os) -{ -  switch (s->header.type) -    { -    default: -      fprintf (config.map_file, _("Fail with %d\n"), s->header.type); -      FAIL (); -      break; -    case lang_constructors_statement_enum: -      if (constructor_list.head != NULL) -	{ -	  if (constructors_sorted) -	    minfo (" SORT (CONSTRUCTORS)\n"); -	  else -	    minfo (" CONSTRUCTORS\n"); -	  print_statement_list (constructor_list.head, os); -	} -      break; -    case lang_wild_statement_enum: -      print_wild_statement (&s->wild_statement, os); -      break; -    case lang_address_statement_enum: -      print_address_statement (&s->address_statement); -      break; -    case lang_object_symbols_statement_enum: -      minfo (" CREATE_OBJECT_SYMBOLS\n"); -      break; -    case lang_fill_statement_enum: -      print_fill_statement (&s->fill_statement); -      break; -    case lang_data_statement_enum: -      print_data_statement (&s->data_statement); -      break; -    case lang_reloc_statement_enum: -      print_reloc_statement (&s->reloc_statement); -      break; -    case lang_input_section_enum: -      print_input_section (&s->input_section); -      break; -    case lang_padding_statement_enum: -      print_padding_statement (&s->padding_statement); -      break; -    case lang_output_section_statement_enum: -      print_output_section_statement (&s->output_section_statement); -      break; -    case lang_assignment_statement_enum: -      print_assignment (&s->assignment_statement, os); -      break; -    case lang_target_statement_enum: -      fprintf (config.map_file, "TARGET(%s)\n", s->target_statement.target); -      break; -    case lang_output_statement_enum: -      minfo ("OUTPUT(%s", s->output_statement.name); -      if (output_target != NULL) -	minfo (" %s", output_target); -      minfo (")\n"); -      break; -    case lang_input_statement_enum: -      print_input_statement (&s->input_statement); -      break; -    case lang_group_statement_enum: -      print_group (&s->group_statement, os); -      break; -    case lang_afile_asection_pair_statement_enum: -      FAIL (); -      break; -    } -} - -static void -print_statements (void) -{ -  print_statement_list (statement_list.head, abs_output_section); -} - -/* Print the first N statements in statement list S to STDERR. -   If N == 0, nothing is printed. -   If N < 0, the entire list is printed. -   Intended to be called from GDB.  */ - -void -dprint_statement (lang_statement_union_type *s, int n) -{ -  FILE *map_save = config.map_file; - -  config.map_file = stderr; - -  if (n < 0) -    print_statement_list (s, abs_output_section); -  else -    { -      while (s && --n >= 0) -	{ -	  print_statement (s, abs_output_section); -	  s = s->header.next; -	} -    } - -  config.map_file = map_save; -} - -static void -insert_pad (lang_statement_union_type **ptr, -	    fill_type *fill, -	    unsigned int alignment_needed, -	    asection *output_section, -	    bfd_vma dot) -{ -  static fill_type zero_fill = { 1, { 0 } }; -  lang_statement_union_type *pad; - -  pad = ((lang_statement_union_type *) -	 ((char *) ptr - offsetof (lang_statement_union_type, header.next))); -  if (ptr != &statement_list.head -      && pad->header.type == lang_padding_statement_enum -      && pad->padding_statement.output_section == output_section) -    { -      /* Use the existing pad statement.  The above test on output -	 section is probably redundant, but it doesn't hurt to check.  */ -    } -  else -    { -      /* Make a new padding statement, linked into existing chain.  */ -      pad = stat_alloc (sizeof (lang_padding_statement_type)); -      pad->header.next = *ptr; -      *ptr = pad; -      pad->header.type = lang_padding_statement_enum; -      pad->padding_statement.output_section = output_section; -      if (fill == NULL) -	fill = &zero_fill; -      pad->padding_statement.fill = fill; -    } -  pad->padding_statement.output_offset = dot - output_section->vma; -  pad->padding_statement.size = alignment_needed; -  output_section->_raw_size += alignment_needed; -} - -/* Work out how much this section will move the dot point.  */ - -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) -{ -  lang_input_section_type *is = &((*this_ptr)->input_section); -  asection *i = is->section; - -  if (!is->ifile->just_syms_flag) -    { -      unsigned int alignment_needed; -      asection *o; - -      /* Align this section first to the input sections requirement, -	 then to the output section's requirement.  If this alignment -	 is greater than any seen before, then record it too.  Perform -	 the alignment by inserting a magic 'padding' statement.  */ - -      if (output_section_statement->subsection_alignment != -1) -	i->alignment_power = output_section_statement->subsection_alignment; - -      o = output_section_statement->bfd_section; -      if (o->alignment_power < i->alignment_power) -	o->alignment_power = i->alignment_power; - -      alignment_needed = align_power (dot, i->alignment_power) - dot; - -      if (alignment_needed != 0) -	{ -	  insert_pad (this_ptr, fill, TO_SIZE (alignment_needed), o, dot); -	  dot += alignment_needed; -	} - -      /* Remember where in the output section this input section goes.  */ - -      i->output_offset = dot - o->vma; - -      /* Mark how big the output section must be to contain this now.  */ -      if (i->_cooked_size != 0) -	dot += TO_ADDR (i->_cooked_size); -      else -	dot += TO_ADDR (i->_raw_size); -      o->_raw_size = TO_SIZE (dot - o->vma); -    } -  else -    { -      i->output_offset = i->vma - output_section_statement->bfd_section->vma; -    } - -  return dot; -} - -#define IGNORE_SECTION(bfd, s) \ -  (((bfd_get_section_flags (bfd, s) & SEC_THREAD_LOCAL)			\ -    ? ((bfd_get_section_flags (bfd, s) & (SEC_LOAD | SEC_NEVER_LOAD))	\ -       != SEC_LOAD)							\ -    :  ((bfd_get_section_flags (bfd, s) & (SEC_ALLOC | SEC_NEVER_LOAD)) \ -	!= SEC_ALLOC))							\ -   || bfd_section_size (bfd, s) == 0) - -/* Check to see if any allocated sections overlap with other allocated -   sections.  This can happen when the linker script specifically specifies -   the output section addresses of the two sections.  */ - -static void -lang_check_section_addresses (void) -{ -  asection *s; - -  /* Scan all sections in the output list.  */ -  for (s = output_bfd->sections; s != NULL; s = s->next) -    { -      asection *os; - -      /* Ignore sections which are not loaded or which have no contents.  */ -      if (IGNORE_SECTION (output_bfd, s)) -	continue; - -      /* Once we reach section 's' stop our seach.  This prevents two -	 warning messages from being produced, one for 'section A overlaps -	 section B' and one for 'section B overlaps section A'.  */ -      for (os = output_bfd->sections; os != s; os = os->next) -	{ -	  bfd_vma s_start; -	  bfd_vma s_end; -	  bfd_vma os_start; -	  bfd_vma os_end; - -	  /* Only consider loadable sections with real contents.  */ -	  if (IGNORE_SECTION (output_bfd, os)) -	    continue; - -	  /* We must check the sections' LMA addresses not their -	     VMA addresses because overlay sections can have -	     overlapping VMAs but they must have distinct LMAs.  */ -	  s_start = bfd_section_lma (output_bfd, s); -	  os_start = bfd_section_lma (output_bfd, os); -	  s_end = s_start + TO_ADDR (bfd_section_size (output_bfd, s)) - 1; -	  os_end = os_start + TO_ADDR (bfd_section_size (output_bfd, os)) - 1; - -	  /* Look for an overlap.  */ -	  if ((s_end < os_start) || (s_start > os_end)) -	    continue; - -	  einfo ( -_("%X%P: section %s [%V -> %V] overlaps section %s [%V -> %V]\n"), -		 s->name, s_start, s_end, os->name, os_start, os_end); - -	  /* Once we have found one overlap for this section, -	     stop looking for others.  */ -	  break; -	} -    } -} - -/* Make sure the new address is within the region.  We explicitly permit the -   current address to be at the exact end of the region when the address is -   non-zero, in case the region is at the end of addressable memory and the -   calculation wraps around.  */ - -static void -os_region_check (lang_output_section_statement_type *os, -		 lang_memory_region_type *region, -		 etree_type *tree, -		 bfd_vma base) -{ -  if ((region->current < region->origin -       || (region->current - region->origin > region->length)) -      && ((region->current != region->origin + region->length) -	  || base == 0)) -    { -      if (tree != NULL) -	{ -	  einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"), -		 region->current, -		 os->bfd_section->owner, -		 os->bfd_section->name, -		 region->name); -	} -      else -	{ -	  einfo (_("%X%P: region %s is full (%B section %s)\n"), -		 region->name, -		 os->bfd_section->owner, -		 os->bfd_section->name); -	} -      /* Reset the region pointer.  */ -      region->current = region->origin; -    } -} - -/* Set the sizes for all the output sections.  */ - -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) -{ -  /* Size up the sections from their constituent parts.  */ -  for (; s != NULL; s = s->header.next) -    { -      switch (s->header.type) -	{ -	case lang_output_section_statement_enum: -	  { -	    bfd_vma after; -	    lang_output_section_statement_type *os; - -	    os = &s->output_section_statement; -	    if (os->bfd_section == NULL) -	      /* This section was never actually created.  */ -	      break; - -	    /* If this is a COFF shared library section, use the size and -	       address from the input section.  FIXME: This is COFF -	       specific; it would be cleaner if there were some other way -	       to do this, but nothing simple comes to mind.  */ -	    if ((os->bfd_section->flags & SEC_COFF_SHARED_LIBRARY) != 0) -	      { -		asection *input; - -		if (os->children.head == NULL -		    || os->children.head->header.next != NULL -		    || os->children.head->header.type != lang_input_section_enum) -		  einfo (_("%P%X: Internal error on COFF shared library section %s\n"), -			 os->name); - -		input = os->children.head->input_section.section; -		bfd_set_section_vma (os->bfd_section->owner, -				     os->bfd_section, -				     bfd_section_vma (input->owner, input)); -		os->bfd_section->_raw_size = input->_raw_size; -		break; -	      } - -	    if (bfd_is_abs_section (os->bfd_section)) -	      { -		/* No matter what happens, an abs section starts at zero.  */ -		ASSERT (os->bfd_section->vma == 0); -	      } -	    else -	      { -		if (os->addr_tree == NULL) -		  { -		    /* No address specified for this section, get one -		       from the region specification.  */ -		    if (os->region == NULL -			|| (((bfd_get_section_flags (output_bfd, os->bfd_section) -			      & (SEC_ALLOC | SEC_LOAD)) != 0) -			    && os->region->name[0] == '*' -			    && strcmp (os->region->name, DEFAULT_MEMORY_REGION) == 0)) -		      { -			os->region = lang_memory_default (os->bfd_section); -		      } - -		    /* If a loadable section is using the default memory -		       region, and some non default memory regions were -		       defined, issue an error message.  */ -		    if (!IGNORE_SECTION (output_bfd, os->bfd_section) -			&& ! link_info.relocatable -			&& check_regions -			&& strcmp (os->region->name, DEFAULT_MEMORY_REGION) == 0 -			&& lang_memory_region_list != NULL -			&& (strcmp (lang_memory_region_list->name, -				    DEFAULT_MEMORY_REGION) != 0 -			    || lang_memory_region_list->next != NULL)) -		      { -			/* By default this is an error rather than just a -			   warning because if we allocate the section to the -			   default memory region we can end up creating an -			   excessively large binary, or even seg faulting when -			   attempting to perform a negative seek.  See -			     http://sources.redhat.com/ml/binutils/2003-04/msg00423.html -			   for an example of this.  This behaviour can be -			   overridden by the using the --no-check-sections -			   switch.  */ -			if (command_line.check_section_addresses) -			  einfo (_("%P%F: error: no memory region specified for loadable section `%s'\n"), -				 bfd_get_section_name (output_bfd, -						       os->bfd_section)); -			else -			  einfo (_("%P: warning: no memory region specified for loadable section `%s'\n"), -				 bfd_get_section_name (output_bfd, -						       os->bfd_section)); -		      } - -		    dot = os->region->current; - -		    if (os->section_alignment == -1) -		      { -			bfd_vma olddot; - -			olddot = dot; -			dot = align_power (dot, -					   os->bfd_section->alignment_power); - -			if (dot != olddot && config.warn_section_align) -			  einfo (_("%P: warning: changing start of section %s by %u bytes\n"), -				 os->name, (unsigned int) (dot - olddot)); -		      } -		  } -		else -		  { -		    etree_value_type r; - -		    os->processed = -1; -		    r = exp_fold_tree (os->addr_tree, -				       abs_output_section, -				       lang_allocating_phase_enum, -				       dot, &dot); -		    os->processed = 0; -		     -		    if (!r.valid_p) -		      einfo (_("%F%S: non constant or forward reference address expression for section %s\n"), -			     os->name); - -		    dot = r.value + r.section->bfd_section->vma; -		  } - -		/* The section starts here. -		   First, align to what the section needs.  */ - -		if (os->section_alignment != -1) -		  dot = align_power (dot, os->section_alignment); - -		bfd_set_section_vma (0, os->bfd_section, dot); - -		os->bfd_section->output_offset = 0; -	      } - -	    lang_size_sections_1 (os->children.head, os, &os->children.head, -				  os->fill, dot, relax, check_regions); - -	    /* Put the section within the requested block size, or -	       align at the block boundary.  */ -	    after = ((os->bfd_section->vma -		      + TO_ADDR (os->bfd_section->_raw_size) -		      + os->block_value - 1) -		     & - (bfd_vma) os->block_value); - -	    if (bfd_is_abs_section (os->bfd_section)) -	      ASSERT (after == os->bfd_section->vma); -	    else -	      os->bfd_section->_raw_size -		= TO_SIZE (after - os->bfd_section->vma); - -	    dot = os->bfd_section->vma; -	    /* .tbss sections effectively have zero size.  */ -	    if ((os->bfd_section->flags & SEC_HAS_CONTENTS) != 0 -		|| (os->bfd_section->flags & SEC_THREAD_LOCAL) == 0 -		|| link_info.relocatable) -	      dot += TO_ADDR (os->bfd_section->_raw_size); - -	    os->processed = 1; - -	    if (os->update_dot_tree != 0) -	      exp_fold_tree (os->update_dot_tree, abs_output_section, -			     lang_allocating_phase_enum, dot, &dot); - -	    /* Update dot in the region ? -	       We only do this if the section is going to be allocated, -	       since unallocated sections do not contribute to the region's -	       overall size in memory. - -	       If the SEC_NEVER_LOAD bit is not set, it will affect the -	       addresses of sections after it. We have to update -	       dot.  */ -	    if (os->region != NULL -		&& ((bfd_get_section_flags (output_bfd, os->bfd_section) -		     & SEC_NEVER_LOAD) == 0 -		    || (bfd_get_section_flags (output_bfd, os->bfd_section) -			& (SEC_ALLOC | SEC_LOAD)))) -	      { -		os->region->current = dot; - -		if (check_regions) -		  /* Make sure the new address is within the region.  */ -		  os_region_check (os, os->region, os->addr_tree, -				   os->bfd_section->vma); - -		/* If there's no load address specified, use the run -		   region as the load region.  */ -		if (os->lma_region == NULL && os->load_base == NULL) -		  os->lma_region = os->region; - -		if (os->lma_region != NULL && os->lma_region != os->region) -		  { -		    /* Set load_base, which will be handled later.  */ -		    os->load_base = exp_intop (os->lma_region->current); -		    os->lma_region->current += -		      TO_ADDR (os->bfd_section->_raw_size); -		    if (check_regions) -		      os_region_check (os, os->lma_region, NULL, -				       os->bfd_section->lma); -		  } -	      } -	  } -	  break; - -	case lang_constructors_statement_enum: -	  dot = lang_size_sections_1 (constructor_list.head, -				      output_section_statement, -				      &s->wild_statement.children.head, -				      fill, dot, relax, check_regions); -	  break; - -	case lang_data_statement_enum: -	  { -	    unsigned int size = 0; - -	    s->data_statement.output_vma = -	      dot - output_section_statement->bfd_section->vma; -	    s->data_statement.output_section = -	      output_section_statement->bfd_section; - -	    /* We might refer to provided symbols in the expression, and -	       need to mark them as needed.  */ -	    exp_fold_tree (s->data_statement.exp, abs_output_section, -			   lang_allocating_phase_enum, dot, &dot); - -	    switch (s->data_statement.type) -	      { -	      default: -		abort (); -	      case QUAD: -	      case SQUAD: -		size = QUAD_SIZE; -		break; -	      case LONG: -		size = LONG_SIZE; -		break; -	      case SHORT: -		size = SHORT_SIZE; -		break; -	      case BYTE: -		size = BYTE_SIZE; -		break; -	      } -	    if (size < TO_SIZE ((unsigned) 1)) -	      size = TO_SIZE ((unsigned) 1); -	    dot += TO_ADDR (size); -	    output_section_statement->bfd_section->_raw_size += size; -	    /* The output section gets contents, and then we inspect for -	       any flags set in the input script which override any ALLOC.  */ -	    output_section_statement->bfd_section->flags |= SEC_HAS_CONTENTS; -	    if (!(output_section_statement->flags & SEC_NEVER_LOAD)) -	      { -		output_section_statement->bfd_section->flags |= -		  SEC_ALLOC | SEC_LOAD; -	      } -	  } -	  break; - -	case lang_reloc_statement_enum: -	  { -	    int size; - -	    s->reloc_statement.output_vma = -	      dot - output_section_statement->bfd_section->vma; -	    s->reloc_statement.output_section = -	      output_section_statement->bfd_section; -	    size = bfd_get_reloc_size (s->reloc_statement.howto); -	    dot += TO_ADDR (size); -	    output_section_statement->bfd_section->_raw_size += size; -	  } -	  break; - -	case lang_wild_statement_enum: - -	  dot = lang_size_sections_1 (s->wild_statement.children.head, -				      output_section_statement, -				      &s->wild_statement.children.head, -				      fill, dot, relax, check_regions); - -	  break; - -	case lang_object_symbols_statement_enum: -	  link_info.create_object_symbols_section = -	    output_section_statement->bfd_section; -	  break; -	case lang_output_statement_enum: -	case lang_target_statement_enum: -	  break; -	case lang_input_section_enum: -	  { -	    asection *i; - -	    i = (*prev)->input_section.section; -	    if (! relax) -	      { -		if (i->_cooked_size == 0) -		  i->_cooked_size = i->_raw_size; -	      } -	    else -	      { -		bfd_boolean again; - -		if (! bfd_relax_section (i->owner, i, &link_info, &again)) -		  einfo (_("%P%F: can't relax section: %E\n")); -		if (again) -		  *relax = TRUE; -	      } -	    dot = size_input_section (prev, output_section_statement, -				      output_section_statement->fill, dot); -	  } -	  break; -	case lang_input_statement_enum: -	  break; -	case lang_fill_statement_enum: -	  s->fill_statement.output_section = -	    output_section_statement->bfd_section; - -	  fill = s->fill_statement.fill; -	  break; -	case lang_assignment_statement_enum: -	  { -	    bfd_vma newdot = dot; - -	    exp_fold_tree (s->assignment_statement.exp, -			   output_section_statement, -			   lang_allocating_phase_enum, -			   dot, -			   &newdot); - -	    if (newdot != dot) -	      { -		if (output_section_statement == abs_output_section) -		  { -		    /* If we don't have an output section, then just adjust -		       the default memory address.  */ -		    lang_memory_region_lookup (DEFAULT_MEMORY_REGION, FALSE)->current = newdot; -		  } -		else -		  { -		    /* Insert a pad after this statement.  We can't -		       put the pad before when relaxing, in case the -		       assignment references dot.  */ -		    insert_pad (&s->header.next, fill, TO_SIZE (newdot - dot), -				output_section_statement->bfd_section, dot); - -		    /* Don't neuter the pad below when relaxing.  */ -		    s = s->header.next; -		  } - -		/* If dot is advanced, this implies that the section should -		   have space allocated to it, unless the user has explicitly -		   stated that the section should never be loaded.  */ -		if (!(output_section_statement->flags & (SEC_NEVER_LOAD | SEC_ALLOC))) -		  output_section_statement->bfd_section->flags |= SEC_ALLOC; - -		dot = newdot; -	      } -	  } -	  break; - -	case lang_padding_statement_enum: -	  /* If this is the first time lang_size_sections is called, -	     we won't have any padding statements.  If this is the -	     second or later passes when relaxing, we should allow -	     padding to shrink.  If padding is needed on this pass, it -	     will be added back in.  */ -	  s->padding_statement.size = 0; - -	  /* Make sure output_offset is valid.  If relaxation shrinks -	     the section and this pad isn't needed, it's possible to -	     have output_offset larger than the final size of the -	     section.  bfd_set_section_contents will complain even for -	     a pad size of zero.  */ -	  s->padding_statement.output_offset -	    = dot - output_section_statement->bfd_section->vma; -	  break; - -	case lang_group_statement_enum: -	  dot = lang_size_sections_1 (s->group_statement.children.head, -				      output_section_statement, -				      &s->group_statement.children.head, -				      fill, dot, relax, check_regions); -	  break; - -	default: -	  FAIL (); -	  break; - -	  /* We can only get here when relaxing is turned on.  */ -	case lang_address_statement_enum: -	  break; -	} -      prev = &s->header.next; -    } -  return dot; -} - -bfd_vma -lang_size_sections -  (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) -{ -  bfd_vma result; -  asection *o; - -  /* Callers of exp_fold_tree need to increment this.  */ -  lang_statement_iteration++; - -  exp_data_seg.phase = exp_dataseg_none; -  result = lang_size_sections_1 (s, output_section_statement, prev, fill, -				 dot, relax, check_regions); -  if (exp_data_seg.phase == exp_dataseg_end_seen) -    { -      /* If DATA_SEGMENT_ALIGN DATA_SEGMENT_END pair was seen, check whether -	 a page could be saved in the data segment.  */ -      bfd_vma first, last; - -      first = -exp_data_seg.base & (exp_data_seg.pagesize - 1); -      last = exp_data_seg.end & (exp_data_seg.pagesize - 1); -      if (first && last -	  && ((exp_data_seg.base & ~(exp_data_seg.pagesize - 1)) -	      != (exp_data_seg.end & ~(exp_data_seg.pagesize - 1))) -	  && first + last <= exp_data_seg.pagesize) -	{ -	  exp_data_seg.phase = exp_dataseg_adjust; -	  lang_statement_iteration++; -	  result = lang_size_sections_1 (s, output_section_statement, prev, -					 fill, dot, relax, check_regions); -	} -    } - -  /* Some backend relaxers want to refer to the output section size.  Give -     them a section size that does not change on the next call while they -     relax.  We can't set this at top because lang_reset_memory_regions -     which is called before we get here, sets _raw_size to 0 on relaxing -     rounds.  */ -  for (o = output_bfd->sections; o != NULL; o = o->next) -    o->_cooked_size = o->_raw_size; - -  return result; -} - -/* Worker function for lang_do_assignments.  Recursiveness goes here.  */ - -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) -{ -  for (; s != NULL; s = s->header.next) -    { -      switch (s->header.type) -	{ -	case lang_constructors_statement_enum: -	  dot = lang_do_assignments_1 (constructor_list.head, -				       output_section_statement, -				       fill, -				       dot); -	  break; - -	case lang_output_section_statement_enum: -	  { -	    lang_output_section_statement_type *os; - -	    os = &(s->output_section_statement); -	    if (os->bfd_section != NULL) -	      { -		dot = os->bfd_section->vma; -		lang_do_assignments_1 (os->children.head, os, os->fill, dot); -		dot = (os->bfd_section->vma -		       + TO_ADDR (os->bfd_section->_raw_size)); - -	      } -	    if (os->load_base) -	      { -		/* If nothing has been placed into the output section then -		   it won't have a bfd_section.  */ -		if (os->bfd_section) -		  { -		    os->bfd_section->lma -		      = exp_get_abs_int (os->load_base, 0, "load base", -					 lang_final_phase_enum); -		  } -	      } -	  } -	  break; -	case lang_wild_statement_enum: - -	  dot = lang_do_assignments_1 (s->wild_statement.children.head, -				       output_section_statement, -				       fill, dot); - -	  break; - -	case lang_object_symbols_statement_enum: -	case lang_output_statement_enum: -	case lang_target_statement_enum: -#if 0 -	case lang_common_statement_enum: -#endif -	  break; -	case lang_data_statement_enum: -	  { -	    etree_value_type value; - -	    value = exp_fold_tree (s->data_statement.exp, -				   abs_output_section, -				   lang_final_phase_enum, dot, &dot); -	    if (!value.valid_p) -	      einfo (_("%F%P: invalid data statement\n")); -	    s->data_statement.value -	      = value.value + value.section->bfd_section->vma; -	  } -	  { -	    unsigned int size; -	    switch (s->data_statement.type) -	      { -	      default: -		abort (); -	      case QUAD: -	      case SQUAD: -		size = QUAD_SIZE; -		break; -	      case LONG: -		size = LONG_SIZE; -		break; -	      case SHORT: -		size = SHORT_SIZE; -		break; -	      case BYTE: -		size = BYTE_SIZE; -		break; -	      } -	    if (size < TO_SIZE ((unsigned) 1)) -	      size = TO_SIZE ((unsigned) 1); -	    dot += TO_ADDR (size); -	  } -	  break; - -	case lang_reloc_statement_enum: -	  { -	    etree_value_type value; - -	    value = exp_fold_tree (s->reloc_statement.addend_exp, -				   abs_output_section, -				   lang_final_phase_enum, dot, &dot); -	    s->reloc_statement.addend_value = value.value; -	    if (!value.valid_p) -	      einfo (_("%F%P: invalid reloc statement\n")); -	  } -	  dot += TO_ADDR (bfd_get_reloc_size (s->reloc_statement.howto)); -	  break; - -	case lang_input_section_enum: -	  { -	    asection *in = s->input_section.section; - -	    if (in->_cooked_size != 0) -	      dot += TO_ADDR (in->_cooked_size); -	    else -	      dot += TO_ADDR (in->_raw_size); -	  } -	  break; - -	case lang_input_statement_enum: -	  break; -	case lang_fill_statement_enum: -	  fill = s->fill_statement.fill; -	  break; -	case lang_assignment_statement_enum: -	  { -	    exp_fold_tree (s->assignment_statement.exp, -			   output_section_statement, -			   lang_final_phase_enum, -			   dot, -			   &dot); -	  } - -	  break; -	case lang_padding_statement_enum: -	  dot += TO_ADDR (s->padding_statement.size); -	  break; - -	case lang_group_statement_enum: -	  dot = lang_do_assignments_1 (s->group_statement.children.head, -				       output_section_statement, -				       fill, dot); - -	  break; - -	default: -	  FAIL (); -	  break; -	case lang_address_statement_enum: -	  break; -	} - -    } -  return dot; -} - -void -lang_do_assignments (lang_statement_union_type *s, -		     lang_output_section_statement_type *output_section_statement, -		     fill_type *fill, -		     bfd_vma dot) -{ -  /* Callers of exp_fold_tree need to increment this.  */ -  lang_statement_iteration++; -  lang_do_assignments_1 (s, output_section_statement, fill, dot); -} - -/* Fix any .startof. or .sizeof. symbols.  When the assemblers see the -   operator .startof. (section_name), it produces an undefined symbol -   .startof.section_name.  Similarly, when it sees -   .sizeof. (section_name), it produces an undefined symbol -   .sizeof.section_name.  For all the output sections, we look for -   such symbols, and set them to the correct value.  */ - -static void -lang_set_startof (void) -{ -  asection *s; - -  if (link_info.relocatable) -    return; - -  for (s = output_bfd->sections; s != NULL; s = s->next) -    { -      const char *secname; -      char *buf; -      struct bfd_link_hash_entry *h; - -      secname = bfd_get_section_name (output_bfd, s); -      buf = xmalloc (10 + strlen (secname)); - -      sprintf (buf, ".startof.%s", secname); -      h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE, TRUE); -      if (h != NULL && h->type == bfd_link_hash_undefined) -	{ -	  h->type = bfd_link_hash_defined; -	  h->u.def.value = bfd_get_section_vma (output_bfd, s); -	  h->u.def.section = bfd_abs_section_ptr; -	} - -      sprintf (buf, ".sizeof.%s", secname); -      h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE, TRUE); -      if (h != NULL && h->type == bfd_link_hash_undefined) -	{ -	  h->type = bfd_link_hash_defined; -	  if (s->_cooked_size != 0) -	    h->u.def.value = TO_ADDR (s->_cooked_size); -	  else -	    h->u.def.value = TO_ADDR (s->_raw_size); -	  h->u.def.section = bfd_abs_section_ptr; -	} - -      free (buf); -    } -} - -static void -lang_finish (void) -{ -  struct bfd_link_hash_entry *h; -  bfd_boolean warn; - -  if (link_info.relocatable || link_info.shared) -    warn = FALSE; -  else -    warn = TRUE; - -  if (entry_symbol.name == NULL) -    { -      /* No entry has been specified.  Look for start, but don't warn -	 if we don't find it.  */ -      entry_symbol.name = "start"; -      warn = FALSE; -    } - -  h = bfd_link_hash_lookup (link_info.hash, entry_symbol.name, -			    FALSE, FALSE, TRUE); -  if (h != NULL -      && (h->type == bfd_link_hash_defined -	  || h->type == bfd_link_hash_defweak) -      && h->u.def.section->output_section != NULL) -    { -      bfd_vma val; - -      val = (h->u.def.value -	     + bfd_get_section_vma (output_bfd, -				    h->u.def.section->output_section) -	     + h->u.def.section->output_offset); -      if (! bfd_set_start_address (output_bfd, val)) -	einfo (_("%P%F:%s: can't set start address\n"), entry_symbol.name); -    } -  else -    { -      bfd_vma val; -      const char *send; - -      /* We couldn't find the entry symbol.  Try parsing it as a -         number.  */ -      val = bfd_scan_vma (entry_symbol.name, &send, 0); -      if (*send == '\0') -	{ -	  if (! bfd_set_start_address (output_bfd, val)) -	    einfo (_("%P%F: can't set start address\n")); -	} -      else -	{ -	  asection *ts; - -	  /* Can't find the entry symbol, and it's not a number.  Use -	     the first address in the text section.  */ -	  ts = bfd_get_section_by_name (output_bfd, entry_section); -	  if (ts != NULL) -	    { -	      if (warn) -		einfo (_("%P: warning: cannot find entry symbol %s; defaulting to %V\n"), -		       entry_symbol.name, -		       bfd_get_section_vma (output_bfd, ts)); -	      if (! bfd_set_start_address (output_bfd, -					   bfd_get_section_vma (output_bfd, -								ts))) -		einfo (_("%P%F: can't set start address\n")); -	    } -	  else -	    { -	      if (warn) -		einfo (_("%P: warning: cannot find entry symbol %s; not setting start address\n"), -		       entry_symbol.name); -	    } -	} -    } - -  bfd_hash_table_free (&lang_definedness_table); -} - -/* This is a small function used when we want to ignore errors from -   BFD.  */ - -static void -ignore_bfd_errors (const char *s ATTRIBUTE_UNUSED, ...) -{ -  /* Don't do anything.  */ -} - -/* Check that the architecture of all the input files is compatible -   with the output file.  Also call the backend to let it do any -   other checking that is needed.  */ - -static void -lang_check (void) -{ -  lang_statement_union_type *file; -  bfd *input_bfd; -  const bfd_arch_info_type *compatible; - -  for (file = file_chain.head; file != NULL; file = file->input_statement.next) -    { -      input_bfd = file->input_statement.the_bfd; -      compatible = bfd_arch_get_compatible (input_bfd, output_bfd, -					    command_line.accept_unknown_input_arch); - -      /* In general it is not possible to perform a relocatable -	 link between differing object formats when the input -	 file has relocations, because the relocations in the -	 input format may not have equivalent representations in -	 the output format (and besides BFD does not translate -	 relocs for other link purposes than a final link).  */ -      if ((link_info.relocatable || link_info.emitrelocations) -	  && (compatible == NULL -	      || bfd_get_flavour (input_bfd) != bfd_get_flavour (output_bfd)) -	  && (bfd_get_file_flags (input_bfd) & HAS_RELOC) != 0) -	{ -	  einfo (_("%P%F: Relocatable linking with relocations from format %s (%B) to format %s (%B) is not supported\n"), -		 bfd_get_target (input_bfd), input_bfd, -		 bfd_get_target (output_bfd), output_bfd); -	  /* einfo with %F exits.  */ -	} - -      if (compatible == NULL) -	{ -	  if (command_line.warn_mismatch) -	    einfo (_("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n"), -		   bfd_printable_name (input_bfd), input_bfd, -		   bfd_printable_name (output_bfd)); -	} -      else if (bfd_count_sections (input_bfd)) -	{ -	  /* If the input bfd has no contents, it shouldn't set the -	     private data of the output bfd.  */ - -	  bfd_error_handler_type pfn = NULL; - -	  /* If we aren't supposed to warn about mismatched input -             files, temporarily set the BFD error handler to a -             function which will do nothing.  We still want to call -             bfd_merge_private_bfd_data, since it may set up -             information which is needed in the output file.  */ -	  if (! command_line.warn_mismatch) -	    pfn = bfd_set_error_handler (ignore_bfd_errors); -	  if (! bfd_merge_private_bfd_data (input_bfd, output_bfd)) -	    { -	      if (command_line.warn_mismatch) -		einfo (_("%P%X: failed to merge target specific data of file %B\n"), -		       input_bfd); -	    } -	  if (! command_line.warn_mismatch) -	    bfd_set_error_handler (pfn); -	} -    } -} - -/* Look through all the global common symbols and attach them to the -   correct section.  The -sort-common command line switch may be used -   to roughly sort the entries by size.  */ - -static void -lang_common (void) -{ -  if (command_line.inhibit_common_definition) -    return; -  if (link_info.relocatable -      && ! command_line.force_common_definition) -    return; - -  if (! config.sort_common) -    bfd_link_hash_traverse (link_info.hash, lang_one_common, NULL); -  else -    { -      int power; - -      for (power = 4; power >= 0; power--) -	bfd_link_hash_traverse (link_info.hash, lang_one_common, &power); -    } -} - -/* Place one common symbol in the correct section.  */ - -static bfd_boolean -lang_one_common (struct bfd_link_hash_entry *h, void *info) -{ -  unsigned int power_of_two; -  bfd_vma size; -  asection *section; - -  if (h->type != bfd_link_hash_common) -    return TRUE; - -  size = h->u.c.size; -  power_of_two = h->u.c.p->alignment_power; - -  if (config.sort_common -      && power_of_two < (unsigned int) *(int *) info) -    return TRUE; - -  section = h->u.c.p->section; - -  /* Increase the size of the section to align the common sym.  */ -  section->_cooked_size += ((bfd_vma) 1 << (power_of_two + opb_shift)) - 1; -  section->_cooked_size &= (- (bfd_vma) 1 << (power_of_two + opb_shift)); - -  /* Adjust the alignment if necessary.  */ -  if (power_of_two > section->alignment_power) -    section->alignment_power = power_of_two; - -  /* Change the symbol from common to defined.  */ -  h->type = bfd_link_hash_defined; -  h->u.def.section = section; -  h->u.def.value = section->_cooked_size; - -  /* Increase the size of the section.  */ -  section->_cooked_size += size; - -  /* Make sure the section is allocated in memory, and make sure that -     it is no longer a common section.  */ -  section->flags |= SEC_ALLOC; -  section->flags &= ~SEC_IS_COMMON; - -  if (config.map_file != NULL) -    { -      static bfd_boolean header_printed; -      int len; -      char *name; -      char buf[50]; - -      if (! header_printed) -	{ -	  minfo (_("\nAllocating common symbols\n")); -	  minfo (_("Common symbol       size              file\n\n")); -	  header_printed = TRUE; -	} - -      name = demangle (h->root.string); -      minfo ("%s", name); -      len = strlen (name); -      free (name); - -      if (len >= 19) -	{ -	  print_nl (); -	  len = 0; -	} -      while (len < 20) -	{ -	  print_space (); -	  ++len; -	} - -      minfo ("0x"); -      if (size <= 0xffffffff) -	sprintf (buf, "%lx", (unsigned long) size); -      else -	sprintf_vma (buf, size); -      minfo ("%s", buf); -      len = strlen (buf); - -      while (len < 16) -	{ -	  print_space (); -	  ++len; -	} - -      minfo ("%B\n", section->owner); -    } - -  return TRUE; -} - -/* Run through the input files and ensure that every input section has -   somewhere to go.  If one is found without a destination then create -   an input request and place it into the statement tree.  */ - -static void -lang_place_orphans (void) -{ -  LANG_FOR_EACH_INPUT_STATEMENT (file) -    { -      asection *s; - -      for (s = file->the_bfd->sections; s != NULL; s = s->next) -	{ -	  if (s->output_section == NULL) -	    { -	      /* This section of the file is not attached, root -	         around for a sensible place for it to go.  */ - -	      if (file->just_syms_flag) -		{ -		  abort (); -		} -	      else if (strcmp (s->name, "COMMON") == 0) -		{ -		  /* This is a lonely common section which must have -		     come from an archive.  We attach to the section -		     with the wildcard.  */ -		  if (! link_info.relocatable -		      || command_line.force_common_definition) -		    { -		      if (default_common_section == NULL) -			{ -#if 0 -			  /* This message happens when using the -                             svr3.ifile linker script, so I have -                             disabled it.  */ -			  info_msg (_("%P: no [COMMON] command, defaulting to .bss\n")); -#endif -			  default_common_section = -			    lang_output_section_statement_lookup (".bss"); - -			} -		      lang_add_section (&default_common_section->children, s, -					default_common_section, file); -		    } -		} -	      else if (ldemul_place_orphan (file, s)) -		; -	      else -		{ -		  lang_output_section_statement_type *os; - -		  os = lang_output_section_statement_lookup (s->name); -		  lang_add_section (&os->children, s, os, file); -		} -	    } -	} -    } -} - -void -lang_set_flags (lang_memory_region_type *ptr, const char *flags, int invert) -{ -  flagword *ptr_flags; - -  ptr_flags = invert ? &ptr->not_flags : &ptr->flags; -  while (*flags) -    { -      switch (*flags) -	{ -	case 'A': case 'a': -	  *ptr_flags |= SEC_ALLOC; -	  break; - -	case 'R': case 'r': -	  *ptr_flags |= SEC_READONLY; -	  break; - -	case 'W': case 'w': -	  *ptr_flags |= SEC_DATA; -	  break; - -	case 'X': case 'x': -	  *ptr_flags |= SEC_CODE; -	  break; - -	case 'L': case 'l': -	case 'I': case 'i': -	  *ptr_flags |= SEC_LOAD; -	  break; - -	default: -	  einfo (_("%P%F: invalid syntax in flags\n")); -	  break; -	} -      flags++; -    } -} - -/* Call a function on each input file.  This function will be called -   on an archive, but not on the elements.  */ - -void -lang_for_each_input_file (void (*func) (lang_input_statement_type *)) -{ -  lang_input_statement_type *f; - -  for (f = (lang_input_statement_type *) input_file_chain.head; -       f != NULL; -       f = (lang_input_statement_type *) f->next_real_file) -    func (f); -} - -/* Call a function on each file.  The function will be called on all -   the elements of an archive which are included in the link, but will -   not be called on the archive file itself.  */ - -void -lang_for_each_file (void (*func) (lang_input_statement_type *)) -{ -  LANG_FOR_EACH_INPUT_STATEMENT (f) -    { -      func (f); -    } -} - -void -ldlang_add_file (lang_input_statement_type *entry) -{ -  bfd **pp; - -  lang_statement_append (&file_chain, -			 (lang_statement_union_type *) entry, -			 &entry->next); - -  /* The BFD linker needs to have a list of all input BFDs involved in -     a link.  */ -  ASSERT (entry->the_bfd->link_next == NULL); -  ASSERT (entry->the_bfd != output_bfd); -  for (pp = &link_info.input_bfds; *pp != NULL; pp = &(*pp)->link_next) -    ; -  *pp = entry->the_bfd; -  entry->the_bfd->usrdata = entry; -  bfd_set_gp_size (entry->the_bfd, g_switch_value); - -  /* Look through the sections and check for any which should not be -     included in the link.  We need to do this now, so that we can -     notice when the backend linker tries to report multiple -     definition errors for symbols which are in sections we aren't -     going to link.  FIXME: It might be better to entirely ignore -     symbols which are defined in sections which are going to be -     discarded.  This would require modifying the backend linker for -     each backend which might set the SEC_LINK_ONCE flag.  If we do -     this, we should probably handle SEC_EXCLUDE in the same way.  */ - -  bfd_map_over_sections (entry->the_bfd, section_already_linked, entry); -} - -void -lang_add_output (const char *name, int from_script) -{ -  /* Make -o on command line override OUTPUT in script.  */ -  if (!had_output_filename || !from_script) -    { -      output_filename = name; -      had_output_filename = TRUE; -    } -} - -static lang_output_section_statement_type *current_section; - -static int -topower (int x) -{ -  unsigned int i = 1; -  int l; - -  if (x < 0) -    return -1; - -  for (l = 0; l < 32; l++) -    { -      if (i >= (unsigned int) x) -	return l; -      i <<= 1; -    } - -  return 0; -} - -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) -{ -  lang_output_section_statement_type *os; - -  current_section = -   os = -    lang_output_section_statement_lookup (output_section_statement_name); - -  /* Add this statement to tree.  */ -#if 0 -  add_statement (lang_output_section_statement_enum, -		 output_section_statement); -#endif -  /* Make next things chain into subchain of this.  */ - -  if (os->addr_tree == NULL) -    { -      os->addr_tree = address_exp; -    } -  os->sectype = sectype; -  if (sectype != noload_section) -    os->flags = SEC_NO_FLAGS; -  else -    os->flags = SEC_NEVER_LOAD; -  os->block_value = 1; -  stat_ptr = &os->children; - -  os->subsection_alignment = -    topower (exp_get_value_int (subalign, -1, "subsection alignment", 0)); -  os->section_alignment = -    topower (exp_get_value_int (align, -1, "section alignment", 0)); - -  os->load_base = ebase; -  return os; -} - -void -lang_final (void) -{ -  lang_output_statement_type *new = -    new_stat (lang_output_statement, stat_ptr); - -  new->name = output_filename; -} - -/* Reset the current counters in the regions.  */ - -void -lang_reset_memory_regions (void) -{ -  lang_memory_region_type *p = lang_memory_region_list; -  asection *o; - -  for (p = lang_memory_region_list; p != NULL; p = p->next) -    { -      p->old_length = (bfd_size_type) (p->current - p->origin); -      p->current = p->origin; -    } - -  for (o = output_bfd->sections; o != NULL; o = o->next) -    o->_raw_size = 0; -} - -/* If the wild pattern was marked KEEP, the member sections -   should be as well.  */ - -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) -{ -  if (ptr->keep_sections) -    section->flags |= SEC_KEEP; -} - -/* Handle a wild statement, marking it against GC.  */ - -static void -lang_gc_wild (lang_wild_statement_type *s) -{ -  walk_wild (s, gc_section_callback, NULL); -} - -/* Iterate over sections marking them against GC.  */ - -static void -lang_gc_sections_1 (lang_statement_union_type *s) -{ -  for (; s != NULL; s = s->header.next) -    { -      switch (s->header.type) -	{ -	case lang_wild_statement_enum: -	  lang_gc_wild (&s->wild_statement); -	  break; -	case lang_constructors_statement_enum: -	  lang_gc_sections_1 (constructor_list.head); -	  break; -	case lang_output_section_statement_enum: -	  lang_gc_sections_1 (s->output_section_statement.children.head); -	  break; -	case lang_group_statement_enum: -	  lang_gc_sections_1 (s->group_statement.children.head); -	  break; -	default: -	  break; -	} -    } -} - -static void -lang_gc_sections (void) -{ -  struct bfd_link_hash_entry *h; -  ldlang_undef_chain_list_type *ulist; - -  /* Keep all sections so marked in the link script.  */ - -  lang_gc_sections_1 (statement_list.head); - -  /* Keep all sections containing symbols undefined on the command-line, -     and the section containing the entry symbol.  */ - -  for (ulist = link_info.gc_sym_list; ulist; ulist = ulist->next) -    { -      h = bfd_link_hash_lookup (link_info.hash, ulist->name, -				FALSE, FALSE, FALSE); - -      if (h != NULL -	  && (h->type == bfd_link_hash_defined -	      || h->type == bfd_link_hash_defweak) -	  && ! bfd_is_abs_section (h->u.def.section)) -	{ -	  h->u.def.section->flags |= SEC_KEEP; -	} -    } - -  bfd_gc_sections (output_bfd, &link_info); -} - -void -lang_process (void) -{ -  lang_reasonable_defaults (); -  current_target = default_target; - -  /* Open the output file.  */ -  lang_for_each_statement (ldlang_open_output); -  init_opb (); - -  ldemul_create_output_section_statements (); - -  /* Add to the hash table all undefineds on the command line.  */ -  lang_place_undefineds (); - -  already_linked_table_init (); - -  /* Create a bfd for each input file.  */ -  current_target = default_target; -  open_input_bfds (statement_list.head, FALSE); - -  link_info.gc_sym_list = &entry_symbol; -  if (entry_symbol.name == NULL) -    link_info.gc_sym_list = ldlang_undef_chain_list_head; - -  ldemul_after_open (); - -  already_linked_table_free (); - -  /* Make sure that we're not mixing architectures.  We call this -     after all the input files have been opened, but before we do any -     other processing, so that any operations merge_private_bfd_data -     does on the output file will be known during the rest of the -     link.  */ -  lang_check (); - -  /* Handle .exports instead of a version script if we're told to do so.  */ -  if (command_line.version_exports_section) -    lang_do_version_exports_section (); - -  /* Build all sets based on the information gathered from the input -     files.  */ -  ldctor_build_sets (); - -  /* Remove unreferenced sections if asked to.  */ -  if (command_line.gc_sections) -    lang_gc_sections (); - -  /* If there were any SEC_MERGE sections, finish their merging, so that -     section sizes can be computed.  This has to be done after GC of sections, -     so that GCed sections are not merged, but before assigning output -     sections, since removing whole input sections is hard then.  */ -  bfd_merge_sections (output_bfd, &link_info); - -  /* Size up the common data.  */ -  lang_common (); - -  /* Run through the contours of the script and attach input sections -     to the correct output sections.  */ -  map_input_to_output_sections (statement_list.head, NULL, NULL); - -  /* Find any sections not attached explicitly and handle them.  */ -  lang_place_orphans (); - -  if (! link_info.relocatable) -    { -      /* Look for a text section and set the readonly attribute in it.  */ -      asection *found = bfd_get_section_by_name (output_bfd, ".text"); - -      if (found != NULL) -	{ -	  if (config.text_read_only) -	    found->flags |= SEC_READONLY; -	  else -	    found->flags &= ~SEC_READONLY; -	} -    } - -  /* Do anything special before sizing sections.  This is where ELF -     and other back-ends size dynamic sections.  */ -  ldemul_before_allocation (); - -  if (!link_info.relocatable) -    strip_excluded_output_sections (); - -  /* We must record the program headers before we try to fix the -     section positions, since they will affect SIZEOF_HEADERS.  */ -  lang_record_phdrs (); - -  /* Size up the sections.  */ -  lang_size_sections (statement_list.head, abs_output_section, -		      &statement_list.head, 0, 0, NULL, -		      command_line.relax ? FALSE : TRUE); - -  /* Now run around and relax if we can.  */ -  if (command_line.relax) -    { -      /* Keep relaxing until bfd_relax_section gives up.  */ -      bfd_boolean relax_again; - -      do -	{ -	  relax_again = FALSE; - -	  /* Note: pe-dll.c does something like this also.  If you find -	     you need to change this code, you probably need to change -	     pe-dll.c also.  DJ  */ - -	  /* Do all the assignments with our current guesses as to -	     section sizes.  */ -	  lang_do_assignments (statement_list.head, abs_output_section, -			       NULL, 0); - -	  /* We must do this after lang_do_assignments, because it uses -	     _raw_size.  */ -	  lang_reset_memory_regions (); - -	  /* Perform another relax pass - this time we know where the -	     globals are, so can make a better guess.  */ -	  lang_size_sections (statement_list.head, abs_output_section, -			      &statement_list.head, 0, 0, &relax_again, FALSE); - -	  /* If the normal relax is done and the relax finalize pass -	     is not performed yet, we perform another relax pass.  */ -	  if (!relax_again && link_info.need_relax_finalize) -	    { -	      link_info.need_relax_finalize = FALSE; -	      relax_again = TRUE; -	    } -	} -      while (relax_again); - -      /* Final extra sizing to report errors.  */ -      lang_do_assignments (statement_list.head, abs_output_section, NULL, 0); -      lang_reset_memory_regions (); -      lang_size_sections (statement_list.head, abs_output_section, -			  &statement_list.head, 0, 0, NULL, TRUE); -    } - -  /* See if anything special should be done now we know how big -     everything is.  */ -  ldemul_after_allocation (); - -  /* Fix any .startof. or .sizeof. symbols.  */ -  lang_set_startof (); - -  /* Do all the assignments, now that we know the final resting places -     of all the symbols.  */ - -  lang_do_assignments (statement_list.head, abs_output_section, NULL, 0); - -  /* Make sure that the section addresses make sense.  */ -  if (! link_info.relocatable -      && command_line.check_section_addresses) -    lang_check_section_addresses (); - -  /* Final stuffs.  */ - -  ldemul_finish (); -  lang_finish (); -} - -/* EXPORTED TO YACC */ - -void -lang_add_wild (struct wildcard_spec *filespec, -	       struct wildcard_list *section_list, -	       bfd_boolean keep_sections) -{ -  struct wildcard_list *curr, *next; -  lang_wild_statement_type *new; - -  /* Reverse the list as the parser puts it back to front.  */ -  for (curr = section_list, section_list = NULL; -       curr != NULL; -       section_list = curr, curr = next) -    { -      if (curr->spec.name != NULL && strcmp (curr->spec.name, "COMMON") == 0) -	placed_commons = TRUE; - -      next = curr->next; -      curr->next = section_list; -    } - -  if (filespec != NULL && filespec->name != NULL) -    { -      if (strcmp (filespec->name, "*") == 0) -	filespec->name = NULL; -      else if (! wildcardp (filespec->name)) -	lang_has_input_file = TRUE; -    } - -  new = new_stat (lang_wild_statement, stat_ptr); -  new->filename = NULL; -  new->filenames_sorted = FALSE; -  if (filespec != NULL) -    { -      new->filename = filespec->name; -      new->filenames_sorted = filespec->sorted; -    } -  new->section_list = section_list; -  new->keep_sections = keep_sections; -  lang_list_init (&new->children); -} - -void -lang_section_start (const char *name, etree_type *address) -{ -  lang_address_statement_type *ad; - -  ad = new_stat (lang_address_statement, stat_ptr); -  ad->section_name = name; -  ad->address = address; -} - -/* Set the start symbol to NAME.  CMDLINE is nonzero if this is called -   because of a -e argument on the command line, or zero if this is -   called by ENTRY in a linker script.  Command line arguments take -   precedence.  */ - -void -lang_add_entry (const char *name, bfd_boolean cmdline) -{ -  if (entry_symbol.name == NULL -      || cmdline -      || ! entry_from_cmdline) -    { -      entry_symbol.name = name; -      entry_from_cmdline = cmdline; -    } -} - -void -lang_add_target (const char *name) -{ -  lang_target_statement_type *new = new_stat (lang_target_statement, -					      stat_ptr); - -  new->target = name; - -} - -void -lang_add_map (const char *name) -{ -  while (*name) -    { -      switch (*name) -	{ -	case 'F': -	  map_option_f = TRUE; -	  break; -	} -      name++; -    } -} - -void -lang_add_fill (fill_type *fill) -{ -  lang_fill_statement_type *new = new_stat (lang_fill_statement, -					    stat_ptr); - -  new->fill = fill; -} - -void -lang_add_data (int type, union etree_union *exp) -{ - -  lang_data_statement_type *new = new_stat (lang_data_statement, -					    stat_ptr); - -  new->exp = exp; -  new->type = type; - -} - -/* Create a new reloc statement.  RELOC is the BFD relocation type to -   generate.  HOWTO is the corresponding howto structure (we could -   look this up, but the caller has already done so).  SECTION is the -   section to generate a reloc against, or NAME is the name of the -   symbol to generate a reloc against.  Exactly one of SECTION and -   NAME must be NULL.  ADDEND is an expression for the addend.  */ - -void -lang_add_reloc (bfd_reloc_code_real_type reloc, -		reloc_howto_type *howto, -		asection *section, -		const char *name, -		union etree_union *addend) -{ -  lang_reloc_statement_type *p = new_stat (lang_reloc_statement, stat_ptr); - -  p->reloc = reloc; -  p->howto = howto; -  p->section = section; -  p->name = name; -  p->addend_exp = addend; - -  p->addend_value = 0; -  p->output_section = NULL; -  p->output_vma = 0; -} - -lang_assignment_statement_type * -lang_add_assignment (etree_type *exp) -{ -  lang_assignment_statement_type *new = new_stat (lang_assignment_statement, -						  stat_ptr); - -  new->exp = exp; -  return new; -} - -void -lang_add_attribute (enum statement_enum attribute) -{ -  new_statement (attribute, sizeof (lang_statement_union_type), stat_ptr); -} - -void -lang_startup (const char *name) -{ -  if (startup_file != NULL) -    { -      einfo (_("%P%Fmultiple STARTUP files\n")); -    } -  first_file->filename = name; -  first_file->local_sym_name = name; -  first_file->real = TRUE; - -  startup_file = name; -} - -void -lang_float (bfd_boolean maybe) -{ -  lang_float_flag = maybe; -} - - -/* Work out the load- and run-time regions from a script statement, and -   store them in *LMA_REGION and *REGION respectively. - -   MEMSPEC is the name of the run-time region, or the value of -   DEFAULT_MEMORY_REGION if the statement didn't specify one. -   LMA_MEMSPEC is the name of the load-time region, or null if the -   statement didn't specify one.HAVE_LMA_P is TRUE if the statement -   had an explicit load address. - -   It is an error to specify both a load region and a load address.  */ - -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) -{ -  *lma_region = lang_memory_region_lookup (lma_memspec, FALSE); - -  /* If no runtime region or VMA has been specified, but the load region has -     been specified, then use the load region for the runtime region as well.  */ -  if (lma_memspec != NULL -      && ! have_vma -      && strcmp (memspec, DEFAULT_MEMORY_REGION) == 0) -    *region = *lma_region; -  else -    *region = lang_memory_region_lookup (memspec, FALSE); - -  if (have_lma && lma_memspec != 0) -    einfo (_("%X%P:%S: section has both a load address and a load region\n")); -} - -void -lang_leave_output_section_statement (fill_type *fill, const char *memspec, -				     lang_output_section_phdr_list *phdrs, -				     const char *lma_memspec) -{ -  lang_get_regions (¤t_section->region, -		    ¤t_section->lma_region, -		    memspec, lma_memspec, -		    current_section->load_base != NULL, -		    current_section->addr_tree != NULL); -  current_section->fill = fill; -  current_section->phdrs = phdrs; -  stat_ptr = &statement_list; -} - -/* Create an absolute symbol with the given name with the value of the -   address of first byte of the section named. - -   If the symbol already exists, then do nothing.  */ - -void -lang_abs_symbol_at_beginning_of (const char *secname, const char *name) -{ -  struct bfd_link_hash_entry *h; - -  h = bfd_link_hash_lookup (link_info.hash, name, TRUE, TRUE, TRUE); -  if (h == NULL) -    einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n")); - -  if (h->type == bfd_link_hash_new -      || h->type == bfd_link_hash_undefined) -    { -      asection *sec; - -      h->type = bfd_link_hash_defined; - -      sec = bfd_get_section_by_name (output_bfd, secname); -      if (sec == NULL) -	h->u.def.value = 0; -      else -	h->u.def.value = bfd_get_section_vma (output_bfd, sec); - -      h->u.def.section = bfd_abs_section_ptr; -    } -} - -/* Create an absolute symbol with the given name with the value of the -   address of the first byte after the end of the section named. - -   If the symbol already exists, then do nothing.  */ - -void -lang_abs_symbol_at_end_of (const char *secname, const char *name) -{ -  struct bfd_link_hash_entry *h; - -  h = bfd_link_hash_lookup (link_info.hash, name, TRUE, TRUE, TRUE); -  if (h == NULL) -    einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n")); - -  if (h->type == bfd_link_hash_new -      || h->type == bfd_link_hash_undefined) -    { -      asection *sec; - -      h->type = bfd_link_hash_defined; - -      sec = bfd_get_section_by_name (output_bfd, secname); -      if (sec == NULL) -	h->u.def.value = 0; -      else -	h->u.def.value = (bfd_get_section_vma (output_bfd, sec) -			  + TO_ADDR (bfd_section_size (output_bfd, sec))); - -      h->u.def.section = bfd_abs_section_ptr; -    } -} - -void -lang_statement_append (lang_statement_list_type *list, -		       lang_statement_union_type *element, -		       lang_statement_union_type **field) -{ -  *(list->tail) = element; -  list->tail = field; -} - -/* Set the output format type.  -oformat overrides scripts.  */ - -void -lang_add_output_format (const char *format, -			const char *big, -			const char *little, -			int from_script) -{ -  if (output_target == NULL || !from_script) -    { -      if (command_line.endian == ENDIAN_BIG -	  && big != NULL) -	format = big; -      else if (command_line.endian == ENDIAN_LITTLE -	       && little != NULL) -	format = little; - -      output_target = format; -    } -} - -/* Enter a group.  This creates a new lang_group_statement, and sets -   stat_ptr to build new statements within the group.  */ - -void -lang_enter_group (void) -{ -  lang_group_statement_type *g; - -  g = new_stat (lang_group_statement, stat_ptr); -  lang_list_init (&g->children); -  stat_ptr = &g->children; -} - -/* Leave a group.  This just resets stat_ptr to start writing to the -   regular list of statements again.  Note that this will not work if -   groups can occur inside anything else which can adjust stat_ptr, -   but currently they can't.  */ - -void -lang_leave_group (void) -{ -  stat_ptr = &statement_list; -} - -/* Add a new program header.  This is called for each entry in a PHDRS -   command in a linker script.  */ - -void -lang_new_phdr (const char *name, -	       etree_type *type, -	       bfd_boolean filehdr, -	       bfd_boolean phdrs, -	       etree_type *at, -	       etree_type *flags) -{ -  struct lang_phdr *n, **pp; - -  n = stat_alloc (sizeof (struct lang_phdr)); -  n->next = NULL; -  n->name = name; -  n->type = exp_get_value_int (type, 0, "program header type", -			       lang_final_phase_enum); -  n->filehdr = filehdr; -  n->phdrs = phdrs; -  n->at = at; -  n->flags = flags; - -  for (pp = &lang_phdr_list; *pp != NULL; pp = &(*pp)->next) -    ; -  *pp = n; -} - -/* Record the program header information in the output BFD.  FIXME: We -   should not be calling an ELF specific function here.  */ - -static void -lang_record_phdrs (void) -{ -  unsigned int alc; -  asection **secs; -  lang_output_section_phdr_list *last; -  struct lang_phdr *l; -  lang_statement_union_type *u; - -  alc = 10; -  secs = xmalloc (alc * sizeof (asection *)); -  last = NULL; -  for (l = lang_phdr_list; l != NULL; l = l->next) -    { -      unsigned int c; -      flagword flags; -      bfd_vma at; - -      c = 0; -      for (u = lang_output_section_statement.head; -	   u != NULL; -	   u = u->output_section_statement.next) -	{ -	  lang_output_section_statement_type *os; -	  lang_output_section_phdr_list *pl; - -	  os = &u->output_section_statement; - -	  pl = os->phdrs; -	  if (pl != NULL) -	    last = pl; -	  else -	    { -	      if (os->sectype == noload_section -		  || os->bfd_section == NULL -		  || (os->bfd_section->flags & SEC_ALLOC) == 0) -		continue; -	      pl = last; -	    } - -	  if (os->bfd_section == NULL) -	    continue; - -	  for (; pl != NULL; pl = pl->next) -	    { -	      if (strcmp (pl->name, l->name) == 0) -		{ -		  if (c >= alc) -		    { -		      alc *= 2; -		      secs = xrealloc (secs, alc * sizeof (asection *)); -		    } -		  secs[c] = os->bfd_section; -		  ++c; -		  pl->used = TRUE; -		} -	    } -	} - -      if (l->flags == NULL) -	flags = 0; -      else -	flags = exp_get_vma (l->flags, 0, "phdr flags", -			     lang_final_phase_enum); - -      if (l->at == NULL) -	at = 0; -      else -	at = exp_get_vma (l->at, 0, "phdr load address", -			  lang_final_phase_enum); - -      if (! bfd_record_phdr (output_bfd, l->type, -			     l->flags != NULL, flags, l->at != NULL, -			     at, l->filehdr, l->phdrs, c, secs)) -	einfo (_("%F%P: bfd_record_phdr failed: %E\n")); -    } - -  free (secs); - -  /* Make sure all the phdr assignments succeeded.  */ -  for (u = lang_output_section_statement.head; -       u != NULL; -       u = u->output_section_statement.next) -    { -      lang_output_section_phdr_list *pl; - -      if (u->output_section_statement.bfd_section == NULL) -	continue; - -      for (pl = u->output_section_statement.phdrs; -	   pl != NULL; -	   pl = pl->next) -	if (! pl->used && strcmp (pl->name, "NONE") != 0) -	  einfo (_("%X%P: section `%s' assigned to non-existent phdr `%s'\n"), -		 u->output_section_statement.name, pl->name); -    } -} - -/* Record a list of sections which may not be cross referenced.  */ - -void -lang_add_nocrossref (lang_nocrossref_type *l) -{ -  struct lang_nocrossrefs *n; - -  n = xmalloc (sizeof *n); -  n->next = nocrossref_list; -  n->list = l; -  nocrossref_list = n; - -  /* Set notice_all so that we get informed about all symbols.  */ -  link_info.notice_all = TRUE; -} - -/* Overlay handling.  We handle overlays with some static variables.  */ - -/* The overlay virtual address.  */ -static etree_type *overlay_vma; -/* And subsection alignment.  */ -static etree_type *overlay_subalign; - -/* An expression for the maximum section size seen so far.  */ -static etree_type *overlay_max; - -/* A list of all the sections in this overlay.  */ - -struct overlay_list { -  struct overlay_list *next; -  lang_output_section_statement_type *os; -}; - -static struct overlay_list *overlay_list; - -/* Start handling an overlay.  */ - -void -lang_enter_overlay (etree_type *vma_expr, etree_type *subalign) -{ -  /* The grammar should prevent nested overlays from occurring.  */ -  ASSERT (overlay_vma == NULL -	  && overlay_subalign == NULL -	  && overlay_max == NULL); - -  overlay_vma = vma_expr; -  overlay_subalign = subalign; -} - -/* Start a section in an overlay.  We handle this by calling -   lang_enter_output_section_statement with the correct VMA. -   lang_leave_overlay sets up the LMA and memory regions.  */ - -void -lang_enter_overlay_section (const char *name) -{ -  struct overlay_list *n; -  etree_type *size; - -  lang_enter_output_section_statement (name, overlay_vma, normal_section, -				       0, overlay_subalign, 0); - -  /* If this is the first section, then base the VMA of future -     sections on this one.  This will work correctly even if `.' is -     used in the addresses.  */ -  if (overlay_list == NULL) -    overlay_vma = exp_nameop (ADDR, name); - -  /* Remember the section.  */ -  n = xmalloc (sizeof *n); -  n->os = current_section; -  n->next = overlay_list; -  overlay_list = n; - -  size = exp_nameop (SIZEOF, name); - -  /* Arrange to work out the maximum section end address.  */ -  if (overlay_max == NULL) -    overlay_max = size; -  else -    overlay_max = exp_binop (MAX_K, overlay_max, size); -} - -/* Finish a section in an overlay.  There isn't any special to do -   here.  */ - -void -lang_leave_overlay_section (fill_type *fill, -			    lang_output_section_phdr_list *phdrs) -{ -  const char *name; -  char *clean, *s2; -  const char *s1; -  char *buf; - -  name = current_section->name; - -  /* For now, assume that DEFAULT_MEMORY_REGION is the run-time memory -     region and that no load-time region has been specified.  It doesn't -     really matter what we say here, since lang_leave_overlay will -     override it.  */ -  lang_leave_output_section_statement (fill, DEFAULT_MEMORY_REGION, phdrs, 0); - -  /* Define the magic symbols.  */ - -  clean = xmalloc (strlen (name) + 1); -  s2 = clean; -  for (s1 = name; *s1 != '\0'; s1++) -    if (ISALNUM (*s1) || *s1 == '_') -      *s2++ = *s1; -  *s2 = '\0'; - -  buf = xmalloc (strlen (clean) + sizeof "__load_start_"); -  sprintf (buf, "__load_start_%s", clean); -  lang_add_assignment (exp_assop ('=', buf, -				  exp_nameop (LOADADDR, name))); - -  buf = xmalloc (strlen (clean) + sizeof "__load_stop_"); -  sprintf (buf, "__load_stop_%s", clean); -  lang_add_assignment (exp_assop ('=', buf, -				  exp_binop ('+', -					     exp_nameop (LOADADDR, name), -					     exp_nameop (SIZEOF, name)))); - -  free (clean); -} - -/* Finish an overlay.  If there are any overlay wide settings, this -   looks through all the sections in the overlay and sets them.  */ - -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) -{ -  lang_memory_region_type *region; -  lang_memory_region_type *lma_region; -  struct overlay_list *l; -  lang_nocrossref_type *nocrossref; - -  lang_get_regions (®ion, &lma_region, -		    memspec, lma_memspec, -		    lma_expr != NULL, FALSE); - -  nocrossref = NULL; - -  /* After setting the size of the last section, set '.' to end of the -     overlay region.  */ -  if (overlay_list != NULL) -    overlay_list->os->update_dot_tree -      = exp_assop ('=', ".", exp_binop ('+', overlay_vma, overlay_max)); - -  l = overlay_list; -  while (l != NULL) -    { -      struct overlay_list *next; - -      if (fill != NULL && l->os->fill == NULL) -	l->os->fill = fill; - -      l->os->region = region; -      l->os->lma_region = lma_region; - -      /* The first section has the load address specified in the -	 OVERLAY statement.  The rest are worked out from that. -	 The base address is not needed (and should be null) if -	 an LMA region was specified.  */ -      if (l->next == 0) -	l->os->load_base = lma_expr; -      else if (lma_region == 0) -	l->os->load_base = exp_binop ('+', -				      exp_nameop (LOADADDR, l->next->os->name), -				      exp_nameop (SIZEOF, l->next->os->name)); - -      if (phdrs != NULL && l->os->phdrs == NULL) -	l->os->phdrs = phdrs; - -      if (nocrossrefs) -	{ -	  lang_nocrossref_type *nc; - -	  nc = xmalloc (sizeof *nc); -	  nc->name = l->os->name; -	  nc->next = nocrossref; -	  nocrossref = nc; -	} - -      next = l->next; -      free (l); -      l = next; -    } - -  if (nocrossref != NULL) -    lang_add_nocrossref (nocrossref); - -  overlay_vma = NULL; -  overlay_list = NULL; -  overlay_max = NULL; -} - -/* Version handling.  This is only useful for ELF.  */ - -/* This global variable holds the version tree that we build.  */ - -struct bfd_elf_version_tree *lang_elf_version_info; - -/* If PREV is NULL, return first version pattern matching particular symbol. -   If PREV is non-NULL, return first version pattern matching particular -   symbol after PREV (previously returned by lang_vers_match).  */ - -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) -{ -  const char *cxx_sym = sym; -  const char *java_sym = sym; -  struct bfd_elf_version_expr *expr = NULL; - -  if (head->mask & BFD_ELF_VERSION_CXX_TYPE) -    { -      cxx_sym = cplus_demangle (sym, DMGL_PARAMS | DMGL_ANSI); -      if (!cxx_sym) -	cxx_sym = sym; -    } -  if (head->mask & BFD_ELF_VERSION_JAVA_TYPE) -    { -      java_sym = cplus_demangle (sym, DMGL_JAVA); -      if (!java_sym) -	java_sym = sym; -    } - -  if (head->htab && (prev == NULL || prev->symbol)) -    { -      struct bfd_elf_version_expr e; - -      switch (prev ? prev->mask : 0) -	{ -	  case 0: -	    if (head->mask & BFD_ELF_VERSION_C_TYPE) -	      { -		e.symbol = sym; -		expr = htab_find (head->htab, &e); -		while (expr && strcmp (expr->symbol, sym) == 0) -		  if (expr->mask == BFD_ELF_VERSION_C_TYPE) -		    goto out_ret; -		else -		  expr = expr->next; -	      } -	    /* Fallthrough */ -	  case BFD_ELF_VERSION_C_TYPE: -	    if (head->mask & BFD_ELF_VERSION_CXX_TYPE) -	      { -		e.symbol = cxx_sym; -		expr = htab_find (head->htab, &e); -		while (expr && strcmp (expr->symbol, cxx_sym) == 0) -		  if (expr->mask == BFD_ELF_VERSION_CXX_TYPE) -		    goto out_ret; -		else -		  expr = expr->next; -	      } -	    /* Fallthrough */ -	  case BFD_ELF_VERSION_CXX_TYPE: -	    if (head->mask & BFD_ELF_VERSION_JAVA_TYPE) -	      { -		e.symbol = java_sym; -		expr = htab_find (head->htab, &e); -		while (expr && strcmp (expr->symbol, java_sym) == 0) -		  if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE) -		    goto out_ret; -		else -		  expr = expr->next; -	      } -	    /* Fallthrough */ -	  default: -	    break; -	} -    } - -  /* Finally, try the wildcards.  */ -  if (prev == NULL || prev->symbol) -    expr = head->remaining; -  else -    expr = prev->next; -  while (expr) -    { -      const char *s; - -      if (expr->pattern[0] == '*' && expr->pattern[1] == '\0') -	break; - -      if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE) -	s = java_sym; -      else if (expr->mask == BFD_ELF_VERSION_CXX_TYPE) -	s = cxx_sym; -      else -	s = sym; -      if (fnmatch (expr->pattern, s, 0) == 0) -	break; -      expr = expr->next; -    } - -out_ret: -  if (cxx_sym != sym) -    free ((char *) cxx_sym); -  if (java_sym != sym) -    free ((char *) java_sym); -  return expr; -} - -/* Return NULL if the PATTERN argument is a glob pattern, otherwise, -   return a string pointing to the symbol name.  */ - -static const char * -realsymbol (const char *pattern) -{ -  const char *p; -  bfd_boolean changed = FALSE, backslash = FALSE; -  char *s, *symbol = xmalloc (strlen (pattern) + 1); - -  for (p = pattern, s = symbol; *p != '\0'; ++p) -    { -      /* It is a glob pattern only if there is no preceding -	 backslash.  */ -      if (! backslash && (*p == '?' || *p == '*' || *p == '[')) -	{ -	  free (symbol); -	  return NULL; -	} - -      if (backslash) -	{ -	  /* Remove the preceding backslash.  */ -	  *(s - 1) = *p; -	  changed = TRUE; -	} -      else -	*s++ = *p; - -      backslash = *p == '\\'; -    } - -  if (changed) -    { -      *s = '\0'; -      return symbol; -    } -  else -    { -      free (symbol); -      return pattern; -    } -} - -/* This is called for each variable name or match expression.  */ - -struct bfd_elf_version_expr * -lang_new_vers_pattern (struct bfd_elf_version_expr *orig, -		       const char *new, -		       const char *lang) -{ -  struct bfd_elf_version_expr *ret; - -  ret = xmalloc (sizeof *ret); -  ret->next = orig; -  ret->pattern = new; -  ret->symver = 0; -  ret->script = 0; -  ret->symbol = realsymbol (new); - -  if (lang == NULL || strcasecmp (lang, "C") == 0) -    ret->mask = BFD_ELF_VERSION_C_TYPE; -  else if (strcasecmp (lang, "C++") == 0) -    ret->mask = BFD_ELF_VERSION_CXX_TYPE; -  else if (strcasecmp (lang, "Java") == 0) -    ret->mask = BFD_ELF_VERSION_JAVA_TYPE; -  else -    { -      einfo (_("%X%P: unknown language `%s' in version information\n"), -	     lang); -      ret->mask = BFD_ELF_VERSION_C_TYPE; -    } - -  return ldemul_new_vers_pattern (ret); -} - -/* This is called for each set of variable names and match -   expressions.  */ - -struct bfd_elf_version_tree * -lang_new_vers_node (struct bfd_elf_version_expr *globals, -		    struct bfd_elf_version_expr *locals) -{ -  struct bfd_elf_version_tree *ret; - -  ret = xcalloc (1, sizeof *ret); -  ret->globals.list = globals; -  ret->locals.list = locals; -  ret->match = lang_vers_match; -  ret->name_indx = (unsigned int) -1; -  return ret; -} - -/* This static variable keeps track of version indices.  */ - -static int version_index; - -static hashval_t -version_expr_head_hash (const void *p) -{ -  const struct bfd_elf_version_expr *e = p; - -  return htab_hash_string (e->symbol); -} - -static int -version_expr_head_eq (const void *p1, const void *p2) -{ -  const struct bfd_elf_version_expr *e1 = p1; -  const struct bfd_elf_version_expr *e2 = p2; - -  return strcmp (e1->symbol, e2->symbol) == 0; -} - -static void -lang_finalize_version_expr_head (struct bfd_elf_version_expr_head *head) -{ -  size_t count = 0; -  struct bfd_elf_version_expr *e, *next; -  struct bfd_elf_version_expr **list_loc, **remaining_loc; - -  for (e = head->list; e; e = e->next) -    { -      if (e->symbol) -	count++; -      head->mask |= e->mask; -    } - -  if (count) -    { -      head->htab = htab_create (count * 2, version_expr_head_hash, -				version_expr_head_eq, NULL); -      list_loc = &head->list; -      remaining_loc = &head->remaining; -      for (e = head->list; e; e = next) -	{ -	  next = e->next; -	  if (!e->symbol) -	    { -	      *remaining_loc = e; -	      remaining_loc = &e->next; -	    } -	  else -	    { -	      void **loc = htab_find_slot (head->htab, e, INSERT); - -	      if (*loc) -		{ -		  struct bfd_elf_version_expr *e1, *last; - -		  e1 = *loc; -		  last = NULL; -		  do -		    { -		      if (e1->mask == e->mask) -			{ -			  last = NULL; -			  break; -			} -		      last = e1; -		      e1 = e1->next; -		    } -		  while (e1 && strcmp (e1->symbol, e->symbol) == 0); - -		  if (last == NULL) -		    { -		      /* This is a duplicate.  */ -		      /* FIXME: Memory leak.  Sometimes pattern is not -			 xmalloced alone, but in larger chunk of memory.  */ -		      /* free (e->symbol); */ -		      free (e); -		    } -		  else -		    { -		      e->next = last->next; -		      last->next = e; -		    } -		} -	      else -		{ -		  *loc = e; -		  *list_loc = e; -		  list_loc = &e->next; -		} -	    } -	} -      *remaining_loc = NULL; -      *list_loc = head->remaining; -    } -  else -    head->remaining = head->list; -} - -/* This is called when we know the name and dependencies of the -   version.  */ - -void -lang_register_vers_node (const char *name, -			 struct bfd_elf_version_tree *version, -			 struct bfd_elf_version_deps *deps) -{ -  struct bfd_elf_version_tree *t, **pp; -  struct bfd_elf_version_expr *e1; - -  if (name == NULL) -    name = ""; - -  if ((name[0] == '\0' && lang_elf_version_info != NULL) -      || (lang_elf_version_info && lang_elf_version_info->name[0] == '\0')) -    { -      einfo (_("%X%P: anonymous version tag cannot be combined with other version tags\n")); -      free (version); -      return; -    } - -  /* Make sure this node has a unique name.  */ -  for (t = lang_elf_version_info; t != NULL; t = t->next) -    if (strcmp (t->name, name) == 0) -      einfo (_("%X%P: duplicate version tag `%s'\n"), name); - -  lang_finalize_version_expr_head (&version->globals); -  lang_finalize_version_expr_head (&version->locals); - -  /* Check the global and local match names, and make sure there -     aren't any duplicates.  */ - -  for (e1 = version->globals.list; e1 != NULL; e1 = e1->next) -    { -      for (t = lang_elf_version_info; t != NULL; t = t->next) -	{ -	  struct bfd_elf_version_expr *e2; - -	  if (t->locals.htab && e1->symbol) -	    { -	      e2 = htab_find (t->locals.htab, e1); -	      while (e2 && strcmp (e1->symbol, e2->symbol) == 0) -		{ -		  if (e1->mask == e2->mask) -		    einfo (_("%X%P: duplicate expression `%s' in version information\n"), -			   e1->symbol); -		  e2 = e2->next; -		} -	    } -	  else if (!e1->symbol) -	    for (e2 = t->locals.remaining; e2 != NULL; e2 = e2->next) -	      if (strcmp (e1->pattern, e2->pattern) == 0 && e1->mask == e2->mask) -		einfo (_("%X%P: duplicate expression `%s' in version information\n"), -		       e1->pattern); -	} -    } - -  for (e1 = version->locals.list; e1 != NULL; e1 = e1->next) -    { -      for (t = lang_elf_version_info; t != NULL; t = t->next) -	{ -	  struct bfd_elf_version_expr *e2; - -	  if (t->globals.htab && e1->symbol) -	    { -	      e2 = htab_find (t->globals.htab, e1); -	      while (e2 && strcmp (e1->symbol, e2->symbol) == 0) -		{ -		  if (e1->mask == e2->mask) -		    einfo (_("%X%P: duplicate expression `%s' in version information\n"), -			   e1->symbol); -		  e2 = e2->next; -		} -	    } -	  else if (!e1->symbol) -	    for (e2 = t->globals.remaining; e2 != NULL; e2 = e2->next) -	      if (strcmp (e1->pattern, e2->pattern) == 0 && e1->mask == e2->mask) -		einfo (_("%X%P: duplicate expression `%s' in version information\n"), -		       e1->pattern); -	} -    } - -  version->deps = deps; -  version->name = name; -  if (name[0] != '\0') -    { -      ++version_index; -      version->vernum = version_index; -    } -  else -    version->vernum = 0; - -  for (pp = &lang_elf_version_info; *pp != NULL; pp = &(*pp)->next) -    ; -  *pp = version; -} - -/* This is called when we see a version dependency.  */ - -struct bfd_elf_version_deps * -lang_add_vers_depend (struct bfd_elf_version_deps *list, const char *name) -{ -  struct bfd_elf_version_deps *ret; -  struct bfd_elf_version_tree *t; - -  ret = xmalloc (sizeof *ret); -  ret->next = list; - -  for (t = lang_elf_version_info; t != NULL; t = t->next) -    { -      if (strcmp (t->name, name) == 0) -	{ -	  ret->version_needed = t; -	  return ret; -	} -    } - -  einfo (_("%X%P: unable to find version dependency `%s'\n"), name); - -  return ret; -} - -static void -lang_do_version_exports_section (void) -{ -  struct bfd_elf_version_expr *greg = NULL, *lreg; - -  LANG_FOR_EACH_INPUT_STATEMENT (is) -    { -      asection *sec = bfd_get_section_by_name (is->the_bfd, ".exports"); -      char *contents, *p; -      bfd_size_type len; - -      if (sec == NULL) -	continue; - -      len = bfd_section_size (is->the_bfd, sec); -      contents = xmalloc (len); -      if (!bfd_get_section_contents (is->the_bfd, sec, contents, 0, len)) -	einfo (_("%X%P: unable to read .exports section contents\n"), sec); - -      p = contents; -      while (p < contents + len) -	{ -	  greg = lang_new_vers_pattern (greg, p, NULL); -	  p = strchr (p, '\0') + 1; -	} - -      /* Do not free the contents, as we used them creating the regex.  */ - -      /* Do not include this section in the link.  */ -      bfd_set_section_flags (is->the_bfd, sec, -	bfd_get_section_flags (is->the_bfd, sec) | SEC_EXCLUDE); -    } - -  lreg = lang_new_vers_pattern (NULL, "*", NULL); -  lang_register_vers_node (command_line.version_exports_section, -			   lang_new_vers_node (greg, lreg), NULL); -} - -void -lang_add_unique (const char *name) -{ -  struct unique_sections *ent; - -  for (ent = unique_section_list; ent; ent = ent->next) -    if (strcmp (ent->name, name) == 0) -      return; - -  ent = xmalloc (sizeof *ent); -  ent->name = xstrdup (name); -  ent->next = unique_section_list; -  unique_section_list = ent; -}  | 
