xref: /openbsd-src/gnu/usr.bin/binutils-2.17/ld/mri.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
1*3d8817e4Smiod /* mri.c -- handle MRI style linker scripts
2*3d8817e4Smiod    Copyright 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000, 2001,
3*3d8817e4Smiod    2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4*3d8817e4Smiod 
5*3d8817e4Smiod This file is part of GLD, the Gnu Linker.
6*3d8817e4Smiod 
7*3d8817e4Smiod GLD is free software; you can redistribute it and/or modify
8*3d8817e4Smiod it under the terms of the GNU General Public License as published by
9*3d8817e4Smiod the Free Software Foundation; either version 2, or (at your option)
10*3d8817e4Smiod any later version.
11*3d8817e4Smiod 
12*3d8817e4Smiod GLD is distributed in the hope that it will be useful,
13*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
14*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*3d8817e4Smiod GNU General Public License for more details.
16*3d8817e4Smiod 
17*3d8817e4Smiod You should have received a copy of the GNU General Public License
18*3d8817e4Smiod along with GLD; see the file COPYING.  If not, write to the Free
19*3d8817e4Smiod Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20*3d8817e4Smiod 02110-1301, USA.
21*3d8817e4Smiod 
22*3d8817e4Smiod    This bit does the tree decoration when MRI style link scripts
23*3d8817e4Smiod    are parsed.
24*3d8817e4Smiod 
25*3d8817e4Smiod    Contributed by Steve Chamberlain <sac@cygnus.com>.  */
26*3d8817e4Smiod 
27*3d8817e4Smiod #include "bfd.h"
28*3d8817e4Smiod #include "sysdep.h"
29*3d8817e4Smiod #include "ld.h"
30*3d8817e4Smiod #include "ldexp.h"
31*3d8817e4Smiod #include "ldlang.h"
32*3d8817e4Smiod #include "ldmisc.h"
33*3d8817e4Smiod #include "mri.h"
34*3d8817e4Smiod #include <ldgram.h>
35*3d8817e4Smiod #include "libiberty.h"
36*3d8817e4Smiod 
37*3d8817e4Smiod struct section_name_struct {
38*3d8817e4Smiod   struct section_name_struct *next;
39*3d8817e4Smiod   const char *name;
40*3d8817e4Smiod   const char *alias;
41*3d8817e4Smiod   etree_type *vma;
42*3d8817e4Smiod   etree_type *align;
43*3d8817e4Smiod   etree_type *subalign;
44*3d8817e4Smiod   int ok_to_load;
45*3d8817e4Smiod };
46*3d8817e4Smiod 
47*3d8817e4Smiod static unsigned int symbol_truncate = 10000;
48*3d8817e4Smiod static struct section_name_struct *order;
49*3d8817e4Smiod static struct section_name_struct *only_load;
50*3d8817e4Smiod static struct section_name_struct *address;
51*3d8817e4Smiod static struct section_name_struct *alias;
52*3d8817e4Smiod 
53*3d8817e4Smiod static struct section_name_struct *alignment;
54*3d8817e4Smiod static struct section_name_struct *subalignment;
55*3d8817e4Smiod 
56*3d8817e4Smiod static struct section_name_struct **
lookup(const char * name,struct section_name_struct ** list)57*3d8817e4Smiod lookup (const char *name, struct section_name_struct **list)
58*3d8817e4Smiod {
59*3d8817e4Smiod   struct section_name_struct **ptr = list;
60*3d8817e4Smiod 
61*3d8817e4Smiod   while (*ptr)
62*3d8817e4Smiod     {
63*3d8817e4Smiod       if (strcmp (name, (*ptr)->name) == 0)
64*3d8817e4Smiod 	/* If this is a match, delete it, we only keep the last instance
65*3d8817e4Smiod 	   of any name.  */
66*3d8817e4Smiod 	*ptr = (*ptr)->next;
67*3d8817e4Smiod       else
68*3d8817e4Smiod 	ptr = &((*ptr)->next);
69*3d8817e4Smiod     }
70*3d8817e4Smiod 
71*3d8817e4Smiod   *ptr = xmalloc (sizeof (struct section_name_struct));
72*3d8817e4Smiod   return ptr;
73*3d8817e4Smiod }
74*3d8817e4Smiod 
75*3d8817e4Smiod 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*3d8817e4Smiod mri_add_to_list (struct section_name_struct **list,
77*3d8817e4Smiod 		 const char *name,
78*3d8817e4Smiod 		 etree_type *vma,
79*3d8817e4Smiod 		 const char *zalias,
80*3d8817e4Smiod 		 etree_type *align,
81*3d8817e4Smiod 		 etree_type *subalign)
82*3d8817e4Smiod {
83*3d8817e4Smiod   struct section_name_struct **ptr = lookup (name, list);
84*3d8817e4Smiod 
85*3d8817e4Smiod   (*ptr)->name = name;
86*3d8817e4Smiod   (*ptr)->vma = vma;
87*3d8817e4Smiod   (*ptr)->next = NULL;
88*3d8817e4Smiod   (*ptr)->ok_to_load = 0;
89*3d8817e4Smiod   (*ptr)->alias = zalias;
90*3d8817e4Smiod   (*ptr)->align = align;
91*3d8817e4Smiod   (*ptr)->subalign = subalign;
92*3d8817e4Smiod }
93*3d8817e4Smiod 
94*3d8817e4Smiod void
mri_output_section(const char * name,etree_type * vma)95*3d8817e4Smiod mri_output_section (const char *name, etree_type *vma)
96*3d8817e4Smiod {
97*3d8817e4Smiod   mri_add_to_list (&address, name, vma, 0, 0, 0);
98*3d8817e4Smiod }
99*3d8817e4Smiod 
100*3d8817e4Smiod /* If any ABSOLUTE <name> are in the script, only load those files
101*3d8817e4Smiod    marked thus.  */
102*3d8817e4Smiod 
103*3d8817e4Smiod void
mri_only_load(const char * name)104*3d8817e4Smiod mri_only_load (const char *name)
105*3d8817e4Smiod {
106*3d8817e4Smiod   mri_add_to_list (&only_load, name, 0, 0, 0, 0);
107*3d8817e4Smiod }
108*3d8817e4Smiod 
109*3d8817e4Smiod void
mri_base(etree_type * exp)110*3d8817e4Smiod mri_base (etree_type *exp)
111*3d8817e4Smiod {
112*3d8817e4Smiod   base = exp;
113*3d8817e4Smiod }
114*3d8817e4Smiod 
115*3d8817e4Smiod static int done_tree = 0;
116*3d8817e4Smiod 
117*3d8817e4Smiod void
mri_draw_tree(void)118*3d8817e4Smiod mri_draw_tree (void)
119*3d8817e4Smiod {
120*3d8817e4Smiod   if (done_tree)
121*3d8817e4Smiod     return;
122*3d8817e4Smiod 
123*3d8817e4Smiod   /* Now build the statements for the ldlang machine.  */
124*3d8817e4Smiod 
125*3d8817e4Smiod   /* Attach the addresses of any which have addresses,
126*3d8817e4Smiod      and add the ones not mentioned.  */
127*3d8817e4Smiod   if (address != NULL)
128*3d8817e4Smiod     {
129*3d8817e4Smiod       struct section_name_struct *alist;
130*3d8817e4Smiod       struct section_name_struct *olist;
131*3d8817e4Smiod 
132*3d8817e4Smiod       if (order == NULL)
133*3d8817e4Smiod 	order = address;
134*3d8817e4Smiod 
135*3d8817e4Smiod       for (alist = address;
136*3d8817e4Smiod 	   alist != NULL;
137*3d8817e4Smiod 	   alist = alist->next)
138*3d8817e4Smiod 	{
139*3d8817e4Smiod 	  int done = 0;
140*3d8817e4Smiod 
141*3d8817e4Smiod 	  for (olist = order; done == 0 && olist != NULL; olist = olist->next)
142*3d8817e4Smiod 	    {
143*3d8817e4Smiod 	      if (strcmp (alist->name, olist->name) == 0)
144*3d8817e4Smiod 		{
145*3d8817e4Smiod 		  olist->vma = alist->vma;
146*3d8817e4Smiod 		  done = 1;
147*3d8817e4Smiod 		}
148*3d8817e4Smiod 	    }
149*3d8817e4Smiod 
150*3d8817e4Smiod 	  if (!done)
151*3d8817e4Smiod 	    {
152*3d8817e4Smiod 	      /* Add this onto end of order list.  */
153*3d8817e4Smiod 	      mri_add_to_list (&order, alist->name, alist->vma, 0, 0, 0);
154*3d8817e4Smiod 	    }
155*3d8817e4Smiod 	}
156*3d8817e4Smiod     }
157*3d8817e4Smiod 
158*3d8817e4Smiod   /* If we're only supposed to load a subset of them in, then prune
159*3d8817e4Smiod      the list.  */
160*3d8817e4Smiod   if (only_load != NULL)
161*3d8817e4Smiod     {
162*3d8817e4Smiod       struct section_name_struct *ptr1;
163*3d8817e4Smiod       struct section_name_struct *ptr2;
164*3d8817e4Smiod 
165*3d8817e4Smiod       if (order == NULL)
166*3d8817e4Smiod 	order = only_load;
167*3d8817e4Smiod 
168*3d8817e4Smiod       /* See if this name is in the list, if it is then we can load it.  */
169*3d8817e4Smiod       for (ptr1 = only_load; ptr1; ptr1 = ptr1->next)
170*3d8817e4Smiod 	for (ptr2 = order; ptr2; ptr2 = ptr2->next)
171*3d8817e4Smiod 	  if (strcmp (ptr2->name, ptr1->name) == 0)
172*3d8817e4Smiod 	    ptr2->ok_to_load = 1;
173*3d8817e4Smiod     }
174*3d8817e4Smiod   else
175*3d8817e4Smiod     {
176*3d8817e4Smiod       /* No only load list, so everything is ok to load.  */
177*3d8817e4Smiod       struct section_name_struct *ptr;
178*3d8817e4Smiod 
179*3d8817e4Smiod       for (ptr = order; ptr; ptr = ptr->next)
180*3d8817e4Smiod 	ptr->ok_to_load = 1;
181*3d8817e4Smiod     }
182*3d8817e4Smiod 
183*3d8817e4Smiod   /* Create the order of sections to load.  */
184*3d8817e4Smiod   if (order != NULL)
185*3d8817e4Smiod     {
186*3d8817e4Smiod       /* Been told to output the sections in a certain order.  */
187*3d8817e4Smiod       struct section_name_struct *p = order;
188*3d8817e4Smiod 
189*3d8817e4Smiod       while (p)
190*3d8817e4Smiod 	{
191*3d8817e4Smiod 	  struct section_name_struct *aptr;
192*3d8817e4Smiod 	  etree_type *align = 0;
193*3d8817e4Smiod 	  etree_type *subalign = 0;
194*3d8817e4Smiod 	  struct wildcard_list *tmp;
195*3d8817e4Smiod 
196*3d8817e4Smiod 	  /* See if an alignment has been specified.  */
197*3d8817e4Smiod 	  for (aptr = alignment; aptr; aptr = aptr->next)
198*3d8817e4Smiod 	    if (strcmp (aptr->name, p->name) == 0)
199*3d8817e4Smiod 	      align = aptr->align;
200*3d8817e4Smiod 
201*3d8817e4Smiod 	  for (aptr = subalignment; aptr; aptr = aptr->next)
202*3d8817e4Smiod 	    if (strcmp (aptr->name, p->name) == 0)
203*3d8817e4Smiod 	      subalign = aptr->subalign;
204*3d8817e4Smiod 
205*3d8817e4Smiod 	  if (base == 0)
206*3d8817e4Smiod 	    base = p->vma ? p->vma : exp_nameop (NAME, ".");
207*3d8817e4Smiod 
208*3d8817e4Smiod 	  lang_enter_output_section_statement (p->name, base,
209*3d8817e4Smiod 					       p->ok_to_load ? 0 : noload_section,
210*3d8817e4Smiod 					       align, subalign, NULL, 0);
211*3d8817e4Smiod 	  base = 0;
212*3d8817e4Smiod 	  tmp = xmalloc (sizeof *tmp);
213*3d8817e4Smiod 	  tmp->next = NULL;
214*3d8817e4Smiod 	  tmp->spec.name = p->name;
215*3d8817e4Smiod 	  tmp->spec.exclude_name_list = NULL;
216*3d8817e4Smiod 	  tmp->spec.sorted = none;
217*3d8817e4Smiod 	  lang_add_wild (NULL, tmp, FALSE);
218*3d8817e4Smiod 
219*3d8817e4Smiod 	  /* If there is an alias for this section, add it too.  */
220*3d8817e4Smiod 	  for (aptr = alias; aptr; aptr = aptr->next)
221*3d8817e4Smiod 	    if (strcmp (aptr->alias, p->name) == 0)
222*3d8817e4Smiod 	      {
223*3d8817e4Smiod 		tmp = xmalloc (sizeof *tmp);
224*3d8817e4Smiod 		tmp->next = NULL;
225*3d8817e4Smiod 		tmp->spec.name = aptr->name;
226*3d8817e4Smiod 		tmp->spec.exclude_name_list = NULL;
227*3d8817e4Smiod 		tmp->spec.sorted = none;
228*3d8817e4Smiod 		lang_add_wild (NULL, tmp, FALSE);
229*3d8817e4Smiod 	      }
230*3d8817e4Smiod 
231*3d8817e4Smiod 	  lang_leave_output_section_statement (0, "*default*", NULL, NULL);
232*3d8817e4Smiod 
233*3d8817e4Smiod 	  p = p->next;
234*3d8817e4Smiod 	}
235*3d8817e4Smiod     }
236*3d8817e4Smiod 
237*3d8817e4Smiod   done_tree = 1;
238*3d8817e4Smiod }
239*3d8817e4Smiod 
240*3d8817e4Smiod void
mri_load(const char * name)241*3d8817e4Smiod mri_load (const char *name)
242*3d8817e4Smiod {
243*3d8817e4Smiod   base = 0;
244*3d8817e4Smiod   lang_add_input_file (name, lang_input_file_is_file_enum, NULL);
245*3d8817e4Smiod }
246*3d8817e4Smiod 
247*3d8817e4Smiod void
mri_order(const char * name)248*3d8817e4Smiod mri_order (const char *name)
249*3d8817e4Smiod {
250*3d8817e4Smiod   mri_add_to_list (&order, name, 0, 0, 0, 0);
251*3d8817e4Smiod }
252*3d8817e4Smiod 
253*3d8817e4Smiod void
mri_alias(const char * want,const char * is,int isn)254*3d8817e4Smiod mri_alias (const char *want, const char *is, int isn)
255*3d8817e4Smiod {
256*3d8817e4Smiod   if (!is)
257*3d8817e4Smiod     {
258*3d8817e4Smiod       char buf[20];
259*3d8817e4Smiod 
260*3d8817e4Smiod       /* Some sections are digits.  */
261*3d8817e4Smiod       sprintf (buf, "%d", isn);
262*3d8817e4Smiod 
263*3d8817e4Smiod       is = xstrdup (buf);
264*3d8817e4Smiod 
265*3d8817e4Smiod       if (is == NULL)
266*3d8817e4Smiod 	abort ();
267*3d8817e4Smiod     }
268*3d8817e4Smiod 
269*3d8817e4Smiod   mri_add_to_list (&alias, is, 0, want, 0, 0);
270*3d8817e4Smiod }
271*3d8817e4Smiod 
272*3d8817e4Smiod void
mri_name(const char * name)273*3d8817e4Smiod mri_name (const char *name)
274*3d8817e4Smiod {
275*3d8817e4Smiod   lang_add_output (name, 1);
276*3d8817e4Smiod }
277*3d8817e4Smiod 
278*3d8817e4Smiod void
mri_format(const char * name)279*3d8817e4Smiod mri_format (const char *name)
280*3d8817e4Smiod {
281*3d8817e4Smiod   if (strcmp (name, "S") == 0)
282*3d8817e4Smiod     lang_add_output_format ("srec", NULL, NULL, 1);
283*3d8817e4Smiod 
284*3d8817e4Smiod   else if (strcmp (name, "IEEE") == 0)
285*3d8817e4Smiod     lang_add_output_format ("ieee", NULL, NULL, 1);
286*3d8817e4Smiod 
287*3d8817e4Smiod   else if (strcmp (name, "COFF") == 0)
288*3d8817e4Smiod     lang_add_output_format ("coff-m68k", NULL, NULL, 1);
289*3d8817e4Smiod 
290*3d8817e4Smiod   else
291*3d8817e4Smiod     einfo (_("%P%F: unknown format type %s\n"), name);
292*3d8817e4Smiod }
293*3d8817e4Smiod 
294*3d8817e4Smiod void
mri_public(const char * name,etree_type * exp)295*3d8817e4Smiod mri_public (const char *name, etree_type *exp)
296*3d8817e4Smiod {
297*3d8817e4Smiod   lang_add_assignment (exp_assop ('=', name, exp));
298*3d8817e4Smiod }
299*3d8817e4Smiod 
300*3d8817e4Smiod void
mri_align(const char * name,etree_type * exp)301*3d8817e4Smiod mri_align (const char *name, etree_type *exp)
302*3d8817e4Smiod {
303*3d8817e4Smiod   mri_add_to_list (&alignment, name, 0, 0, exp, 0);
304*3d8817e4Smiod }
305*3d8817e4Smiod 
306*3d8817e4Smiod void
mri_alignmod(const char * name,etree_type * exp)307*3d8817e4Smiod mri_alignmod (const char *name, etree_type *exp)
308*3d8817e4Smiod {
309*3d8817e4Smiod   mri_add_to_list (&subalignment, name, 0, 0, 0, exp);
310*3d8817e4Smiod }
311*3d8817e4Smiod 
312*3d8817e4Smiod void
mri_truncate(unsigned int exp)313*3d8817e4Smiod mri_truncate (unsigned int exp)
314*3d8817e4Smiod {
315*3d8817e4Smiod   symbol_truncate = exp;
316*3d8817e4Smiod }
317