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