133965Sjdp/* mri.c -- handle MRI style linker scripts 2218822Sdim Copyright 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000, 2001, 3218822Sdim 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. 433965Sjdp 533965SjdpThis file is part of GLD, the Gnu Linker. 633965Sjdp 733965SjdpGLD is free software; you can redistribute it and/or modify 833965Sjdpit under the terms of the GNU General Public License as published by 960484Sobrienthe Free Software Foundation; either version 2, or (at your option) 1033965Sjdpany later version. 1133965Sjdp 1233965SjdpGLD is distributed in the hope that it will be useful, 1333965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 1433965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1533965SjdpGNU General Public License for more details. 1633965Sjdp 1733965SjdpYou should have received a copy of the GNU General Public License 1833965Sjdpalong with GLD; see the file COPYING. If not, write to the Free 19218822SdimSoftware Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 20218822Sdim02110-1301, USA. 2133965Sjdp 2277298Sobrien This bit does the tree decoration when MRI style link scripts 2377298Sobrien are parsed. 2433965Sjdp 2577298Sobrien Contributed by Steve Chamberlain <sac@cygnus.com>. */ 2633965Sjdp 27218822Sdim#include "sysdep.h" 2833965Sjdp#include "bfd.h" 2933965Sjdp#include "ld.h" 3033965Sjdp#include "ldexp.h" 3133965Sjdp#include "ldlang.h" 3233965Sjdp#include "ldmisc.h" 3333965Sjdp#include "mri.h" 34107492Sobrien#include <ldgram.h> 3533965Sjdp#include "libiberty.h" 3633965Sjdp 3733965Sjdpstruct section_name_struct { 3833965Sjdp struct section_name_struct *next; 39104834Sobrien const char *name; 40104834Sobrien const char *alias; 4133965Sjdp etree_type *vma; 4233965Sjdp etree_type *align; 4333965Sjdp etree_type *subalign; 4433965Sjdp int ok_to_load; 4577298Sobrien}; 4633965Sjdp 47218822Sdimstatic unsigned int symbol_truncate = 10000; 48218822Sdimstatic struct section_name_struct *order; 49218822Sdimstatic struct section_name_struct *only_load; 50218822Sdimstatic struct section_name_struct *address; 51218822Sdimstatic struct section_name_struct *alias; 5233965Sjdp 53218822Sdimstatic struct section_name_struct *alignment; 54218822Sdimstatic struct section_name_struct *subalignment; 5533965Sjdp 5633965Sjdpstatic struct section_name_struct ** 57130561Sobrienlookup (const char *name, struct section_name_struct **list) 5833965Sjdp{ 5977298Sobrien struct section_name_struct **ptr = list; 6033965Sjdp 6177298Sobrien while (*ptr) 6277298Sobrien { 6377298Sobrien if (strcmp (name, (*ptr)->name) == 0) 6477298Sobrien /* If this is a match, delete it, we only keep the last instance 6577298Sobrien of any name. */ 6677298Sobrien *ptr = (*ptr)->next; 6777298Sobrien else 6877298Sobrien ptr = &((*ptr)->next); 6933965Sjdp } 7033965Sjdp 71130561Sobrien *ptr = xmalloc (sizeof (struct section_name_struct)); 7233965Sjdp return ptr; 7333965Sjdp} 7433965Sjdp 7533965Sjdpstatic void 76130561Sobrienmri_add_to_list (struct section_name_struct **list, 77130561Sobrien const char *name, 78130561Sobrien etree_type *vma, 79130561Sobrien const char *zalias, 80130561Sobrien etree_type *align, 81130561Sobrien etree_type *subalign) 8233965Sjdp{ 8377298Sobrien struct section_name_struct **ptr = lookup (name, list); 8477298Sobrien 8533965Sjdp (*ptr)->name = name; 8633965Sjdp (*ptr)->vma = vma; 87130561Sobrien (*ptr)->next = NULL; 8833965Sjdp (*ptr)->ok_to_load = 0; 8933965Sjdp (*ptr)->alias = zalias; 9033965Sjdp (*ptr)->align = align; 9133965Sjdp (*ptr)->subalign = subalign; 9233965Sjdp} 9333965Sjdp 9433965Sjdpvoid 95130561Sobrienmri_output_section (const char *name, etree_type *vma) 9633965Sjdp{ 9777298Sobrien mri_add_to_list (&address, name, vma, 0, 0, 0); 9833965Sjdp} 9933965Sjdp 10077298Sobrien/* If any ABSOLUTE <name> are in the script, only load those files 10177298Sobrien marked thus. */ 10233965Sjdp 10333965Sjdpvoid 104130561Sobrienmri_only_load (const char *name) 10533965Sjdp{ 10677298Sobrien mri_add_to_list (&only_load, name, 0, 0, 0, 0); 10733965Sjdp} 10833965Sjdp 10933965Sjdpvoid 110130561Sobrienmri_base (etree_type *exp) 11133965Sjdp{ 11233965Sjdp base = exp; 11333965Sjdp} 11433965Sjdp 11533965Sjdpstatic int done_tree = 0; 11633965Sjdp 11733965Sjdpvoid 118130561Sobrienmri_draw_tree (void) 11933965Sjdp{ 12077298Sobrien if (done_tree) 12177298Sobrien return; 12233965Sjdp 12377298Sobrien /* Now build the statements for the ldlang machine. */ 12433965Sjdp 125130561Sobrien /* Attach the addresses of any which have addresses, 12677298Sobrien and add the ones not mentioned. */ 127130561Sobrien if (address != NULL) 12877298Sobrien { 12977298Sobrien struct section_name_struct *alist; 13077298Sobrien struct section_name_struct *olist; 13133965Sjdp 132130561Sobrien if (order == NULL) 13377298Sobrien order = address; 13477298Sobrien 13577298Sobrien for (alist = address; 136130561Sobrien alist != NULL; 13777298Sobrien alist = alist->next) 13833965Sjdp { 13977298Sobrien int done = 0; 14077298Sobrien 141130561Sobrien for (olist = order; done == 0 && olist != NULL; olist = olist->next) 14277298Sobrien { 14377298Sobrien if (strcmp (alist->name, olist->name) == 0) 14477298Sobrien { 14577298Sobrien olist->vma = alist->vma; 14677298Sobrien done = 1; 14777298Sobrien } 14877298Sobrien } 14977298Sobrien 15077298Sobrien if (!done) 15177298Sobrien { 15277298Sobrien /* Add this onto end of order list. */ 15377298Sobrien mri_add_to_list (&order, alist->name, alist->vma, 0, 0, 0); 15477298Sobrien } 15533965Sjdp } 15633965Sjdp } 15733965Sjdp 15833965Sjdp /* If we're only supposed to load a subset of them in, then prune 15933965Sjdp the list. */ 160130561Sobrien if (only_load != NULL) 16177298Sobrien { 16277298Sobrien struct section_name_struct *ptr1; 16377298Sobrien struct section_name_struct *ptr2; 16433965Sjdp 165130561Sobrien if (order == NULL) 16677298Sobrien order = only_load; 16777298Sobrien 16877298Sobrien /* See if this name is in the list, if it is then we can load it. */ 16977298Sobrien for (ptr1 = only_load; ptr1; ptr1 = ptr1->next) 17077298Sobrien for (ptr2 = order; ptr2; ptr2 = ptr2->next) 17177298Sobrien if (strcmp (ptr2->name, ptr1->name) == 0) 17277298Sobrien ptr2->ok_to_load = 1; 17377298Sobrien } 17477298Sobrien else 17533965Sjdp { 17677298Sobrien /* No only load list, so everything is ok to load. */ 17777298Sobrien struct section_name_struct *ptr; 17877298Sobrien 17977298Sobrien for (ptr = order; ptr; ptr = ptr->next) 18077298Sobrien ptr->ok_to_load = 1; 18133965Sjdp } 18233965Sjdp 18377298Sobrien /* Create the order of sections to load. */ 184130561Sobrien if (order != NULL) 18577298Sobrien { 18677298Sobrien /* Been told to output the sections in a certain order. */ 18777298Sobrien struct section_name_struct *p = order; 18833965Sjdp 18977298Sobrien while (p) 19077298Sobrien { 19177298Sobrien struct section_name_struct *aptr; 19277298Sobrien etree_type *align = 0; 19377298Sobrien etree_type *subalign = 0; 19489857Sobrien struct wildcard_list *tmp; 19533965Sjdp 19677298Sobrien /* See if an alignment has been specified. */ 19777298Sobrien for (aptr = alignment; aptr; aptr = aptr->next) 19877298Sobrien if (strcmp (aptr->name, p->name) == 0) 19977298Sobrien align = aptr->align; 20033965Sjdp 20177298Sobrien for (aptr = subalignment; aptr; aptr = aptr->next) 20277298Sobrien if (strcmp (aptr->name, p->name) == 0) 20377298Sobrien subalign = aptr->subalign; 20433965Sjdp 20577298Sobrien if (base == 0) 20677298Sobrien base = p->vma ? p->vma : exp_nameop (NAME, "."); 20733965Sjdp 20877298Sobrien lang_enter_output_section_statement (p->name, base, 20977298Sobrien p->ok_to_load ? 0 : noload_section, 210218822Sdim align, subalign, NULL, 0); 21177298Sobrien base = 0; 212130561Sobrien tmp = xmalloc (sizeof *tmp); 21389857Sobrien tmp->next = NULL; 21489857Sobrien tmp->spec.name = p->name; 21589857Sobrien tmp->spec.exclude_name_list = NULL; 216218822Sdim tmp->spec.sorted = none; 217130561Sobrien lang_add_wild (NULL, tmp, FALSE); 21833965Sjdp 21977298Sobrien /* If there is an alias for this section, add it too. */ 22077298Sobrien for (aptr = alias; aptr; aptr = aptr->next) 22177298Sobrien if (strcmp (aptr->alias, p->name) == 0) 22289857Sobrien { 223130561Sobrien tmp = xmalloc (sizeof *tmp); 22489857Sobrien tmp->next = NULL; 22589857Sobrien tmp->spec.name = aptr->name; 22689857Sobrien tmp->spec.exclude_name_list = NULL; 227218822Sdim tmp->spec.sorted = none; 228130561Sobrien lang_add_wild (NULL, tmp, FALSE); 22989857Sobrien } 23033965Sjdp 231130561Sobrien lang_leave_output_section_statement (0, "*default*", NULL, NULL); 23233965Sjdp 23377298Sobrien p = p->next; 23477298Sobrien } 23533965Sjdp } 23633965Sjdp 23733965Sjdp done_tree = 1; 23877298Sobrien} 23933965Sjdp 24033965Sjdpvoid 241130561Sobrienmri_load (const char *name) 24233965Sjdp{ 24333965Sjdp base = 0; 244130561Sobrien lang_add_input_file (name, lang_input_file_is_file_enum, NULL); 24533965Sjdp} 24633965Sjdp 24733965Sjdpvoid 248130561Sobrienmri_order (const char *name) 24933965Sjdp{ 25077298Sobrien mri_add_to_list (&order, name, 0, 0, 0, 0); 25133965Sjdp} 25233965Sjdp 25377298Sobrienvoid 254130561Sobrienmri_alias (const char *want, const char *is, int isn) 25533965Sjdp{ 25677298Sobrien if (!is) 25777298Sobrien { 25877298Sobrien char buf[20]; 25933965Sjdp 26077298Sobrien /* Some sections are digits. */ 26177298Sobrien sprintf (buf, "%d", isn); 26277298Sobrien 26377298Sobrien is = xstrdup (buf); 26477298Sobrien 26577298Sobrien if (is == NULL) 26677298Sobrien abort (); 26777298Sobrien } 26877298Sobrien 26977298Sobrien mri_add_to_list (&alias, is, 0, want, 0, 0); 27033965Sjdp} 27133965Sjdp 27277298Sobrienvoid 273130561Sobrienmri_name (const char *name) 27433965Sjdp{ 27577298Sobrien lang_add_output (name, 1); 27633965Sjdp} 27733965Sjdp 27833965Sjdpvoid 279130561Sobrienmri_format (const char *name) 28033965Sjdp{ 28177298Sobrien if (strcmp (name, "S") == 0) 282130561Sobrien lang_add_output_format ("srec", NULL, NULL, 1); 28377298Sobrien 28477298Sobrien else if (strcmp (name, "IEEE") == 0) 285130561Sobrien lang_add_output_format ("ieee", NULL, NULL, 1); 28677298Sobrien 28777298Sobrien else if (strcmp (name, "COFF") == 0) 288130561Sobrien lang_add_output_format ("coff-m68k", NULL, NULL, 1); 28977298Sobrien 29077298Sobrien else 29177298Sobrien einfo (_("%P%F: unknown format type %s\n"), name); 29233965Sjdp} 29333965Sjdp 29433965Sjdpvoid 295130561Sobrienmri_public (const char *name, etree_type *exp) 29633965Sjdp{ 29777298Sobrien lang_add_assignment (exp_assop ('=', name, exp)); 29833965Sjdp} 29933965Sjdp 30077298Sobrienvoid 301130561Sobrienmri_align (const char *name, etree_type *exp) 30233965Sjdp{ 30377298Sobrien mri_add_to_list (&alignment, name, 0, 0, exp, 0); 30433965Sjdp} 30533965Sjdp 30677298Sobrienvoid 307130561Sobrienmri_alignmod (const char *name, etree_type *exp) 30833965Sjdp{ 30977298Sobrien mri_add_to_list (&subalignment, name, 0, 0, 0, exp); 31033965Sjdp} 31133965Sjdp 31277298Sobrienvoid 313130561Sobrienmri_truncate (unsigned int exp) 31433965Sjdp{ 31533965Sjdp symbol_truncate = exp; 31633965Sjdp} 317