Index: bfd/elf32-rl78.c |
diff --git a/bfd/elf32-rl78.c b/bfd/elf32-rl78.c |
index f116839927473a180a920ab83105dcc7fce7c2a9..5bdef6754538b96824e2037994efbed6777b9968 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-2013 Free Software Foundation, Inc. |
This file is part of BFD, the Binary File Descriptor library. |
@@ -461,12 +460,13 @@ 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; |
} |
@@ -778,6 +778,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 +810,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 +1021,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 +1033,23 @@ 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)); |
+ } |
+ } |
return !error; |
} |
@@ -1044,6 +1068,9 @@ 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]")); |
+ |
fputc ('\n', file); |
return TRUE; |
} |
@@ -1066,96 +1093,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 +1116,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 +1129,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 +1139,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. |
@@ -1251,7 +1198,7 @@ rl78_elf_check_relocs |
break; |
} |
} |
- |
+ |
return TRUE; |
} |
@@ -1264,24 +1211,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_linker_section (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); |
} |
} |
@@ -1530,6 +1481,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. */ |
@@ -1545,7 +1502,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 |
@@ -1971,7 +1928,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 } |
}; |
@@ -2187,6 +2144,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 --; |
@@ -2227,7 +2185,13 @@ rl78_elf_relax_section |
if (irel->r_addend & 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]) |
{ |
@@ -2296,6 +2260,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 */ |
@@ -2348,7 +2315,7 @@ rl78_elf_relax_section |
} |
break; |
} |
- |
+ |
} |
if (irel->r_addend & RL78_RELAXA_ADDR16) |
@@ -2414,7 +2381,7 @@ rl78_elf_relax_section |
insn[poff] = relax_addr16[idx].insn_for_saddr; |
SNIP (poff+2, 1, R_RL78_RH_SADDR); |
} |
- |
+ |
} |
} |
} |