OLD | NEW |
1 /* Renesas / SuperH specific support for Symbian 32-bit ELF files | 1 /* Renesas / SuperH specific support for Symbian 32-bit ELF files |
2 Copyright 2004, 2005, 2006, 2007, 2008 | 2 Copyright 2004, 2005, 2006, 2007, 2008 |
3 Free Software Foundation, Inc. | 3 Free Software Foundation, Inc. |
4 Contributed by Red Hat | 4 Contributed by Red Hat |
5 | 5 |
6 This file is part of BFD, the Binary File Descriptor library. | 6 This file is part of BFD, the Binary File Descriptor library. |
7 | 7 |
8 This program is free software; you can redistribute it and/or modify | 8 This program is free software; you can redistribute it and/or modify |
9 it under the terms of the GNU General Public License as published by | 9 it under the terms of the GNU General Public License as published by |
10 the Free Software Foundation; either version 3 of the License, or | 10 the Free Software Foundation; either version 3 of the License, or |
11 (at your option) any later version. | 11 (at your option) any later version. |
12 | 12 |
13 This program is distributed in the hope that it will be useful, | 13 This program is distributed in the hope that it will be useful, |
14 but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 GNU General Public License for more details. | 16 GNU General Public License for more details. |
17 | 17 |
18 You should have received a copy of the GNU General Public License | 18 You should have received a copy of the GNU General Public License |
19 along with this program; if not, write to the Free Software | 19 along with this program; if not, write to the Free Software |
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, | 20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
21 MA 02110-1301, USA. */ | 21 MA 02110-1301, USA. */ |
22 | 22 |
23 | 23 |
24 /* Stop elf32-sh.c from defining any target vectors. */ | 24 /* Stop elf32-sh.c from defining any target vectors. */ |
25 #define SH_TARGET_ALREADY_DEFINED | 25 #define SH_TARGET_ALREADY_DEFINED |
26 #define sh_find_elf_flags sh_symbian_find_elf_flags | 26 #define sh_find_elf_flags sh_symbian_find_elf_flags |
27 #define sh_elf_get_flags_from_mach sh_symbian_elf_get_flags_from_mach | 27 #define sh_elf_get_flags_from_mach sh_symbian_elf_get_flags_from_mach |
28 #include "elf32-sh.c" | 28 #include "elf32-sh.c" |
29 | 29 |
30 | 30 |
31 //#define SYMBIAN_DEBUG 1 | 31 //#define SYMBIAN_DEBUG 1 |
32 #define SYMBIAN_DEBUG 0 | 32 #define SYMBIAN_DEBUG 0 |
33 | 33 |
34 #define DIRECTIVE_HEADER "#<SYMEDIT>#\n" | 34 #define DIRECTIVE_HEADER "#<SYMEDIT>#\n" |
35 #define DIRECTIVE_IMPORT "IMPORT " | 35 #define DIRECTIVE_IMPORT "IMPORT " |
36 #define DIRECTIVE_EXPORT "EXPORT " | 36 #define DIRECTIVE_EXPORT "EXPORT " |
37 #define DIRECTIVE_AS "AS " | 37 #define DIRECTIVE_AS "AS " |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 for (node = rename_list; node; node = node->next) | 122 for (node = rename_list; node; node = node->next) |
123 if (strcmp (node->current_name, current_name) == 0) | 123 if (strcmp (node->current_name, current_name) == 0) |
124 { | 124 { |
125 if (strcmp (node->new_name, new_name) == 0) | 125 if (strcmp (node->new_name, new_name) == 0) |
126 /* Already added to rename list. */ | 126 /* Already added to rename list. */ |
127 return TRUE; | 127 return TRUE; |
128 | 128 |
129 bfd_set_error (bfd_error_invalid_operation); | 129 bfd_set_error (bfd_error_invalid_operation); |
130 _bfd_error_handler (_("%B: IMPORT AS directive for %s conceals previous
IMPORT AS"), | 130 _bfd_error_handler (_("%B: IMPORT AS directive for %s conceals previous
IMPORT AS"), |
131 abfd, current_name); | 131 abfd, current_name); |
132 » return FALSE;» | 132 » return FALSE; |
133 } | 133 } |
134 | 134 |
135 if ((node = bfd_malloc (sizeof * node)) == NULL) | 135 if ((node = bfd_malloc (sizeof * node)) == NULL) |
136 { | 136 { |
137 if (SYMBIAN_DEBUG) | 137 if (SYMBIAN_DEBUG) |
138 fprintf (stderr, "IMPORT AS: No mem for new rename node\n"); | 138 fprintf (stderr, "IMPORT AS: No mem for new rename node\n"); |
139 return FALSE; | 139 return FALSE; |
140 } | 140 } |
141 | 141 |
142 if ((node->current_name = bfd_malloc (strlen (current_name) + 1)) == NULL) | 142 if ((node->current_name = bfd_malloc (strlen (current_name) + 1)) == NULL) |
143 { | 143 { |
144 if (SYMBIAN_DEBUG) | 144 if (SYMBIAN_DEBUG) |
145 fprintf (stderr, "IMPORT AS: No mem for current name field in rename nod
e\n"); | 145 fprintf (stderr, "IMPORT AS: No mem for current name field in rename nod
e\n"); |
146 free (node); | 146 free (node); |
147 return FALSE; | 147 return FALSE; |
148 } | 148 } |
149 else | 149 else |
150 strcpy (node->current_name, current_name); | 150 strcpy (node->current_name, current_name); |
151 | 151 |
152 if ((node->new_name = bfd_malloc (strlen (new_name) + 1)) == NULL) | 152 if ((node->new_name = bfd_malloc (strlen (new_name) + 1)) == NULL) |
153 { | 153 { |
154 if (SYMBIAN_DEBUG) | 154 if (SYMBIAN_DEBUG) |
155 fprintf (stderr, "IMPORT AS: No mem for new name field in rename node\n"
); | 155 fprintf (stderr, "IMPORT AS: No mem for new name field in rename node\n"
); |
156 free (node->current_name); | 156 free (node->current_name); |
157 free (node); | 157 free (node); |
158 return FALSE; | 158 return FALSE; |
159 } | 159 } |
160 else | 160 else |
161 strcpy (node->new_name, new_name); | 161 strcpy (node->new_name, new_name); |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 default: | 371 default: |
372 result = FALSE; | 372 result = FALSE; |
373 break; | 373 break; |
374 } | 374 } |
375 | 375 |
376 if (! result) | 376 if (! result) |
377 { | 377 { |
378 if (SYMBIAN_DEBUG) | 378 if (SYMBIAN_DEBUG) |
379 fprintf (stderr, "offset into .directive section: %ld\n", | 379 fprintf (stderr, "offset into .directive section: %ld\n", |
380 (long) (directive - (char *) contents)); | 380 (long) (directive - (char *) contents)); |
381 » | 381 |
382 bfd_set_error (bfd_error_invalid_operation); | 382 bfd_set_error (bfd_error_invalid_operation); |
383 _bfd_error_handler (_("%B: Unrecognised .directive command: %s"), | 383 _bfd_error_handler (_("%B: Unrecognised .directive command: %s"), |
384 abfd, directive); | 384 abfd, directive); |
385 break; | 385 break; |
386 } | 386 } |
387 } | 387 } |
388 | 388 |
389 return result; | 389 return result; |
390 } | 390 } |
391 | 391 |
(...skipping 10 matching lines...) Expand all Loading... |
402 bfd_size_type sz; | 402 bfd_size_type sz; |
403 | 403 |
404 if (!sec) | 404 if (!sec) |
405 return TRUE; | 405 return TRUE; |
406 | 406 |
407 sz = sec->rawsize ? sec->rawsize : sec->size; | 407 sz = sec->rawsize ? sec->rawsize : sec->size; |
408 contents = bfd_malloc (sz); | 408 contents = bfd_malloc (sz); |
409 | 409 |
410 if (!contents) | 410 if (!contents) |
411 bfd_set_error (bfd_error_no_memory); | 411 bfd_set_error (bfd_error_no_memory); |
412 else | 412 else |
413 { | 413 { |
414 if (bfd_get_section_contents (abfd, sec, contents, 0, sz)) | 414 if (bfd_get_section_contents (abfd, sec, contents, 0, sz)) |
415 result = sh_symbian_process_embedded_commands (info, abfd, sec, contents
); | 415 result = sh_symbian_process_embedded_commands (info, abfd, sec, contents
); |
416 free (contents); | 416 free (contents); |
417 } | 417 } |
418 | 418 |
419 return result; | 419 return result; |
420 } | 420 } |
421 | 421 |
422 /* Intercept the normal sh_relocate_section() function | 422 /* Intercept the normal sh_relocate_section() function |
(...skipping 14 matching lines...) Expand all Loading... |
437 { | 437 { |
438 Elf_Internal_Rela * rel; | 438 Elf_Internal_Rela * rel; |
439 Elf_Internal_Rela * relend; | 439 Elf_Internal_Rela * relend; |
440 Elf_Internal_Shdr * symtab_hdr; | 440 Elf_Internal_Shdr * symtab_hdr; |
441 struct elf_link_hash_entry ** sym_hashes; | 441 struct elf_link_hash_entry ** sym_hashes; |
442 struct elf_link_hash_entry ** sym_hashes_end; | 442 struct elf_link_hash_entry ** sym_hashes_end; |
443 struct elf_link_hash_table * hash_table; | 443 struct elf_link_hash_table * hash_table; |
444 symbol_rename * ptr; | 444 symbol_rename * ptr; |
445 bfd_size_type num_global_syms; | 445 bfd_size_type num_global_syms; |
446 unsigned long num_local_syms; | 446 unsigned long num_local_syms; |
447 | 447 |
448 BFD_ASSERT (! elf_bad_symtab (input_bfd)); | 448 BFD_ASSERT (! elf_bad_symtab (input_bfd)); |
449 | 449 |
450 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; | 450 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; |
451 hash_table = elf_hash_table (info); | 451 hash_table = elf_hash_table (info); |
452 num_local_syms = symtab_hdr->sh_info; | 452 num_local_syms = symtab_hdr->sh_info; |
453 num_global_syms = symtab_hdr->sh_size / sizeof (Elf32_External_Sym); | 453 num_global_syms = symtab_hdr->sh_size / sizeof (Elf32_External_Sym); |
454 num_global_syms -= num_local_syms; | 454 num_global_syms -= num_local_syms; |
455 sym_hashes = elf_sym_hashes (input_bfd); | 455 sym_hashes = elf_sym_hashes (input_bfd); |
456 sym_hashes_end = sym_hashes + num_global_syms; | 456 sym_hashes_end = sym_hashes + num_global_syms; |
457 | 457 |
458 /* First scan the rename table, caching the hash entry and the new index.
*/ | 458 /* First scan the rename table, caching the hash entry and the new index.
*/ |
459 for (ptr = rename_list; ptr; ptr = ptr->next) | 459 for (ptr = rename_list; ptr; ptr = ptr->next) |
460 { | 460 { |
461 struct elf_link_hash_entry * new_hash; | 461 struct elf_link_hash_entry * new_hash; |
462 struct elf_link_hash_entry ** h; | 462 struct elf_link_hash_entry ** h; |
463 | 463 |
464 ptr->current_hash = elf_link_hash_lookup (hash_table, ptr->current_nam
e, FALSE, FALSE, TRUE); | 464 ptr->current_hash = elf_link_hash_lookup (hash_table, ptr->current_nam
e, FALSE, FALSE, TRUE); |
465 | 465 |
466 if (ptr->current_hash == NULL) | 466 if (ptr->current_hash == NULL) |
467 { | 467 { |
468 if (SYMBIAN_DEBUG) | 468 if (SYMBIAN_DEBUG) |
469 fprintf (stderr, "IMPORT AS: current symbol '%s' does not exist\
n", ptr->current_name); | 469 fprintf (stderr, "IMPORT AS: current symbol '%s' does not exist\
n", ptr->current_name); |
470 continue; | 470 continue; |
471 } | 471 } |
472 | |
473 new_hash = elf_link_hash_lookup (hash_table, ptr->new_name, FALSE, FAL
SE, TRUE); | |
474 | 472 |
| 473 new_hash = elf_link_hash_lookup (hash_table, ptr->new_name, |
| 474 FALSE, FALSE, TRUE); |
475 /* If we could not find the symbol then it is a new, undefined symbol. | 475 /* If we could not find the symbol then it is a new, undefined symbol. |
476 Symbian want this behaviour - ie they want to be able to rename the | 476 Symbian want this behaviour - ie they want to be able to rename the |
477 reference in a reloc from one undefined symbol to another, new and | 477 reference in a reloc from one undefined symbol to another, new and |
478 undefined symbol. So we create that symbol here. */ | 478 undefined symbol. So we create that symbol here. */ |
479 if (new_hash == NULL) | 479 if (new_hash == NULL) |
480 { | 480 { |
481 » asection * psec = bfd_und_section_ptr; | 481 » struct bfd_link_hash_entry *bh = NULL; |
482 » Elf_Internal_Sym new_sym; | 482 » bfd_boolean collect = get_elf_backend_data (input_bfd)->collect; |
483 » bfd_vma new_value = 0; | 483 » if (_bfd_generic_link_add_one_symbol (info, input_bfd, |
484 » bfd_boolean skip; | 484 » » » » » » ptr->new_name, BSF_GLOBAL, |
485 » bfd_boolean override; | 485 » » » » » » bfd_und_section_ptr, 0, |
486 » bfd_boolean type_change_ok; | 486 » » » » » » NULL, FALSE, collect, |
487 » bfd_boolean size_change_ok; | 487 » » » » » » &bh)) |
| 488 » » { |
| 489 » » new_hash = (struct elf_link_hash_entry *) bh; |
| 490 » » new_hash->type = STT_FUNC; |
| 491 » » new_hash->non_elf = 0; |
488 | 492 |
489 » new_sym.st_value = 0; | 493 » » if (SYMBIAN_DEBUG) |
490 » new_sym.st_size = 0; | 494 » » fprintf (stderr, "Created new symbol %s\n", ptr->new_name); |
491 » new_sym.st_name = -1; | 495 » » } |
492 » new_sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_FUNC); | 496 » } |
493 » new_sym.st_other = ELF_ST_VISIBILITY (STV_DEFAULT); | |
494 » new_sym.st_shndx = SHN_UNDEF; | |
495 » new_sym.st_target_internal = 0; | |
496 | 497 |
497 » if (! _bfd_elf_merge_symbol (input_bfd, info, | 498 » if (new_hash == NULL) |
498 » » » » » ptr->new_name, & new_sym, | 499 » { |
499 » » » » » & psec, & new_value, NULL, | 500 » _bfd_error_handler (_("%B: Failed to add renamed symbol %s"), |
500 » » » » » & new_hash, & skip, | 501 » » » » input_bfd, ptr->new_name); |
501 » » » » » & override, & type_change_ok, | 502 » continue; |
502 » » » » » & size_change_ok)) | |
503 » » { | |
504 » » _bfd_error_handler (_("%B: Failed to add renamed symbol %s"), | |
505 » » » » input_bfd, ptr->new_name); | |
506 » » continue; | |
507 » » } | |
508 » /* XXX - should we check psec, skip, override etc ? */ | |
509 | |
510 » new_hash->root.type = bfd_link_hash_undefined; | |
511 | |
512 » /* Allow the symbol to become local if necessary. */ | |
513 » if (new_hash->dynindx == -1) | |
514 » » new_hash->def_regular = 1; | |
515 | |
516 » if (SYMBIAN_DEBUG) | |
517 » » fprintf (stderr, "Created new symbol %s\n", ptr->new_name); | |
518 } | 503 } |
519 | 504 |
520 /* Convert the new_hash value into a index into the table of symbol ha
shes. */ | 505 /* Convert the new_hash value into a index into the table of symbol ha
shes. */ |
521 for (h = sym_hashes; h < sym_hashes_end; h ++) | 506 for (h = sym_hashes; h < sym_hashes_end; h ++) |
522 { | 507 { |
523 if (* h == new_hash) | 508 if (* h == new_hash) |
524 { | 509 { |
525 ptr->new_symndx = h - sym_hashes + num_local_syms; | 510 ptr->new_symndx = h - sym_hashes + num_local_syms; |
526 if (SYMBIAN_DEBUG) | 511 if (SYMBIAN_DEBUG) |
527 fprintf (stderr, "Converted new hash to index of %ld\n", ptr
->new_symndx); | 512 fprintf (stderr, "Converted new hash to index of %ld\n", ptr
->new_symndx); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
561 | 546 |
562 /* Walk the reloc list looking for references to renamed symbols. | 547 /* Walk the reloc list looking for references to renamed symbols. |
563 When we find one, we alter the index in the reloc to point to the new s
ymbol. */ | 548 When we find one, we alter the index in the reloc to point to the new s
ymbol. */ |
564 for (rel = relocs, relend = relocs + input_section->reloc_count; | 549 for (rel = relocs, relend = relocs + input_section->reloc_count; |
565 rel < relend; | 550 rel < relend; |
566 rel ++) | 551 rel ++) |
567 { | 552 { |
568 int r_type; | 553 int r_type; |
569 unsigned long r_symndx; | 554 unsigned long r_symndx; |
570 struct elf_link_hash_entry * h; | 555 struct elf_link_hash_entry * h; |
571 | 556 |
572 r_symndx = ELF32_R_SYM (rel->r_info); | 557 r_symndx = ELF32_R_SYM (rel->r_info); |
573 r_type = ELF32_R_TYPE (rel->r_info); | 558 r_type = ELF32_R_TYPE (rel->r_info); |
574 | 559 |
575 /* Ignore unused relocs. */ | 560 /* Ignore unused relocs. */ |
576 if ((r_type >= (int) R_SH_GNU_VTINHERIT | 561 if ((r_type >= (int) R_SH_GNU_VTINHERIT |
577 && r_type <= (int) R_SH_LABEL) | 562 && r_type <= (int) R_SH_LABEL) |
578 || r_type == (int) R_SH_NONE | 563 || r_type == (int) R_SH_NONE |
579 || r_type < 0 | 564 || r_type < 0 |
580 || r_type >= R_SH_max) | 565 || r_type >= R_SH_max) |
581 continue; | 566 continue; |
(...skipping 23 matching lines...) Expand all Loading... |
605 BFD_ASSERT (ptr->new_symndx); | 590 BFD_ASSERT (ptr->new_symndx); |
606 if (SYMBIAN_DEBUG) | 591 if (SYMBIAN_DEBUG) |
607 fprintf (stderr, "convert reloc %lx from using index %ld to us
ing index %ld\n", | 592 fprintf (stderr, "convert reloc %lx from using index %ld to us
ing index %ld\n", |
608 (unsigned long) rel->r_info, | 593 (unsigned long) rel->r_info, |
609 (long) ELF32_R_SYM (rel->r_info), ptr->new_symndx); | 594 (long) ELF32_R_SYM (rel->r_info), ptr->new_symndx); |
610 rel->r_info = ELF32_R_INFO (ptr->new_symndx, r_type); | 595 rel->r_info = ELF32_R_INFO (ptr->new_symndx, r_type); |
611 break; | 596 break; |
612 } | 597 } |
613 } | 598 } |
614 } | 599 } |
615 | 600 |
616 return sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, | 601 return sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, |
617 contents, relocs, local_syms, local_sections); | 602 contents, relocs, local_syms, local_sections); |
618 } | 603 } |
619 | 604 |
620 #define TARGET_LITTLE_SYM bfd_elf32_shl_symbian_vec | 605 #define TARGET_LITTLE_SYM bfd_elf32_shl_symbian_vec |
621 #define TARGET_LITTLE_NAME "elf32-shl-symbian" | 606 #define TARGET_LITTLE_NAME "elf32-shl-symbian" |
622 | 607 |
623 #undef elf_backend_relocate_section | 608 #undef elf_backend_relocate_section |
624 #define elf_backend_relocate_section sh_symbian_relocate_section | 609 #define elf_backend_relocate_section sh_symbian_relocate_section |
625 #undef elf_backend_check_directives | 610 #undef elf_backend_check_directives |
626 #define elf_backend_check_directives sh_symbian_process_directives | 611 #define elf_backend_check_directives sh_symbian_process_directives |
627 | 612 |
628 #include "elf32-target.h" | 613 #include "elf32-target.h" |
OLD | NEW |