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