133965Sjdp/* mri.c -- handle MRI style linker scripts
2218822Sdim   Copyright 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000, 2001,
3218822Sdim   2002, 2003, 2004, 2005, 2007 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
19218822SdimSoftware Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20218822Sdim02110-1301, 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
27218822Sdim#include "sysdep.h"
2833965Sjdp#include "bfd.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
47218822Sdimstatic unsigned int symbol_truncate = 10000;
48218822Sdimstatic struct section_name_struct *order;
49218822Sdimstatic struct section_name_struct *only_load;
50218822Sdimstatic struct section_name_struct *address;
51218822Sdimstatic struct section_name_struct *alias;
5233965Sjdp
53218822Sdimstatic struct section_name_struct *alignment;
54218822Sdimstatic struct section_name_struct *subalignment;
5533965Sjdp
5633965Sjdpstatic struct section_name_struct **
57130561Sobrienlookup (const char *name, struct section_name_struct **list)
5833965Sjdp{
5977298Sobrien  struct section_name_struct **ptr = list;
6033965Sjdp
6177298Sobrien  while (*ptr)
6277298Sobrien    {
6377298Sobrien      if (strcmp (name, (*ptr)->name) == 0)
6477298Sobrien	/* If this is a match, delete it, we only keep the last instance
6577298Sobrien	   of any name.  */
6677298Sobrien	*ptr = (*ptr)->next;
6777298Sobrien      else
6877298Sobrien	ptr = &((*ptr)->next);
6933965Sjdp    }
7033965Sjdp
71130561Sobrien  *ptr = xmalloc (sizeof (struct section_name_struct));
7233965Sjdp  return ptr;
7333965Sjdp}
7433965Sjdp
7533965Sjdpstatic void
76130561Sobrienmri_add_to_list (struct section_name_struct **list,
77130561Sobrien		 const char *name,
78130561Sobrien		 etree_type *vma,
79130561Sobrien		 const char *zalias,
80130561Sobrien		 etree_type *align,
81130561Sobrien		 etree_type *subalign)
8233965Sjdp{
8377298Sobrien  struct section_name_struct **ptr = lookup (name, list);
8477298Sobrien
8533965Sjdp  (*ptr)->name = name;
8633965Sjdp  (*ptr)->vma = vma;
87130561Sobrien  (*ptr)->next = NULL;
8833965Sjdp  (*ptr)->ok_to_load = 0;
8933965Sjdp  (*ptr)->alias = zalias;
9033965Sjdp  (*ptr)->align = align;
9133965Sjdp  (*ptr)->subalign = subalign;
9233965Sjdp}
9333965Sjdp
9433965Sjdpvoid
95130561Sobrienmri_output_section (const char *name, etree_type *vma)
9633965Sjdp{
9777298Sobrien  mri_add_to_list (&address, name, vma, 0, 0, 0);
9833965Sjdp}
9933965Sjdp
10077298Sobrien/* If any ABSOLUTE <name> are in the script, only load those files
10177298Sobrien   marked thus.  */
10233965Sjdp
10333965Sjdpvoid
104130561Sobrienmri_only_load (const char *name)
10533965Sjdp{
10677298Sobrien  mri_add_to_list (&only_load, name, 0, 0, 0, 0);
10733965Sjdp}
10833965Sjdp
10933965Sjdpvoid
110130561Sobrienmri_base (etree_type *exp)
11133965Sjdp{
11233965Sjdp  base = exp;
11333965Sjdp}
11433965Sjdp
11533965Sjdpstatic int done_tree = 0;
11633965Sjdp
11733965Sjdpvoid
118130561Sobrienmri_draw_tree (void)
11933965Sjdp{
12077298Sobrien  if (done_tree)
12177298Sobrien    return;
12233965Sjdp
12377298Sobrien  /* Now build the statements for the ldlang machine.  */
12433965Sjdp
125130561Sobrien  /* Attach the addresses of any which have addresses,
12677298Sobrien     and add the ones not mentioned.  */
127130561Sobrien  if (address != NULL)
12877298Sobrien    {
12977298Sobrien      struct section_name_struct *alist;
13077298Sobrien      struct section_name_struct *olist;
13133965Sjdp
132130561Sobrien      if (order == NULL)
13377298Sobrien	order = address;
13477298Sobrien
13577298Sobrien      for (alist = address;
136130561Sobrien	   alist != NULL;
13777298Sobrien	   alist = alist->next)
13833965Sjdp	{
13977298Sobrien	  int done = 0;
14077298Sobrien
141130561Sobrien	  for (olist = order; done == 0 && olist != NULL; olist = olist->next)
14277298Sobrien	    {
14377298Sobrien	      if (strcmp (alist->name, olist->name) == 0)
14477298Sobrien		{
14577298Sobrien		  olist->vma = alist->vma;
14677298Sobrien		  done = 1;
14777298Sobrien		}
14877298Sobrien	    }
14977298Sobrien
15077298Sobrien	  if (!done)
15177298Sobrien	    {
15277298Sobrien	      /* Add this onto end of order list.  */
15377298Sobrien	      mri_add_to_list (&order, alist->name, alist->vma, 0, 0, 0);
15477298Sobrien	    }
15533965Sjdp	}
15633965Sjdp    }
15733965Sjdp
15833965Sjdp  /* If we're only supposed to load a subset of them in, then prune
15933965Sjdp     the list.  */
160130561Sobrien  if (only_load != NULL)
16177298Sobrien    {
16277298Sobrien      struct section_name_struct *ptr1;
16377298Sobrien      struct section_name_struct *ptr2;
16433965Sjdp
165130561Sobrien      if (order == NULL)
16677298Sobrien	order = only_load;
16777298Sobrien
16877298Sobrien      /* See if this name is in the list, if it is then we can load it.  */
16977298Sobrien      for (ptr1 = only_load; ptr1; ptr1 = ptr1->next)
17077298Sobrien	for (ptr2 = order; ptr2; ptr2 = ptr2->next)
17177298Sobrien	  if (strcmp (ptr2->name, ptr1->name) == 0)
17277298Sobrien	    ptr2->ok_to_load = 1;
17377298Sobrien    }
17477298Sobrien  else
17533965Sjdp    {
17677298Sobrien      /* No only load list, so everything is ok to load.  */
17777298Sobrien      struct section_name_struct *ptr;
17877298Sobrien
17977298Sobrien      for (ptr = order; ptr; ptr = ptr->next)
18077298Sobrien	ptr->ok_to_load = 1;
18133965Sjdp    }
18233965Sjdp
18377298Sobrien  /* Create the order of sections to load.  */
184130561Sobrien  if (order != NULL)
18577298Sobrien    {
18677298Sobrien      /* Been told to output the sections in a certain order.  */
18777298Sobrien      struct section_name_struct *p = order;
18833965Sjdp
18977298Sobrien      while (p)
19077298Sobrien	{
19177298Sobrien	  struct section_name_struct *aptr;
19277298Sobrien	  etree_type *align = 0;
19377298Sobrien	  etree_type *subalign = 0;
19489857Sobrien	  struct wildcard_list *tmp;
19533965Sjdp
19677298Sobrien	  /* See if an alignment has been specified.  */
19777298Sobrien	  for (aptr = alignment; aptr; aptr = aptr->next)
19877298Sobrien	    if (strcmp (aptr->name, p->name) == 0)
19977298Sobrien	      align = aptr->align;
20033965Sjdp
20177298Sobrien	  for (aptr = subalignment; aptr; aptr = aptr->next)
20277298Sobrien	    if (strcmp (aptr->name, p->name) == 0)
20377298Sobrien	      subalign = aptr->subalign;
20433965Sjdp
20577298Sobrien	  if (base == 0)
20677298Sobrien	    base = p->vma ? p->vma : exp_nameop (NAME, ".");
20733965Sjdp
20877298Sobrien	  lang_enter_output_section_statement (p->name, base,
20977298Sobrien					       p->ok_to_load ? 0 : noload_section,
210218822Sdim					       align, subalign, NULL, 0);
21177298Sobrien	  base = 0;
212130561Sobrien	  tmp = xmalloc (sizeof *tmp);
21389857Sobrien	  tmp->next = NULL;
21489857Sobrien	  tmp->spec.name = p->name;
21589857Sobrien	  tmp->spec.exclude_name_list = NULL;
216218822Sdim	  tmp->spec.sorted = none;
217130561Sobrien	  lang_add_wild (NULL, tmp, FALSE);
21833965Sjdp
21977298Sobrien	  /* If there is an alias for this section, add it too.  */
22077298Sobrien	  for (aptr = alias; aptr; aptr = aptr->next)
22177298Sobrien	    if (strcmp (aptr->alias, p->name) == 0)
22289857Sobrien	      {
223130561Sobrien		tmp = xmalloc (sizeof *tmp);
22489857Sobrien		tmp->next = NULL;
22589857Sobrien		tmp->spec.name = aptr->name;
22689857Sobrien		tmp->spec.exclude_name_list = NULL;
227218822Sdim		tmp->spec.sorted = none;
228130561Sobrien		lang_add_wild (NULL, tmp, FALSE);
22989857Sobrien	      }
23033965Sjdp
231130561Sobrien	  lang_leave_output_section_statement (0, "*default*", NULL, NULL);
23233965Sjdp
23377298Sobrien	  p = p->next;
23477298Sobrien	}
23533965Sjdp    }
23633965Sjdp
23733965Sjdp  done_tree = 1;
23877298Sobrien}
23933965Sjdp
24033965Sjdpvoid
241130561Sobrienmri_load (const char *name)
24233965Sjdp{
24333965Sjdp  base = 0;
244130561Sobrien  lang_add_input_file (name, lang_input_file_is_file_enum, NULL);
24533965Sjdp}
24633965Sjdp
24733965Sjdpvoid
248130561Sobrienmri_order (const char *name)
24933965Sjdp{
25077298Sobrien  mri_add_to_list (&order, name, 0, 0, 0, 0);
25133965Sjdp}
25233965Sjdp
25377298Sobrienvoid
254130561Sobrienmri_alias (const char *want, const char *is, int isn)
25533965Sjdp{
25677298Sobrien  if (!is)
25777298Sobrien    {
25877298Sobrien      char buf[20];
25933965Sjdp
26077298Sobrien      /* Some sections are digits.  */
26177298Sobrien      sprintf (buf, "%d", isn);
26277298Sobrien
26377298Sobrien      is = xstrdup (buf);
26477298Sobrien
26577298Sobrien      if (is == NULL)
26677298Sobrien	abort ();
26777298Sobrien    }
26877298Sobrien
26977298Sobrien  mri_add_to_list (&alias, is, 0, want, 0, 0);
27033965Sjdp}
27133965Sjdp
27277298Sobrienvoid
273130561Sobrienmri_name (const char *name)
27433965Sjdp{
27577298Sobrien  lang_add_output (name, 1);
27633965Sjdp}
27733965Sjdp
27833965Sjdpvoid
279130561Sobrienmri_format (const char *name)
28033965Sjdp{
28177298Sobrien  if (strcmp (name, "S") == 0)
282130561Sobrien    lang_add_output_format ("srec", NULL, NULL, 1);
28377298Sobrien
28477298Sobrien  else if (strcmp (name, "IEEE") == 0)
285130561Sobrien    lang_add_output_format ("ieee", NULL, NULL, 1);
28677298Sobrien
28777298Sobrien  else if (strcmp (name, "COFF") == 0)
288130561Sobrien    lang_add_output_format ("coff-m68k", NULL, NULL, 1);
28977298Sobrien
29077298Sobrien  else
29177298Sobrien    einfo (_("%P%F: unknown format type %s\n"), name);
29233965Sjdp}
29333965Sjdp
29433965Sjdpvoid
295130561Sobrienmri_public (const char *name, etree_type *exp)
29633965Sjdp{
29777298Sobrien  lang_add_assignment (exp_assop ('=', name, exp));
29833965Sjdp}
29933965Sjdp
30077298Sobrienvoid
301130561Sobrienmri_align (const char *name, etree_type *exp)
30233965Sjdp{
30377298Sobrien  mri_add_to_list (&alignment, name, 0, 0, exp, 0);
30433965Sjdp}
30533965Sjdp
30677298Sobrienvoid
307130561Sobrienmri_alignmod (const char *name, etree_type *exp)
30833965Sjdp{
30977298Sobrien  mri_add_to_list (&subalignment, name, 0, 0, 0, exp);
31033965Sjdp}
31133965Sjdp
31277298Sobrienvoid
313130561Sobrienmri_truncate (unsigned int exp)
31433965Sjdp{
31533965Sjdp  symbol_truncate = exp;
31633965Sjdp}
317