Changes to make -Ur work again.
[external/binutils.git] / ld / ldwrite.c
1 /* ldwrite.c -- write out the linked file
2    Copyright (C) 1993 Free Software Foundation, Inc.
3    Written by Steve Chamberlain sac@cygnus.com
4
5 This file is part of GLD, the Gnu Linker.
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "bfdlink.h"
24
25 #include "ld.h"
26 #include "ldexp.h"
27 #include "ldlang.h"
28 #include "ldwrite.h"
29 #include "ldmisc.h"
30 #include "ldgram.h"
31 #include "ldmain.h"
32
33 static void build_link_order PARAMS ((lang_statement_union_type *));
34 static void print_symbol_table PARAMS ((void));
35 static void print_file_stuff PARAMS ((lang_input_statement_type *));
36 static boolean print_symbol PARAMS ((struct bfd_link_hash_entry *, PTR));
37
38 /* Build link_order structures for the BFD linker.  */
39
40 static void
41 build_link_order (statement)
42      lang_statement_union_type *statement;
43 {
44   switch (statement->header.type)
45     {
46     case lang_data_statement_enum:
47       /* FIXME: This should probably build a link_order, but instead
48          it just does the output directly.  */
49       {
50         bfd_vma value = statement->data_statement.value;
51         bfd_byte play_area[QUAD_SIZE];
52         unsigned int size = 0;
53         asection *output_section = statement->data_statement.output_section;
54
55         ASSERT (output_section->owner == output_bfd);
56         switch (statement->data_statement.type)
57           {
58           case QUAD:
59             bfd_put_64 (output_bfd, value, play_area);
60             size = QUAD_SIZE;
61             break;
62           case LONG:
63             bfd_put_32 (output_bfd, value, play_area);
64             size = LONG_SIZE;
65             break;
66           case SHORT:
67             bfd_put_16 (output_bfd, value, play_area);
68             size = SHORT_SIZE;
69             break;
70           case BYTE:
71             bfd_put_8 (output_bfd, value, play_area);
72             size = BYTE_SIZE;
73             break;
74           default:
75             abort ();
76           }
77
78         if (! bfd_set_section_contents (output_bfd, output_section,
79                                         play_area,
80                                         statement->data_statement.output_vma,
81                                         size))
82           einfo ("%P%X: writing data failed: %E\n");
83       }
84       break;
85
86     case lang_reloc_statement_enum:
87       {
88         lang_reloc_statement_type *rs;
89         asection *output_section;
90         struct bfd_link_order *link_order;
91
92         rs = &statement->reloc_statement;
93
94         output_section = rs->output_section;
95         ASSERT (output_section->owner == output_bfd);
96
97         link_order = bfd_new_link_order (output_bfd, output_section);
98         if (link_order == NULL)
99           einfo ("%P%F: bfd_new_link_order failed");
100
101         link_order->offset = rs->output_vma;
102         link_order->size = bfd_get_reloc_size (rs->howto);
103
104         link_order->u.reloc.p =
105           ((struct bfd_link_order_reloc *)
106            xmalloc (sizeof (struct bfd_link_order_reloc)));
107
108         link_order->u.reloc.p->reloc = rs->reloc;
109         link_order->u.reloc.p->addend = rs->addend_value;
110
111         if (rs->section != (asection *) NULL)
112           {
113             ASSERT (rs->name == (const char *) NULL);
114             link_order->type = bfd_section_reloc_link_order;
115             if (rs->section->owner == output_bfd)
116               link_order->u.reloc.p->u.section = rs->section;
117             else
118               {
119                 link_order->u.reloc.p->u.section = rs->section->output_section;
120                 link_order->u.reloc.p->addend += rs->section->output_offset;
121               }
122           }
123         else
124           {
125             ASSERT (rs->name != (const char *) NULL);
126             link_order->type = bfd_symbol_reloc_link_order;
127             link_order->u.reloc.p->u.name = rs->name;
128           }
129       }
130       break;
131
132     case lang_input_section_enum:
133       /* Create a new link_order in the output section with this
134          attached */
135       if (statement->input_section.ifile->just_syms_flag == false)
136         {
137           asection *i = statement->input_section.section;
138           asection *output_section = i->output_section;
139
140           ASSERT (output_section->owner == output_bfd);
141
142           if ((output_section->flags & SEC_HAS_CONTENTS) != 0)
143             {
144               struct bfd_link_order *link_order;
145
146               link_order = bfd_new_link_order (output_bfd, output_section);
147
148               if (i->flags & SEC_NEVER_LOAD)
149                 {
150                   /* We've got a never load section inside one which
151                      is going to be output, we'll change it into a
152                      fill link_order */
153                   link_order->type = bfd_fill_link_order;
154                   link_order->u.fill.value = 0;
155                 }
156               else
157                 {
158                   link_order->type = bfd_indirect_link_order;
159                   link_order->u.indirect.section = i;
160                   ASSERT (i->output_section == output_section);
161                 }
162               if (i->_cooked_size)
163                 link_order->size = i->_cooked_size;
164               else
165                 link_order->size = bfd_get_section_size_before_reloc (i);
166               link_order->offset = i->output_offset;
167             }
168         }
169       break;
170
171     case lang_padding_statement_enum:
172       /* Make a new link_order with the right filler */
173       {
174         asection *output_section;
175         struct bfd_link_order *link_order;
176
177         output_section = statement->padding_statement.output_section;
178         ASSERT (statement->padding_statement.output_section->owner
179                 == output_bfd);
180         if ((output_section->flags & SEC_HAS_CONTENTS) != 0)
181           {
182             link_order = bfd_new_link_order (output_bfd, output_section);
183             link_order->type = bfd_fill_link_order;
184             link_order->size = statement->padding_statement.size;
185             link_order->offset = statement->padding_statement.output_offset;
186             link_order->u.fill.value = statement->padding_statement.fill;
187           }
188       }
189       break;
190
191     default:
192       /* All the other ones fall through */
193       break;
194     }
195 }
196
197 /* Call BFD to write out the linked file.  */
198
199 void
200 ldwrite ()
201 {
202   lang_for_each_statement (build_link_order);
203
204   if (! bfd_final_link (output_bfd, &link_info))
205     einfo ("%F%P: final link failed: %E\n", output_bfd);
206
207   if (config.map_file)
208     {
209       print_symbol_table ();
210       lang_map ();
211     }
212 }
213
214 /* Print the symbol table.  */
215
216 static void
217 print_symbol_table ()
218 {
219   fprintf (config.map_file, "**FILES**\n\n");
220   lang_for_each_file (print_file_stuff);
221
222   fprintf (config.map_file, "**GLOBAL SYMBOLS**\n\n");
223   fprintf (config.map_file, "offset    section    offset   symbol\n");
224   bfd_link_hash_traverse (link_info.hash, print_symbol, (PTR) NULL);
225 }
226
227 /* Print information about a file.  */
228
229 static void
230 print_file_stuff (f)
231      lang_input_statement_type * f;
232 {
233   fprintf (config.map_file, "  %s\n", f->filename);
234   if (f->just_syms_flag)
235     {
236       fprintf (config.map_file, " symbols only\n");
237     }
238   else
239     {
240       asection *s;
241       if (true)
242         {
243           for (s = f->the_bfd->sections;
244                s != (asection *) NULL;
245                s = s->next)
246             {
247               print_address (s->output_offset);
248               if (s->reloc_done)
249                 {
250                   fprintf (config.map_file, " %08x 2**%2ud %s\n",
251                            (unsigned) bfd_get_section_size_after_reloc (s),
252                            s->alignment_power, s->name);
253                 }
254
255               else
256                 {
257                   fprintf (config.map_file, " %08x 2**%2ud %s\n",
258                            (unsigned) bfd_get_section_size_before_reloc (s),
259                            s->alignment_power, s->name);
260                 }
261             }
262         }
263       else
264         {
265           for (s = f->the_bfd->sections;
266                s != (asection *) NULL;
267                s = s->next)
268             {
269               fprintf (config.map_file, "%s ", s->name);
270               print_address (s->output_offset);
271               fprintf (config.map_file, "(%x)",
272                        (unsigned) bfd_get_section_size_after_reloc (s));
273             }
274           fprintf (config.map_file, "hex \n");
275         }
276     }
277   print_nl ();
278 }
279
280 /* Print a symbol.  */
281
282 /*ARGSUSED*/
283 static boolean
284 print_symbol (p, ignore)
285      struct bfd_link_hash_entry *p;
286      PTR ignore;
287 {
288   while (p->type == bfd_link_hash_indirect
289          || p->type == bfd_link_hash_warning)
290     p = p->u.i.link;
291
292   switch (p->type) 
293     {
294     case bfd_link_hash_new:
295       abort ();
296
297     case bfd_link_hash_undefined:
298       fprintf (config.map_file, "undefined                     ");
299       fprintf (config.map_file, "%s ", p->root.string);
300       print_nl ();    
301       break;
302
303     case bfd_link_hash_weak:
304       fprintf (config.map_file, "weak                          ");
305       fprintf (config.map_file, "%s ", p->root.string);
306       print_nl ();    
307       break;
308
309     case bfd_link_hash_defined:     
310       {
311         asection *defsec = p->u.def.section;
312
313         print_address (p->u.def.value);
314         if (defsec)
315           {
316             fprintf (config.map_file, "  %-10s",
317                      bfd_section_name (output_bfd, defsec));
318             print_space ();
319             print_address (p->u.def.value + defsec->vma);
320           }
321         else
322           {
323             fprintf (config.map_file, "         .......");
324           }
325         fprintf (config.map_file, " %s ", p->root.string);
326       }
327       print_nl ();    
328       break;
329
330     case bfd_link_hash_common:
331       fprintf (config.map_file, "common               ");
332       print_address (p->u.c.size);
333       fprintf (config.map_file, " %s ", p->root.string);
334       print_nl ();
335       break;
336
337     default:
338       abort ();
339     }
340
341   return true;
342 }