X-Git-Url: http://drtracing.org/?a=blobdiff_plain;ds=sidebyside;f=bfd%2Felf32-rl78.c;h=1bb5edcac31f0286cae7369520f34a8c8c096dc2;hb=386047969d9d36980fd6c4129b372e4a400114e0;hp=2806cd3c82d9455dee91787c0b13f433e60123b0;hpb=dbaa2011452c7ce7ca612c6298964452dce179eb;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-rl78.c b/bfd/elf32-rl78.c index 2806cd3c82..1bb5edcac3 100644 --- a/bfd/elf32-rl78.c +++ b/bfd/elf32-rl78.c @@ -1,6 +1,5 @@ /* Renesas RL78 specific support for 32-bit ELF. - Copyright (C) 2011, 2012 - Free Software Foundation, Inc. + Copyright (C) 2011-2015 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -38,7 +37,7 @@ static reloc_howto_type rl78_elf_howto_table [] = { - RL78REL (NONE, 0, 0, 0, dont, FALSE), + RL78REL (NONE, 3, 0, 0, dont, FALSE), RL78REL (DIR32, 2, 32, 0, signed, FALSE), RL78REL (DIR24S, 2, 24, 0, signed, FALSE), RL78REL (DIR16, 1, 16, 0, dont, FALSE), @@ -247,7 +246,7 @@ rl78_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, if (code == BFD_RELOC_RL78_32_OP) return rl78_elf_howto_table + R_RL78_DIR32; - for (i = ARRAY_SIZE (rl78_reloc_map); --i;) + for (i = ARRAY_SIZE (rl78_reloc_map); i--;) if (rl78_reloc_map [i].bfd_reloc_val == code) return rl78_elf_howto_table + rl78_reloc_map[i].rl78_reloc_val; @@ -277,7 +276,11 @@ rl78_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED, unsigned int r_type; r_type = ELF32_R_TYPE (dst->r_info); - BFD_ASSERT (r_type < (unsigned int) R_RL78_max); + if (r_type >= (unsigned int) R_RL78_max) + { + _bfd_error_handler (_("%B: invalid RL78 reloc number: %d"), abfd, r_type); + r_type = 0; + } cache_ptr->howto = rl78_elf_howto_table + r_type; } @@ -425,7 +428,7 @@ rl78_elf_relocate_section dynobj = elf_hash_table (info)->dynobj; splt = NULL; if (dynobj != NULL) - splt = bfd_get_section_by_name (dynobj, ".plt"); + splt = bfd_get_linker_section (dynobj, ".plt"); for (rel = relocs; rel < relend; rel ++) { @@ -461,19 +464,20 @@ rl78_elf_relocate_section } else { - bfd_boolean warned; + bfd_boolean warned ATTRIBUTE_UNUSED; + bfd_boolean ignored ATTRIBUTE_UNUSED; RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, r_symndx, symtab_hdr, sym_hashes, h, sec, relocation, unresolved_reloc, - warned); + warned, ignored); name = h->root.root.string; } if (sec != NULL && discarded_section (sec)) RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, - rel, relend, howto, contents); + rel, 1, relend, howto, 0, contents); if (info->relocatable) { @@ -778,6 +782,8 @@ rl78_elf_relocate_section + sec->output_section->vma + sec->output_offset + rel->r_addend); + else if (h->root.type == bfd_link_hash_undefweak) + RL78_STACK_PUSH (0); else _bfd_error_handler (_("Warning: RL78_SYM reloc with an unknown symbol")); } @@ -808,10 +814,13 @@ rl78_elf_relocate_section { int32_t tmp1, tmp2; - RL78_STACK_POP (tmp2); - RL78_STACK_POP (tmp1); - tmp2 -= tmp1; - RL78_STACK_PUSH (tmp2); + /* For the expression "A - B", the assembler pushes A, + then B, then OPSUB. So the first op we pop is B, not + A. */ + RL78_STACK_POP (tmp2); /* B */ + RL78_STACK_POP (tmp1); /* A */ + tmp1 -= tmp2; /* A - B */ + RL78_STACK_PUSH (tmp1); } break; @@ -1016,9 +1025,11 @@ static bfd_boolean rl78_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd) { flagword new_flags; + flagword old_flags; bfd_boolean error = FALSE; new_flags = elf_elfheader (ibfd)->e_flags; + old_flags = elf_elfheader (obfd)->e_flags; if (!elf_flags_init (obfd)) { @@ -1026,6 +1037,36 @@ rl78_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd) elf_flags_init (obfd) = TRUE; elf_elfheader (obfd)->e_flags = new_flags; } + else if (old_flags != new_flags) + { + flagword changed_flags = old_flags ^ new_flags; + + if (changed_flags & E_FLAG_RL78_G10) + { + (*_bfd_error_handler) + (_("RL78/G10 ABI conflict: cannot link G10 and non-G10 objects together")); + + if (old_flags & E_FLAG_RL78_G10) + (*_bfd_error_handler) (_("- %s is G10, %s is not"), + bfd_get_filename (obfd), bfd_get_filename (ibfd)); + else + (*_bfd_error_handler) (_("- %s is G10, %s is not"), + bfd_get_filename (ibfd), bfd_get_filename (obfd)); + } + + if (changed_flags & E_FLAG_RL78_64BIT_DOUBLES) + { + (*_bfd_error_handler) + (_("RL78 merge conflict: cannot link 32-bit and 64-bit objects together")); + + if (old_flags & E_FLAG_RL78_64BIT_DOUBLES) + (*_bfd_error_handler) (_("- %s is 64-bit, %s is not"), + bfd_get_filename (obfd), bfd_get_filename (ibfd)); + else + (*_bfd_error_handler) (_("- %s is 64-bit, %s is not"), + bfd_get_filename (ibfd), bfd_get_filename (obfd)); + } + } return !error; } @@ -1044,6 +1085,12 @@ rl78_elf_print_private_bfd_data (bfd * abfd, void * ptr) flags = elf_elfheader (abfd)->e_flags; fprintf (file, _("private flags = 0x%lx:"), (long) flags); + if (flags & E_FLAG_RL78_G10) + fprintf (file, _(" [G10]")); + + if (flags & E_FLAG_RL78_64BIT_DOUBLES) + fprintf (file, _(" [64-bit doubles]")); + fputc ('\n', file); return TRUE; } @@ -1066,96 +1113,12 @@ rl78_elf_object_p (bfd * abfd) elf32_rl78_machine (abfd)); return TRUE; } - -#ifdef DEBUG -void -rl78_dump_symtab (bfd * abfd, void * internal_syms, void * external_syms) -{ - size_t locsymcount; - Elf_Internal_Sym * isymbuf; - Elf_Internal_Sym * isymend; - Elf_Internal_Sym * isym; - Elf_Internal_Shdr * symtab_hdr; - bfd_boolean free_internal = FALSE, free_external = FALSE; - char * st_info_str; - char * st_info_stb_str; - char * st_other_str; - char * st_shndx_str; - - if (! internal_syms) - { - internal_syms = bfd_malloc (1000); - free_internal = 1; - } - if (! external_syms) - { - external_syms = bfd_malloc (1000); - free_external = 1; - } - - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - locsymcount = symtab_hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym; - if (free_internal) - isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, - symtab_hdr->sh_info, 0, - internal_syms, external_syms, NULL); - else - isymbuf = internal_syms; - isymend = isymbuf + locsymcount; - - for (isym = isymbuf ; isym < isymend ; isym++) - { - switch (ELF_ST_TYPE (isym->st_info)) - { - case STT_FUNC: st_info_str = "STT_FUNC"; - case STT_SECTION: st_info_str = "STT_SECTION"; - case STT_FILE: st_info_str = "STT_FILE"; - case STT_OBJECT: st_info_str = "STT_OBJECT"; - case STT_TLS: st_info_str = "STT_TLS"; - default: st_info_str = ""; - } - switch (ELF_ST_BIND (isym->st_info)) - { - case STB_LOCAL: st_info_stb_str = "STB_LOCAL"; - case STB_GLOBAL: st_info_stb_str = "STB_GLOBAL"; - default: st_info_stb_str = ""; - } - switch (ELF_ST_VISIBILITY (isym->st_other)) - { - case STV_DEFAULT: st_other_str = "STV_DEFAULT"; - case STV_INTERNAL: st_other_str = "STV_INTERNAL"; - case STV_PROTECTED: st_other_str = "STV_PROTECTED"; - default: st_other_str = ""; - } - switch (isym->st_shndx) - { - case SHN_ABS: st_shndx_str = "SHN_ABS"; - case SHN_COMMON: st_shndx_str = "SHN_COMMON"; - case SHN_UNDEF: st_shndx_str = "SHN_UNDEF"; - default: st_shndx_str = ""; - } - } - if (free_internal) - free (internal_syms); - if (free_external) - free (external_syms); -} - -char * -rl78_get_reloc (long reloc) -{ - if (0 <= reloc && reloc < R_RL78_max) - return rl78_elf_howto_table[reloc].name; - return ""; -} -#endif /* DEBUG */ - /* support PLT for 16-bit references to 24-bit functions. */ /* We support 16-bit pointers to code above 64k by generating a thunk below 64k containing a JMP instruction to the final address. */ - + static bfd_boolean rl78_elf_check_relocs (bfd * abfd, @@ -1173,7 +1136,7 @@ rl78_elf_check_relocs if (info->relocatable) return TRUE; - + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); local_plt_offsets = elf_local_got_offsets (abfd); @@ -1186,7 +1149,7 @@ rl78_elf_check_relocs struct elf_link_hash_entry *h; unsigned long r_symndx; bfd_vma *offset; - + r_symndx = ELF32_R_SYM (rel->r_info); if (r_symndx < symtab_hdr->sh_info) h = NULL; @@ -1196,8 +1159,12 @@ rl78_elf_check_relocs 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; + + /* PR15323, ref flags aren't set for references in the same + object. */ + h->root.non_ir_ref = 1; } - + switch (ELF32_R_TYPE (rel->r_info)) { /* This relocation describes a 16-bit pointer to a function. @@ -1208,13 +1175,14 @@ rl78_elf_check_relocs elf_hash_table (info)->dynobj = dynobj = abfd; if (splt == NULL) { - splt = bfd_get_section_by_name (dynobj, ".plt"); + splt = bfd_get_linker_section (dynobj, ".plt"); if (splt == NULL) { flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED | SEC_READONLY | SEC_CODE); - splt = bfd_make_section_with_flags (dynobj, ".plt", flags); + splt = bfd_make_section_anyway_with_flags (dynobj, ".plt", + flags); if (splt == NULL || ! bfd_set_section_alignment (dynobj, splt, 1)) return FALSE; @@ -1250,7 +1218,7 @@ rl78_elf_check_relocs break; } } - + return TRUE; } @@ -1263,24 +1231,28 @@ rl78_elf_finish_dynamic_sections (bfd *abfd ATTRIBUTE_UNUSED, bfd *dynobj; asection *splt; + if (!elf_hash_table (info)->dynamic_sections_created) + return TRUE; + /* As an extra sanity check, verify that all plt entries have been filled in. However, relaxing might have changed the relocs so that some plt entries don't get filled in, so we have to skip this check if we're relaxing. Unfortunately, check_relocs is called before relaxation. */ - if (info->relax_trip > 0) + if (info->relax_trip > 0) + return TRUE; + + if ((dynobj = elf_hash_table (info)->dynobj) != NULL + && (splt = bfd_get_linker_section (dynobj, ".plt")) != NULL) { - if ((dynobj = elf_hash_table (info)->dynobj) != NULL - && (splt = bfd_get_section_by_name (dynobj, ".plt")) != NULL) + bfd_byte *contents = splt->contents; + unsigned int i, size = splt->size; + + for (i = 0; i < size; i += 4) { - bfd_byte *contents = splt->contents; - unsigned int i, size = splt->size; - for (i = 0; i < size; i += 4) - { - unsigned int x = bfd_get_32 (dynobj, contents + i); - BFD_ASSERT (x != 0); - } + unsigned int x = bfd_get_32 (dynobj, contents + i); + BFD_ASSERT (x != 0); } } @@ -1301,7 +1273,7 @@ rl78_elf_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED, if (dynobj == NULL) return TRUE; - splt = bfd_get_section_by_name (dynobj, ".plt"); + splt = bfd_get_linker_section (dynobj, ".plt"); BFD_ASSERT (splt != NULL); splt->contents = (bfd_byte *) bfd_zalloc (dynobj, splt->size); @@ -1325,8 +1297,7 @@ struct relax_plt_data }; static bfd_boolean -rl78_relax_plt_check (struct elf_link_hash_entry *h, - PTR xdata) +rl78_relax_plt_check (struct elf_link_hash_entry *h, void * xdata) { struct relax_plt_data *data = (struct relax_plt_data *) xdata; @@ -1357,8 +1328,7 @@ rl78_relax_plt_check (struct elf_link_hash_entry *h, previously had a plt entry, give it a new entry offset. */ static bfd_boolean -rl78_relax_plt_realloc (struct elf_link_hash_entry *h, - PTR xdata) +rl78_relax_plt_realloc (struct elf_link_hash_entry *h, void * xdata) { bfd_vma *entry = (bfd_vma *) xdata; @@ -1404,7 +1374,7 @@ rl78_elf_relax_plt_section (bfd *dynobj, /* Likewise for local symbols, though that's somewhat less convenient as we have to walk the list of input bfds and swap in symbol data. */ - for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link.next) { bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd); Elf_Internal_Shdr *symtab_hdr; @@ -1478,7 +1448,7 @@ rl78_elf_relax_plt_section (bfd *dynobj, elf_link_hash_traverse (elf_hash_table (info), rl78_relax_plt_realloc, &entry); - for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link.next) { bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd); unsigned int nlocals = elf_tdata (ibfd)->symtab_hdr.sh_info; @@ -1531,6 +1501,12 @@ elf32_rl78_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, int count toaddr = alignment_rel->r_offset; irel = elf_section_data (sec)->relocs; + if (irel == NULL) + { + _bfd_elf_link_read_relocs (sec->owner, sec, NULL, NULL, TRUE); + irel = elf_section_data (sec)->relocs; + } + irelend = irel + sec->reloc_count; /* Actually delete the bytes. */ @@ -1546,7 +1522,7 @@ elf32_rl78_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, int count memset (contents + toaddr - count, 0x03, count); /* Adjust all the relocs. */ - for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) + for (; irel && irel < irelend; irel++) { /* Get the new reloc address. */ if (irel->r_offset > addr @@ -1972,7 +1948,7 @@ struct { { 0x71, 0x58, 0x53, 0x5b }, /* CLR1 !addr16.0 */ { 0x71, 0x68, 0x63, 0x6b }, /* CLR1 !addr16.0 */ { 0x71, 0x78, 0x73, 0x7b }, /* CLR1 !addr16.0 */ - + { -1, -1, -1, -1 } }; @@ -2055,14 +2031,14 @@ rl78_elf_relax_section if (shndx_buf == NULL) goto error_return; if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt) + || bfd_bread (shndx_buf, amt, abfd) != amt) goto error_return; shndx_hdr->contents = (bfd_byte *) shndx_buf; } /* Get a copy of the native relocations. */ internal_relocs = (_bfd_elf_link_read_relocs - (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, + (abfd, sec, NULL, (Elf_Internal_Rela *) NULL, link_info->keep_memory)); if (internal_relocs == NULL) goto error_return; @@ -2188,6 +2164,7 @@ rl78_elf_relax_section + srel->r_offset; #define GET_RELOC \ + BFD_ASSERT (nrelocs > 0); \ symval = OFFSET_FOR_RELOC (srel, &srel, &scale); \ pcrel = symval - pc + srel->r_addend; \ nrelocs --; @@ -2226,9 +2203,15 @@ rl78_elf_relax_section 61 F3 EF ad SKNH ; BR $rel8 */ - if (irel->r_addend & RL78_RELAXA_BRA) + if ((irel->r_addend & RL78_RELAXA_MASK) == RL78_RELAXA_BRA) { - GET_RELOC; + /* SKIP opcodes that skip non-branches will have a relax tag + but no corresponding symbol to relax against; we just + skip those. */ + if (irel->r_addend & RL78_RELAXA_RNUM) + { + GET_RELOC; + } switch (insn[0]) { @@ -2297,6 +2280,9 @@ rl78_elf_relax_section /* For SKIP/BR, we change the BR opcode and delete the SKIP. That way, we don't have to find and change the relocation for the BR. */ + /* Note that, for the case where we're skipping some + other insn, we have no "other" reloc but that's safe + here anyway. */ switch (insn[1]) { case 0xc8: /* SKC */ @@ -2349,10 +2335,10 @@ rl78_elf_relax_section } break; } - + } - if (irel->r_addend & RL78_RELAXA_ADDR16) + if ((irel->r_addend & RL78_RELAXA_MASK) == RL78_RELAXA_ADDR16) { /*----------------------------------------------------------------------*/ /* Some insns have both a 16-bit address operand and an 8-bit @@ -2415,7 +2401,7 @@ rl78_elf_relax_section insn[poff] = relax_addr16[idx].insn_for_saddr; SNIP (poff+2, 1, R_RL78_RH_SADDR); } - + } } } @@ -2451,7 +2437,7 @@ rl78_elf_relax_section #define ELF_MACHINE_CODE EM_RL78 #define ELF_MAXPAGESIZE 0x1000 -#define TARGET_LITTLE_SYM bfd_elf32_rl78_vec +#define TARGET_LITTLE_SYM rl78_elf32_vec #define TARGET_LITTLE_NAME "elf32-rl78" #define elf_info_to_howto_rel NULL