Commit | Line | Data |
---|---|---|
252b5132 RH |
1 | # This shell script emits a C file. -*- C -*- |
2 | # It does some substitutions. | |
3 | cat >e${EMULATION_NAME}.c <<EOF | |
4900fc06 AM |
4 | /* This file is is generated by a shell script. DO NOT EDIT! */ |
5 | ||
252b5132 | 6 | /* An emulation for HP PA-RISC ELF linkers. |
4900fc06 AM |
7 | Copyright (C) 1991, 93, 94, 95, 97, 99, 2000 |
8 | Free Software Foundation, Inc. | |
252b5132 RH |
9 | Written by Steve Chamberlain steve@cygnus.com |
10 | ||
11 | This file is part of GLD, the Gnu Linker. | |
12 | ||
13 | This program is free software; you can redistribute it and/or modify | |
14 | it under the terms of the GNU General Public License as published by | |
15 | the Free Software Foundation; either version 2 of the License, or | |
16 | (at your option) any later version. | |
17 | ||
18 | This program is distributed in the hope that it will be useful, | |
19 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 | GNU General Public License for more details. | |
22 | ||
23 | You should have received a copy of the GNU General Public License | |
24 | along with this program; if not, write to the Free Software | |
25 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
26 | ||
27 | #include "bfd.h" | |
28 | #include "sysdep.h" | |
4900fc06 | 29 | #include <ctype.h> |
252b5132 RH |
30 | #include "bfdlink.h" |
31 | ||
32 | #include "ld.h" | |
4900fc06 | 33 | #include "ldmain.h" |
4900fc06 | 34 | #include "ldmisc.h" |
252b5132 RH |
35 | #include "ldexp.h" |
36 | #include "ldlang.h" | |
b71e2778 AM |
37 | #include "ldfile.h" |
38 | #include "ldemul.h" | |
4900fc06 | 39 | #include "ldgram.h" |
252b5132 | 40 | #include "ldctor.h" |
4900fc06 | 41 | #include "elf32-hppa.h" |
252b5132 | 42 | |
4900fc06 AM |
43 | static void hppaelf_before_parse PARAMS ((void)); |
44 | static void hppaelf_set_output_arch PARAMS ((void)); | |
45 | static void hppaelf_create_output_section_statements PARAMS ((void)); | |
46 | static void hppaelf_delete_padding_statements | |
47 | PARAMS ((lang_statement_list_type *list)); | |
48 | static void hppaelf_finish PARAMS ((void)); | |
49 | static boolean gld${EMULATION_NAME}_place_orphan | |
50 | PARAMS ((lang_input_statement_type *, asection *)); | |
51 | static lang_output_section_statement_type *output_rel_find PARAMS ((void)); | |
52 | static char *hppaelf_get_script PARAMS ((int *)); | |
252b5132 RH |
53 | |
54 | ||
4900fc06 AM |
55 | /* Fake input file for stubs. */ |
56 | static lang_input_statement_type *stub_file; | |
252b5132 RH |
57 | |
58 | /* Perform some emulation specific initialization. For PA ELF we set | |
59 | up the local label prefix and the output architecture. */ | |
60 | ||
61 | static void | |
62 | hppaelf_before_parse () | |
63 | { | |
64 | ldfile_output_architecture = bfd_arch_hppa; | |
65 | } | |
66 | ||
67 | /* Set the output architecture and machine. */ | |
68 | ||
69 | static void | |
70 | hppaelf_set_output_arch() | |
71 | { | |
72 | unsigned long machine = 0; | |
73 | ||
74 | bfd_set_arch_mach (output_bfd, ldfile_output_architecture, machine); | |
75 | } | |
76 | ||
77 | /* This is called before the input files are opened. We create a new | |
4900fc06 | 78 | fake input file to hold the stub sections. */ |
252b5132 RH |
79 | |
80 | static void | |
81 | hppaelf_create_output_section_statements () | |
82 | { | |
83 | stub_file = lang_add_input_file ("linker stubs", | |
84 | lang_input_file_is_fake_enum, | |
85 | NULL); | |
86 | stub_file->the_bfd = bfd_create ("linker stubs", output_bfd); | |
87 | if (stub_file->the_bfd == NULL | |
88 | || ! bfd_set_arch_mach (stub_file->the_bfd, | |
89 | bfd_get_arch (output_bfd), | |
90 | bfd_get_mach (output_bfd))) | |
91 | { | |
92 | einfo ("%X%P: can not create BFD %E\n"); | |
93 | return; | |
94 | } | |
95 | ||
252b5132 RH |
96 | ldlang_add_file (stub_file); |
97 | } | |
98 | ||
4900fc06 | 99 | /* Walk all the lang statements splicing out any padding statements from |
252b5132 RH |
100 | the list. */ |
101 | ||
102 | static void | |
4900fc06 AM |
103 | hppaelf_delete_padding_statements (list) |
104 | lang_statement_list_type *list; | |
252b5132 | 105 | { |
4900fc06 AM |
106 | lang_statement_union_type *s; |
107 | lang_statement_union_type **ps; | |
108 | for (ps = &list->head; (s = *ps) != NULL; ps = &s->next) | |
252b5132 RH |
109 | { |
110 | switch (s->header.type) | |
111 | { | |
112 | ||
4900fc06 | 113 | /* We want to recursively walk these sections. */ |
252b5132 | 114 | case lang_constructors_statement_enum: |
4900fc06 | 115 | hppaelf_delete_padding_statements (&constructor_list); |
252b5132 RH |
116 | break; |
117 | ||
118 | case lang_output_section_statement_enum: | |
4900fc06 AM |
119 | hppaelf_delete_padding_statements (&s->output_section_statement.children); |
120 | break; | |
121 | ||
122 | case lang_group_statement_enum: | |
123 | hppaelf_delete_padding_statements (&s->group_statement.children); | |
252b5132 RH |
124 | break; |
125 | ||
252b5132 | 126 | case lang_wild_statement_enum: |
4900fc06 | 127 | hppaelf_delete_padding_statements (&s->wild_statement.children); |
252b5132 RH |
128 | break; |
129 | ||
130 | /* Here's what we are really looking for. Splice these out of | |
131 | the list. */ | |
132 | case lang_padding_statement_enum: | |
4900fc06 AM |
133 | *ps = s->next; |
134 | if (*ps == NULL) | |
135 | list->tail = ps; | |
252b5132 RH |
136 | break; |
137 | ||
138 | /* We don't care about these cases. */ | |
139 | case lang_data_statement_enum: | |
140 | case lang_object_symbols_statement_enum: | |
141 | case lang_output_statement_enum: | |
142 | case lang_target_statement_enum: | |
143 | case lang_input_section_enum: | |
144 | case lang_input_statement_enum: | |
145 | case lang_assignment_statement_enum: | |
146 | case lang_address_statement_enum: | |
147 | break; | |
148 | ||
149 | default: | |
150 | abort (); | |
151 | break; | |
152 | } | |
252b5132 RH |
153 | } |
154 | } | |
155 | ||
4900fc06 AM |
156 | |
157 | struct hook_stub_info | |
158 | { | |
159 | lang_statement_list_type add; | |
160 | asection *input_section; | |
161 | }; | |
162 | ||
163 | /* Traverse the linker tree to find the spot where the stub goes. */ | |
164 | ||
165 | static boolean | |
166 | hook_in_stub (info, lp) | |
167 | struct hook_stub_info *info; | |
168 | lang_statement_union_type **lp; | |
169 | { | |
170 | lang_statement_union_type *l; | |
171 | boolean ret; | |
172 | ||
173 | for (; (l = *lp) != NULL; lp = &l->next) | |
174 | { | |
175 | switch (l->header.type) | |
176 | { | |
177 | case lang_constructors_statement_enum: | |
178 | ret = hook_in_stub (info, &constructor_list.head); | |
179 | if (ret) | |
180 | return ret; | |
181 | break; | |
182 | ||
183 | case lang_output_section_statement_enum: | |
184 | ret = hook_in_stub (info, | |
185 | &l->output_section_statement.children.head); | |
186 | if (ret) | |
187 | return ret; | |
188 | break; | |
189 | ||
190 | case lang_wild_statement_enum: | |
191 | ret = hook_in_stub (info, &l->wild_statement.children.head); | |
192 | if (ret) | |
193 | return ret; | |
194 | break; | |
195 | ||
196 | case lang_group_statement_enum: | |
197 | ret = hook_in_stub (info, &l->group_statement.children.head); | |
198 | if (ret) | |
199 | return ret; | |
200 | break; | |
201 | ||
202 | case lang_input_section_enum: | |
203 | if (l->input_section.section == info->input_section) | |
204 | { | |
205 | /* We've found our section. Insert the stub immediately | |
206 | before its associated input section. */ | |
207 | *lp = info->add.head; | |
208 | *(info->add.tail) = l; | |
209 | return true; | |
210 | } | |
211 | break; | |
212 | ||
213 | case lang_data_statement_enum: | |
214 | case lang_reloc_statement_enum: | |
215 | case lang_object_symbols_statement_enum: | |
216 | case lang_output_statement_enum: | |
217 | case lang_target_statement_enum: | |
218 | case lang_input_statement_enum: | |
219 | case lang_assignment_statement_enum: | |
220 | case lang_padding_statement_enum: | |
221 | case lang_address_statement_enum: | |
222 | case lang_fill_statement_enum: | |
223 | break; | |
224 | ||
225 | default: | |
226 | FAIL (); | |
227 | break; | |
228 | } | |
229 | } | |
230 | return false; | |
231 | } | |
232 | ||
233 | /* Call-back for elf32_hppa_size_stubs. */ | |
234 | ||
235 | /* Create a new stub section, and arrange for it to be linked | |
236 | immediately before INPUT_SECTION. */ | |
237 | ||
238 | static asection * | |
239 | hppaelf_add_stub_section (stub_name, input_section) | |
240 | const char *stub_name; | |
241 | asection *input_section; | |
242 | { | |
243 | asection *stub_sec; | |
244 | flagword flags; | |
245 | asection *output_section; | |
246 | const char *secname; | |
247 | lang_output_section_statement_type *os; | |
248 | struct hook_stub_info info; | |
249 | ||
250 | stub_sec = bfd_make_section_anyway (stub_file->the_bfd, stub_name); | |
251 | if (stub_sec == NULL) | |
252 | goto err_ret; | |
253 | ||
254 | flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | |
255 | | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_KEEP); | |
256 | if (!bfd_set_section_flags (stub_file->the_bfd, stub_sec, flags)) | |
257 | goto err_ret; | |
258 | ||
259 | output_section = input_section->output_section; | |
260 | secname = bfd_get_section_name (output_section->owner, output_section); | |
261 | os = lang_output_section_find (secname); | |
262 | ||
263 | info.input_section = input_section; | |
264 | lang_list_init (&info.add); | |
265 | wild_doit (&info.add, stub_sec, os, stub_file); | |
266 | ||
267 | if (info.add.head == NULL) | |
268 | goto err_ret; | |
269 | ||
270 | if (hook_in_stub (&info, &os->children.head)) | |
271 | return stub_sec; | |
272 | ||
273 | err_ret: | |
274 | einfo ("%X%P: can not make stub section: %E\n"); | |
275 | return NULL; | |
276 | } | |
277 | ||
278 | /* Another call-back for elf32_hppa_size_stubs. */ | |
279 | ||
280 | static void | |
281 | hppaelf_layaout_sections_again () | |
282 | { | |
283 | /* If we have changed sizes of the stub sections, then we need | |
284 | to recalculate all the section offsets. This may mean we need to | |
285 | add even more stubs. */ | |
286 | ||
287 | /* Delete all the padding statements, they're no longer valid. */ | |
288 | hppaelf_delete_padding_statements (stat_ptr); | |
289 | ||
290 | /* Resize the sections. */ | |
291 | lang_size_sections (stat_ptr->head, abs_output_section, | |
292 | &stat_ptr->head, 0, (bfd_vma) 0, false); | |
293 | ||
294 | /* Redo special stuff. */ | |
295 | ldemul_after_allocation (); | |
296 | ||
297 | /* Do the assignments again. */ | |
298 | lang_do_assignments (stat_ptr->head, abs_output_section, | |
299 | (fill_type) 0, (bfd_vma) 0); | |
300 | } | |
301 | ||
302 | ||
252b5132 RH |
303 | /* Final emulation specific call. For the PA we use this opportunity |
304 | to build linker stubs. */ | |
305 | ||
306 | static void | |
307 | hppaelf_finish () | |
308 | { | |
4900fc06 AM |
309 | /* If generating a relocateable output file, then we don't |
310 | have to examine the relocs. */ | |
311 | if (link_info.relocateable) | |
312 | return; | |
313 | ||
252b5132 | 314 | /* Call into the BFD backend to do the real work. */ |
4900fc06 AM |
315 | if (elf32_hppa_size_stubs (stub_file->the_bfd, |
316 | &link_info, | |
317 | &hppaelf_add_stub_section, | |
318 | &hppaelf_layaout_sections_again) == false) | |
252b5132 RH |
319 | { |
320 | einfo ("%X%P: can not size stub section: %E\n"); | |
321 | return; | |
322 | } | |
4900fc06 AM |
323 | |
324 | /* Now build the linker stubs. */ | |
325 | if (stub_file->the_bfd->sections != NULL) | |
252b5132 | 326 | { |
252b5132 | 327 | if (elf32_hppa_build_stubs (stub_file->the_bfd, &link_info) == false) |
4900fc06 AM |
328 | einfo ("%X%P: can not build stubs: %E\n"); |
329 | } | |
330 | } | |
331 | ||
332 | ||
333 | /* Place an orphan section. We use this to put random SHF_ALLOC | |
334 | sections in the right segment. */ | |
335 | ||
336 | struct orphan_save | |
337 | { | |
338 | lang_output_section_statement_type *os; | |
339 | asection **section; | |
340 | lang_statement_union_type **stmt; | |
341 | }; | |
342 | ||
343 | /*ARGSUSED*/ | |
344 | static boolean | |
345 | gld${EMULATION_NAME}_place_orphan (file, s) | |
346 | lang_input_statement_type *file; | |
347 | asection *s; | |
348 | { | |
349 | static struct orphan_save hold_text; | |
350 | static struct orphan_save hold_rodata; | |
351 | static struct orphan_save hold_data; | |
352 | static struct orphan_save hold_bss; | |
353 | static struct orphan_save hold_rel; | |
354 | static struct orphan_save hold_interp; | |
355 | struct orphan_save *place; | |
356 | lang_statement_list_type *old; | |
357 | lang_statement_list_type add; | |
358 | etree_type *address; | |
359 | const char *secname, *ps; | |
360 | const char *outsecname; | |
361 | lang_output_section_statement_type *os; | |
362 | ||
363 | secname = bfd_get_section_name (s->owner, s); | |
364 | ||
365 | /* Look through the script to see where to place this section. */ | |
366 | os = lang_output_section_find (secname); | |
367 | ||
368 | if (os != NULL | |
369 | && os->bfd_section != NULL | |
370 | && ((s->flags ^ os->bfd_section->flags) & (SEC_LOAD | SEC_ALLOC)) == 0) | |
371 | { | |
372 | /* We have already placed a section with this name. */ | |
373 | wild_doit (&os->children, s, os, file); | |
374 | return true; | |
375 | } | |
376 | ||
377 | if (hold_text.os == NULL) | |
378 | hold_text.os = lang_output_section_find (".text"); | |
379 | ||
380 | /* If this is a final link, then always put .gnu.warning.SYMBOL | |
381 | sections into the .text section to get them out of the way. */ | |
382 | if (! link_info.shared | |
383 | && ! link_info.relocateable | |
384 | && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0 | |
385 | && hold_text.os != NULL) | |
386 | { | |
387 | wild_doit (&hold_text.os->children, s, hold_text.os, file); | |
388 | return true; | |
389 | } | |
390 | ||
391 | /* Decide which segment the section should go in based on the | |
392 | section name and section flags. We put loadable .note sections | |
393 | right after the .interp section, so that the PT_NOTE segment is | |
394 | stored right after the program headers where the OS can read it | |
395 | in the first page. */ | |
396 | #define HAVE_SECTION(hold, name) \ | |
397 | (hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL) | |
398 | ||
399 | if (s->flags & SEC_EXCLUDE) | |
400 | return false; | |
401 | else if ((s->flags & SEC_ALLOC) == 0) | |
402 | place = NULL; | |
403 | else if ((s->flags & SEC_LOAD) != 0 | |
404 | && strncmp (secname, ".note", 4) == 0 | |
405 | && HAVE_SECTION (hold_interp, ".interp")) | |
406 | place = &hold_interp; | |
407 | else if ((s->flags & SEC_HAS_CONTENTS) == 0 | |
408 | && HAVE_SECTION (hold_bss, ".bss")) | |
409 | place = &hold_bss; | |
410 | else if ((s->flags & SEC_READONLY) == 0 | |
411 | && HAVE_SECTION (hold_data, ".data")) | |
412 | place = &hold_data; | |
413 | else if (strncmp (secname, ".rel", 4) == 0 | |
414 | && (hold_rel.os != NULL | |
415 | || (hold_rel.os = output_rel_find ()) != NULL)) | |
416 | place = &hold_rel; | |
417 | else if ((s->flags & SEC_CODE) == 0 | |
418 | && (s->flags & SEC_READONLY) != 0 | |
419 | && HAVE_SECTION (hold_rodata, ".rodata")) | |
420 | place = &hold_rodata; | |
421 | else if ((s->flags & SEC_READONLY) != 0 | |
422 | && hold_text.os != NULL) | |
423 | place = &hold_text; | |
424 | else | |
425 | place = NULL; | |
426 | ||
427 | #undef HAVE_SECTION | |
428 | ||
429 | /* Choose a unique name for the section. This will be needed if the | |
430 | same section name appears in the input file with different | |
431 | loadable or allocateable characteristics. */ | |
432 | outsecname = secname; | |
433 | if (bfd_get_section_by_name (output_bfd, outsecname) != NULL) | |
434 | { | |
435 | unsigned int len; | |
436 | char *newname; | |
437 | unsigned int i; | |
438 | ||
439 | len = strlen (outsecname); | |
440 | newname = xmalloc (len + 5); | |
441 | strcpy (newname, outsecname); | |
442 | i = 0; | |
443 | do | |
444 | { | |
445 | sprintf (newname + len, "%d", i); | |
446 | ++i; | |
447 | } | |
448 | while (bfd_get_section_by_name (output_bfd, newname) != NULL); | |
449 | ||
450 | outsecname = newname; | |
451 | } | |
452 | ||
453 | if (place != NULL) | |
454 | { | |
455 | /* Start building a list of statements for this section. */ | |
456 | old = stat_ptr; | |
457 | stat_ptr = &add; | |
458 | lang_list_init (stat_ptr); | |
459 | ||
460 | /* If the name of the section is representable in C, then create | |
461 | symbols to mark the start and the end of the section. */ | |
462 | for (ps = outsecname; *ps != '\0'; ps++) | |
463 | if (! isalnum ((unsigned char) *ps) && *ps != '_') | |
464 | break; | |
465 | if (*ps == '\0' && config.build_constructors) | |
252b5132 | 466 | { |
4900fc06 AM |
467 | char *symname; |
468 | etree_type *e_align; | |
469 | ||
470 | symname = (char *) xmalloc (ps - outsecname + sizeof "__start_"); | |
471 | sprintf (symname, "__start_%s", outsecname); | |
472 | e_align = exp_unop (ALIGN_K, | |
473 | exp_intop ((bfd_vma) 1 << s->alignment_power)); | |
474 | lang_add_assignment (exp_assop ('=', symname, e_align)); | |
252b5132 RH |
475 | } |
476 | } | |
4900fc06 AM |
477 | |
478 | if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0) | |
479 | address = exp_intop ((bfd_vma) 0); | |
480 | else | |
481 | address = NULL; | |
482 | ||
483 | os = lang_enter_output_section_statement (outsecname, address, 0, | |
484 | (bfd_vma) 0, | |
485 | (etree_type *) NULL, | |
486 | (etree_type *) NULL, | |
487 | (etree_type *) NULL); | |
488 | ||
489 | wild_doit (&os->children, s, os, file); | |
490 | ||
491 | lang_leave_output_section_statement | |
492 | ((bfd_vma) 0, "*default*", | |
493 | (struct lang_output_section_phdr_list *) NULL, "*default*"); | |
494 | ||
495 | if (place != NULL) | |
496 | { | |
497 | asection *snew, **pps; | |
498 | ||
499 | stat_ptr = &add; | |
500 | ||
501 | if (*ps == '\0' && config.build_constructors) | |
502 | { | |
503 | char *symname; | |
504 | ||
505 | symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_"); | |
506 | sprintf (symname, "__stop_%s", outsecname); | |
507 | lang_add_assignment (exp_assop ('=', symname, | |
508 | exp_nameop (NAME, "."))); | |
509 | } | |
510 | stat_ptr = old; | |
511 | ||
512 | snew = os->bfd_section; | |
513 | if (place->os->bfd_section != NULL || place->section != NULL) | |
514 | { | |
515 | /* Shuffle the section to make the output file look neater. */ | |
516 | if (place->section == NULL) | |
517 | { | |
518 | #if 0 | |
519 | /* Finding the end of the list is a little tricky. We | |
520 | make a wild stab at it by comparing section flags. */ | |
521 | flagword first_flags = place->os->bfd_section->flags; | |
522 | for (pps = &place->os->bfd_section->next; | |
523 | *pps != NULL && (*pps)->flags == first_flags; | |
524 | pps = &(*pps)->next) | |
525 | ; | |
526 | place->section = pps; | |
527 | #else | |
528 | /* Put orphans after the first section on the list. */ | |
529 | place->section = &place->os->bfd_section->next; | |
530 | #endif | |
531 | } | |
532 | ||
533 | /* Unlink the section. */ | |
534 | for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next) | |
535 | ; | |
536 | *pps = snew->next; | |
537 | ||
538 | /* Now tack it on to the "place->os" section list. */ | |
539 | snew->next = *place->section; | |
540 | *place->section = snew; | |
541 | } | |
542 | place->section = &snew->next; /* Save the end of this list. */ | |
543 | ||
544 | if (place->stmt == NULL) | |
545 | { | |
546 | /* Put the new statement list right at the head. */ | |
547 | *add.tail = place->os->header.next; | |
548 | place->os->header.next = add.head; | |
549 | } | |
550 | else | |
551 | { | |
552 | /* Put it after the last orphan statement we added. */ | |
553 | *add.tail = *place->stmt; | |
554 | *place->stmt = add.head; | |
555 | } | |
556 | place->stmt = add.tail; /* Save the end of this list. */ | |
557 | } | |
558 | ||
559 | return true; | |
560 | } | |
561 | ||
562 | /* A variant of lang_output_section_find. */ | |
563 | static lang_output_section_statement_type * | |
564 | output_rel_find () | |
565 | { | |
566 | lang_statement_union_type *u; | |
567 | lang_output_section_statement_type *lookup; | |
568 | ||
569 | for (u = lang_output_section_statement.head; | |
570 | u != (lang_statement_union_type *) NULL; | |
571 | u = lookup->next) | |
572 | { | |
573 | lookup = &u->output_section_statement; | |
574 | if (strncmp (".rel", lookup->name, 4) == 0 | |
575 | && lookup->bfd_section != NULL | |
576 | && (lookup->bfd_section->flags & SEC_ALLOC) != 0) | |
577 | { | |
578 | return lookup; | |
579 | } | |
580 | } | |
581 | return (lang_output_section_statement_type *) NULL; | |
252b5132 RH |
582 | } |
583 | ||
584 | /* The script itself gets inserted here. */ | |
585 | ||
586 | static char * | |
587 | hppaelf_get_script(isfile) | |
588 | int *isfile; | |
589 | EOF | |
590 | ||
591 | if test -n "$COMPILE_IN" | |
592 | then | |
593 | # Scripts compiled in. | |
594 | ||
595 | # sed commands to quote an ld script as a C string. | |
597e2591 | 596 | sc="-f stringify.sed" |
252b5132 RH |
597 | |
598 | cat >>e${EMULATION_NAME}.c <<EOF | |
4900fc06 | 599 | { |
252b5132 RH |
600 | *isfile = 0; |
601 | ||
602 | if (link_info.relocateable == true && config.build_constructors == true) | |
597e2591 | 603 | return |
252b5132 | 604 | EOF |
597e2591 ILT |
605 | sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c |
606 | echo ' ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c | |
607 | sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c | |
608 | echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c | |
609 | sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c | |
610 | echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c | |
611 | sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c | |
4900fc06 AM |
612 | |
613 | if test -n "$GENERATE_SHLIB_SCRIPT" ; then | |
614 | echo ' ; else if (link_info.shared) return' >> e${EMULATION_NAME}.c | |
615 | sed $sc ldscripts/${EMULATION_NAME}.xs >> e${EMULATION_NAME}.c | |
616 | fi | |
617 | ||
597e2591 ILT |
618 | echo ' ; else return' >> e${EMULATION_NAME}.c |
619 | sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c | |
620 | echo '; }' >> e${EMULATION_NAME}.c | |
252b5132 RH |
621 | |
622 | else | |
623 | # Scripts read from the filesystem. | |
624 | ||
625 | cat >>e${EMULATION_NAME}.c <<EOF | |
626 | { | |
627 | *isfile = 1; | |
628 | ||
629 | if (link_info.relocateable == true && config.build_constructors == true) | |
630 | return "ldscripts/${EMULATION_NAME}.xu"; | |
631 | else if (link_info.relocateable == true) | |
632 | return "ldscripts/${EMULATION_NAME}.xr"; | |
633 | else if (!config.text_read_only) | |
634 | return "ldscripts/${EMULATION_NAME}.xbn"; | |
635 | else if (!config.magic_demand_paged) | |
636 | return "ldscripts/${EMULATION_NAME}.xn"; | |
4900fc06 AM |
637 | else if (link_info.shared) |
638 | return "ldscripts/${EMULATION_NAME}.xs"; | |
252b5132 RH |
639 | else |
640 | return "ldscripts/${EMULATION_NAME}.x"; | |
641 | } | |
642 | EOF | |
643 | ||
644 | fi | |
645 | ||
646 | cat >>e${EMULATION_NAME}.c <<EOF | |
647 | ||
4900fc06 | 648 | struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = |
252b5132 RH |
649 | { |
650 | hppaelf_before_parse, | |
651 | syslib_default, | |
652 | hll_default, | |
653 | after_parse_default, | |
654 | after_open_default, | |
655 | after_allocation_default, | |
656 | hppaelf_set_output_arch, | |
657 | ldemul_default_target, | |
658 | before_allocation_default, | |
659 | hppaelf_get_script, | |
4900fc06 | 660 | "${EMULATION_NAME}", |
252b5132 RH |
661 | "elf32-hppa", |
662 | hppaelf_finish, | |
663 | hppaelf_create_output_section_statements, | |
4900fc06 AM |
664 | NULL, /* open dynamic */ |
665 | gld${EMULATION_NAME}_place_orphan, | |
666 | NULL, /* set_symbols */ | |
667 | NULL, /* parse_args */ | |
668 | NULL, /* unrecognized_file */ | |
669 | NULL, /* list_options */ | |
670 | NULL, /* recognized_file */ | |
671 | NULL /* find_potential_libraries */ | |
252b5132 RH |
672 | }; |
673 | EOF |