| 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 |