mri.c revision 107492
133965Sjdp/* mri.c -- handle MRI style linker scripts
2104834Sobrien   Copyright 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000, 2002
377298Sobrien   Free Software Foundation, Inc.
433965Sjdp
533965SjdpThis file is part of GLD, the Gnu Linker.
633965Sjdp
733965SjdpGLD is free software; you can redistribute it and/or modify
833965Sjdpit under the terms of the GNU General Public License as published by
960484Sobrienthe Free Software Foundation; either version 2, or (at your option)
1033965Sjdpany later version.
1133965Sjdp
1233965SjdpGLD is distributed in the hope that it will be useful,
1333965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of
1433965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1533965SjdpGNU General Public License for more details.
1633965Sjdp
1733965SjdpYou should have received a copy of the GNU General Public License
1833965Sjdpalong with GLD; see the file COPYING.  If not, write to the Free
1933965SjdpSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
2077298Sobrien02111-1307, USA.
2133965Sjdp
2277298Sobrien   This bit does the tree decoration when MRI style link scripts
2377298Sobrien   are parsed.
2433965Sjdp
2577298Sobrien   Contributed by Steve Chamberlain <sac@cygnus.com>.  */
2633965Sjdp
2733965Sjdp#include "bfd.h"
2877298Sobrien#include "sysdep.h"
2933965Sjdp#include "ld.h"
3033965Sjdp#include "ldexp.h"
3133965Sjdp#include "ldlang.h"
3233965Sjdp#include "ldmisc.h"
3333965Sjdp#include "mri.h"
34107492Sobrien#include <ldgram.h>
3533965Sjdp#include "libiberty.h"
3633965Sjdp
3733965Sjdpstruct section_name_struct {
3833965Sjdp  struct section_name_struct *next;
39104834Sobrien  const char *name;
40104834Sobrien  const char *alias;
4133965Sjdp  etree_type *vma;
4233965Sjdp  etree_type *align;
4333965Sjdp  etree_type *subalign;
4433965Sjdp  int ok_to_load;
4577298Sobrien};
4633965Sjdp
4733965Sjdpunsigned int symbol_truncate = 10000;
4833965Sjdpstruct section_name_struct *order;
4933965Sjdpstruct section_name_struct *only_load;
5033965Sjdpstruct section_name_struct *address;
5133965Sjdpstruct section_name_struct *alias;
5233965Sjdp
5333965Sjdpstruct section_name_struct *alignment;
5433965Sjdpstruct section_name_struct *subalignment;
5533965Sjdp
5633965Sjdpstatic struct section_name_struct **lookup
5733965Sjdp  PARAMS ((const char *name, struct section_name_struct **list));
5833965Sjdpstatic void mri_add_to_list PARAMS ((struct section_name_struct **list,
5933965Sjdp				     const char *name, etree_type *vma,
6033965Sjdp				     const char *zalias, etree_type *align,
6133965Sjdp				     etree_type *subalign));
6233965Sjdp
6333965Sjdpstatic struct section_name_struct **
6433965Sjdplookup (name, list)
65104834Sobrien     const char *name;
6633965Sjdp     struct section_name_struct **list;
6733965Sjdp{
6877298Sobrien  struct section_name_struct **ptr = list;
6933965Sjdp
7077298Sobrien  while (*ptr)
7177298Sobrien    {
7277298Sobrien      if (strcmp (name, (*ptr)->name) == 0)
7377298Sobrien	/* If this is a match, delete it, we only keep the last instance
7477298Sobrien	   of any name.  */
7577298Sobrien	*ptr = (*ptr)->next;
7677298Sobrien      else
7777298Sobrien	ptr = &((*ptr)->next);
7833965Sjdp    }
7933965Sjdp
8077298Sobrien  *ptr = (struct section_name_struct *) xmalloc (sizeof (struct section_name_struct));
8133965Sjdp  return ptr;
8233965Sjdp}
8333965Sjdp
8433965Sjdpstatic void
8533965Sjdpmri_add_to_list (list, name, vma, zalias, align, subalign)
8633965Sjdp     struct section_name_struct **list;
87104834Sobrien     const char *name;
8833965Sjdp     etree_type *vma;
89104834Sobrien     const char *zalias;
9033965Sjdp     etree_type *align;
9133965Sjdp     etree_type *subalign;
9233965Sjdp{
9377298Sobrien  struct section_name_struct **ptr = lookup (name, list);
9477298Sobrien
9533965Sjdp  (*ptr)->name = name;
9633965Sjdp  (*ptr)->vma = vma;
9777298Sobrien  (*ptr)->next = (struct section_name_struct *) NULL;
9833965Sjdp  (*ptr)->ok_to_load = 0;
9933965Sjdp  (*ptr)->alias = zalias;
10033965Sjdp  (*ptr)->align = align;
10133965Sjdp  (*ptr)->subalign = subalign;
10233965Sjdp}
10333965Sjdp
10433965Sjdpvoid
10533965Sjdpmri_output_section (name, vma)
106104834Sobrien     const char *name;
10733965Sjdp     etree_type *vma;
10833965Sjdp{
10977298Sobrien  mri_add_to_list (&address, name, vma, 0, 0, 0);
11033965Sjdp}
11133965Sjdp
11277298Sobrien/* If any ABSOLUTE <name> are in the script, only load those files
11377298Sobrien   marked thus.  */
11433965Sjdp
11533965Sjdpvoid
11633965Sjdpmri_only_load (name)
117104834Sobrien     const char *name;
11833965Sjdp{
11977298Sobrien  mri_add_to_list (&only_load, name, 0, 0, 0, 0);
12033965Sjdp}
12133965Sjdp
12233965Sjdpvoid
12333965Sjdpmri_base (exp)
12433965Sjdp     etree_type *exp;
12533965Sjdp{
12633965Sjdp  base = exp;
12733965Sjdp}
12833965Sjdp
12933965Sjdpstatic int done_tree = 0;
13033965Sjdp
13133965Sjdpvoid
13233965Sjdpmri_draw_tree ()
13333965Sjdp{
13477298Sobrien  if (done_tree)
13577298Sobrien    return;
13633965Sjdp
13777298Sobrien#if 0   /* We don't bother with memory regions.  */
13877298Sobrien  /* Create the regions.  */
13977298Sobrien  {
14077298Sobrien    lang_memory_region_type *r;
14177298Sobrien
14277298Sobrien    r = lang_memory_region_lookup("long");
14377298Sobrien    r->current = r->origin = exp_get_vma (base, (bfd_vma)0, "origin",
14477298Sobrien					  lang_first_phase_enum);
14577298Sobrien    r->length = (bfd_size_type) exp_get_vma (0, (bfd_vma) ~((bfd_size_type)0),
14677298Sobrien					     "length", lang_first_phase_enum);
14777298Sobrien  }
14833965Sjdp#endif
14933965Sjdp
15077298Sobrien  /* Now build the statements for the ldlang machine.  */
15133965Sjdp
15277298Sobrien  /* Attatch the addresses of any which have addresses,
15377298Sobrien     and add the ones not mentioned.  */
15477298Sobrien  if (address != (struct section_name_struct *) NULL)
15577298Sobrien    {
15677298Sobrien      struct section_name_struct *alist;
15777298Sobrien      struct section_name_struct *olist;
15833965Sjdp
15977298Sobrien      if (order == (struct section_name_struct *) NULL)
16077298Sobrien	order = address;
16177298Sobrien
16277298Sobrien      for (alist = address;
16377298Sobrien	   alist != (struct section_name_struct *) NULL;
16477298Sobrien	   alist = alist->next)
16533965Sjdp	{
16677298Sobrien	  int done = 0;
16777298Sobrien
16877298Sobrien	  for (olist = order;
16977298Sobrien	       done == 0 && olist != (struct section_name_struct *) NULL;
17077298Sobrien	       olist = olist->next)
17177298Sobrien	    {
17277298Sobrien	      if (strcmp (alist->name, olist->name) == 0)
17377298Sobrien		{
17477298Sobrien		  olist->vma = alist->vma;
17577298Sobrien		  done = 1;
17677298Sobrien		}
17777298Sobrien	    }
17877298Sobrien
17977298Sobrien	  if (!done)
18077298Sobrien	    {
18177298Sobrien	      /* Add this onto end of order list.  */
18277298Sobrien	      mri_add_to_list (&order, alist->name, alist->vma, 0, 0, 0);
18377298Sobrien	    }
18433965Sjdp	}
18533965Sjdp    }
18633965Sjdp
18733965Sjdp  /* If we're only supposed to load a subset of them in, then prune
18833965Sjdp     the list.  */
18977298Sobrien  if (only_load != (struct section_name_struct *) NULL)
19077298Sobrien    {
19177298Sobrien      struct section_name_struct *ptr1;
19277298Sobrien      struct section_name_struct *ptr2;
19333965Sjdp
19477298Sobrien      if (order == (struct section_name_struct *) NULL)
19577298Sobrien	order = only_load;
19677298Sobrien
19777298Sobrien      /* See if this name is in the list, if it is then we can load it.  */
19877298Sobrien      for (ptr1 = only_load; ptr1; ptr1 = ptr1->next)
19977298Sobrien	for (ptr2 = order; ptr2; ptr2 = ptr2->next)
20077298Sobrien	  if (strcmp (ptr2->name, ptr1->name) == 0)
20177298Sobrien	    ptr2->ok_to_load = 1;
20277298Sobrien    }
20377298Sobrien  else
20433965Sjdp    {
20577298Sobrien      /* No only load list, so everything is ok to load.  */
20677298Sobrien      struct section_name_struct *ptr;
20777298Sobrien
20877298Sobrien      for (ptr = order; ptr; ptr = ptr->next)
20977298Sobrien	ptr->ok_to_load = 1;
21033965Sjdp    }
21133965Sjdp
21277298Sobrien  /* Create the order of sections to load.  */
21377298Sobrien  if (order != (struct section_name_struct *) NULL)
21477298Sobrien    {
21577298Sobrien      /* Been told to output the sections in a certain order.  */
21677298Sobrien      struct section_name_struct *p = order;
21733965Sjdp
21877298Sobrien      while (p)
21977298Sobrien	{
22077298Sobrien	  struct section_name_struct *aptr;
22177298Sobrien	  etree_type *align = 0;
22277298Sobrien	  etree_type *subalign = 0;
22389857Sobrien	  struct wildcard_list *tmp;
22433965Sjdp
22577298Sobrien	  /* See if an alignment has been specified.  */
22677298Sobrien	  for (aptr = alignment; aptr; aptr = aptr->next)
22777298Sobrien	    if (strcmp (aptr->name, p->name) == 0)
22877298Sobrien	      align = aptr->align;
22933965Sjdp
23077298Sobrien	  for (aptr = subalignment; aptr; aptr = aptr->next)
23177298Sobrien	    if (strcmp (aptr->name, p->name) == 0)
23277298Sobrien	      subalign = aptr->subalign;
23333965Sjdp
23477298Sobrien	  if (base == 0)
23577298Sobrien	    base = p->vma ? p->vma : exp_nameop (NAME, ".");
23633965Sjdp
23777298Sobrien	  lang_enter_output_section_statement (p->name, base,
23877298Sobrien					       p->ok_to_load ? 0 : noload_section,
23977298Sobrien					       1, align, subalign,
24077298Sobrien					       (etree_type *) NULL);
24177298Sobrien	  base = 0;
24289857Sobrien	  tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
24389857Sobrien	  tmp->next = NULL;
24489857Sobrien	  tmp->spec.name = p->name;
24589857Sobrien	  tmp->spec.exclude_name_list = NULL;
24689857Sobrien	  tmp->spec.sorted = false;
24789857Sobrien	  lang_add_wild (NULL, tmp, false);
24833965Sjdp
24977298Sobrien	  /* If there is an alias for this section, add it too.  */
25077298Sobrien	  for (aptr = alias; aptr; aptr = aptr->next)
25177298Sobrien	    if (strcmp (aptr->alias, p->name) == 0)
25289857Sobrien	      {
25389857Sobrien		tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
25489857Sobrien		tmp->next = NULL;
25589857Sobrien		tmp->spec.name = aptr->name;
25689857Sobrien		tmp->spec.exclude_name_list = NULL;
25789857Sobrien		tmp->spec.sorted = false;
25889857Sobrien		lang_add_wild (NULL, tmp, false);
25989857Sobrien	      }
26033965Sjdp
26177298Sobrien	  lang_leave_output_section_statement
26277298Sobrien	    (0, "*default*", (struct lang_output_section_phdr_list *) NULL,
263104834Sobrien	     NULL);
26433965Sjdp
26577298Sobrien	  p = p->next;
26677298Sobrien	}
26733965Sjdp    }
26833965Sjdp
26933965Sjdp  done_tree = 1;
27077298Sobrien}
27133965Sjdp
27233965Sjdpvoid
27333965Sjdpmri_load (name)
274104834Sobrien     const char *name;
27533965Sjdp{
27633965Sjdp  base = 0;
27777298Sobrien  lang_add_input_file (name,
27877298Sobrien		       lang_input_file_is_file_enum, (char *) NULL);
27977298Sobrien#if 0
28077298Sobrien  lang_leave_output_section_statement (0, "*default*");
28177298Sobrien#endif
28233965Sjdp}
28333965Sjdp
28433965Sjdpvoid
28533965Sjdpmri_order (name)
286104834Sobrien     const char *name;
28733965Sjdp{
28877298Sobrien  mri_add_to_list (&order, name, 0, 0, 0, 0);
28933965Sjdp}
29033965Sjdp
29177298Sobrienvoid
29233965Sjdpmri_alias (want, is, isn)
293104834Sobrien     const char *want;
294104834Sobrien     const char *is;
29533965Sjdp     int isn;
29633965Sjdp{
29777298Sobrien  if (!is)
29877298Sobrien    {
29977298Sobrien      char buf[20];
30033965Sjdp
30177298Sobrien      /* Some sections are digits.  */
30277298Sobrien      sprintf (buf, "%d", isn);
30377298Sobrien
30477298Sobrien      is = xstrdup (buf);
30577298Sobrien
30677298Sobrien      if (is == NULL)
30777298Sobrien	abort ();
30877298Sobrien    }
30977298Sobrien
31077298Sobrien  mri_add_to_list (&alias, is, 0, want, 0, 0);
31133965Sjdp}
31233965Sjdp
31377298Sobrienvoid
31433965Sjdpmri_name (name)
315104834Sobrien     const char *name;
31633965Sjdp{
31777298Sobrien  lang_add_output (name, 1);
31833965Sjdp}
31933965Sjdp
32033965Sjdpvoid
32133965Sjdpmri_format (name)
322104834Sobrien     const char *name;
32333965Sjdp{
32477298Sobrien  if (strcmp (name, "S") == 0)
32577298Sobrien    lang_add_output_format ("srec", (char *) NULL, (char *) NULL, 1);
32677298Sobrien
32777298Sobrien  else if (strcmp (name, "IEEE") == 0)
32877298Sobrien    lang_add_output_format ("ieee", (char *) NULL, (char *) NULL, 1);
32977298Sobrien
33077298Sobrien  else if (strcmp (name, "COFF") == 0)
33177298Sobrien    lang_add_output_format ("coff-m68k", (char *) NULL, (char *) NULL, 1);
33277298Sobrien
33377298Sobrien  else
33477298Sobrien    einfo (_("%P%F: unknown format type %s\n"), name);
33533965Sjdp}
33633965Sjdp
33733965Sjdpvoid
33833965Sjdpmri_public (name, exp)
339104834Sobrien     const char *name;
34033965Sjdp     etree_type *exp;
34133965Sjdp{
34277298Sobrien  lang_add_assignment (exp_assop ('=', name, exp));
34333965Sjdp}
34433965Sjdp
34577298Sobrienvoid
34633965Sjdpmri_align (name, exp)
347104834Sobrien     const char *name;
34833965Sjdp     etree_type *exp;
34933965Sjdp{
35077298Sobrien  mri_add_to_list (&alignment, name, 0, 0, exp, 0);
35133965Sjdp}
35233965Sjdp
35377298Sobrienvoid
35433965Sjdpmri_alignmod (name, exp)
355104834Sobrien     const char *name;
35633965Sjdp     etree_type *exp;
35733965Sjdp{
35877298Sobrien  mri_add_to_list (&subalignment, name, 0, 0, 0, exp);
35933965Sjdp}
36033965Sjdp
36177298Sobrienvoid
36233965Sjdpmri_truncate (exp)
36333965Sjdp     unsigned int exp;
36433965Sjdp{
36533965Sjdp  symbol_truncate = exp;
36633965Sjdp}
367