/* PowerPC-specific support for 32-bit ELF
- Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
- Free Software Foundation, Inc.
+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+ 2004 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
if (ELIMINATE_COPY_RELOCS
&& ind->root.type != bfd_link_hash_indirect
- && (dir->elf_link_hash_flags & ELF_LINK_HASH_DYNAMIC_ADJUSTED) != 0)
- /* If called to transfer flags for a weakdef during processing
- of elf_adjust_dynamic_symbol, don't copy ELF_LINK_NON_GOT_REF.
- We clear it ourselves for ELIMINATE_COPY_RELOCS. */
- dir->elf_link_hash_flags |=
- (ind->elf_link_hash_flags & (ELF_LINK_HASH_REF_DYNAMIC
- | ELF_LINK_HASH_REF_REGULAR
- | ELF_LINK_HASH_REF_REGULAR_NONWEAK));
+ && dir->dynamic_adjusted)
+ {
+ /* If called to transfer flags for a weakdef during processing
+ of elf_adjust_dynamic_symbol, don't copy non_got_ref.
+ We clear it ourselves for ELIMINATE_COPY_RELOCS. */
+ dir->ref_dynamic |= ind->ref_dynamic;
+ dir->ref_regular |= ind->ref_regular;
+ dir->ref_regular_nonweak |= ind->ref_regular_nonweak;
+ dir->needs_plt |= ind->needs_plt;
+ }
else
_bfd_elf_link_hash_copy_indirect (bed, dir, ind);
}
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
- /* Phony reloc to handle branch stubs. */
- HOWTO (R_PPC_RELAX32, /* type */
- 0, /* rightshift */
- 0, /* size */
+ /* Phony relocs to handle branch stubs. */
+ HOWTO (R_PPC_RELAX32, /* type */
+ 0, /* rightshift */
+ 0, /* size */
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
- "R_PPC_RELAX32", /* name */
+ "R_PPC_RELAX32", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0, /* dst_mask */
+ 0, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_PPC_RELAX32PC, /* type */
+ 0, /* rightshift */
+ 0, /* size */
+ 0, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_RELAX32PC", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
FALSE), /* pcrel_offset */
/* GNU extension to record C++ vtable hierarchy. */
}
}
\f
-static bfd_reloc_status_type
-ppc_elf_install_value (bfd *abfd,
- bfd_byte *hit_addr,
- bfd_vma v,
- unsigned int r_type)
-{
- bfd_vma t0, t1;
-#ifdef BFD_HOST_U_64_BIT
- BFD_HOST_U_64_BIT val = (BFD_HOST_U_64_BIT) v;
-#else
- bfd_vma val = v;
-#endif
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
- switch (r_type)
- {
- case R_PPC_RELAX32:
- /* Do stuff here. */
- t0 = bfd_get_32 (abfd, hit_addr);
- t1 = bfd_get_32 (abfd, hit_addr + 4);
-
- /* We're clearing the bits for R_PPC_ADDR16_HA
- and R_PPC_ADDR16_LO here. */
- t0 &= ~0xffff;
- t1 &= ~0xffff;
-
- /* t0 is HA, t1 is lo */
- t0 |= ((val + 0x8000) >> 16) & 0xffff;
- t1 |= val & 0xffff;
-
- bfd_put_32 (abfd, t0, hit_addr);
- bfd_put_32 (abfd, t1, hit_addr + 4);
- break;
-
- case R_PPC_REL24:
- t0 = bfd_get_32 (abfd, hit_addr);
- t0 &= ~0x3fffffc;
- t0 |= val & 0x3fffffc;
- bfd_put_32 (abfd, t0, hit_addr);
- break;
-
- case R_PPC_REL14:
- case R_PPC_REL14_BRTAKEN:
- case R_PPC_REL14_BRNTAKEN:
- t0 = bfd_get_32 (abfd, hit_addr);
- t0 &= ~0xfffc;
- t0 |= val & 0xfffc;
- bfd_put_32 (abfd, t0, hit_addr);
- break;
-
- case R_PPC_LOCAL24PC:
- case R_PPC_PLTREL24:
- t0 = bfd_get_32 (abfd, hit_addr);
- t0 &= ~0x3fffffc;
- t0 |= val & 0x3fffffc;
- bfd_put_32 (abfd, t0, hit_addr);
- break;
-
- default:
- return bfd_reloc_notsupported;
- }
-
- return bfd_reloc_ok;
-}
-
-static const bfd_byte shared_stub_entry[] =
+static const int shared_stub_entry[] =
{
- 0x48, 0x00, 0x00, 0x24, /* b .+36 */
- 0x7c, 0x08, 0x02, 0xa6, /* mflr 0 */
- 0x42, 0x9f, 0x00, 0x05, /* bcl 20, 31, .Lxxx */
- 0x7d, 0x68, 0x02, 0xa6, /* mflr 11 */
- 0x3d, 0x60, 0x00, 0x00, /* addis 11, 11, (xxx-.Lxxx)@ha */
- 0x39, 0x6b, 0x00, 0x18, /* addi 11, 11, (xxx-.Lxxx)@l */
- 0x7c, 0x08, 0x03, 0xa6, /* mtlr 0 */
- 0x7d, 0x69, 0x03, 0xa6, /* mtctr 11 */
- 0x4e, 0x80, 0x04, 0x20, /* bctr */
+ 0x7c0802a6, /* mflr 0 */
+ 0x429f0005, /* bcl 20, 31, .Lxxx */
+ 0x7d6802a6, /* mflr 11 */
+ 0x3d6b0000, /* addis 11, 11, (xxx-.Lxxx)@ha */
+ 0x396b0018, /* addi 11, 11, (xxx-.Lxxx)@l */
+ 0x7c0803a6, /* mtlr 0 */
+ 0x7d6903a6, /* mtctr 11 */
+ 0x4e800420, /* bctr */
};
-static const bfd_byte stub_entry[] =
+static const int stub_entry[] =
{
- 0x48, 0x00, 0x00, 0x14, /* b .+20 */
- 0x3d, 0x60, 0x00, 0x00, /* lis 11,xxx@ha */
- 0x39, 0x6b, 0x00, 0x00, /* addi 11,11,xxx@l */
- 0x7d, 0x69, 0x03, 0xa6, /* mtctr 11 */
- 0x4e, 0x80, 0x04, 0x20, /* bctr */
+ 0x3d600000, /* lis 11,xxx@ha */
+ 0x396b0000, /* addi 11,11,xxx@l */
+ 0x7d6903a6, /* mtctr 11 */
+ 0x4e800420, /* bctr */
};
Elf_Internal_Rela *internal_relocs = NULL;
Elf_Internal_Rela *irel, *irelend;
struct one_fixup *fixups = NULL;
- bfd_boolean changed_contents = FALSE;
- bfd_boolean changed_relocs = FALSE;
+ bfd_boolean changed;
struct ppc_elf_link_hash_table *ppc_info;
+ bfd_size_type trampoff;
*again = FALSE;
- /* Nothing to do if there are no relocations and no need for
- the relax finalize pass. */
- if ((isec->flags & SEC_RELOC) == 0
- || isec->reloc_count == 0
- || link_info->relax_finalizing)
+ /* Nothing to do if there are no relocations. */
+ if ((isec->flags & SEC_RELOC) == 0 || isec->reloc_count == 0)
return TRUE;
- /* If needed, initialize this section's cooked size. */
- if (isec->_cooked_size == 0)
- isec->_cooked_size = isec->_raw_size;
+ trampoff = (isec->size + 3) & (bfd_vma) -4;
+ /* Space for a branch around any trampolines. */
+ trampoff += 4;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
ppc_info = ppc_elf_hash_table (link_info);
irelend = internal_relocs + isec->reloc_count;
- /* Get the section contents. */
- /* Get cached copy if it exists. */
- if (elf_section_data (isec)->this_hdr.contents != NULL)
- contents = elf_section_data (isec)->this_hdr.contents;
- else
- {
- /* Go get them off disk. */
- contents = bfd_malloc (isec->_raw_size);
- if (contents == NULL)
- goto error_return;
-
- if (!bfd_get_section_contents (abfd, isec, contents, 0, isec->_raw_size))
- goto error_return;
- }
-
for (irel = internal_relocs; irel < irelend; irel++)
{
unsigned long r_type = ELF32_R_TYPE (irel->r_info);
- bfd_vma symaddr, reladdr, trampoff, toff, roff;
+ bfd_vma symaddr, reladdr, toff, roff;
asection *tsec;
- bfd_size_type amt;
struct one_fixup *f;
size_t insn_offset = 0;
- bfd_vma max_branch_offset;
+ bfd_vma max_branch_offset, val;
+ bfd_byte *hit_addr;
+ unsigned long t0;
+ unsigned char sym_type;
switch (r_type)
{
case R_PPC_REL24:
case R_PPC_LOCAL24PC:
+ case R_PPC_PLTREL24:
+ max_branch_offset = 1 << 25;
+ break;
+
case R_PPC_REL14:
case R_PPC_REL14_BRTAKEN:
case R_PPC_REL14_BRNTAKEN:
- case R_PPC_PLTREL24:
+ max_branch_offset = 1 << 15;
break;
default:
}
isym = isymbuf + ELF32_R_SYM (irel->r_info);
if (isym->st_shndx == SHN_UNDEF)
- continue; /* We can't do anthing with undefined symbols. */
+ continue; /* We can't do anything with undefined symbols. */
else if (isym->st_shndx == SHN_ABS)
tsec = bfd_abs_section_ptr;
else if (isym->st_shndx == SHN_COMMON)
tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
toff = isym->st_value;
+ sym_type = ELF_ST_TYPE (isym->st_info);
}
else
{
- /* Need dynamic symbol handling. */
+ /* Global symbol handling. */
unsigned long indx;
struct elf_link_hash_entry *h;
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
- if (r_type == R_PPC_PLTREL24)
+ if (r_type == R_PPC_PLTREL24
+ && ppc_info->plt != NULL
+ && h->plt.offset != (bfd_vma) -1)
{
- Elf_Internal_Sym *isym;
-
- if (h->plt.offset == (bfd_vma) -1
- || ppc_info->plt == NULL)
- {
-
- /* Read this BFD's local symbols. */
- if (isymbuf == NULL)
- {
- isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
- if (isymbuf == NULL)
- isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
- symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
- if (isymbuf == 0)
- goto error_return;
- }
- isym = isymbuf + ELF32_R_SYM (irel->r_info);
-
- if (isym->st_shndx == SHN_UNDEF)
- /* We can't do anthing with undefined symbols. */
- continue;
- else if (isym->st_shndx == SHN_ABS)
- tsec = bfd_abs_section_ptr;
- else if (isym->st_shndx == SHN_COMMON)
- tsec = bfd_com_section_ptr;
- else
- tsec = h->root.u.def.section;
-
- toff = h->root.u.def.value;
- }
- else
- {
- tsec = ppc_info->plt;
- toff = h->plt.offset;
- }
+ tsec = ppc_info->plt;
+ toff = h->plt.offset;
}
- else if (h->root.type == bfd_link_hash_undefined
- || h->root.type == bfd_link_hash_undefweak)
- continue;
-
- else
+ else if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
{
tsec = h->root.u.def.section;
toff = h->root.u.def.value;
}
+ else
+ continue;
+
+ sym_type = h->type;
}
- if (tsec->sec_info_type == ELF_INFO_TYPE_MERGE)
- toff = _bfd_merged_section_offset (abfd, &tsec,
- elf_section_data (tsec)->sec_info,
- toff + irel->r_addend, 0);
+ /* If the branch and target are in the same section, you have
+ no hope of adding stubs. We'll error out later should the
+ branch overflow. */
+ if (tsec == isec)
+ continue;
+
+ /* There probably isn't any reason to handle symbols in
+ SEC_MERGE sections; SEC_MERGE doesn't seem a likely
+ attribute for a code section, and we are only looking at
+ branches. However, implement it correctly here as a
+ reference for other target relax_section functions. */
+ if (0 && tsec->sec_info_type == ELF_INFO_TYPE_MERGE)
+ {
+ /* At this stage in linking, no SEC_MERGE symbol has been
+ adjusted, so all references to such symbols need to be
+ passed through _bfd_merged_section_offset. (Later, in
+ relocate_section, all SEC_MERGE symbols *except* for
+ section symbols have been adjusted.)
+
+ gas may reduce relocations against symbols in SEC_MERGE
+ sections to a relocation against the section symbol when
+ the original addend was zero. When the reloc is against
+ a section symbol we should include the addend in the
+ offset passed to _bfd_merged_section_offset, since the
+ location of interest is the original symbol. On the
+ other hand, an access to "sym+addend" where "sym" is not
+ a section symbol should not include the addend; Such an
+ access is presumed to be an offset from "sym"; The
+ location of interest is just "sym". */
+ if (sym_type == STT_SECTION)
+ toff += irel->r_addend;
+
+ toff = _bfd_merged_section_offset (abfd, &tsec,
+ elf_section_data (tsec)->sec_info,
+ toff);
+
+ if (sym_type != STT_SECTION)
+ toff += irel->r_addend;
+ }
else
toff += irel->r_addend;
symaddr = tsec->output_section->vma + tsec->output_offset + toff;
roff = irel->r_offset;
-
- reladdr = (isec->output_section->vma
- + isec->output_offset
- + roff) & (bfd_vma) -4;
+ reladdr = isec->output_section->vma + isec->output_offset + roff;
/* If the branch is in range, no need to do anything. */
- max_branch_offset = 1 << 25;
- if (r_type != R_PPC_REL24
- && r_type != R_PPC_LOCAL24PC
- && r_type != R_PPC_PLTREL24)
- max_branch_offset = 1 << 15;
-
- if ((bfd_vma) (symaddr - reladdr) + max_branch_offset
- <= 2 * max_branch_offset)
- continue;
-
- /* If the branch and target are in the same section, you have
- no hope. We'll error out later. */
- if (tsec == isec)
+ if (symaddr - reladdr + max_branch_offset < 2 * max_branch_offset)
continue;
/* Look for an existing fixup to this address. */
if (f == NULL)
{
size_t size;
+ unsigned long stub_rtype;
- if (link_info->shared
- || tsec == ppc_info->plt
- || r_type == R_PPC_LOCAL24PC)
+ val = trampoff - roff;
+ if (val >= max_branch_offset)
+ /* Oh dear, we can't reach a trampoline. Don't try to add
+ one. We'll report an error later. */
+ continue;
+
+ if (link_info->shared)
{
- size = sizeof (shared_stub_entry);
- insn_offset = 16;
+ size = 4 * ARRAY_SIZE (shared_stub_entry);
+ insn_offset = 12;
+ stub_rtype = R_PPC_RELAX32PC;
}
else
{
- size = sizeof (stub_entry);
- insn_offset = 4;
+ size = 4 * ARRAY_SIZE (stub_entry);
+ insn_offset = 0;
+ stub_rtype = R_PPC_RELAX32;
}
- /* Resize the current section to make room for the new branch. */
- trampoff = (isec->_cooked_size + 3) & (bfd_vma) - 4;
- amt = trampoff + size;
- contents = bfd_realloc (contents, amt);
- if (contents == NULL)
- abort ();
-
- isec->_cooked_size = amt;
-
- if (link_info->shared
- || tsec == ppc_info->plt
- || r_type == R_PPC_LOCAL24PC)
- memcpy (contents + trampoff, shared_stub_entry, size);
- else
- memcpy (contents + trampoff, stub_entry, size);
-
/* Hijack the old relocation. Since we need two
relocations for this use a "composite" reloc. */
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
- R_PPC_RELAX32);
+ stub_rtype);
irel->r_offset = trampoff + insn_offset;
/* Record the fixup so we don't do it again this section. */
f->toff = toff;
f->trampoff = trampoff;
fixups = f;
+
+ trampoff += size;
}
else
{
+ val = f->trampoff - roff;
+ if (val >= max_branch_offset)
+ continue;
+
/* Nop out the reloc, since we're finalizing things here. */
irel->r_info = ELF32_R_INFO (0, R_PPC_NONE);
}
- /* Fix up the existing branch to hit the trampoline. Hope like
- hell this doesn't overflow too. */
- if (ppc_elf_install_value (abfd, contents + roff,
- f->trampoff - (roff & (bfd_vma) -3) + 4,
- r_type) != bfd_reloc_ok)
- abort ();
+ /* Get the section contents. */
+ if (contents == NULL)
+ {
+ /* Get cached copy if it exists. */
+ if (elf_section_data (isec)->this_hdr.contents != NULL)
+ contents = elf_section_data (isec)->this_hdr.contents;
+ else
+ {
+ /* Go get them off disk. */
+ if (!bfd_malloc_and_get_section (abfd, isec, &contents))
+ goto error_return;
+ }
+ }
+
+ /* Fix up the existing branch to hit the trampoline. */
+ hit_addr = contents + roff;
+ switch (r_type)
+ {
+ case R_PPC_REL24:
+ case R_PPC_LOCAL24PC:
+ case R_PPC_PLTREL24:
+ t0 = bfd_get_32 (abfd, hit_addr);
+ t0 &= ~0x3fffffc;
+ t0 |= val & 0x3fffffc;
+ bfd_put_32 (abfd, t0, hit_addr);
+ break;
- changed_contents = TRUE;
- changed_relocs = TRUE;
+ case R_PPC_REL14:
+ case R_PPC_REL14_BRTAKEN:
+ case R_PPC_REL14_BRNTAKEN:
+ t0 = bfd_get_32 (abfd, hit_addr);
+ t0 &= ~0xfffc;
+ t0 |= val & 0xfffc;
+ bfd_put_32 (abfd, t0, hit_addr);
+ break;
+ }
}
- /* Clean up. */
- while (fixups)
+ /* Write out the trampolines. */
+ changed = fixups != NULL;
+ if (fixups != NULL)
{
- struct one_fixup *f = fixups;
- fixups = fixups->next;
- free (f);
+ const int *stub;
+ bfd_byte *dest;
+ bfd_vma val;
+ int i, size;
+
+ do
+ {
+ struct one_fixup *f = fixups;
+ fixups = fixups->next;
+ free (f);
+ }
+ while (fixups);
+
+ contents = bfd_realloc (contents, trampoff);
+ if (contents == NULL)
+ goto error_return;
+
+ isec->size = (isec->size + 3) & (bfd_vma) -4;
+ /* Branch around the trampolines. */
+ val = trampoff - isec->size + 0x48000000;
+ dest = contents + isec->size;
+ isec->size = trampoff;
+ bfd_put_32 (abfd, val, dest);
+ dest += 4;
+
+ if (link_info->shared)
+ {
+ stub = shared_stub_entry;
+ size = ARRAY_SIZE (shared_stub_entry);
+ }
+ else
+ {
+ stub = stub_entry;
+ size = ARRAY_SIZE (stub_entry);
+ }
+
+ i = 0;
+ while (dest < contents + trampoff)
+ {
+ bfd_put_32 (abfd, stub[i], dest);
+ i++;
+ if (i == size)
+ i = 0;
+ dest += 4;
+ }
+ BFD_ASSERT (i == 0);
}
+
if (isymbuf != NULL
&& symtab_hdr->contents != (unsigned char *) isymbuf)
{
if (contents != NULL
&& elf_section_data (isec)->this_hdr.contents != contents)
{
- if (!changed_contents && !link_info->keep_memory)
+ if (!changed && !link_info->keep_memory)
free (contents);
else
{
if (elf_section_data (isec)->relocs != internal_relocs)
{
- if (!changed_relocs)
+ if (!changed)
free (internal_relocs);
else
elf_section_data (isec)->relocs = internal_relocs;
}
- *again = changed_contents || changed_relocs;
+ *again = changed;
return TRUE;
error_return:
return bfd_reloc_ok;
}
- if (reloc_entry->address > input_section->_cooked_size)
+ if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
return bfd_reloc_outofrange;
if (bfd_is_com_section (symbol->section))
{
error = TRUE;
(*_bfd_error_handler)
- (_("%s: compiled with -mrelocatable and linked with "
- "modules compiled normally"),
- bfd_archive_filename (ibfd));
+ (_("%B: compiled with -mrelocatable and linked with "
+ "modules compiled normally"), ibfd);
}
else if ((new_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0
&& (old_flags & EF_PPC_RELOCATABLE) != 0)
{
error = TRUE;
(*_bfd_error_handler)
- (_("%s: compiled normally and linked with "
- "modules compiled with -mrelocatable"),
- bfd_archive_filename (ibfd));
+ (_("%B: compiled normally and linked with "
+ "modules compiled with -mrelocatable"), ibfd);
}
/* The output is -mrelocatable-lib iff both the input files are. */
{
error = TRUE;
(*_bfd_error_handler)
- (_("%s: uses different e_flags (0x%lx) fields "
+ (_("%B: uses different e_flags (0x%lx) fields "
"than previous modules (0x%lx)"),
- bfd_archive_filename (ibfd), (long) new_flags, (long) old_flags);
+ ibfd, (long) new_flags, (long) old_flags);
}
if (error)
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
- if (! _bfd_elf_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (lsect->rel_section)
- lsect->rel_section->_raw_size += sizeof (Elf32_External_Rela);
+ lsect->rel_section->size += sizeof (Elf32_External_Rela);
}
else
{
output a R_<xxx>_RELATIVE reloc so that the
dynamic linker can adjust this GOT entry. */
BFD_ASSERT (lsect->rel_section != NULL);
- lsect->rel_section->_raw_size += sizeof (Elf32_External_Rela);
+ lsect->rel_section->size += sizeof (Elf32_External_Rela);
}
}
linker_section_ptr->written_address_p = FALSE;
*ptr_linker_section_ptr = linker_section_ptr;
- linker_section_ptr->offset = lsect->section->_raw_size;
- lsect->section->_raw_size += 4;
+ linker_section_ptr->offset = lsect->section->size;
+ lsect->section->size += 4;
#ifdef DEBUG
fprintf (stderr,
"Create pointer in linker section %s, offset = %ld, section size = %ld\n",
lsect->name, (long) linker_section_ptr->offset,
- (long) lsect->section->_raw_size);
+ (long) lsect->section->size);
#endif
return TRUE;
if (! elf_hash_table (info)->dynamic_sections_created
|| (info->shared
&& info->symbolic
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+ && h->def_regular))
{
/* This is actually a static link, or it is a
-Bsymbolic link and the symbol is defined
{
elf_linker_section_t *lsect;
struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info);
- asection *s;
+ asection *s, *sym_sec;
bfd_size_type amt;
flagword flags;
const char *name;
lsect->sym_offset = sym_offset;
/* See if the sections already exist. */
- s = bfd_get_section_by_name (htab->elf.dynobj, name);
+ sym_sec = s = bfd_get_section_by_name (htab->elf.dynobj, name);
if (s == NULL || (s->flags & flags) != flags)
{
s = bfd_make_section_anyway (htab->elf.dynobj, name);
if (s == NULL
|| !bfd_set_section_flags (htab->elf.dynobj, s, flags))
return NULL;
+ if (sym_sec == NULL)
+ sym_sec = s;
}
lsect->section = s;
&& !bfd_set_section_alignment (htab->elf.dynobj, s, 2))
return NULL;
- s->_raw_size = align_power (s->_raw_size, 2);
+ s->size = align_power (s->size, 2);
#ifdef DEBUG
fprintf (stderr, "Creating section %s, current size = %ld\n",
- name, (long) s->_raw_size);
+ name, (long) s->size);
#endif
if (sym_name)
if ((bh == NULL || bh->type == bfd_link_hash_undefined)
&& !(_bfd_generic_link_add_one_symbol
- (info, abfd, sym_name, BSF_GLOBAL, s, sym_offset, NULL,
+ (info, abfd, sym_name, BSF_GLOBAL, sym_sec, sym_offset, NULL,
FALSE, get_elf_backend_data (abfd)->collect, &bh)))
return NULL;
h = (struct elf_link_hash_entry *) bh;
lsect->sym_hash = h;
if (info->shared
- && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
return NULL;
}
++ret;
s = bfd_get_section_by_name (abfd, ".sbss2");
- if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->_raw_size > 0)
+ if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->size > 0)
++ret;
s = bfd_get_section_by_name (abfd, ".PPC.EMB.sbss0");
- if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->_raw_size > 0)
+ if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->size > 0)
++ret;
return ret;
}
-
-/* Modify the segment map if needed. */
-
-static bfd_boolean
-ppc_elf_modify_segment_map (bfd *abfd ATTRIBUTE_UNUSED)
-{
- return TRUE;
-}
\f
/* The powerpc .got has a blrl instruction in it. Mark it executable. */
/* Make sure we know what is going on here. */
htab = ppc_elf_hash_table (info);
BFD_ASSERT (htab->elf.dynobj != NULL
- && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
- || h->weakdef != NULL
- || ((h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_DYNAMIC) != 0
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_REF_REGULAR) != 0
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0)));
+ && (h->needs_plt
+ || h->u.weakdef != NULL
+ || (h->def_dynamic
+ && h->ref_regular
+ && !h->def_regular)));
/* Deal with function syms. */
if (h->type == STT_FUNC
- || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
+ || h->needs_plt)
{
/* Clear procedure linkage table information for any symbol that
won't need a .plt entry. */
3. We know for certain that a call to this symbol
will go to this object, or will remain undefined. */
h->plt.offset = (bfd_vma) -1;
- h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+ h->needs_plt = 0;
}
return TRUE;
}
/* If this is a weak symbol, and there is a real definition, the
processor independent code will have arranged for us to see the
real definition first, and we can just use the same value. */
- if (h->weakdef != NULL)
+ if (h->u.weakdef != NULL)
{
- BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
- || h->weakdef->root.type == bfd_link_hash_defweak);
- h->root.u.def.section = h->weakdef->root.u.def.section;
- h->root.u.def.value = h->weakdef->root.u.def.value;
+ BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
+ || h->u.weakdef->root.type == bfd_link_hash_defweak);
+ h->root.u.def.section = h->u.weakdef->root.u.def.section;
+ h->root.u.def.value = h->u.weakdef->root.u.def.value;
if (ELIMINATE_COPY_RELOCS)
- h->elf_link_hash_flags
- = ((h->elf_link_hash_flags & ~ELF_LINK_NON_GOT_REF)
- | (h->weakdef->elf_link_hash_flags & ELF_LINK_NON_GOT_REF));
+ h->non_got_ref = h->u.weakdef->non_got_ref;
return TRUE;
}
/* If there are no references to this symbol that do not use the
GOT, we don't need to generate a copy reloc. */
- if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0)
+ if (!h->non_got_ref)
return TRUE;
if (ELIMINATE_COPY_RELOCS)
we'll be keeping the dynamic relocs and avoiding the copy reloc. */
if (p == NULL)
{
- h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF;
+ h->non_got_ref = 0;
return TRUE;
}
}
else
srel = htab->relbss;
BFD_ASSERT (srel != NULL);
- srel->_raw_size += sizeof (Elf32_External_Rela);
- h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
+ srel->size += sizeof (Elf32_External_Rela);
+ h->needs_copy = 1;
}
/* We need to figure out the alignment required for this symbol. I
power_of_two = 4;
/* Apply the required alignment. */
- s->_raw_size = BFD_ALIGN (s->_raw_size,
- (bfd_size_type) (1 << power_of_two));
+ s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
if (power_of_two > bfd_get_section_alignment (htab->elf.dynobj, s))
{
if (! bfd_set_section_alignment (htab->elf.dynobj, s, power_of_two))
/* Define the symbol as being at this point in the section. */
h->root.u.def.section = s;
- h->root.u.def.value = s->_raw_size;
+ h->root.u.def.value = s->size;
/* Increment the section size to make room for the symbol. */
- s->_raw_size += h->size;
+ s->size += h->size;
return TRUE;
}
\f
-/* This is the condition under which finish_dynamic_symbol will be
- called from elflink.h. If elflink.h doesn't call our
- finish_dynamic_symbol routine, we'll need to do something about
- initializing any .plt and .got entries in relocate_section. */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \
- ((DYN) \
- && ((SHARED) \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
- && ((H)->dynindx != -1 \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
-
/* Of those relocs that might be copied as dynamic relocs, this macro
selects those that must be copied when linking a shared library,
even when the symbol is local. */
{
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1
- && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+ && !h->forced_local)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* If this is the first .plt entry, make room for the special
first entry. */
- if (s->_raw_size == 0)
- s->_raw_size += PLT_INITIAL_ENTRY_SIZE;
+ if (s->size == 0)
+ s->size += PLT_INITIAL_ENTRY_SIZE;
/* The PowerPC PLT is actually composed of two parts, the
first part is 2 words (for a load and a jump), and then
there is a remaining word available at the end. */
h->plt.offset = (PLT_INITIAL_ENTRY_SIZE
+ (PLT_SLOT_SIZE
- * ((s->_raw_size - PLT_INITIAL_ENTRY_SIZE)
+ * ((s->size - PLT_INITIAL_ENTRY_SIZE)
/ PLT_ENTRY_SIZE)));
/* If this symbol is not defined in a regular file, and we
function pointers compare as equal between the normal
executable and the shared library. */
if (! info->shared
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ && !h->def_regular)
{
h->root.u.def.section = s;
h->root.u.def.value = h->plt.offset;
/* Make room for this entry. After the 8192nd entry, room
for two entries is allocated. */
- s->_raw_size += PLT_ENTRY_SIZE;
- if ((s->_raw_size - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE
+ s->size += PLT_ENTRY_SIZE;
+ if ((s->size - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE
> PLT_NUM_SINGLE_ENTRIES)
- s->_raw_size += PLT_ENTRY_SIZE;
+ s->size += PLT_ENTRY_SIZE;
/* We also need to make an entry in the .rela.plt section. */
- htab->relplt->_raw_size += sizeof (Elf32_External_Rela);
+ htab->relplt->size += sizeof (Elf32_External_Rela);
}
else
{
h->plt.offset = (bfd_vma) -1;
- h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+ h->needs_plt = 0;
}
}
else
{
h->plt.offset = (bfd_vma) -1;
- h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+ h->needs_plt = 0;
}
eh = (struct ppc_elf_link_hash_entry *) h;
{
/* Make sure this symbol is output as a dynamic symbol. */
if (eh->elf.dynindx == -1
- && (eh->elf.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+ && !eh->elf.forced_local)
{
- if (!bfd_elf32_link_record_dynamic_symbol (info, &eh->elf))
+ if (!bfd_elf_link_record_dynamic_symbol (info, &eh->elf))
return FALSE;
}
if (eh->tls_mask == (TLS_TLS | TLS_LD)
- && !(eh->elf.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC))
+ && !eh->elf.def_dynamic)
/* If just an LD reloc, we'll just use htab->tlsld_got.offset. */
eh->elf.got.offset = (bfd_vma) -1;
else
{
bfd_boolean dyn;
- eh->elf.got.offset = htab->got->_raw_size;
+ eh->elf.got.offset = htab->got->size;
if ((eh->tls_mask & TLS_TLS) != 0)
{
if ((eh->tls_mask & TLS_LD) != 0)
- htab->got->_raw_size += 8;
+ htab->got->size += 8;
if ((eh->tls_mask & TLS_GD) != 0)
- htab->got->_raw_size += 8;
+ htab->got->size += 8;
if ((eh->tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0)
- htab->got->_raw_size += 4;
+ htab->got->size += 4;
if ((eh->tls_mask & TLS_DTPREL) != 0)
- htab->got->_raw_size += 4;
+ htab->got->size += 4;
}
else
- htab->got->_raw_size += 4;
+ htab->got->size += 4;
dyn = htab->elf.dynamic_sections_created;
if ((info->shared
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, &eh->elf))
|| eh->elf.root.type != bfd_link_hash_undefweak))
{
/* All the entries we allocated need relocs. */
- htab->relgot->_raw_size
- += ((htab->got->_raw_size - eh->elf.got.offset) / 4
+ htab->relgot->size
+ += ((htab->got->size - eh->elf.got.offset) / 4
* sizeof (Elf32_External_Rela));
/* Except LD only needs one. */
if ((eh->tls_mask & TLS_LD) != 0)
- htab->relgot->_raw_size -= sizeof (Elf32_External_Rela);
+ htab->relgot->size -= sizeof (Elf32_External_Rela);
}
}
}
if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
&& h->root.type == bfd_link_hash_undefweak)
eh->dyn_relocs = NULL;
+
+ /* Make sure undefined weak symbols are output as a dynamic symbol
+ in PIEs. */
+ if (info->pie
+ && eh->dyn_relocs != NULL
+ && h->dynindx == -1
+ && h->root.type == bfd_link_hash_undefweak
+ && !h->forced_local)
+ {
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
}
else if (ELIMINATE_COPY_RELOCS)
{
symbols which turn out to need copy relocs or are not
dynamic. */
- if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ if (!h->non_got_ref
+ && h->def_dynamic
+ && !h->def_regular)
{
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
if (h->dynindx == -1
- && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+ && !h->forced_local)
{
- if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
for (p = eh->dyn_relocs; p != NULL; p = p->next)
{
asection *sreloc = elf_section_data (p->sec)->sreloc;
- sreloc->_raw_size += p->count * sizeof (Elf32_External_Rela);
+ sreloc->size += p->count * sizeof (Elf32_External_Rela);
}
return TRUE;
{
s = bfd_get_section_by_name (htab->elf.dynobj, ".interp");
BFD_ASSERT (s != NULL);
- s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
+ s->size = sizeof ELF_DYNAMIC_INTERPRETER;
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
}
}
if (htab->tlsld_got.refcount > 0)
{
- htab->tlsld_got.offset = htab->got->_raw_size;
- htab->got->_raw_size += 8;
+ htab->tlsld_got.offset = htab->got->size;
+ htab->got->size += 8;
if (info->shared)
- htab->relgot->_raw_size += sizeof (Elf32_External_Rela);
+ htab->relgot->size += sizeof (Elf32_External_Rela);
}
else
htab->tlsld_got.offset = (bfd_vma) -1;
}
else if (p->count != 0)
{
- elf_section_data (p->sec)->sreloc->_raw_size
+ elf_section_data (p->sec)->sreloc->size
+= p->count * sizeof (Elf32_External_Rela);
if ((p->sec->output_section->flags
& (SEC_READONLY | SEC_ALLOC))
htab->tlsld_got.offset. */
if (htab->tlsld_got.offset == (bfd_vma) -1)
{
- htab->tlsld_got.offset = s->_raw_size;
- s->_raw_size += 8;
+ htab->tlsld_got.offset = s->size;
+ s->size += 8;
if (info->shared)
- srel->_raw_size += sizeof (Elf32_External_Rela);
+ srel->size += sizeof (Elf32_External_Rela);
}
*local_got = (bfd_vma) -1;
}
else
{
- *local_got = s->_raw_size;
+ *local_got = s->size;
if ((*lgot_masks & TLS_TLS) != 0)
{
if ((*lgot_masks & TLS_GD) != 0)
- s->_raw_size += 8;
+ s->size += 8;
if ((*lgot_masks & (TLS_TPREL | TLS_TPRELGD)) != 0)
- s->_raw_size += 4;
+ s->size += 4;
if ((*lgot_masks & TLS_DTPREL) != 0)
- s->_raw_size += 4;
+ s->size += 4;
}
else
- s->_raw_size += 4;
+ s->size += 4;
if (info->shared)
- srel->_raw_size += ((s->_raw_size - *local_got) / 4
- * sizeof (Elf32_External_Rela));
+ srel->size += ((s->size - *local_got) / 4
+ * sizeof (Elf32_External_Rela));
}
}
else
}
else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0)
{
- if (s->_raw_size == 0)
+ if (s->size == 0)
{
/* If we don't need this section, strip it from the
output file. This is mostly to handle .rela.bss and
continue;
}
- if (s->_raw_size == 0)
+ if (s->size == 0)
{
_bfd_strip_section_from_output (info, s);
continue;
}
/* Allocate memory for the section contents. */
- s->contents = bfd_zalloc (htab->elf.dynobj, s->_raw_size);
+ s->contents = bfd_zalloc (htab->elf.dynobj, s->size);
if (s->contents == NULL)
return FALSE;
}
the .dynamic section. The DT_DEBUG entry is filled in by the
dynamic linker and used by the debugger. */
#define add_dynamic_entry(TAG, VAL) \
- bfd_elf32_add_dynamic_entry (info, (TAG), (VAL))
+ _bfd_elf_add_dynamic_entry (info, TAG, VAL)
if (info->executable)
{
return FALSE;
}
- if (htab->plt != NULL && htab->plt->_raw_size != 0)
+ if (htab->plt != NULL && htab->plt->size != 0)
{
if (!add_dynamic_entry (DT_PLTGOT, 0)
|| !add_dynamic_entry (DT_PLTRELSZ, 0)
bad_shared_reloc (bfd *abfd, enum elf_ppc_reloc_type r_type)
{
(*_bfd_error_handler)
- (_("%s: relocation %s cannot be used when making a shared object"),
- bfd_archive_filename (abfd),
+ (_("%B: relocation %s cannot be used when making a shared object"),
+ abfd,
ppc_elf_howto_table[r_type]->name);
bfd_set_error (bfd_error_bad_value);
}
return TRUE;
#ifdef DEBUG
- fprintf (stderr, "ppc_elf_check_relocs called for section %s in %s\n",
- bfd_get_section_name (abfd, sec),
- bfd_archive_filename (abfd));
+ _bfd_error_handler ("ppc_elf_check_relocs called for section %A in %B",
+ sec, abfd);
#endif
/* Initialize howto table if not already done. */
{
/* It does not make sense to have a procedure linkage
table entry for a local symbol. */
- (*_bfd_error_handler) (_("%s(%s+0x%lx): %s reloc against "
+ (*_bfd_error_handler) (_("%B(%A+0x%lx): %s reloc against "
"local symbol"),
- bfd_archive_filename (abfd),
- sec->name,
+ abfd,
+ sec,
(long) rel->r_offset,
ppc_elf_howto_table[r_type]->name);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
- h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+ h->needs_plt = 1;
h->plt.refcount++;
break;
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_PPC_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ 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_PPC_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
h->plt.refcount++;
/* We may need a copy reloc too. */
- h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
+ h->non_got_ref = 1;
}
dodyn:
|| (h != NULL
&& (! info->symbolic
|| h->root.type == bfd_link_hash_defweak
- || (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0))))
+ || !h->def_regular))))
|| (ELIMINATE_COPY_RELOCS
&& !info->shared
&& (sec->flags & SEC_ALLOC) != 0
&& h != NULL
&& (h->root.type == bfd_link_hash_defweak
- || (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0)))
+ || !h->def_regular)))
{
struct ppc_elf_dyn_relocs *p;
struct ppc_elf_dyn_relocs **head;
is_local = FALSE;
if (h == NULL
- || !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC))
+ || !h->def_dynamic)
is_local = TRUE;
r_type = ELF32_R_TYPE (rel->r_info);
static bfd_boolean
ppc_elf_add_symbol_hook (bfd *abfd,
struct bfd_link_info *info,
- const Elf_Internal_Sym *sym,
+ Elf_Internal_Sym *sym,
const char **namep ATTRIBUTE_UNUSED,
flagword *flagsp ATTRIBUTE_UNUSED,
asection **secp,
+ reloc_index * sizeof (Elf32_External_Rela));
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ if (!h->def_regular)
{
/* Mark the symbol as undefined, rather than as defined in
the .plt section. Leave the value alone. */
Otherwise, the PLT entry would provide a definition for
the symbol even if the symbol wasn't defined anywhere,
and so the symbol would never be NULL. */
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK)
- == 0)
+ if (!h->ref_regular_nonweak)
sym->st_value = 0;
}
}
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
+ if (h->needs_copy)
{
asection *s;
Elf_Internal_Rela rela;
BFD_ASSERT (htab->plt != NULL && sdyn != NULL);
dyncon = (Elf32_External_Dyn *) sdyn->contents;
- dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+ dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
for (; dyncon < dynconend; dyncon++)
{
Elf_Internal_Dyn dyn;
break;
case DT_PLTRELSZ:
- dyn.d_un.d_val = htab->relplt->_raw_size;
+ dyn.d_un.d_val = htab->relplt->size;
break;
case DT_JMPREL:
bfd_boolean ret = TRUE;
#ifdef DEBUG
- fprintf (stderr, "ppc_elf_relocate_section called for %s section %s, "
- "%ld relocations%s\n",
- bfd_archive_filename (input_bfd),
- bfd_section_name(input_bfd, input_section),
- (long) input_section->reloc_count,
- (info->relocatable) ? " (relocatable)" : "");
+ _bfd_error_handler ("ppc_elf_relocate_section called for %B section %A, "
+ "%ld relocations%s",
+ input_bfd, input_section,
+ (long) input_section->reloc_count,
+ (info->relocatable) ? " (relocatable)" : "");
#endif
if (info->relocatable)
sec = local_sections[r_symndx];
sym_name = bfd_elf_local_sym_name (input_bfd, sym);
- relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
+ relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
}
else
{
- RELOC_FOR_GLOBAL_SYMBOL (h, sym_hashes, r_symndx,
- symtab_hdr, relocation, sec,
- unresolved_reloc, info,
- warned);
-
+ RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+ r_symndx, symtab_hdr, sym_hashes,
+ h, sec, relocation,
+ unresolved_reloc, warned);
+
sym_name = h->root.root.string;
}
branch_bit = BRANCH_PREDICT_BIT;
/* Fall thru */
- /* Branch not taken predicition relocations. */
+ /* Branch not taken prediction relocations. */
case R_PPC_ADDR14_BRNTAKEN:
case R_PPC_REL14_BRNTAKEN:
insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
{
default:
(*_bfd_error_handler)
- (_("%s: unknown relocation type %d for symbol %s"),
- bfd_archive_filename (input_bfd), (int) r_type, sym_name);
+ (_("%B: unknown relocation type %d for symbol %s"),
+ input_bfd, (int) r_type, sym_name);
bfd_set_error (bfd_error_bad_value);
ret = FALSE;
indx = 0;
if (tls_type == (TLS_TLS | TLS_LD)
&& (h == NULL
- || !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)))
+ || !h->def_dynamic))
offp = &htab->tlsld_got.offset;
else if (h != NULL)
{
if (offp == &htab->tlsld_got.offset)
tls_m = TLS_LD;
else if (h == NULL
- || !(h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_DYNAMIC))
+ || !h->def_dynamic)
tls_m &= ~TLS_LD;
/* We might have multiple got entries for this sym.
{
if ((tls_mask & TLS_LD) != 0
&& !(h == NULL
- || !(h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_DYNAMIC)))
+ || !h->def_dynamic))
off += 8;
if (tls_type != (TLS_TLS | TLS_GD))
{
got at entry m+n bears little relation to the entry m. */
if (addend != 0)
(*_bfd_error_handler)
- (_("%s(%s+0x%lx): non-zero addend on %s reloc against `%s'"),
- bfd_archive_filename (input_bfd),
- bfd_get_section_name (input_bfd, input_section),
+ (_("%B(%A+0x%lx): non-zero addend on %s reloc against `%s'"),
+ input_bfd,
+ input_section,
(long) rel->r_offset,
howto->name,
sym_name);
&& (input_section->flags & SEC_ALLOC) != 0
&& h != NULL
&& h->dynindx != -1
- && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0))
+ && !h->non_got_ref
+ && h->def_dynamic
+ && !h->def_regular))
{
int skip;
}
break;
+ case R_PPC_RELAX32PC:
+ relocation -= (input_section->output_section->vma
+ + input_section->output_offset
+ + rel->r_offset - 4);
+ /* Fall thru */
case R_PPC_RELAX32:
{
- unsigned long r_symndx;
- Elf_Internal_Sym *sym;
- asection *sym_sec;
- bfd_byte *hit_addr = 0;
- bfd_vma value = 0;
+ unsigned long t0;
+ unsigned long t1;
- r_symndx = ELF32_R_SYM (rel->r_info);
+ t0 = bfd_get_32 (output_bfd, contents + rel->r_offset);
+ t1 = bfd_get_32 (output_bfd, contents + rel->r_offset + 4);
- if (r_symndx < symtab_hdr->sh_info)
- {
- sym = local_syms + r_symndx;
- sym_sec = local_sections[r_symndx];
+ /* We're clearing the bits for R_PPC_ADDR16_HA
+ and R_PPC_ADDR16_LO here. */
+ t0 &= ~0xffff;
+ t1 &= ~0xffff;
- value = _bfd_elf_rela_local_sym (output_bfd, sym, sym_sec, rel);
- }
- else
- {
- bfd_boolean warned;
- bfd_boolean unresolved_reloc;
-
- RELOC_FOR_GLOBAL_SYMBOL (h, elf_sym_hashes (input_bfd),
- r_symndx, symtab_hdr,
- value, sym_sec,
- unresolved_reloc, info,
- warned);
- if (warned)
- continue;
- }
- hit_addr = contents + rel->r_offset;
- value += rel->r_addend;
+ /* t0 is HA, t1 is LO */
+ relocation += addend;
+ t0 |= ((relocation + 0x8000) >> 16) & 0xffff;
+ t1 |= relocation & 0xffff;
- r = ppc_elf_install_value (output_bfd, hit_addr, value, r_type);
- if (r != bfd_reloc_ok)
- break;
- else
- continue;
+ bfd_put_32 (output_bfd, t0, contents + rel->r_offset);
+ bfd_put_32 (output_bfd, t1, contents + rel->r_offset + 4);
}
+ continue;
/* Indirect .sdata relocation. */
case R_PPC_EMB_SDAI16:
BFD_ASSERT (sec != NULL);
BFD_ASSERT (bfd_is_und_section (sec)
|| strcmp (bfd_get_section_name (abfd, sec), ".got") == 0
- || strcmp (bfd_get_section_name (abfd, sec), ".cgot") == 0)
+ || strcmp (bfd_get_section_name (abfd, sec), ".cgot") == 0);
addend -= sec->output_section->vma + sec->output_offset + 0x8000;
break;
&& (name[5] == 0 || name[5] == '.'))))
{
(*_bfd_error_handler)
- (_("%s: the target (%s) of a %s relocation is "
+ (_("%B: the target (%s) of a %s relocation is "
"in the wrong output section (%s)"),
- bfd_archive_filename (input_bfd),
+ input_bfd,
sym_name,
howto->name,
name);
|| strncmp (name, ".sbss2", 6) == 0))
{
(*_bfd_error_handler)
- (_("%s: the target (%s) of a %s relocation is "
+ (_("%B: the target (%s) of a %s relocation is "
"in the wrong output section (%s)"),
- bfd_archive_filename (input_bfd),
+ input_bfd,
sym_name,
howto->name,
name);
else
{
(*_bfd_error_handler)
- (_("%s: the target (%s) of a %s relocation is "
+ (_("%B: the target (%s) of a %s relocation is "
"in the wrong output section (%s)"),
- bfd_archive_filename (input_bfd),
+ input_bfd,
sym_name,
howto->name,
name);
case R_PPC_EMB_RELST_HA:
case R_PPC_EMB_BIT_FLD:
(*_bfd_error_handler)
- (_("%s: relocation %s is not yet supported for symbol %s."),
- bfd_archive_filename (input_bfd),
+ (_("%B: relocation %s is not yet supported for symbol %s."),
+ input_bfd,
howto->name,
sym_name);
if (unresolved_reloc
&& !((input_section->flags & SEC_DEBUGGING) != 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0))
+ && h->def_dynamic))
{
(*_bfd_error_handler)
- (_("%s(%s+0x%lx): unresolvable %s relocation against symbol `%s'"),
- bfd_archive_filename (input_bfd),
- bfd_get_section_name (input_bfd, input_section),
+ (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
+ input_bfd,
+ input_section,
(long) rel->r_offset,
howto->name,
sym_name);
}
if (! (*info->callbacks->reloc_overflow) (info,
+ (h ? &h->root : NULL),
sym_name,
howto->name,
rel->r_addend,
else
{
(*_bfd_error_handler)
- (_("%s(%s+0x%lx): %s reloc against `%s': error %d"),
- bfd_archive_filename (input_bfd),
- bfd_get_section_name (input_bfd, input_section),
+ (_("%B(%A+0x%lx): %s reloc against `%s': error %d"),
+ input_bfd, input_section,
(long) rel->r_offset, howto->name, sym_name, (int) r);
ret = FALSE;
}
ppc_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
{
int offset;
- unsigned int raw_size;
+ unsigned int size;
switch (note->descsz)
{
/* pr_reg */
offset = 72;
- raw_size = 192;
+ size = 192;
break;
}
/* Make a ".reg/999" section. */
return _bfd_elfcore_make_pseudosection (abfd, ".reg",
- raw_size, note->descpos + offset);
+ size, note->descpos + offset);
}
static bfd_boolean
if (asec)
{
++ num_input_sections;
- output_section_size += asec->_raw_size;
+ output_section_size += asec->size;
}
}
if (asec == NULL)
continue;
- length = asec->_raw_size;
+ length = asec->size;
if (length < 24)
{
- error_message = _("corrupt or empty %s section in %s");
+ error_message = _("corrupt or empty %s section in %B");
goto fail;
}
if (bfd_seek (ibfd, asec->filepos, SEEK_SET) != 0
|| (bfd_bread (buffer + offset, length, ibfd) != length))
{
- error_message = _("unable to read in %s section from %s");
+ error_message = _("unable to read in %s section from %B");
goto fail;
}
/* Process the contents of the section. */
ptr = buffer + offset;
- error_message = _("corrupt %s section in %s");
+ error_message = _("corrupt %s section in %B");
/* Verify the contents of the header. Note - we have to
extract the values this way in order to allow for a
if (! bfd_set_section_size (abfd, asec, output_section_size))
ibfd = abfd,
- error_message = _("warning: unable to set size of %s section in %s");
+ error_message = _("warning: unable to set size of %s section in %B");
fail:
free (buffer);
if (error_message)
- (*_bfd_error_handler) (error_message, APUINFO_SECTION_NAME,
- bfd_archive_filename (ibfd));
+ (*_bfd_error_handler) (error_message, ibfd, APUINFO_SECTION_NAME);
}
if (apuinfo_list_length () == 0)
return;
- length = asec->_raw_size;
+ length = asec->size;
if (length < 20)
return;
length += 4;
}
- if (length != asec->_raw_size)
+ if (length != asec->size)
(*_bfd_error_handler) (_("failed to compute new APUinfo section."));
if (! bfd_set_section_contents (abfd, asec, buffer, (file_ptr) 0, length))
apuinfo_list_finish ();
}
+/* Return address for Ith PLT stub in section PLT, for relocation REL
+ or (bfd_vma) -1 if it should not be included. */
+
+static bfd_vma
+ppc_elf_plt_sym_val (bfd_vma i ATTRIBUTE_UNUSED,
+ const asection *plt ATTRIBUTE_UNUSED,
+ const arelent *rel)
+{
+ return rel->address;
+}
+
/* Add extra PPC sections -- Note, for now, make .sbss2 and
.PPC.EMB.sbss0 a normal section, and not a bss section so
that the linker doesn't crater when trying to make more than
#define elf_backend_finish_dynamic_sections ppc_elf_finish_dynamic_sections
#define elf_backend_fake_sections ppc_elf_fake_sections
#define elf_backend_additional_program_headers ppc_elf_additional_program_headers
-#define elf_backend_modify_segment_map ppc_elf_modify_segment_map
#define elf_backend_grok_prstatus ppc_elf_grok_prstatus
#define elf_backend_grok_psinfo ppc_elf_grok_psinfo
#define elf_backend_reloc_type_class ppc_elf_reloc_type_class
#define elf_backend_final_write_processing ppc_elf_final_write_processing
#define elf_backend_write_section ppc_elf_write_section
#define elf_backend_special_sections ppc_elf_special_sections
+#define elf_backend_plt_sym_val ppc_elf_plt_sym_val
#include "elf32-target.h"