ldwrite.c revision 60484
1/* ldwrite.c -- write out the linked file
2   Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 1998
3   Free Software Foundation, Inc.
4   Written by Steve Chamberlain sac@cygnus.com
5
6This file is part of GLD, the Gnu Linker.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2 of the License, or
11(at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
20Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
22#include "bfd.h"
23#include "sysdep.h"
24#include "bfdlink.h"
25#include "libiberty.h"
26
27#include "ld.h"
28#include "ldexp.h"
29#include "ldlang.h"
30#include "ldwrite.h"
31#include "ldmisc.h"
32#include "ldgram.h"
33#include "ldmain.h"
34
35static void build_link_order PARAMS ((lang_statement_union_type *));
36static asection *clone_section PARAMS ((bfd *, asection *, int *));
37static void split_sections PARAMS ((bfd *, struct bfd_link_info *));
38
39/* Build link_order structures for the BFD linker.  */
40
41static void
42build_link_order (statement)
43     lang_statement_union_type *statement;
44{
45  switch (statement->header.type)
46    {
47    case lang_data_statement_enum:
48      {
49	asection *output_section;
50	struct bfd_link_order *link_order;
51	bfd_vma value;
52	boolean big_endian = false;
53
54	output_section = statement->data_statement.output_section;
55	ASSERT (output_section->owner == output_bfd);
56
57	link_order = bfd_new_link_order (output_bfd, output_section);
58	if (link_order == NULL)
59	  einfo (_("%P%F: bfd_new_link_order failed\n"));
60
61	link_order->type = bfd_data_link_order;
62	link_order->offset = statement->data_statement.output_vma;
63	link_order->u.data.contents = (bfd_byte *) xmalloc (QUAD_SIZE);
64
65	value = statement->data_statement.value;
66
67	/* If the endianness of the output BFD is not known, then we
68	   base the endianness of the data on the first input file.
69	   By convention, the bfd_put routines for an unknown
70	   endianness are big endian, so we must swap here if the
71	   input file is little endian.  */
72	if (bfd_big_endian (output_bfd))
73	  big_endian = true;
74	else if (bfd_little_endian (output_bfd))
75	  big_endian = false;
76	else
77	  {
78	    boolean swap;
79
80	    swap = false;
81	    if (command_line.endian == ENDIAN_BIG)
82	      big_endian = true;
83	    else if (command_line.endian == ENDIAN_LITTLE)
84	      {
85		big_endian = false;
86		swap = true;
87	      }
88	    else if (command_line.endian == ENDIAN_UNSET)
89	      {
90		big_endian = true;
91		{
92		  LANG_FOR_EACH_INPUT_STATEMENT (s)
93		    {
94		      if (s->the_bfd != NULL)
95			{
96			  if (bfd_little_endian (s->the_bfd))
97			    {
98			      big_endian = false;
99			      swap = true;
100			    }
101			  break;
102			}
103		    }
104		}
105	      }
106
107	    if (swap)
108	      {
109		bfd_byte buffer[8];
110
111		switch (statement->data_statement.type)
112		  {
113		  case QUAD:
114		  case SQUAD:
115		    if (sizeof (bfd_vma) >= QUAD_SIZE)
116		      {
117			bfd_putl64 (value, buffer);
118			value = bfd_getb64 (buffer);
119			break;
120		      }
121		    /* Fall through.  */
122		  case LONG:
123		    bfd_putl32 (value, buffer);
124		    value = bfd_getb32 (buffer);
125		    break;
126		  case SHORT:
127		    bfd_putl16 (value, buffer);
128		    value = bfd_getb16 (buffer);
129		    break;
130		  case BYTE:
131		    break;
132		  default:
133		    abort ();
134		  }
135	      }
136	  }
137
138	ASSERT (output_section->owner == output_bfd);
139	switch (statement->data_statement.type)
140	  {
141	  case QUAD:
142	  case SQUAD:
143	    if (sizeof (bfd_vma) >= QUAD_SIZE)
144	      bfd_put_64 (output_bfd, value, link_order->u.data.contents);
145	    else
146	      {
147		bfd_vma high;
148
149		if (statement->data_statement.type == QUAD)
150		  high = 0;
151		else if ((value & 0x80000000) == 0)
152		  high = 0;
153		else
154		  high = (bfd_vma) -1;
155		bfd_put_32 (output_bfd, high,
156			    (link_order->u.data.contents
157			     + (big_endian ? 0 : 4)));
158		bfd_put_32 (output_bfd, value,
159			    (link_order->u.data.contents
160			     + (big_endian ? 4 : 0)));
161	      }
162	    link_order->size = QUAD_SIZE;
163	    break;
164	  case LONG:
165	    bfd_put_32 (output_bfd, value, link_order->u.data.contents);
166	    link_order->size = LONG_SIZE;
167	    break;
168	  case SHORT:
169	    bfd_put_16 (output_bfd, value, link_order->u.data.contents);
170	    link_order->size = SHORT_SIZE;
171	    break;
172	  case BYTE:
173	    bfd_put_8 (output_bfd, value, link_order->u.data.contents);
174	    link_order->size = BYTE_SIZE;
175	    break;
176	  default:
177	    abort ();
178	  }
179      }
180      break;
181
182    case lang_reloc_statement_enum:
183      {
184	lang_reloc_statement_type *rs;
185	asection *output_section;
186	struct bfd_link_order *link_order;
187
188	rs = &statement->reloc_statement;
189
190	output_section = rs->output_section;
191	ASSERT (output_section->owner == output_bfd);
192
193	link_order = bfd_new_link_order (output_bfd, output_section);
194	if (link_order == NULL)
195	  einfo (_("%P%F: bfd_new_link_order failed\n"));
196
197	link_order->offset = rs->output_vma;
198	link_order->size = bfd_get_reloc_size (rs->howto);
199
200	link_order->u.reloc.p =
201	  ((struct bfd_link_order_reloc *)
202	   xmalloc (sizeof (struct bfd_link_order_reloc)));
203
204	link_order->u.reloc.p->reloc = rs->reloc;
205	link_order->u.reloc.p->addend = rs->addend_value;
206
207	if (rs->name == NULL)
208	  {
209	    link_order->type = bfd_section_reloc_link_order;
210	    if (rs->section->owner == output_bfd)
211	      link_order->u.reloc.p->u.section = rs->section;
212	    else
213	      {
214		link_order->u.reloc.p->u.section = rs->section->output_section;
215		link_order->u.reloc.p->addend += rs->section->output_offset;
216	      }
217	  }
218	else
219	  {
220	    link_order->type = bfd_symbol_reloc_link_order;
221	    link_order->u.reloc.p->u.name = rs->name;
222	  }
223      }
224      break;
225
226    case lang_input_section_enum:
227      /* Create a new link_order in the output section with this
228	 attached */
229      if (statement->input_section.ifile->just_syms_flag == false)
230	{
231	  asection *i = statement->input_section.section;
232	  asection *output_section = i->output_section;
233
234	  ASSERT (output_section->owner == output_bfd);
235
236	  if ((output_section->flags & SEC_HAS_CONTENTS) != 0)
237	    {
238	      struct bfd_link_order *link_order;
239
240	      link_order = bfd_new_link_order (output_bfd, output_section);
241
242	      if (i->flags & SEC_NEVER_LOAD)
243		{
244		  /* We've got a never load section inside one which
245		     is going to be output, we'll change it into a
246		     fill link_order */
247		  link_order->type = bfd_fill_link_order;
248		  link_order->u.fill.value = 0;
249		}
250	      else
251		{
252		  link_order->type = bfd_indirect_link_order;
253		  link_order->u.indirect.section = i;
254		  ASSERT (i->output_section == output_section);
255		}
256	      if (i->_cooked_size)
257		link_order->size = i->_cooked_size;
258	      else
259		link_order->size = bfd_get_section_size_before_reloc (i);
260	      link_order->offset = i->output_offset;
261	    }
262	}
263      break;
264
265    case lang_padding_statement_enum:
266      /* Make a new link_order with the right filler */
267      {
268	asection *output_section;
269	struct bfd_link_order *link_order;
270
271	output_section = statement->padding_statement.output_section;
272	ASSERT (statement->padding_statement.output_section->owner
273		== output_bfd);
274	if ((output_section->flags & SEC_HAS_CONTENTS) != 0)
275	  {
276	    link_order = bfd_new_link_order (output_bfd, output_section);
277	    link_order->type = bfd_fill_link_order;
278	    link_order->size = statement->padding_statement.size;
279	    link_order->offset = statement->padding_statement.output_offset;
280	    link_order->u.fill.value = statement->padding_statement.fill;
281	  }
282      }
283      break;
284
285    default:
286      /* All the other ones fall through */
287      break;
288    }
289}
290
291/* Call BFD to write out the linked file.  */
292
293
294/**********************************************************************/
295
296
297/* Wander around the input sections, make sure that
298   we'll never try and create an output section with more relocs
299   than will fit.. Do this by always assuming the worst case, and
300   creating new output sections with all the right bits */
301#define TESTIT 1
302static asection *
303clone_section (abfd, s, count)
304     bfd *abfd;
305     asection *s;
306     int *count;
307{
308#define SSIZE 8
309  char sname[SSIZE];		/* ??  find the name for this size */
310  asection *n;
311  struct bfd_link_hash_entry *h;
312  /* Invent a section name - use first five
313     chars of base section name and a digit suffix */
314  do
315    {
316      unsigned int i;
317      char b[6];
318      for (i = 0; i < sizeof (b) - 1 && s->name[i]; i++)
319	b[i] = s->name[i];
320      b[i] = 0;
321      sprintf (sname, "%s%d", b, (*count)++);
322    }
323  while (bfd_get_section_by_name (abfd, sname));
324
325  n = bfd_make_section_anyway (abfd, xstrdup (sname));
326
327  /* Create a symbol of the same name */
328
329  h = bfd_link_hash_lookup (link_info.hash,
330			    sname, true, true, false);
331  h->type = bfd_link_hash_defined;
332  h->u.def.value = 0;
333  h->u.def.section = n   ;
334
335
336  n->flags = s->flags;
337  n->vma = s->vma;
338  n->user_set_vma = s->user_set_vma;
339  n->lma = s->lma;
340  n->_cooked_size = 0;
341  n->_raw_size = 0;
342  n->output_offset = s->output_offset;
343  n->output_section = n;
344  n->orelocation = 0;
345  n->reloc_count = 0;
346  n->alignment_power = s->alignment_power;
347  return n;
348}
349
350#if TESTING
351static void
352ds (s)
353     asection *s;
354{
355  struct bfd_link_order *l = s->link_order_head;
356  printf ("vma %x size %x\n", s->vma, s->_raw_size);
357  while (l)
358    {
359      if (l->type == bfd_indirect_link_order)
360	{
361	  printf ("%8x %s\n", l->offset, l->u.indirect.section->owner->filename);
362	}
363      else
364	{
365	  printf (_("%8x something else\n"), l->offset);
366	}
367      l = l->next;
368    }
369  printf ("\n");
370}
371dump (s, a1, a2)
372     char *s;
373     asection *a1;
374     asection *a2;
375{
376  printf ("%s\n", s);
377  ds (a1);
378  ds (a2);
379}
380
381static void
382sanity_check (abfd)
383     bfd *abfd;
384{
385  asection *s;
386  for (s = abfd->sections; s; s = s->next)
387    {
388      struct bfd_link_order *p;
389      bfd_vma prev = 0;
390      for (p = s->link_order_head; p; p = p->next)
391	{
392	  if (p->offset > 100000)
393	    abort ();
394	  if (p->offset < prev)
395	    abort ();
396	  prev = p->offset;
397	}
398    }
399}
400#else
401#define sanity_check(a)
402#define dump(a, b, c)
403#endif
404
405static void
406split_sections (abfd, info)
407     bfd *abfd;
408     struct bfd_link_info *info;
409{
410  asection *original_sec;
411  int nsecs = abfd->section_count;
412  sanity_check (abfd);
413  /* look through all the original sections */
414  for (original_sec = abfd->sections;
415       original_sec && nsecs;
416       original_sec = original_sec->next, nsecs--)
417    {
418      boolean first = true;
419      int count = 0;
420      int lines = 0;
421      int relocs = 0;
422      struct bfd_link_order **pp;
423      bfd_vma vma = original_sec->vma;
424      bfd_vma shift_offset = 0;
425      asection *cursor = original_sec;
426
427      /* count up the relocations and line entries to see if
428	 anything would be too big to fit */
429      for (pp = &(cursor->link_order_head); *pp; pp = &((*pp)->next))
430	{
431	  struct bfd_link_order *p = *pp;
432	  int thislines = 0;
433	  int thisrelocs = 0;
434	  if (p->type == bfd_indirect_link_order)
435	    {
436	      asection *sec;
437
438	      sec = p->u.indirect.section;
439
440	      if (info->strip == strip_none
441		  || info->strip == strip_some)
442		thislines = sec->lineno_count;
443
444	      if (info->relocateable)
445		thisrelocs = sec->reloc_count;
446
447	    }
448	  else if (info->relocateable
449		   && (p->type == bfd_section_reloc_link_order
450		       || p->type == bfd_symbol_reloc_link_order))
451	    thisrelocs++;
452
453	  if (! first
454	      && (thisrelocs + relocs > config.split_by_reloc
455		  || thislines + lines > config.split_by_reloc
456		  || config.split_by_file))
457	    {
458	      /* create a new section and put this link order and the
459		 following link orders into it */
460	      struct bfd_link_order *l = p;
461	      asection *n = clone_section (abfd, cursor, &count);
462	      *pp = NULL;	/* Snip off link orders from old section */
463	      n->link_order_head = l;	/* attach to new section */
464	      pp = &n->link_order_head;
465
466	      /* change the size of the original section and
467		 update the vma of the new one */
468
469	      dump ("before snip", cursor, n);
470
471	      n->_raw_size = cursor->_raw_size - l->offset;
472	      cursor->_raw_size = l->offset;
473
474	      vma += cursor->_raw_size;
475	      n->lma = n->vma = vma;
476
477	      shift_offset = l->offset;
478
479	      /* run down the chain and change the output section to
480		 the right one, update the offsets too */
481
482	      while (l)
483		{
484		  l->offset -= shift_offset;
485		  if (l->type == bfd_indirect_link_order)
486		    {
487		      l->u.indirect.section->output_section = n;
488		      l->u.indirect.section->output_offset = l->offset;
489		    }
490		  l = l->next;
491		}
492	      dump ("after snip", cursor, n);
493	      cursor = n;
494	      relocs = thisrelocs;
495	      lines = thislines;
496	    }
497	  else
498	    {
499	      relocs += thisrelocs;
500	      lines += thislines;
501	    }
502
503	  first = false;
504	}
505    }
506  sanity_check (abfd);
507}
508/**********************************************************************/
509void
510ldwrite ()
511{
512  /* Reset error indicator, which can typically something like invalid
513     format from openning up the .o files */
514  bfd_set_error (bfd_error_no_error);
515  lang_for_each_statement (build_link_order);
516
517  if (config.split_by_reloc || config.split_by_file)
518    split_sections (output_bfd, &link_info);
519  if (!bfd_final_link (output_bfd, &link_info))
520    {
521      /* If there was an error recorded, print it out.  Otherwise assume
522	 an appropriate error message like unknown symbol was printed
523	 out.  */
524
525      if (bfd_get_error () != bfd_error_no_error)
526	einfo (_("%F%P: final link failed: %E\n"), output_bfd);
527      else
528	xexit(1);
529    }
530}
531