xref: /openbsd-src/gnu/usr.bin/binutils/ld/mri.c (revision 007c2a4539b8b8aaa95c5e73e77620090abe113b)
1b305b0f1Sespie /* mri.c -- handle MRI style linker scripts
2*007c2a45Smiod    Copyright 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000, 2002,
3*007c2a45Smiod    2003, 2004 Free Software Foundation, Inc.
42159047fSniklas 
52159047fSniklas This file is part of GLD, the Gnu Linker.
62159047fSniklas 
72159047fSniklas GLD is free software; you can redistribute it and/or modify
82159047fSniklas it under the terms of the GNU General Public License as published by
9b305b0f1Sespie the Free Software Foundation; either version 2, or (at your option)
102159047fSniklas any later version.
112159047fSniklas 
122159047fSniklas GLD is distributed in the hope that it will be useful,
132159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
142159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
152159047fSniklas GNU General Public License for more details.
162159047fSniklas 
172159047fSniklas You should have received a copy of the GNU General Public License
18b305b0f1Sespie along with GLD; see the file COPYING.  If not, write to the Free
19b305b0f1Sespie Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20b55d4692Sfgsch 02111-1307, USA.
212159047fSniklas 
22b55d4692Sfgsch    This bit does the tree decoration when MRI style link scripts
23b55d4692Sfgsch    are parsed.
242159047fSniklas 
25b55d4692Sfgsch    Contributed by Steve Chamberlain <sac@cygnus.com>.  */
262159047fSniklas 
272159047fSniklas #include "bfd.h"
282159047fSniklas #include "sysdep.h"
292159047fSniklas #include "ld.h"
302159047fSniklas #include "ldexp.h"
312159047fSniklas #include "ldlang.h"
322159047fSniklas #include "ldmisc.h"
332159047fSniklas #include "mri.h"
34c074d1c9Sdrahn #include <ldgram.h>
35b305b0f1Sespie #include "libiberty.h"
362159047fSniklas 
372159047fSniklas struct section_name_struct {
382159047fSniklas   struct section_name_struct *next;
39c074d1c9Sdrahn   const char *name;
40c074d1c9Sdrahn   const char *alias;
412159047fSniklas   etree_type *vma;
422159047fSniklas   etree_type *align;
432159047fSniklas   etree_type *subalign;
442159047fSniklas   int ok_to_load;
452159047fSniklas };
462159047fSniklas 
472159047fSniklas unsigned int symbol_truncate = 10000;
482159047fSniklas struct section_name_struct *order;
492159047fSniklas struct section_name_struct *only_load;
502159047fSniklas struct section_name_struct *address;
512159047fSniklas struct section_name_struct *alias;
522159047fSniklas 
532159047fSniklas struct section_name_struct *alignment;
542159047fSniklas struct section_name_struct *subalignment;
552159047fSniklas 
562159047fSniklas static struct section_name_struct **
lookup(const char * name,struct section_name_struct ** list)57*007c2a45Smiod lookup (const char *name, struct section_name_struct **list)
582159047fSniklas {
592159047fSniklas   struct section_name_struct **ptr = list;
60b55d4692Sfgsch 
612159047fSniklas   while (*ptr)
622159047fSniklas     {
63b55d4692Sfgsch       if (strcmp (name, (*ptr)->name) == 0)
642159047fSniklas 	/* If this is a match, delete it, we only keep the last instance
65b55d4692Sfgsch 	   of any name.  */
662159047fSniklas 	*ptr = (*ptr)->next;
67b55d4692Sfgsch       else
682159047fSniklas 	ptr = &((*ptr)->next);
692159047fSniklas     }
702159047fSniklas 
71*007c2a45Smiod   *ptr = xmalloc (sizeof (struct section_name_struct));
722159047fSniklas   return ptr;
732159047fSniklas }
742159047fSniklas 
752159047fSniklas static void
mri_add_to_list(struct section_name_struct ** list,const char * name,etree_type * vma,const char * zalias,etree_type * align,etree_type * subalign)76*007c2a45Smiod mri_add_to_list (struct section_name_struct **list,
77*007c2a45Smiod 		 const char *name,
78*007c2a45Smiod 		 etree_type *vma,
79*007c2a45Smiod 		 const char *zalias,
80*007c2a45Smiod 		 etree_type *align,
81*007c2a45Smiod 		 etree_type *subalign)
822159047fSniklas {
832159047fSniklas   struct section_name_struct **ptr = lookup (name, list);
84b55d4692Sfgsch 
852159047fSniklas   (*ptr)->name = name;
862159047fSniklas   (*ptr)->vma = vma;
87*007c2a45Smiod   (*ptr)->next = NULL;
882159047fSniklas   (*ptr)->ok_to_load = 0;
892159047fSniklas   (*ptr)->alias = zalias;
902159047fSniklas   (*ptr)->align = align;
912159047fSniklas   (*ptr)->subalign = subalign;
922159047fSniklas }
932159047fSniklas 
942159047fSniklas void
mri_output_section(const char * name,etree_type * vma)95*007c2a45Smiod mri_output_section (const char *name, etree_type *vma)
962159047fSniklas {
972159047fSniklas   mri_add_to_list (&address, name, vma, 0, 0, 0);
982159047fSniklas }
992159047fSniklas 
100b55d4692Sfgsch /* If any ABSOLUTE <name> are in the script, only load those files
101b55d4692Sfgsch    marked thus.  */
1022159047fSniklas 
1032159047fSniklas void
mri_only_load(const char * name)104*007c2a45Smiod mri_only_load (const char *name)
1052159047fSniklas {
1062159047fSniklas   mri_add_to_list (&only_load, name, 0, 0, 0, 0);
1072159047fSniklas }
1082159047fSniklas 
1092159047fSniklas void
mri_base(etree_type * exp)110*007c2a45Smiod mri_base (etree_type *exp)
1112159047fSniklas {
1122159047fSniklas   base = exp;
1132159047fSniklas }
1142159047fSniklas 
1152159047fSniklas static int done_tree = 0;
1162159047fSniklas 
117191aa565Sniklas void
mri_draw_tree(void)118*007c2a45Smiod mri_draw_tree (void)
1192159047fSniklas {
120b55d4692Sfgsch   if (done_tree)
121b55d4692Sfgsch     return;
1222159047fSniklas 
123b55d4692Sfgsch #if 0   /* We don't bother with memory regions.  */
124b55d4692Sfgsch   /* Create the regions.  */
1252159047fSniklas   {
1262159047fSniklas     lang_memory_region_type *r;
127b55d4692Sfgsch 
1282159047fSniklas     r = lang_memory_region_lookup("long");
1292159047fSniklas     r->current = r->origin = exp_get_vma (base, (bfd_vma)0, "origin",
1302159047fSniklas 					  lang_first_phase_enum);
131*007c2a45Smiod     r->length = (bfd_size_type) exp_get_vma (0, ~(bfd_vma) 0, "length",
132*007c2a45Smiod 					     lang_first_phase_enum);
1332159047fSniklas   }
134191aa565Sniklas #endif
1352159047fSniklas 
136b55d4692Sfgsch   /* Now build the statements for the ldlang machine.  */
1372159047fSniklas 
138c074d1c9Sdrahn   /* Attach the addresses of any which have addresses,
139b55d4692Sfgsch      and add the ones not mentioned.  */
140*007c2a45Smiod   if (address != NULL)
141b55d4692Sfgsch     {
1422159047fSniklas       struct section_name_struct *alist;
1432159047fSniklas       struct section_name_struct *olist;
144b55d4692Sfgsch 
145*007c2a45Smiod       if (order == NULL)
1462159047fSniklas 	order = address;
1472159047fSniklas 
1482159047fSniklas       for (alist = address;
149*007c2a45Smiod 	   alist != NULL;
1502159047fSniklas 	   alist = alist->next)
1512159047fSniklas 	{
1522159047fSniklas 	  int done = 0;
153b55d4692Sfgsch 
154*007c2a45Smiod 	  for (olist = order; done == 0 && olist != NULL; olist = olist->next)
1552159047fSniklas 	    {
1562159047fSniklas 	      if (strcmp (alist->name, olist->name) == 0)
1572159047fSniklas 		{
1582159047fSniklas 		  olist->vma = alist->vma;
1592159047fSniklas 		  done = 1;
1602159047fSniklas 		}
1612159047fSniklas 	    }
162b55d4692Sfgsch 
163b55d4692Sfgsch 	  if (!done)
164b55d4692Sfgsch 	    {
165b55d4692Sfgsch 	      /* Add this onto end of order list.  */
1662159047fSniklas 	      mri_add_to_list (&order, alist->name, alist->vma, 0, 0, 0);
1672159047fSniklas 	    }
1682159047fSniklas 	}
1692159047fSniklas     }
1702159047fSniklas 
1712159047fSniklas   /* If we're only supposed to load a subset of them in, then prune
1722159047fSniklas      the list.  */
173*007c2a45Smiod   if (only_load != NULL)
1742159047fSniklas     {
1752159047fSniklas       struct section_name_struct *ptr1;
1762159047fSniklas       struct section_name_struct *ptr2;
177b55d4692Sfgsch 
178*007c2a45Smiod       if (order == NULL)
1792159047fSniklas 	order = only_load;
1802159047fSniklas 
181b55d4692Sfgsch       /* See if this name is in the list, if it is then we can load it.  */
1822159047fSniklas       for (ptr1 = only_load; ptr1; ptr1 = ptr1->next)
1832159047fSniklas 	for (ptr2 = order; ptr2; ptr2 = ptr2->next)
184b55d4692Sfgsch 	  if (strcmp (ptr2->name, ptr1->name) == 0)
1852159047fSniklas 	    ptr2->ok_to_load = 1;
1862159047fSniklas     }
1872159047fSniklas   else
1882159047fSniklas     {
189b55d4692Sfgsch       /* No only load list, so everything is ok to load.  */
1902159047fSniklas       struct section_name_struct *ptr;
191b55d4692Sfgsch 
192b55d4692Sfgsch       for (ptr = order; ptr; ptr = ptr->next)
1932159047fSniklas 	ptr->ok_to_load = 1;
1942159047fSniklas     }
1952159047fSniklas 
196b55d4692Sfgsch   /* Create the order of sections to load.  */
197*007c2a45Smiod   if (order != NULL)
1982159047fSniklas     {
199b55d4692Sfgsch       /* Been told to output the sections in a certain order.  */
2002159047fSniklas       struct section_name_struct *p = order;
201b55d4692Sfgsch 
2022159047fSniklas       while (p)
2032159047fSniklas 	{
2042159047fSniklas 	  struct section_name_struct *aptr;
2052159047fSniklas 	  etree_type *align = 0;
2062159047fSniklas 	  etree_type *subalign = 0;
207c074d1c9Sdrahn 	  struct wildcard_list *tmp;
2082159047fSniklas 
209b55d4692Sfgsch 	  /* See if an alignment has been specified.  */
2102159047fSniklas 	  for (aptr = alignment; aptr; aptr = aptr->next)
211b55d4692Sfgsch 	    if (strcmp (aptr->name, p->name) == 0)
2122159047fSniklas 	      align = aptr->align;
2132159047fSniklas 
2142159047fSniklas 	  for (aptr = subalignment; aptr; aptr = aptr->next)
215b55d4692Sfgsch 	    if (strcmp (aptr->name, p->name) == 0)
2162159047fSniklas 	      subalign = aptr->subalign;
2172159047fSniklas 
218b55d4692Sfgsch 	  if (base == 0)
2192159047fSniklas 	    base = p->vma ? p->vma : exp_nameop (NAME, ".");
220b55d4692Sfgsch 
2212159047fSniklas 	  lang_enter_output_section_statement (p->name, base,
222b305b0f1Sespie 					       p->ok_to_load ? 0 : noload_section,
223*007c2a45Smiod 					       align, subalign, NULL);
2242159047fSniklas 	  base = 0;
225*007c2a45Smiod 	  tmp = xmalloc (sizeof *tmp);
226c074d1c9Sdrahn 	  tmp->next = NULL;
227c074d1c9Sdrahn 	  tmp->spec.name = p->name;
228c074d1c9Sdrahn 	  tmp->spec.exclude_name_list = NULL;
229c074d1c9Sdrahn 	  tmp->spec.sorted = FALSE;
230c074d1c9Sdrahn 	  lang_add_wild (NULL, tmp, FALSE);
2312159047fSniklas 
232b55d4692Sfgsch 	  /* If there is an alias for this section, add it too.  */
233b55d4692Sfgsch 	  for (aptr = alias; aptr; aptr = aptr->next)
234b55d4692Sfgsch 	    if (strcmp (aptr->alias, p->name) == 0)
235c074d1c9Sdrahn 	      {
236*007c2a45Smiod 		tmp = xmalloc (sizeof *tmp);
237c074d1c9Sdrahn 		tmp->next = NULL;
238c074d1c9Sdrahn 		tmp->spec.name = aptr->name;
239c074d1c9Sdrahn 		tmp->spec.exclude_name_list = NULL;
240c074d1c9Sdrahn 		tmp->spec.sorted = FALSE;
241c074d1c9Sdrahn 		lang_add_wild (NULL, tmp, FALSE);
242c074d1c9Sdrahn 	      }
2432159047fSniklas 
244*007c2a45Smiod 	  lang_leave_output_section_statement (0, "*default*", NULL, NULL);
2450c6d0228Sniklas 
2462159047fSniklas 	  p = p->next;
2472159047fSniklas 	}
2482159047fSniklas     }
2492159047fSniklas 
2502159047fSniklas   done_tree = 1;
2512159047fSniklas }
252b55d4692Sfgsch 
2532159047fSniklas void
mri_load(const char * name)254*007c2a45Smiod mri_load (const char *name)
2552159047fSniklas {
2562159047fSniklas   base = 0;
257*007c2a45Smiod   lang_add_input_file (name, lang_input_file_is_file_enum, NULL);
258b55d4692Sfgsch #if 0
259b55d4692Sfgsch   lang_leave_output_section_statement (0, "*default*");
260b55d4692Sfgsch #endif
2612159047fSniklas }
2622159047fSniklas 
2632159047fSniklas void
mri_order(const char * name)264*007c2a45Smiod mri_order (const char *name)
2652159047fSniklas {
2662159047fSniklas   mri_add_to_list (&order, name, 0, 0, 0, 0);
2672159047fSniklas }
2682159047fSniklas 
2692159047fSniklas void
mri_alias(const char * want,const char * is,int isn)270*007c2a45Smiod mri_alias (const char *want, const char *is, int isn)
2712159047fSniklas {
272b55d4692Sfgsch   if (!is)
273b55d4692Sfgsch     {
2742159047fSniklas       char buf[20];
275b55d4692Sfgsch 
276b55d4692Sfgsch       /* Some sections are digits.  */
2772159047fSniklas       sprintf (buf, "%d", isn);
278b55d4692Sfgsch 
279b305b0f1Sespie       is = xstrdup (buf);
280b55d4692Sfgsch 
2812159047fSniklas       if (is == NULL)
2822159047fSniklas 	abort ();
2832159047fSniklas     }
284b55d4692Sfgsch 
2852159047fSniklas   mri_add_to_list (&alias, is, 0, want, 0, 0);
2862159047fSniklas }
2872159047fSniklas 
2882159047fSniklas void
mri_name(const char * name)289*007c2a45Smiod mri_name (const char *name)
2902159047fSniklas {
2912159047fSniklas   lang_add_output (name, 1);
2922159047fSniklas }
2932159047fSniklas 
2942159047fSniklas void
mri_format(const char * name)295*007c2a45Smiod mri_format (const char *name)
2962159047fSniklas {
2972159047fSniklas   if (strcmp (name, "S") == 0)
298*007c2a45Smiod     lang_add_output_format ("srec", NULL, NULL, 1);
299b55d4692Sfgsch 
3002159047fSniklas   else if (strcmp (name, "IEEE") == 0)
301*007c2a45Smiod     lang_add_output_format ("ieee", NULL, NULL, 1);
302b55d4692Sfgsch 
3032159047fSniklas   else if (strcmp (name, "COFF") == 0)
304*007c2a45Smiod     lang_add_output_format ("coff-m68k", NULL, NULL, 1);
305b55d4692Sfgsch 
306b55d4692Sfgsch   else
307b305b0f1Sespie     einfo (_("%P%F: unknown format type %s\n"), name);
3082159047fSniklas }
3092159047fSniklas 
3102159047fSniklas void
mri_public(const char * name,etree_type * exp)311*007c2a45Smiod mri_public (const char *name, etree_type *exp)
3122159047fSniklas {
3132159047fSniklas   lang_add_assignment (exp_assop ('=', name, exp));
3142159047fSniklas }
3152159047fSniklas 
3162159047fSniklas void
mri_align(const char * name,etree_type * exp)317*007c2a45Smiod mri_align (const char *name, etree_type *exp)
3182159047fSniklas {
3192159047fSniklas   mri_add_to_list (&alignment, name, 0, 0, exp, 0);
3202159047fSniklas }
3212159047fSniklas 
3222159047fSniklas void
mri_alignmod(const char * name,etree_type * exp)323*007c2a45Smiod mri_alignmod (const char *name, etree_type *exp)
3242159047fSniklas {
3252159047fSniklas   mri_add_to_list (&subalignment, name, 0, 0, 0, exp);
3262159047fSniklas }
3272159047fSniklas 
3282159047fSniklas void
mri_truncate(unsigned int exp)329*007c2a45Smiod mri_truncate (unsigned int exp)
3302159047fSniklas {
3312159047fSniklas   symbol_truncate = exp;
3322159047fSniklas }
333