- {BFD_RELOC_NONE, R_SCORE_NONE},
- {BFD_RELOC_HI16_S, R_SCORE_HI16},
- {BFD_RELOC_LO16, R_SCORE_LO16},
- {BFD_RELOC_SCORE_BCMP, R_SCORE_BCMP},
- {BFD_RELOC_SCORE_JMP, R_SCORE_24},
- {BFD_RELOC_SCORE_BRANCH, R_SCORE_PC19},
- {BFD_RELOC_SCORE16_JMP, R_SCORE16_11},
- {BFD_RELOC_SCORE16_BRANCH, R_SCORE16_PC8},
- {BFD_RELOC_32, R_SCORE_ABS32},
- {BFD_RELOC_16, R_SCORE_ABS16},
- {BFD_RELOC_SCORE_DUMMY2, R_SCORE_DUMMY2},
- {BFD_RELOC_SCORE_GPREL15, R_SCORE_GP15},
- {BFD_RELOC_VTABLE_INHERIT, R_SCORE_GNU_VTINHERIT},
- {BFD_RELOC_VTABLE_ENTRY, R_SCORE_GNU_VTENTRY},
- {BFD_RELOC_SCORE_GOT15, R_SCORE_GOT15},
- {BFD_RELOC_SCORE_GOT_LO16, R_SCORE_GOT_LO16},
- {BFD_RELOC_SCORE_CALL15, R_SCORE_CALL15},
- {BFD_RELOC_GPREL32, R_SCORE_GPREL32},
- {BFD_RELOC_32_PCREL, R_SCORE_REL32},
- {BFD_RELOC_SCORE_DUMMY_HI16, R_SCORE_DUMMY_HI16},
- {BFD_RELOC_SCORE_IMM30, R_SCORE_IMM30},
- {BFD_RELOC_SCORE_IMM32, R_SCORE_IMM32},
+ {BFD_RELOC_NONE, R_SCORE_NONE},
+ {BFD_RELOC_HI16_S, R_SCORE_HI16},
+ {BFD_RELOC_LO16, R_SCORE_LO16},
+ {BFD_RELOC_SCORE_BCMP, R_SCORE_BCMP},
+ {BFD_RELOC_SCORE_JMP, R_SCORE_24},
+ {BFD_RELOC_SCORE_BRANCH, R_SCORE_PC19},
+ {BFD_RELOC_SCORE16_JMP, R_SCORE16_11},
+ {BFD_RELOC_SCORE16_BRANCH, R_SCORE16_PC8},
+ {BFD_RELOC_32, R_SCORE_ABS32},
+ {BFD_RELOC_16, R_SCORE_ABS16},
+ {BFD_RELOC_SCORE_DUMMY2, R_SCORE_DUMMY2},
+ {BFD_RELOC_SCORE_GPREL15, R_SCORE_GP15},
+ {BFD_RELOC_VTABLE_INHERIT, R_SCORE_GNU_VTINHERIT},
+ {BFD_RELOC_VTABLE_ENTRY, R_SCORE_GNU_VTENTRY},
+ {BFD_RELOC_SCORE_GOT15, R_SCORE_GOT15},
+ {BFD_RELOC_SCORE_GOT_LO16, R_SCORE_GOT_LO16},
+ {BFD_RELOC_SCORE_CALL15, R_SCORE_CALL15},
+ {BFD_RELOC_GPREL32, R_SCORE_GPREL32},
+ {BFD_RELOC_32_PCREL, R_SCORE_REL32},
+ {BFD_RELOC_SCORE_DUMMY_HI16, R_SCORE_DUMMY_HI16},
+ {BFD_RELOC_SCORE_IMM30, R_SCORE_IMM30},
+ {BFD_RELOC_SCORE_IMM32, R_SCORE_IMM32},
- {
- struct score_got_entry e;
- struct score_got_info *gg = g;
-
- /* Since we're turning what used to be a global symbol into a
- local one, bump up the number of local entries of each GOT
- that had an entry for it. This will automatically decrease
- the number of global entries, since global_gotno is actually
- the upper limit of global entries. */
- e.abfd = dynobj;
- e.symndx = -1;
- e.d.h = h;
-
- for (g = g->next; g != gg; g = g->next)
- if (htab_find (g->got_entries, &e))
- {
- BFD_ASSERT (g->global_gotno > 0);
- g->local_gotno++;
- g->global_gotno--;
- }
-
- /* If this was a global symbol forced into the primary GOT, we
- no longer need an entry for it. We can't release the entry
- at this point, but we must at least stop counting it as one
- of the symbols that required a forced got entry. */
- if (h->root.got.offset == 2)
- {
- BFD_ASSERT (gg->assigned_gotno > 0);
- gg->assigned_gotno--;
- }
- }
+ {
+ struct score_got_entry e;
+ struct score_got_info *gg = g;
+
+ /* Since we're turning what used to be a global symbol into a
+ local one, bump up the number of local entries of each GOT
+ that had an entry for it. This will automatically decrease
+ the number of global entries, since global_gotno is actually
+ the upper limit of global entries. */
+ e.abfd = dynobj;
+ e.symndx = -1;
+ e.d.h = h;
+
+ for (g = g->next; g != gg; g = g->next)
+ if (htab_find (g->got_entries, &e))
+ {
+ BFD_ASSERT (g->global_gotno > 0);
+ g->local_gotno++;
+ g->global_gotno--;
+ }
+
+ /* If this was a global symbol forced into the primary GOT, we
+ no longer need an entry for it. We can't release the entry
+ at this point, but we must at least stop counting it as one
+ of the symbols that required a forced got entry. */
+ if (h->root.got.offset == 2)
+ {
+ BFD_ASSERT (gg->assigned_gotno > 0);
+ gg->assigned_gotno--;
+ }
+ }
- {
- sym = local_syms + r_symndx;
- sec = local_sections[r_symndx];
- relocation = (sec->output_section->vma
- + sec->output_offset
- + sym->st_value);
- name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec);
-
- if (!bfd_link_relocatable (info)
- && (sec->flags & SEC_MERGE)
- && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
- {
- asection *msec;
- bfd_vma addend, value;
-
- switch (r_type)
- {
- case R_SCORE_HI16:
- break;
- case R_SCORE_LO16:
- hi16_addend = score_bfd_get_32 (input_bfd, contents + rel->r_offset - 4);
- hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1;
- value = score_bfd_get_32 (input_bfd, contents + rel->r_offset);
- offset = ((((value >> 16) & 0x3) << 15) | (value & 0x7fff)) >> 1;
- addend = (hi16_offset << 16) | (offset & 0xffff);
- msec = sec;
- addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
- addend -= relocation;
- addend += msec->output_section->vma + msec->output_offset;
- uvalue = addend;
- hi16_offset = (uvalue >> 16) << 1;
- hi16_value = (hi16_addend & (~(howto->dst_mask)))
- | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
- score_bfd_put_32 (input_bfd, hi16_value, contents + rel->r_offset - 4);
- offset = (uvalue & 0xffff) << 1;
- value = (value & (~(howto->dst_mask)))
- | (offset & 0x7fff) | ((offset << 1) & 0x30000);
- score_bfd_put_32 (input_bfd, value, contents + rel->r_offset);
- break;
-
- case R_SCORE_IMM32:
- {
- value = score_bfd_get_48 (input_bfd, contents + rel->r_offset);
- addend = ((value >> 5) & 0x3ff)
- | (((value >> 16) & 0x7fff) << 10)
- | (((value >> 32) & 0x7f) << 25);
- msec = sec;
- addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
- addend -= relocation;
- addend += msec->output_section->vma + msec->output_offset;
- addend &= 0xffffffff;
- value = (value & ~howto->src_mask)
- | ((addend & 0x3ff) << 5)
- | (((addend >> 10) & 0x7fff) << 16)
- | (((addend >> 25) & 0x7f) << 32);
- score_bfd_put_48 (input_bfd, value, contents + rel->r_offset);
- break;
- }
-
- case R_SCORE_IMM30:
- {
- int not_word_align_p = 0;
- value = score_bfd_get_48 (input_bfd, contents + rel->r_offset);
- addend = ((value >> 7) & 0xff)
- | (((value >> 16) & 0x7fff) << 8)
- | (((value >> 32) & 0x7f) << 23);
- addend <<= howto->rightshift;
- msec = sec;
- addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
- addend -= relocation;
- addend += msec->output_section->vma + msec->output_offset;
- addend &= 0xffffffff;
-
- /* Check lw48/sw48 rd, value/label word align. */
- if ((addend & 0x3) != 0)
- not_word_align_p = 1;
-
- addend >>= howto->rightshift;
- value = (value & ~howto->src_mask)
- | (((addend & 0xff) >> 0) << 7)
- | (((addend & 0x7fff00) >> 8) << 16)
- | (((addend & 0x3f800000) >> 23) << 32);
- score_bfd_put_48 (input_bfd, value, contents + rel->r_offset);
-
- if (not_word_align_p)
- return bfd_reloc_other;
- else
- break;
- }
-
- case R_SCORE_GOT_LO16:
- value = score_bfd_get_32 (input_bfd, contents + rel->r_offset);
- addend = (((value >> 16) & 0x3) << 14) | ((value & 0x7fff) >> 1);
- msec = sec;
- addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
- addend += msec->output_section->vma + msec->output_offset;
- value = (value & (~(howto->dst_mask))) | ((addend & 0x3fff) << 1)
- | (((addend >> 14) & 0x3) << 16);
-
- score_bfd_put_32 (input_bfd, value, contents + rel->r_offset);
- break;
-
- case R_SCORE_ABS32:
- case R_SCORE_REL32:
- value = bfd_get_32 (input_bfd, contents + rel->r_offset);
- /* Get the (signed) value from the instruction. */
- addend = value & howto->src_mask;
- if (addend & ((howto->src_mask + 1) >> 1))
- {
- bfd_signed_vma mask;
-
- mask = -1;
- mask &= ~howto->src_mask;
- addend |= mask;
- }
- msec = sec;
- addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
- addend += msec->output_section->vma + msec->output_offset;
- value = (value & ~howto->dst_mask) | (addend & howto->dst_mask);
- bfd_put_32 (input_bfd, value, contents + rel->r_offset);
- break;
-
- default:
- value = score_bfd_get_32 (input_bfd, contents + rel->r_offset);
- /* Get the (signed) value from the instruction. */
- addend = value & howto->src_mask;
- if (addend & ((howto->src_mask + 1) >> 1))
- {
- bfd_signed_vma mask;
-
- mask = -1;
- mask &= ~howto->src_mask;
- addend |= mask;
- }
- msec = sec;
- addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
- addend += msec->output_section->vma + msec->output_offset;
- value = (value & ~howto->dst_mask) | (addend & howto->dst_mask);
- score_bfd_put_32 (input_bfd, value, contents + rel->r_offset);
- break;
- }
- }
- }
+ {
+ sym = local_syms + r_symndx;
+ sec = local_sections[r_symndx];
+ relocation = (sec->output_section->vma
+ + sec->output_offset
+ + sym->st_value);
+ name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec);
+
+ if (!bfd_link_relocatable (info)
+ && (sec->flags & SEC_MERGE)
+ && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+ {
+ asection *msec;
+ bfd_vma addend, value;
+
+ switch (r_type)
+ {
+ case R_SCORE_HI16:
+ break;
+ case R_SCORE_LO16:
+ hi16_addend = score_bfd_get_32 (input_bfd, contents + rel->r_offset - 4);
+ hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1;
+ value = score_bfd_get_32 (input_bfd, contents + rel->r_offset);
+ offset = ((((value >> 16) & 0x3) << 15) | (value & 0x7fff)) >> 1;
+ addend = (hi16_offset << 16) | (offset & 0xffff);
+ msec = sec;
+ addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
+ addend -= relocation;
+ addend += msec->output_section->vma + msec->output_offset;
+ uvalue = addend;
+ hi16_offset = (uvalue >> 16) << 1;
+ hi16_value = (hi16_addend & (~(howto->dst_mask)))
+ | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
+ score_bfd_put_32 (input_bfd, hi16_value, contents + rel->r_offset - 4);
+ offset = (uvalue & 0xffff) << 1;
+ value = (value & (~(howto->dst_mask)))
+ | (offset & 0x7fff) | ((offset << 1) & 0x30000);
+ score_bfd_put_32 (input_bfd, value, contents + rel->r_offset);
+ break;
+
+ case R_SCORE_IMM32:
+ {
+ value = score_bfd_get_48 (input_bfd, contents + rel->r_offset);
+ addend = ((value >> 5) & 0x3ff)
+ | (((value >> 16) & 0x7fff) << 10)
+ | (((value >> 32) & 0x7f) << 25);
+ msec = sec;
+ addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
+ addend -= relocation;
+ addend += msec->output_section->vma + msec->output_offset;
+ addend &= 0xffffffff;
+ value = (value & ~howto->src_mask)
+ | ((addend & 0x3ff) << 5)
+ | (((addend >> 10) & 0x7fff) << 16)
+ | (((addend >> 25) & 0x7f) << 32);
+ score_bfd_put_48 (input_bfd, value, contents + rel->r_offset);
+ break;
+ }
+
+ case R_SCORE_IMM30:
+ {
+ int not_word_align_p = 0;
+ value = score_bfd_get_48 (input_bfd, contents + rel->r_offset);
+ addend = ((value >> 7) & 0xff)
+ | (((value >> 16) & 0x7fff) << 8)
+ | (((value >> 32) & 0x7f) << 23);
+ addend <<= howto->rightshift;
+ msec = sec;
+ addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
+ addend -= relocation;
+ addend += msec->output_section->vma + msec->output_offset;
+ addend &= 0xffffffff;
+
+ /* Check lw48/sw48 rd, value/label word align. */
+ if ((addend & 0x3) != 0)
+ not_word_align_p = 1;
+
+ addend >>= howto->rightshift;
+ value = (value & ~howto->src_mask)
+ | (((addend & 0xff) >> 0) << 7)
+ | (((addend & 0x7fff00) >> 8) << 16)
+ | (((addend & 0x3f800000) >> 23) << 32);
+ score_bfd_put_48 (input_bfd, value, contents + rel->r_offset);
+
+ if (not_word_align_p)
+ return bfd_reloc_other;
+ else
+ break;
+ }
+
+ case R_SCORE_GOT_LO16:
+ value = score_bfd_get_32 (input_bfd, contents + rel->r_offset);
+ addend = (((value >> 16) & 0x3) << 14) | ((value & 0x7fff) >> 1);
+ msec = sec;
+ addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
+ addend += msec->output_section->vma + msec->output_offset;
+ value = (value & (~(howto->dst_mask))) | ((addend & 0x3fff) << 1)
+ | (((addend >> 14) & 0x3) << 16);
+
+ score_bfd_put_32 (input_bfd, value, contents + rel->r_offset);
+ break;
+
+ case R_SCORE_ABS32:
+ case R_SCORE_REL32:
+ value = bfd_get_32 (input_bfd, contents + rel->r_offset);
+ /* Get the (signed) value from the instruction. */
+ addend = value & howto->src_mask;
+ if (addend & ((howto->src_mask + 1) >> 1))
+ {
+ bfd_signed_vma mask;
+
+ mask = -1;
+ mask &= ~howto->src_mask;
+ addend |= mask;
+ }
+ msec = sec;
+ addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
+ addend += msec->output_section->vma + msec->output_offset;
+ value = (value & ~howto->dst_mask) | (addend & howto->dst_mask);
+ bfd_put_32 (input_bfd, value, contents + rel->r_offset);
+ break;
+
+ default:
+ value = score_bfd_get_32 (input_bfd, contents + rel->r_offset);
+ /* Get the (signed) value from the instruction. */
+ addend = value & howto->src_mask;
+ if (addend & ((howto->src_mask + 1) >> 1))
+ {
+ bfd_signed_vma mask;
+
+ mask = -1;
+ mask &= ~howto->src_mask;
+ addend |= mask;
+ }
+ msec = sec;
+ addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
+ addend += msec->output_section->vma + msec->output_offset;
+ value = (value & ~howto->dst_mask) | (addend & howto->dst_mask);
+ score_bfd_put_32 (input_bfd, value, contents + rel->r_offset);
+ break;
+ }
+ }
+ }
- /* Find the real hash-table entry for this symbol. */
- while (h->root.root.type == bfd_link_hash_indirect
- || h->root.root.type == bfd_link_hash_warning)
- h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link;
-
- /* Record the name of this symbol, for our caller. */
- name = h->root.root.root.string;
-
- /* See if this is the special GP_DISP_LABEL symbol. Note that such a
- symbol must always be a global symbol. */
- if (strcmp (name, GP_DISP_LABEL) == 0)
- {
- /* Relocations against GP_DISP_LABEL are permitted only with
- R_SCORE_HI16 and R_SCORE_LO16 relocations. */
- if (r_type != R_SCORE_HI16 && r_type != R_SCORE_LO16)
- return bfd_reloc_notsupported;
-
- gp_disp_p = TRUE;
- }
-
- /* If this symbol is defined, calculate its address. Note that
- GP_DISP_LABEL is a magic symbol, always implicitly defined by the
- linker, so it's inappropriate to check to see whether or not
- its defined. */
- else if ((h->root.root.type == bfd_link_hash_defined
- || h->root.root.type == bfd_link_hash_defweak)
- && h->root.root.u.def.section)
- {
- sec = h->root.root.u.def.section;
- if (sec->output_section)
- relocation = (h->root.root.u.def.value
- + sec->output_section->vma
- + sec->output_offset);
- else
- {
- relocation = h->root.root.u.def.value;
- }
- }
- else if (h->root.root.type == bfd_link_hash_undefweak)
- /* We allow relocations against undefined weak symbols, giving
- it the value zero, so that you can undefined weak functions
- and check to see if they exist by looking at their addresses. */
- relocation = 0;
- else if (info->unresolved_syms_in_objects == RM_IGNORE
- && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
- relocation = 0;
- else if (strcmp (name, "_DYNAMIC_LINK") == 0)
- {
- /* If this is a dynamic link, we should have created a _DYNAMIC_LINK symbol
- in s3_bfd_score_elf_create_dynamic_sections. Otherwise, we should define
- the symbol with a value of 0. */
- BFD_ASSERT (! bfd_link_pic (info));
- BFD_ASSERT (bfd_get_section_by_name (output_bfd, ".dynamic") == NULL);
- relocation = 0;
- }
- else if (!bfd_link_relocatable (info))
- {
- (*info->callbacks->undefined_symbol)
- (info, h->root.root.root.string, input_bfd,
- input_section, rel->r_offset,
- (info->unresolved_syms_in_objects == RM_GENERATE_ERROR)
+ /* Find the real hash-table entry for this symbol. */
+ while (h->root.root.type == bfd_link_hash_indirect
+ || h->root.root.type == bfd_link_hash_warning)
+ h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link;
+
+ /* Record the name of this symbol, for our caller. */
+ name = h->root.root.root.string;
+
+ /* See if this is the special GP_DISP_LABEL symbol. Note that such a
+ symbol must always be a global symbol. */
+ if (strcmp (name, GP_DISP_LABEL) == 0)
+ {
+ /* Relocations against GP_DISP_LABEL are permitted only with
+ R_SCORE_HI16 and R_SCORE_LO16 relocations. */
+ if (r_type != R_SCORE_HI16 && r_type != R_SCORE_LO16)
+ return bfd_reloc_notsupported;
+
+ gp_disp_p = TRUE;
+ }
+
+ /* If this symbol is defined, calculate its address. Note that
+ GP_DISP_LABEL is a magic symbol, always implicitly defined by the
+ linker, so it's inappropriate to check to see whether or not
+ its defined. */
+ else if ((h->root.root.type == bfd_link_hash_defined
+ || h->root.root.type == bfd_link_hash_defweak)
+ && h->root.root.u.def.section)
+ {
+ sec = h->root.root.u.def.section;
+ if (sec->output_section)
+ relocation = (h->root.root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+ else
+ {
+ relocation = h->root.root.u.def.value;
+ }
+ }
+ else if (h->root.root.type == bfd_link_hash_undefweak)
+ /* We allow relocations against undefined weak symbols, giving
+ it the value zero, so that you can undefined weak functions
+ and check to see if they exist by looking at their addresses. */
+ relocation = 0;
+ else if (info->unresolved_syms_in_objects == RM_IGNORE
+ && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
+ relocation = 0;
+ else if (strcmp (name, "_DYNAMIC_LINK") == 0)
+ {
+ /* If this is a dynamic link, we should have created a _DYNAMIC_LINK symbol
+ in s3_bfd_score_elf_create_dynamic_sections. Otherwise, we should define
+ the symbol with a value of 0. */
+ BFD_ASSERT (! bfd_link_pic (info));
+ BFD_ASSERT (bfd_get_section_by_name (output_bfd, ".dynamic") == NULL);
+ relocation = 0;
+ }
+ else if (!bfd_link_relocatable (info))
+ {
+ info->callbacks->undefined_symbol
+ (info, h->root.root.root.string, input_bfd, input_section,
+ rel->r_offset,
+ (info->unresolved_syms_in_objects == RM_DIAGNOSE
+ && !info->warn_unresolved_syms)
- if (bfd_link_pic (info))
- {
- /* When creating a shared object, we must copy these reloc types into
- the output file as R_SCORE_REL32 relocs. We make room for this reloc
- in the .rel.dyn reloc section. */
- score_elf_allocate_dynamic_relocations (dynobj, 1);
- if ((sec->flags & SCORE_READONLY_SECTION)
- == SCORE_READONLY_SECTION)
- /* We tell the dynamic linker that there are
- relocations against the text segment. */
- info->flags |= DF_TEXTREL;
- }
- else
- {
- struct score_elf_link_hash_entry *hscore;
-
- /* We only need to copy this reloc if the symbol is
- defined in a dynamic object. */
- hscore = (struct score_elf_link_hash_entry *)h;
- ++hscore->possibly_dynamic_relocs;
- if ((sec->flags & SCORE_READONLY_SECTION)
- == SCORE_READONLY_SECTION)
- /* We need it to tell the dynamic linker if there
- are relocations against the text segment. */
- hscore->readonly_reloc = TRUE;
- }
-
- /* Even though we don't directly need a GOT entry for this symbol,
- a symbol must have a dynamic symbol table index greater that
- DT_SCORE_GOTSYM if there are dynamic relocations against it. */
- if (h != NULL)
- {
- if (dynobj == NULL)
- elf_hash_table (info)->dynobj = dynobj = abfd;
- if (! score_elf_create_got_section (dynobj, info, TRUE))
- return FALSE;
- g = score_elf_got_info (dynobj, &sgot);
- if (! score_elf_record_global_got_symbol (h, abfd, info, g))
- return FALSE;
- }
- }
- break;
-
- /* This relocation describes the C++ object vtable hierarchy.
- Reconstruct it for later use during GC. */
- case R_SCORE_GNU_VTINHERIT:
- if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
- return FALSE;
- break;
-
- /* This relocation describes which C++ vtable entries are actually
- used. Record for later use during GC. */
- case R_SCORE_GNU_VTENTRY:
- if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
- return FALSE;
- break;
- default:
- break;
- }
+ if (bfd_link_pic (info))
+ {
+ /* When creating a shared object, we must copy these reloc types into
+ the output file as R_SCORE_REL32 relocs. We make room for this reloc
+ in the .rel.dyn reloc section. */
+ score_elf_allocate_dynamic_relocations (dynobj, 1);
+ if ((sec->flags & SCORE_READONLY_SECTION)
+ == SCORE_READONLY_SECTION)
+ /* We tell the dynamic linker that there are
+ relocations against the text segment. */
+ info->flags |= DF_TEXTREL;
+ }
+ else
+ {
+ struct score_elf_link_hash_entry *hscore;
+
+ /* We only need to copy this reloc if the symbol is
+ defined in a dynamic object. */
+ hscore = (struct score_elf_link_hash_entry *)h;
+ ++hscore->possibly_dynamic_relocs;
+ if ((sec->flags & SCORE_READONLY_SECTION)
+ == SCORE_READONLY_SECTION)
+ /* We need it to tell the dynamic linker if there
+ are relocations against the text segment. */
+ hscore->readonly_reloc = TRUE;
+ }
+
+ /* Even though we don't directly need a GOT entry for this symbol,
+ a symbol must have a dynamic symbol table index greater that
+ DT_SCORE_GOTSYM if there are dynamic relocations against it. */
+ if (h != NULL)
+ {
+ if (dynobj == NULL)
+ elf_hash_table (info)->dynobj = dynobj = abfd;
+ if (! score_elf_create_got_section (dynobj, info, TRUE))
+ return FALSE;
+ g = score_elf_got_info (dynobj, &sgot);
+ if (! score_elf_record_global_got_symbol (h, abfd, info, g))
+ return FALSE;
+ }
+ }
+ break;
+
+ /* This relocation describes the C++ object vtable hierarchy.
+ Reconstruct it for later use during GC. */
+ case R_SCORE_GNU_VTINHERIT:
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ return FALSE;
+ break;
+
+ /* This relocation describes which C++ vtable entries are actually
+ used. Record for later use during GC. */
+ case R_SCORE_GNU_VTENTRY:
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+ return FALSE;
+ break;
+ default:
+ break;
+ }
- {
- if (s->size == 0)
- {
- /* We only strip the section if the output section name
- has the same name. Otherwise, there might be several
- input sections for this output section. FIXME: This
- code is probably not needed these days anyhow, since
- the linker now does not create empty output sections. */
- if (s->output_section != NULL
- && strcmp (name,
- bfd_get_section_name (s->output_section->owner,
- s->output_section)) == 0)
- s->flags |= SEC_EXCLUDE;
- }
- else
- {
- const char *outname;
- asection *target;
-
- /* If this relocation section applies to a read only
- section, then we probably need a DT_TEXTREL entry.
- If the relocation section is .rel.dyn, we always
- assert a DT_TEXTREL entry rather than testing whether
- there exists a relocation to a read only section or
- not. */
- outname = bfd_get_section_name (output_bfd, s->output_section);
- target = bfd_get_section_by_name (output_bfd, outname + 4);
- if ((target != NULL
- && (target->flags & SEC_READONLY) != 0
- && (target->flags & SEC_ALLOC) != 0) || strcmp (outname, ".rel.dyn") == 0)
- reltext = TRUE;
-
- /* We use the reloc_count field as a counter if we need
- to copy relocs into the output file. */
- if (strcmp (name, ".rel.dyn") != 0)
- s->reloc_count = 0;
- }
- }
+ {
+ if (s->size == 0)
+ {
+ /* We only strip the section if the output section name
+ has the same name. Otherwise, there might be several
+ input sections for this output section. FIXME: This
+ code is probably not needed these days anyhow, since
+ the linker now does not create empty output sections. */
+ if (s->output_section != NULL
+ && strcmp (name,
+ bfd_section_name (s->output_section)) == 0)
+ s->flags |= SEC_EXCLUDE;
+ }
+ else
+ {
+ const char *outname;
+ asection *target;
+
+ /* If this relocation section applies to a read only
+ section, then we probably need a DT_TEXTREL entry.
+ If the relocation section is .rel.dyn, we always
+ assert a DT_TEXTREL entry rather than testing whether
+ there exists a relocation to a read only section or
+ not. */
+ outname = bfd_section_name (s->output_section);
+ target = bfd_get_section_by_name (output_bfd, outname + 4);
+ if ((target != NULL
+ && (target->flags & SEC_READONLY) != 0
+ && (target->flags & SEC_ALLOC) != 0) || strcmp (outname, ".rel.dyn") == 0)
+ reltext = TRUE;
+
+ /* We use the reloc_count field as a counter if we need
+ to copy relocs into the output file. */
+ if (strcmp (name, ".rel.dyn") != 0)
+ s->reloc_count = 0;
+ }
+ }
- b < sdyn->contents + sdyn->size;
- b += SCORE_ELF_DYN_SIZE (dynobj))
- {
- Elf_Internal_Dyn dyn;
- const char *name;
- size_t elemsize;
- bfd_boolean swap_out_p;
-
- /* Read in the current dynamic entry. */
- (*get_elf_backend_data (dynobj)->s->swap_dyn_in) (dynobj, b, &dyn);
-
- /* Assume that we're going to modify it and write it out. */
- swap_out_p = TRUE;
-
- switch (dyn.d_tag)
- {
- case DT_RELENT:
- dyn.d_un.d_val = SCORE_ELF_REL_SIZE (dynobj);
- break;
-
- case DT_STRSZ:
- /* Rewrite DT_STRSZ. */
- dyn.d_un.d_val
- = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
- break;
-
- case DT_PLTGOT:
- s = elf_hash_table (info)->sgot;
- dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
- break;
-
- case DT_SCORE_BASE_ADDRESS:
- s = output_bfd->sections;
- BFD_ASSERT (s != NULL);
- dyn.d_un.d_ptr = s->vma & ~(bfd_vma) 0xffff;
- break;
-
- case DT_SCORE_LOCAL_GOTNO:
- dyn.d_un.d_val = g->local_gotno;
- break;
-
- case DT_SCORE_UNREFEXTNO:
- /* The index into the dynamic symbol table which is the
- entry of the first external symbol that is not
- referenced within the same object. */
- dyn.d_un.d_val = bfd_count_sections (output_bfd) + 1;
- break;
-
- case DT_SCORE_GOTSYM:
- if (g->global_gotsym)
- {
- dyn.d_un.d_val = g->global_gotsym->dynindx;
- break;
- }
- /* In case if we don't have global got symbols we default
- to setting DT_SCORE_GOTSYM to the same value as
- DT_SCORE_SYMTABNO. */
+ b < sdyn->contents + sdyn->size;
+ b += SCORE_ELF_DYN_SIZE (dynobj))
+ {
+ Elf_Internal_Dyn dyn;
+ const char *name;
+ size_t elemsize;
+ bfd_boolean swap_out_p;
+
+ /* Read in the current dynamic entry. */
+ (*get_elf_backend_data (dynobj)->s->swap_dyn_in) (dynobj, b, &dyn);
+
+ /* Assume that we're going to modify it and write it out. */
+ swap_out_p = TRUE;
+
+ switch (dyn.d_tag)
+ {
+ case DT_RELENT:
+ dyn.d_un.d_val = SCORE_ELF_REL_SIZE (dynobj);
+ break;
+
+ case DT_STRSZ:
+ /* Rewrite DT_STRSZ. */
+ dyn.d_un.d_val
+ = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
+ break;
+
+ case DT_PLTGOT:
+ s = elf_hash_table (info)->sgot;
+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
+ break;
+
+ case DT_SCORE_BASE_ADDRESS:
+ s = output_bfd->sections;
+ BFD_ASSERT (s != NULL);
+ dyn.d_un.d_ptr = s->vma & ~(bfd_vma) 0xffff;
+ break;
+
+ case DT_SCORE_LOCAL_GOTNO:
+ dyn.d_un.d_val = g->local_gotno;
+ break;
+
+ case DT_SCORE_UNREFEXTNO:
+ /* The index into the dynamic symbol table which is the
+ entry of the first external symbol that is not
+ referenced within the same object. */
+ dyn.d_un.d_val = bfd_count_sections (output_bfd) + 1;
+ break;
+
+ case DT_SCORE_GOTSYM:
+ if (g->global_gotsym)
+ {
+ dyn.d_un.d_val = g->global_gotsym->dynindx;
+ break;
+ }
+ /* In case if we don't have global got symbols we default
+ to setting DT_SCORE_GOTSYM to the same value as
+ DT_SCORE_SYMTABNO. */