X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf32-h8300.c;h=3daef62c939cc21134642eff62c171066ef04d14;hb=e22f895c475bd0d646bc4a52435fc1d1bc11e175;hp=452db27f634277634531746bb35f5c3b338d50c7;hpb=8517fae7a54a3d541aecc6be63e22d6ef5d51a66;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-h8300.c b/bfd/elf32-h8300.c index 452db27f63..3daef62c93 100644 --- a/bfd/elf32-h8300.c +++ b/bfd/elf32-h8300.c @@ -1,5 +1,5 @@ /* BFD back-end for Renesas H8/300 ELF binaries. - Copyright 1993, 1995, 1998, 1999, 2001, 2002, 2003 + Copyright 1993, 1995, 1998, 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -30,23 +30,23 @@ static void elf32_h8_info_to_howto (bfd *, arelent *, Elf_Internal_Rela *); static void elf32_h8_info_to_howto_rel (bfd *, arelent *, Elf_Internal_Rela *); -static unsigned long elf32_h8_mach - (flagword); -static void elf32_h8_final_write_processing - (bfd *, bfd_boolean); -static bfd_boolean elf32_h8_object_p - (bfd *); -static bfd_boolean elf32_h8_merge_private_bfd_data - (bfd *, bfd *); +static unsigned long elf32_h8_mach (flagword); +static void elf32_h8_final_write_processing (bfd *, bfd_boolean); +static bfd_boolean elf32_h8_object_p (bfd *); +static bfd_boolean elf32_h8_merge_private_bfd_data (bfd *, bfd *); static bfd_boolean elf32_h8_relax_section (bfd *, asection *, struct bfd_link_info *, bfd_boolean *); static bfd_boolean elf32_h8_relax_delete_bytes (bfd *, asection *, bfd_vma, int); -static bfd_boolean elf32_h8_symbol_address_p - (bfd *, asection *, bfd_vma); +static bfd_boolean elf32_h8_symbol_address_p (bfd *, asection *, bfd_vma); static bfd_byte *elf32_h8_get_relocated_section_contents (bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *, bfd_boolean, asymbol **); +static asection *elf32_h8_gc_mark_hook + (asection *, struct bfd_link_info *, Elf_Internal_Rela *, + struct elf_link_hash_entry *, Elf_Internal_Sym *); +static bfd_boolean elf32_h8_gc_sweep_hook + (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *); static bfd_reloc_status_type elf32_h8_final_link_relocate (unsigned long, bfd *, bfd *, asection *, bfd_byte *, bfd_vma, bfd_vma, bfd_vma, @@ -348,7 +348,7 @@ elf32_h8_final_link_relocate (unsigned long r_type, bfd *input_bfd, value += addend; /* HIT_DATA is the address for the first byte for the relocated - value. Subtract 1 so that we can manipulate the data in 32bit + value. Subtract 1 so that we can manipulate the data in 32-bit hunks. */ hit_data--; @@ -358,7 +358,7 @@ elf32_h8_final_link_relocate (unsigned long r_type, bfd *input_bfd, /* Retrieve the type byte for value from the section contents. */ value |= (bfd_get_32 (input_bfd, hit_data) & 0xff000000); - /* Now scribble it out in one 32bit hunk. */ + /* Now scribble it out in one 32-bit hunk. */ bfd_put_32 (input_bfd, value, hit_data); return bfd_reloc_ok; @@ -439,28 +439,12 @@ elf32_h8_relocate_section (bfd *output_bfd, struct bfd_link_info *info, } else { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - if (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - { - sec = h->root.u.def.section; - relocation = (h->root.u.def.value - + sec->output_section->vma - + sec->output_offset); - } - else if (h->root.type == bfd_link_hash_undefweak) - relocation = 0; - else - { - if (! ((*info->callbacks->undefined_symbol) - (info, h->root.root.string, input_bfd, - input_section, rel->r_offset, TRUE))) - return FALSE; - relocation = 0; - } + bfd_boolean unresolved_reloc, warned; + + RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, + r_symndx, symtab_hdr, sym_hashes, + h, sec, relocation, + unresolved_reloc, warned); } r = elf32_h8_final_link_relocate (r_type, input_bfd, output_bfd, @@ -640,8 +624,8 @@ elf32_h8_merge_private_bfd_data (bfd *ibfd, bfd *obfd) && bfd_get_mach (obfd) < bfd_get_mach (ibfd)) { if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), - bfd_get_mach (ibfd))) - return FALSE; + bfd_get_mach (ibfd))) + return FALSE; } return TRUE; @@ -649,7 +633,7 @@ elf32_h8_merge_private_bfd_data (bfd *ibfd, bfd *obfd) /* This function handles relaxing for the H8.. - There's a few relaxing opportunites available on the H8: + There are a few relaxing opportunities available on the H8: jmp/jsr:24 -> bra/bsr:8 2 bytes The jmp may be completely eliminated if the previous insn is a @@ -659,9 +643,16 @@ elf32_h8_merge_private_bfd_data (bfd *ibfd, bfd *obfd) bCC:16 -> bCC:8 2 bytes bsr:16 -> bsr:8 2 bytes + bset:16 -> bset:8 2 bytes + bset:24/32 -> bset:8 4 bytes + (also applicable to other bit manipulation instructions) + mov.b:16 -> mov.b:8 2 bytes mov.b:24/32 -> mov.b:8 4 bytes + bset:24/32 -> bset:16 2 bytes + (also applicable to other bit manipulation instructions) + mov.[bwl]:24/32 -> mov.[bwl]:16 2 bytes */ static bfd_boolean @@ -688,11 +679,6 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, || (sec->flags & SEC_CODE) == 0) return TRUE; - /* If this is the first time we have been called for this section, - initialize the cooked size. */ - if (sec->_cooked_size == 0) - sec->_cooked_size = sec->_raw_size; - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; /* Get a copy of the native relocations. */ @@ -734,12 +720,7 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, else { /* Go get them off disk. */ - contents = (bfd_byte *) bfd_malloc (sec->_raw_size); - if (contents == NULL) - goto error_return; - - if (! bfd_get_section_contents (abfd, sec, contents, - (file_ptr) 0, sec->_raw_size)) + if (!bfd_malloc_and_get_section (abfd, sec, &contents)) goto error_return; } } @@ -804,7 +785,7 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, the linker is run. */ switch (ELF32_R_TYPE (irel->r_info)) { - /* Try to turn a 24 bit absolute branch/call into an 8 bit + /* Try to turn a 24-bit absolute branch/call into an 8-bit pc-relative branch/call. */ case R_H8_DIR24R8: { @@ -915,8 +896,10 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, } if (code == 0x5e) + /* This is jsr. */ bfd_put_8 (abfd, 0x55, contents + irel->r_offset - 1); else if (code == 0x5a) + /* This is jmp. */ bfd_put_8 (abfd, 0x40, contents + irel->r_offset - 1); else abort (); @@ -937,7 +920,7 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, break; } - /* Try to turn a 16bit pc-relative branch into a 8bit pc-relative + /* Try to turn a 16-bit pc-relative branch into a 8-bit pc-relative branch. */ case R_H8_PCREL16: { @@ -971,14 +954,21 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, if (code == 0x58) { /* bCC:16 -> bCC:8 */ - /* Get the condition code from the original insn. */ + /* Get the second byte of the original insn, which + contains the condition code. */ code = bfd_get_8 (abfd, contents + irel->r_offset - 1); + + /* Compute the fisrt byte of the relaxed + instruction. The original sequence 0x58 0xX0 + is relaxed to 0x4X, where X represents the + condition code. */ code &= 0xf0; code >>= 4; code |= 0x40; bfd_put_8 (abfd, code, contents + irel->r_offset - 2); } else if (code == 0x5c) + /* This is bsr. */ bfd_put_8 (abfd, 0x55, contents + irel->r_offset - 2); else abort (); @@ -1000,8 +990,15 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, break; } - /* This is a 16 bit absolute address in a "mov.b" insn, which may - become an 8 bit absolute address if its in the right range. */ + /* This is a 16-bit absolute address in one of the following + instructions: + + "band", "bclr", "biand", "bild", "bior", "bist", "bixor", + "bld", "bnot", "bor", "bset", "bst", "btst", "bxor", and + "mov.b" + + We may relax this into an 8-bit absolute address if it's in + the right range. */ case R_H8_DIR16A8: { bfd_vma value; @@ -1010,6 +1007,7 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, if (value >= 0xffffff00u) { unsigned char code; + unsigned char temp_code; /* Note that we've changed the relocs, section contents, etc. */ @@ -1020,22 +1018,46 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, /* Get the opcode. */ code = bfd_get_8 (abfd, contents + irel->r_offset - 2); - /* Sanity check. */ + /* All instructions with R_H8_DIR16A8 start with + 0x6a. */ if (code != 0x6a) abort (); - code = bfd_get_8 (abfd, contents + irel->r_offset - 1); + temp_code = code = bfd_get_8 (abfd, contents + irel->r_offset - 1); + /* If this is a mov.b instruction, clear the lower + nibble, which contains the source/destination + register number. */ + if ((temp_code & 0x10) != 0x10) + temp_code &= 0xf0; - if ((code & 0xf0) == 0x00) - bfd_put_8 (abfd, - (code & 0xf) | 0x20, - contents + irel->r_offset - 2); - else if ((code & 0xf0) == 0x80) - bfd_put_8 (abfd, - (code & 0xf) | 0x30, - contents + irel->r_offset - 2); - else - abort (); + switch (temp_code) + { + case 0x00: + /* This is mov.b @aa:16,Rd. */ + bfd_put_8 (abfd, (code & 0xf) | 0x20, + contents + irel->r_offset - 2); + break; + case 0x80: + /* This is mov.b Rs,@aa:16. */ + bfd_put_8 (abfd, (code & 0xf) | 0x30, + contents + irel->r_offset - 2); + break; + case 0x18: + /* This is a bit-maniputation instruction that + stores one bit into memory, one of "bclr", + "bist", "bnot", "bset", and "bst". */ + bfd_put_8 (abfd, 0x7f, contents + irel->r_offset - 2); + break; + case 0x10: + /* This is a bit-maniputation instruction that + loads one bit from memory, one of "band", + "biand", "bild", "bior", "bixor", "bld", "bor", + "btst", and "bxor". */ + bfd_put_8 (abfd, 0x7e, contents + irel->r_offset - 2); + break; + default: + abort (); + } /* Fix the relocation's type. */ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), @@ -1056,8 +1078,15 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, break; } - /* This is a 24 bit absolute address in a "mov.b" insn, which may - become an 8 bit absolute address if its in the right range. */ + /* This is a 24-bit absolute address in one of the following + instructions: + + "band", "bclr", "biand", "bild", "bior", "bist", "bixor", + "bld", "bnot", "bor", "bset", "bst", "btst", "bxor", and + "mov.b" + + We may relax this into an 8-bit absolute address if it's in + the right range. */ case R_H8_DIR24A8: { bfd_vma value; @@ -1066,6 +1095,7 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, if (value >= 0xffffff00u) { unsigned char code; + unsigned char temp_code; /* Note that we've changed the relocs, section contents, etc. */ @@ -1076,24 +1106,46 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, /* Get the opcode. */ code = bfd_get_8 (abfd, contents + irel->r_offset - 2); - /* Sanity check. */ + /* All instructions with R_H8_DIR24A8 start with + 0x6a. */ if (code != 0x6a) abort (); - code = bfd_get_8 (abfd, contents + irel->r_offset - 1); + temp_code = code = bfd_get_8 (abfd, contents + irel->r_offset - 1); - switch (code & 0xf0) + /* If this is a mov.b instruction, clear the lower + nibble, which contains the source/destination + register number. */ + if ((temp_code & 0x30) != 0x30) + temp_code &= 0xf0; + + switch (temp_code) { case 0x20: + /* This is mov.b @aa:24/32,Rd. */ bfd_put_8 (abfd, (code & 0xf) | 0x20, contents + irel->r_offset - 2); break; case 0xa0: + /* This is mov.b Rs,@aa:24/32. */ bfd_put_8 (abfd, (code & 0xf) | 0x30, contents + irel->r_offset - 2); break; + case 0x38: + /* This is a bit-maniputation instruction that + stores one bit into memory, one of "bclr", + "bist", "bnot", "bset", and "bst". */ + bfd_put_8 (abfd, 0x7f, contents + irel->r_offset - 2); + break; + case 0x30: + /* This is a bit-maniputation instruction that + loads one bit from memory, one of "band", + "biand", "bild", "bior", "bixor", "bld", "bor", + "btst", and "bxor". */ + bfd_put_8 (abfd, 0x7e, contents + irel->r_offset - 2); + break; default: - abort (); + abort(); } /* Fix the relocation's type. */ @@ -1113,10 +1165,17 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, } } - /* FALLTHRU */ + /* Fall through. */ - /* This is a 24/32bit absolute address in a "mov" insn, which may - become a 16bit absoulte address if it is in the right range. */ + /* This is a 24-/32-bit absolute address in one of the + following instructions: + + "band", "bclr", "biand", "bild", "bior", "bist", + "bixor", "bld", "bnot", "bor", "bset", "bst", "btst", + "bxor", "ldc.w", "stc.w" and "mov.[bwl]" + + We may relax this into an 16-bit absolute address if it's + in the right range. */ case R_H8_DIR32A16: { bfd_vma value; @@ -1135,7 +1194,9 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, /* Get the opcode. */ code = bfd_get_8 (abfd, contents + irel->r_offset - 1); - /* We just need to turn off bit 0x20. */ + /* Fix the opcode. For all the instructions that + belong to this relaxation, we simply need to turn + off bit 0x20 in the previous byte. */ code &= ~0x20; bfd_put_8 (abfd, code, contents + irel->r_offset - 1); @@ -1226,7 +1287,7 @@ elf32_h8_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, int count) power larger than the number of bytes we are deleting. */ irelalign = NULL; - toaddr = sec->_cooked_size; + toaddr = sec->size; irel = elf_section_data (sec)->relocs; irelend = irel + sec->reloc_count; @@ -1234,7 +1295,7 @@ elf32_h8_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, int count) /* Actually delete the bytes. */ memmove (contents + addr, contents + addr + count, (size_t) (toaddr - addr - count)); - sec->_cooked_size -= count; + sec->size -= count; /* Adjust all the relocs. */ for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) @@ -1351,7 +1412,7 @@ elf32_h8_get_relocated_section_contents (bfd *output_bfd, symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; memcpy (data, elf_section_data (input_section)->this_hdr.contents, - (size_t) input_section->_raw_size); + (size_t) input_section->size); if ((input_section->flags & SEC_RELOC) != 0 && input_section->reloc_count > 0) @@ -1428,6 +1489,42 @@ elf32_h8_get_relocated_section_contents (bfd *output_bfd, return NULL; } +static asection * +elf32_h8_gc_mark_hook (asection *sec, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + Elf_Internal_Rela *rel ATTRIBUTE_UNUSED, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) +{ + if (h != NULL) + { + switch (h->root.type) + { + case bfd_link_hash_defined: + case bfd_link_hash_defweak: + return h->root.u.def.section; + + case bfd_link_hash_common: + return h->root.u.c.p->section; + + default: + break; + } + } + else + return bfd_section_from_elf_index (sec->owner, sym->st_shndx); + return NULL; +} + +static bfd_boolean +elf32_h8_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + asection *sec ATTRIBUTE_UNUSED, + const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED) +{ + return TRUE; +} + #define TARGET_BIG_SYM bfd_elf32_h8300_vec #define TARGET_BIG_NAME "elf32-h8300" @@ -1446,10 +1543,12 @@ elf32_h8_get_relocated_section_contents (bfd *output_bfd, elf32_h8_object_p #define bfd_elf32_bfd_merge_private_bfd_data \ elf32_h8_merge_private_bfd_data +#define elf_backend_gc_mark_hook elf32_h8_gc_mark_hook +#define elf_backend_gc_sweep_hook elf32_h8_gc_sweep_hook /* ??? when elf_backend_relocate_section is not defined, elf32-target.h defaults to using _bfd_generic_link_hash_table_create, but - elflink.h:bfd_elf32_size_dynamic_sections uses + bfd_elf_size_dynamic_sections uses dynobj = elf_hash_table (info)->dynobj; and thus requires an elf hash table. */ #define bfd_elf32_bfd_link_hash_table_create _bfd_elf_link_hash_table_create @@ -1457,6 +1556,7 @@ elf32_h8_get_relocated_section_contents (bfd *output_bfd, /* Use an H8 specific linker, not the ELF generic linker. */ #define elf_backend_relocate_section elf32_h8_relocate_section #define elf_backend_rela_normal 1 +#define elf_backend_can_gc_sections 1 /* And relaxing stuff. */ #define bfd_elf32_bfd_relax_section elf32_h8_relax_section