]>
Commit | Line | Data |
---|---|---|
a6152e39 DM |
1 | # This shell script emits a C file. -*- C -*- |
2 | # It does some substitutions. | |
8ddef552 | 3 | cat >em_${EMULATION_NAME}.c <<EOF |
d4e5e3c3 | 4 | /* An emulation for HP PA-RISC ELF linkers. |
4a6afc88 | 5 | Copyright (C) 1991, 1993 Free Software Foundation, Inc. |
8ddef552 DM |
6 | Written by Steve Chamberlain [email protected] |
7 | ||
8 | This file is part of GLD, the Gnu Linker. | |
9 | ||
10 | This program is free software; you can redistribute it and/or modify | |
11 | it under the terms of the GNU General Public License as published by | |
12 | the Free Software Foundation; either version 2 of the License, or | |
13 | (at your option) any later version. | |
14 | ||
15 | This program is distributed in the hope that it will be useful, | |
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | GNU General Public License for more details. | |
19 | ||
20 | You should have received a copy of the GNU General Public License | |
21 | along with this program; if not, write to the Free Software | |
22 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
23 | ||
24 | #include "bfd.h" | |
25 | #include "sysdep.h" | |
4a6afc88 | 26 | #include "bfdlink.h" |
8ddef552 DM |
27 | |
28 | #include "ld.h" | |
29 | #include "config.h" | |
30 | #include "ldemul.h" | |
31 | #include "ldfile.h" | |
93df4ec5 | 32 | #include "ldexp.h" |
9d9d72fc | 33 | #include "ldlang.h" |
8ddef552 | 34 | #include "ldmisc.h" |
4a6afc88 ILT |
35 | #include "ldmain.h" |
36 | #include "ldctor.h" | |
8ddef552 | 37 | |
531a5bd1 JL |
38 | static lang_input_statement_type *stub_file = 0; |
39 | static lang_input_section_type *stub_input_section = NULL; | |
40 | ||
41 | /* FIXME. This doesn't belong here. */ | |
2e39abdb | 42 | extern lang_statement_list_type file_chain; |
531a5bd1 JL |
43 | |
44 | /* Perform some emulation specific initialization. For PA ELF we set | |
45 | up the local label prefix and the output architecture. */ | |
46 | ||
47 | static void | |
48 | hppaelf_before_parse () | |
8ddef552 | 49 | { |
4a6afc88 ILT |
50 | link_info.lprefix = "L$"; |
51 | link_info.lprefix_len = 2; | |
93df4ec5 | 52 | |
8ddef552 DM |
53 | ldfile_output_architecture = bfd_arch_hppa; |
54 | } | |
8ddef552 | 55 | |
531a5bd1 JL |
56 | /* Walk all the lang statements splicing out any padding statements from |
57 | the list. */ | |
9d9d72fc | 58 | |
9d9d72fc | 59 | static void |
531a5bd1 JL |
60 | hppaelf_search_for_padding_statements (s, prev) |
61 | lang_statement_union_type *s; | |
62 | lang_statement_union_type **prev; | |
9d9d72fc JL |
63 | { |
64 | lang_statement_union_type *sprev = NULL; | |
531a5bd1 | 65 | for (; s != NULL; s = s->next) |
9d9d72fc JL |
66 | { |
67 | switch (s->header.type) | |
68 | { | |
531a5bd1 JL |
69 | |
70 | /* We want recursively walk these sections. */ | |
9d9d72fc | 71 | case lang_constructors_statement_enum: |
531a5bd1 JL |
72 | hppaelf_search_for_padding_statements (constructor_list.head, |
73 | &constructor_list.head); | |
9d9d72fc | 74 | break; |
531a5bd1 | 75 | |
9d9d72fc | 76 | case lang_output_section_statement_enum: |
531a5bd1 JL |
77 | hppaelf_search_for_padding_statements (s->output_section_statement. |
78 | children.head, | |
79 | &s->output_section_statement. | |
80 | children.head); | |
9d9d72fc | 81 | break; |
531a5bd1 JL |
82 | |
83 | /* Huh? What is a lang_wild_statement? */ | |
9d9d72fc | 84 | case lang_wild_statement_enum: |
531a5bd1 JL |
85 | hppaelf_search_for_padding_statements(s->wild_statement. |
86 | children.head, | |
87 | &s->wild_statement. | |
88 | children.head); | |
89 | break; | |
90 | ||
91 | /* Here's what we are really looking for. Splice these out of | |
92 | the list. */ | |
93 | case lang_padding_statement_enum: | |
94 | if (sprev) | |
95 | sprev->header.next = s->header.next; | |
96 | else | |
97 | **prev = *s; | |
9d9d72fc | 98 | break; |
531a5bd1 JL |
99 | |
100 | /* We don't care about these cases. */ | |
9d9d72fc JL |
101 | case lang_data_statement_enum: |
102 | case lang_object_symbols_statement_enum: | |
103 | case lang_output_statement_enum: | |
104 | case lang_target_statement_enum: | |
105 | case lang_input_section_enum: | |
106 | case lang_input_statement_enum: | |
107 | case lang_assignment_statement_enum: | |
108 | case lang_address_statement_enum: | |
109 | break; | |
531a5bd1 | 110 | |
9d9d72fc | 111 | default: |
531a5bd1 | 112 | abort (); |
9d9d72fc JL |
113 | break; |
114 | } | |
115 | sprev = s; | |
116 | } | |
117 | } | |
118 | ||
531a5bd1 JL |
119 | /* Final emulation specific call. For the PA we use this opportunity |
120 | to determine what linker stubs are needed and generate them. | |
121 | ||
122 | FIXME: fast-linker work broke this in a big way. statement->asymbols | |
123 | doesn't have anything useful in it anymore. And if we slurp in | |
124 | the symbol table here and pass it down then we get lots of undefined | |
125 | symbols. Egad. */ | |
126 | ||
9d9d72fc | 127 | static void |
531a5bd1 | 128 | hppaelf_finish () |
9d9d72fc | 129 | { |
9d9d72fc | 130 | |
531a5bd1 JL |
131 | /* Disabled until it's fixed to work with the new linker. A noteworty |
132 | amount of code will still function without linker stubs allowing us | |
133 | to continue testing. */ | |
134 | ||
531a5bd1 | 135 | /* Only create stubs for final objects. */ |
4a6afc88 | 136 | if (link_info.relocateable == false) |
9d9d72fc | 137 | { |
9dd7d585 | 138 | lang_input_statement_type *statement; |
531a5bd1 JL |
139 | |
140 | /* Look at all the statements. */ | |
9dd7d585 | 141 | for (statement = (lang_input_statement_type *)file_chain.head; |
531a5bd1 | 142 | statement != NULL; |
9dd7d585 JL |
143 | statement = (lang_input_statement_type *)statement->next) |
144 | { | |
145 | asection *section; | |
146 | bfd *abfd = statement->the_bfd; | |
531a5bd1 JL |
147 | |
148 | /* Look at all the sections attached to the bfd associated with | |
149 | the current statement. */ | |
9dd7d585 JL |
150 | for (section = abfd->sections; |
151 | section != (asection *)NULL; | |
152 | section = section ->next) | |
153 | { | |
154 | int new_sym_cnt = 0; | |
155 | int i,j; | |
156 | asymbol *syms; | |
531a5bd1 JL |
157 | |
158 | /* Do the dirty work; an array of symbols for each new stub | |
159 | will be returned. */ | |
9dd7d585 JL |
160 | syms = hppa_look_for_stubs_in_section (stub_file->the_bfd, |
161 | abfd, | |
162 | output_bfd, | |
163 | section, | |
9dd7d585 JL |
164 | &new_sym_cnt, |
165 | &link_info); | |
531a5bd1 JL |
166 | |
167 | if (new_sym_cnt > 0 && syms) | |
9dd7d585 JL |
168 | { |
169 | struct symbol_cache_entry **old_asymbols; | |
531a5bd1 | 170 | |
9dd7d585 | 171 | old_asymbols = stub_file->asymbols; |
531a5bd1 JL |
172 | |
173 | /* Allocate space for the updated symbols */ | |
174 | stub_file->asymbols | |
175 | = xmalloc ((stub_file->symbol_count + new_sym_cnt) | |
176 | * sizeof(asymbol *)); | |
177 | if (stub_file->asymbols == NULL) | |
178 | abort (); | |
179 | ||
180 | /* Copy the old symbols. | |
181 | ||
182 | FIXME. Shouldn't we free the space used by the old | |
183 | symbols here? Might there be dangling references | |
184 | made within hppa_look_for_stubs_in_section? */ | |
185 | for (j = 0; j < stub_file->symbol_count; j++) | |
9dd7d585 | 186 | stub_file->asymbols[j] = old_asymbols[j]; |
531a5bd1 JL |
187 | |
188 | /* Copy in the new symbols. */ | |
189 | for (j = 0, i = stub_file->symbol_count; | |
190 | j < new_sym_cnt; | |
191 | j++, i++) | |
9dd7d585 | 192 | stub_file->asymbols[i] = &syms[j]; |
531a5bd1 JL |
193 | |
194 | /* Finally, adjust the symbol count. */ | |
9dd7d585 JL |
195 | stub_file->symbol_count += new_sym_cnt; |
196 | } | |
197 | } | |
198 | } | |
531a5bd1 JL |
199 | |
200 | /* Add a statement to get the linker stubs included in the output. */ | |
201 | lang_add_wild (".hppa_linker_stubs",NULL); | |
202 | ||
203 | /* If stubs were added, then remove all the (now invalid) padding | |
204 | statements. */ | |
205 | hppaelf_search_for_padding_statements (stat_ptr->head, | |
206 | &stat_ptr->head); | |
9d9d72fc | 207 | } |
531a5bd1 | 208 | |
a62494c4 | 209 | /* Size up the sections again. */ |
531a5bd1 JL |
210 | lang_size_sections (stat_ptr->head, abs_output_section, |
211 | &stat_ptr->head, 0, (bfd_vma) 0, false); | |
212 | ||
213 | /* FIXME: Do we need to redo the "assignments" too? */ | |
9d9d72fc JL |
214 | } |
215 | ||
531a5bd1 JL |
216 | /* Create any emulation specific output statements. FIXME? Is this |
217 | redundant with above lang_add_wild or the code in the script? */ | |
218 | ||
9d9d72fc | 219 | static void |
531a5bd1 | 220 | hppaelf_create_output_section_statements () |
9d9d72fc JL |
221 | { |
222 | asection *stub_sec; | |
531a5bd1 | 223 | asection *output_text_sec = bfd_make_section_old_way (output_bfd, ".text"); |
9d9d72fc | 224 | lang_input_section_type *new_input_sec; |
531a5bd1 JL |
225 | |
226 | /* Add a new "input file" (the linker stubs themselves). */ | |
9d9d72fc JL |
227 | stub_file = lang_add_input_file ("linker stubs", |
228 | lang_input_file_is_fake_enum, | |
531a5bd1 | 229 | NULL); |
9d9d72fc JL |
230 | stub_file->the_bfd = bfd_create ("linker stubs", output_bfd); |
231 | stub_file->symbol_count = 0; | |
232 | stub_file->the_bfd->sections = 0; | |
531a5bd1 JL |
233 | |
234 | /* Add a section to the fake input file. */ | |
235 | stub_sec = bfd_make_section_old_way (stub_file->the_bfd, | |
236 | ".hppa_linker_stubs"); | |
9d9d72fc | 237 | stub_sec->output_section = output_text_sec; |
531a5bd1 JL |
238 | bfd_set_section_flags (stub_file->the_bfd, stub_sec, |
239 | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_CODE | SEC_RELOC); | |
9d9d72fc | 240 | |
531a5bd1 | 241 | /* The user data of a bfd points to the input statement attached. */ |
9d9d72fc | 242 | stub_file->the_bfd->usrdata = (void *)stub_file; |
531a5bd1 | 243 | stub_file->common_section = bfd_make_section(stub_file->the_bfd,"COMMON"); |
9d9d72fc | 244 | |
531a5bd1 JL |
245 | new_input_sec = (lang_input_section_type *) |
246 | stat_alloc (sizeof (lang_input_section_type)); | |
247 | ||
248 | if (new_input_sec) | |
9d9d72fc JL |
249 | { |
250 | lang_output_section_statement_type *text_output_sec; | |
251 | lang_statement_union_type *stmt; | |
531a5bd1 | 252 | |
9d9d72fc JL |
253 | new_input_sec->section = stub_sec; |
254 | new_input_sec->ifile = stub_file; | |
255 | new_input_sec->header.type = lang_input_section_enum; | |
256 | new_input_sec->header.next = NULL; | |
257 | ||
258 | stub_input_section = new_input_sec; | |
259 | ||
531a5bd1 JL |
260 | /* Find the output_section_statement for .text, |
261 | then find the wild_statement for .hppa_linker_stubs. */ | |
262 | text_output_sec = lang_output_section_find (".text"); | |
9d9d72fc JL |
263 | |
264 | stmt = text_output_sec->children.head; | |
265 | ||
266 | while (stmt && stmt->header.type != lang_wild_statement_enum) | |
531a5bd1 JL |
267 | stmt = stmt->header.next; |
268 | ||
269 | /* Do something with the wild statement. FIXME. */ | |
270 | if (stmt) | |
9d9d72fc | 271 | { |
531a5bd1 JL |
272 | lang_wild_statement_type *wstmt = (lang_wild_statement_type *)stmt; |
273 | lang_list_init (&wstmt->children); | |
274 | lang_statement_append (&wstmt->children, | |
275 | (lang_statement_union_type *)new_input_sec, | |
276 | &new_input_sec->header.next); | |
9d9d72fc JL |
277 | } |
278 | } | |
279 | } | |
280 | ||
531a5bd1 JL |
281 | /* Set the output architecture and machine. */ |
282 | ||
8ddef552 | 283 | static void |
d4e5e3c3 | 284 | hppaelf_set_output_arch() |
8ddef552 | 285 | { |
531a5bd1 JL |
286 | unsigned long machine = 0; |
287 | ||
288 | bfd_set_arch_mach (output_bfd, ldfile_output_architecture, machine); | |
8ddef552 DM |
289 | } |
290 | ||
531a5bd1 JL |
291 | /* The script itself gets inserted here. */ |
292 | ||
a6152e39 | 293 | static char * |
d4e5e3c3 | 294 | hppaelf_get_script(isfile) |
a6152e39 DM |
295 | int *isfile; |
296 | EOF | |
8ddef552 | 297 | |
d59e5a47 | 298 | if test -n "$COMPILE_IN" |
a6152e39 DM |
299 | then |
300 | # Scripts compiled in. | |
301 | ||
302 | # sed commands to quote an ld script as a C string. | |
303 | sc='s/["\\]/\\&/g | |
304 | s/$/\\n\\/ | |
d4e5e3c3 DM |
305 | 1s/^/"/ |
306 | $s/$/n"/ | |
a6152e39 DM |
307 | ' |
308 | ||
309 | cat >>em_${EMULATION_NAME}.c <<EOF | |
310 | { | |
a6152e39 DM |
311 | *isfile = 0; |
312 | ||
4a6afc88 | 313 | if (link_info.relocateable == true && config.build_constructors == true) |
a6152e39 | 314 | return `sed "$sc" ldscripts/${EMULATION_NAME}.xu`; |
4a6afc88 | 315 | else if (link_info.relocateable == true) |
a6152e39 DM |
316 | return `sed "$sc" ldscripts/${EMULATION_NAME}.xr`; |
317 | else if (!config.text_read_only) | |
318 | return `sed "$sc" ldscripts/${EMULATION_NAME}.xbn`; | |
319 | else if (!config.magic_demand_paged) | |
320 | return `sed "$sc" ldscripts/${EMULATION_NAME}.xn`; | |
321 | else | |
322 | return `sed "$sc" ldscripts/${EMULATION_NAME}.x`; | |
323 | } | |
324 | EOF | |
8ddef552 | 325 | |
a6152e39 DM |
326 | else |
327 | # Scripts read from the filesystem. | |
328 | ||
329 | cat >>em_${EMULATION_NAME}.c <<EOF | |
330 | { | |
a6152e39 DM |
331 | *isfile = 1; |
332 | ||
4a6afc88 | 333 | if (link_info.relocateable == true && config.build_constructors == true) |
a6152e39 | 334 | return "ldscripts/${EMULATION_NAME}.xu"; |
4a6afc88 | 335 | else if (link_info.relocateable == true) |
a6152e39 DM |
336 | return "ldscripts/${EMULATION_NAME}.xr"; |
337 | else if (!config.text_read_only) | |
338 | return "ldscripts/${EMULATION_NAME}.xbn"; | |
339 | else if (!config.magic_demand_paged) | |
340 | return "ldscripts/${EMULATION_NAME}.xn"; | |
341 | else | |
342 | return "ldscripts/${EMULATION_NAME}.x"; | |
343 | } | |
344 | EOF | |
8ddef552 | 345 | |
a6152e39 | 346 | fi |
8ddef552 | 347 | |
a6152e39 | 348 | cat >>em_${EMULATION_NAME}.c <<EOF |
8ddef552 | 349 | |
d4e5e3c3 | 350 | struct ld_emulation_xfer_struct ld_hppaelf_emulation = |
8ddef552 | 351 | { |
d4e5e3c3 | 352 | hppaelf_before_parse, |
8ddef552 DM |
353 | syslib_default, |
354 | hll_default, | |
355 | after_parse_default, | |
356 | after_allocation_default, | |
d4e5e3c3 | 357 | hppaelf_set_output_arch, |
8ddef552 DM |
358 | ldemul_default_target, |
359 | before_allocation_default, | |
d4e5e3c3 DM |
360 | hppaelf_get_script, |
361 | "hppaelf", | |
9d9d72fc | 362 | "elf32-hppa", |
d4e5e3c3 DM |
363 | hppaelf_finish, |
364 | hppaelf_create_output_section_statements | |
8ddef552 DM |
365 | }; |
366 | EOF |