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