1 /* ldwrite.c -- write out the linked file
2 Copyright (C) 1993 Free Software Foundation, Inc.
3 Written by Steve Chamberlain sac@cygnus.com
5 This file is part of GLD, the Gnu Linker.
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.
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.
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. */
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
));
38 /* Build link_order structures for the BFD linker. */
41 build_link_order (statement
)
42 lang_statement_union_type
*statement
;
44 switch (statement
->header
.type
)
46 case lang_data_statement_enum
:
47 /* FIXME: This should probably build a link_order, but instead
48 it just does the output directly. */
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
;
55 ASSERT (output_section
->owner
== output_bfd
);
56 switch (statement
->data_statement
.type
)
59 bfd_put_64 (output_bfd
, value
, play_area
);
63 bfd_put_32 (output_bfd
, value
, play_area
);
67 bfd_put_16 (output_bfd
, value
, play_area
);
71 bfd_put_8 (output_bfd
, value
, play_area
);
78 if (! bfd_set_section_contents (output_bfd
, output_section
,
80 statement
->data_statement
.output_vma
,
82 einfo ("%P%X: writing data failed: %E\n");
86 case lang_reloc_statement_enum
:
88 lang_reloc_statement_type
*rs
;
89 asection
*output_section
;
90 struct bfd_link_order
*link_order
;
92 rs
= &statement
->reloc_statement
;
94 output_section
= rs
->output_section
;
95 ASSERT (output_section
->owner
== output_bfd
);
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");
101 link_order
->offset
= rs
->output_vma
;
102 link_order
->size
= bfd_get_reloc_size (rs
->howto
);
104 link_order
->u
.reloc
.p
=
105 ((struct bfd_link_order_reloc
*)
106 xmalloc (sizeof (struct bfd_link_order_reloc
)));
108 link_order
->u
.reloc
.p
->reloc
= rs
->reloc
;
109 link_order
->u
.reloc
.p
->addend
= rs
->addend_value
;
111 if (rs
->section
!= (asection
*) NULL
)
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
;
119 link_order
->u
.reloc
.p
->u
.section
= rs
->section
->output_section
;
120 link_order
->u
.reloc
.p
->addend
+= rs
->section
->output_offset
;
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
;
132 case lang_input_section_enum
:
133 /* Create a new link_order in the output section with this
135 if (statement
->input_section
.ifile
->just_syms_flag
== false)
137 asection
*i
= statement
->input_section
.section
;
138 asection
*output_section
= i
->output_section
;
140 ASSERT (output_section
->owner
== output_bfd
);
142 if ((output_section
->flags
& SEC_HAS_CONTENTS
) != 0)
144 struct bfd_link_order
*link_order
;
146 link_order
= bfd_new_link_order (output_bfd
, output_section
);
148 if (i
->flags
& SEC_NEVER_LOAD
)
150 /* We've got a never load section inside one which
151 is going to be output, we'll change it into a
153 link_order
->type
= bfd_fill_link_order
;
154 link_order
->u
.fill
.value
= 0;
158 link_order
->type
= bfd_indirect_link_order
;
159 link_order
->u
.indirect
.section
= i
;
160 ASSERT (i
->output_section
== output_section
);
163 link_order
->size
= i
->_cooked_size
;
165 link_order
->size
= bfd_get_section_size_before_reloc (i
);
166 link_order
->offset
= i
->output_offset
;
171 case lang_padding_statement_enum
:
172 /* Make a new link_order with the right filler */
174 asection
*output_section
;
175 struct bfd_link_order
*link_order
;
177 output_section
= statement
->padding_statement
.output_section
;
178 ASSERT (statement
->padding_statement
.output_section
->owner
180 if ((output_section
->flags
& SEC_HAS_CONTENTS
) != 0)
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
;
192 /* All the other ones fall through */
197 /* Call BFD to write out the linked file. */
202 lang_for_each_statement (build_link_order
);
204 if (! bfd_final_link (output_bfd
, &link_info
))
205 einfo ("%F%P: final link failed: %E\n", output_bfd
);
209 print_symbol_table ();
214 /* Print the symbol table. */
217 print_symbol_table ()
219 fprintf (config
.map_file
, "**FILES**\n\n");
220 lang_for_each_file (print_file_stuff
);
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
);
227 /* Print information about a file. */
231 lang_input_statement_type
* f
;
233 fprintf (config
.map_file
, " %s\n", f
->filename
);
234 if (f
->just_syms_flag
)
236 fprintf (config
.map_file
, " symbols only\n");
243 for (s
= f
->the_bfd
->sections
;
244 s
!= (asection
*) NULL
;
247 print_address (s
->output_offset
);
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
);
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
);
265 for (s
= f
->the_bfd
->sections
;
266 s
!= (asection
*) NULL
;
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
));
274 fprintf (config
.map_file
, "hex \n");
280 /* Print a symbol. */
284 print_symbol (p
, ignore
)
285 struct bfd_link_hash_entry
*p
;
288 while (p
->type
== bfd_link_hash_indirect
289 || p
->type
== bfd_link_hash_warning
)
294 case bfd_link_hash_new
:
297 case bfd_link_hash_undefined
:
298 fprintf (config
.map_file
, "undefined ");
299 fprintf (config
.map_file
, "%s ", p
->root
.string
);
303 case bfd_link_hash_weak
:
304 fprintf (config
.map_file
, "weak ");
305 fprintf (config
.map_file
, "%s ", p
->root
.string
);
309 case bfd_link_hash_defined
:
311 asection
*defsec
= p
->u
.def
.section
;
313 print_address (p
->u
.def
.value
);
316 fprintf (config
.map_file
, " %-10s",
317 bfd_section_name (output_bfd
, defsec
));
319 print_address (p
->u
.def
.value
+ defsec
->vma
);
323 fprintf (config
.map_file
, " .......");
325 fprintf (config
.map_file
, " %s ", p
->root
.string
);
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
);