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