#endif
if (sreloc == NULL)
{
- const char *name;
-
- name = (bfd_elf_string_from_elf_section
- (abfd,
- elf_elfheader (abfd)->e_shstrndx,
- elf_section_data (sec)->rel_hdr.sh_name));
- if (name == NULL)
- return FALSE;
-
- BFD_ASSERT (CONST_STRNEQ (name, ".rela")
- && strcmp (bfd_get_section_name (abfd, sec),
- name + 5) == 0);
-
if (htab->elf.dynobj == NULL)
htab->elf.dynobj = abfd;
- sreloc = bfd_get_section_by_name (htab->elf.dynobj, name);
+
+ sreloc = _bfd_elf_make_dynamic_reloc_section
+ (sec, htab->elf.dynobj, 2, abfd, /*rela?*/ TRUE);
+
if (sreloc == NULL)
- {
- flagword flags;
-
- flags = (SEC_HAS_CONTENTS | SEC_READONLY
- | SEC_IN_MEMORY | SEC_LINKER_CREATED
- | SEC_ALLOC | SEC_LOAD);
- sreloc = bfd_make_section_with_flags (htab->elf.dynobj,
- name,
- flags);
- if (sreloc == NULL
- || ! bfd_set_section_alignment (htab->elf.dynobj,
- sreloc, 2))
- return FALSE;
- }
- elf_section_data (sec)->sreloc = sreloc;
+ return FALSE;
}
/* If this is a global symbol, we count the number of
ibfd, obfd, in_abi, out_abi);
}
+ /* Check for conflicting Tag_GNU_Power_ABI_Struct_Return attributes
+ and merge non-conflicting ones. */
+ in_attr = &in_attrs[Tag_GNU_Power_ABI_Struct_Return];
+ out_attr = &out_attrs[Tag_GNU_Power_ABI_Struct_Return];
+ if (in_attr->i != out_attr->i)
+ {
+ out_attr->type = 1;
+ if (out_attr->i == 0)
+ out_attr->i = in_attr->i;
+ else if (in_attr->i == 0)
+ ;
+ else if (out_attr->i == 1 && in_attr->i == 2)
+ _bfd_error_handler
+ (_("Warning: %B uses r3/r4 for small structure returns, %B uses memory"), obfd, ibfd);
+ else if (out_attr->i == 2 && in_attr->i == 1)
+ _bfd_error_handler
+ (_("Warning: %B uses r3/r4 for small structure returns, %B uses memory"), ibfd, obfd);
+ else if (in_attr->i > 2)
+ _bfd_error_handler
+ (_("Warning: %B uses unknown small structure return convention %d"), ibfd,
+ in_attr->i);
+ else
+ _bfd_error_handler
+ (_("Warning: %B uses unknown small structure return convention %d"), obfd,
+ out_attr->i);
+ }
+
/* Merge Tag_compatibility attributes and any common GNU ones. */
_bfd_elf_merge_object_attributes (ibfd, obfd);
eh = (struct ppc_elf_link_hash_entry *) h;
if (eh->elf.got.refcount > 0)
{
+ bfd_boolean dyn;
+ unsigned int need;
+
/* Make sure this symbol is output as a dynamic symbol. */
if (eh->elf.dynindx == -1
&& !eh->elf.forced_local
return FALSE;
}
- if (eh->tls_mask == (TLS_TLS | TLS_LD)
- && !eh->elf.def_dynamic)
- {
- /* If just an LD reloc, we'll just use htab->tlsld_got.offset. */
- htab->tlsld_got.refcount += 1;
- eh->elf.got.offset = (bfd_vma) -1;
- }
- else
+ need = 0;
+ if ((eh->tls_mask & TLS_TLS) != 0)
{
- bfd_boolean dyn;
- unsigned int need = 0;
- if ((eh->tls_mask & TLS_TLS) != 0)
+ if ((eh->tls_mask & TLS_LD) != 0)
{
- if ((eh->tls_mask & TLS_LD) != 0)
- need += 8;
- if ((eh->tls_mask & TLS_GD) != 0)
+ if (!eh->elf.def_dynamic)
+ /* We'll just use htab->tlsld_got.offset. This should
+ always be the case. It's a little odd if we have
+ a local dynamic reloc against a non-local symbol. */
+ htab->tlsld_got.refcount += 1;
+ else
need += 8;
- if ((eh->tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0)
- need += 4;
- if ((eh->tls_mask & TLS_DTPREL) != 0)
- need += 4;
}
- else
+ if ((eh->tls_mask & TLS_GD) != 0)
+ need += 8;
+ if ((eh->tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0)
+ need += 4;
+ if ((eh->tls_mask & TLS_DTPREL) != 0)
need += 4;
+ }
+ else
+ need += 4;
+ if (need == 0)
+ eh->elf.got.offset = (bfd_vma) -1;
+ else
+ {
eh->elf.got.offset = allocate_got (htab, need);
dyn = htab->elf.dynamic_sections_created;
if ((info->shared
{
/* All the entries we allocated need relocs.
Except LD only needs one. */
- if ((eh->tls_mask & TLS_LD) != 0)
+ if ((eh->tls_mask & TLS_LD) != 0
+ && eh->elf.def_dynamic)
need -= 4;
htab->relgot->size += need * (sizeof (Elf32_External_Rela) / 4);
}
for (; local_got < end_local_got; ++local_got, ++lgot_masks)
if (*local_got > 0)
{
- if (*lgot_masks == (TLS_TLS | TLS_LD))
+ unsigned int need = 0;
+ if ((*lgot_masks & TLS_TLS) != 0)
{
- /* If just an LD reloc, we'll just use
- htab->tlsld_got.offset. */
- htab->tlsld_got.refcount += 1;
- *local_got = (bfd_vma) -1;
+ if ((*lgot_masks & TLS_GD) != 0)
+ need += 8;
+ if ((*lgot_masks & TLS_LD) != 0)
+ htab->tlsld_got.refcount += 1;
+ if ((*lgot_masks & (TLS_TPREL | TLS_TPRELGD)) != 0)
+ need += 4;
+ if ((*lgot_masks & TLS_DTPREL) != 0)
+ need += 4;
}
+ else
+ need += 4;
+ if (need == 0)
+ *local_got = (bfd_vma) -1;
else
{
- unsigned int need = 0;
- if ((*lgot_masks & TLS_TLS) != 0)
- {
- if ((*lgot_masks & TLS_GD) != 0)
- need += 8;
- if ((*lgot_masks & (TLS_TPREL | TLS_TPRELGD)) != 0)
- need += 4;
- if ((*lgot_masks & TLS_DTPREL) != 0)
- need += 4;
- }
- else
- need += 4;
*local_got = allocate_got (htab, need);
if (info->shared)
htab->relgot->size += (need
/* Generate relocs for the dynamic linker. */
if ((info->shared || indx != 0)
- && (h == NULL
+ && (offp == &htab->tlsld_got.offset
+ || h == NULL
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak))
{
outrel.r_info = ELF32_R_INFO (indx, R_PPC_RELATIVE);
else
outrel.r_info = ELF32_R_INFO (indx, R_PPC_GLOB_DAT);
- if (indx == 0)
+ if (indx == 0 && tls_ty != (TLS_TLS | TLS_LD))
{
outrel.r_addend += relocation;
if (tls_ty & (TLS_GD | TLS_DTPREL | TLS_TPREL))
time. */
if (sreloc == NULL)
{
- const char *name;
-
- name = (bfd_elf_string_from_elf_section
- (input_bfd,
- elf_elfheader (input_bfd)->e_shstrndx,
- elf_section_data (input_section)->rel_hdr.sh_name));
- if (name == NULL)
+ sreloc = _bfd_elf_get_dynamic_reloc_section
+ (input_bfd, input_section, /*rela?*/ TRUE);
+ if (sreloc == NULL)
return FALSE;
-
- BFD_ASSERT (CONST_STRNEQ (name, ".rela")
- && strcmp (bfd_get_section_name (input_bfd,
- input_section),
- name + 5) == 0);
-
- sreloc = bfd_get_section_by_name (htab->elf.dynobj, name);
- BFD_ASSERT (sreloc != NULL);
}
skip = 0;
}
}
- /* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4 so that a function can
- easily find the address of the _GLOBAL_OFFSET_TABLE_. */
if (htab->got != NULL)
{
- if (htab->elf.hgot->root.u.def.section == htab->got)
+ if (htab->elf.hgot->root.u.def.section == htab->got
+ || htab->elf.hgot->root.u.def.section == htab->sgotplt)
{
- unsigned char *p = htab->got->contents;
- bfd_vma val;
+ unsigned char *p = htab->elf.hgot->root.u.def.section->contents;
p += htab->elf.hgot->root.u.def.value;
if (htab->plt_type == PLT_OLD)
- bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, p - 4);
+ {
+ /* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4
+ so that a function can easily find the address of
+ _GLOBAL_OFFSET_TABLE_. */
+ BFD_ASSERT (htab->elf.hgot->root.u.def.value - 4
+ < htab->elf.hgot->root.u.def.section->size);
+ bfd_put_32 (output_bfd, 0x4e800021, p - 4);
+ }
- val = 0;
if (sdyn != NULL)
- val = sdyn->output_section->vma + sdyn->output_offset;
- bfd_put_32 (output_bfd, val, p);
+ {
+ bfd_vma val = sdyn->output_section->vma + sdyn->output_offset;
+ BFD_ASSERT (htab->elf.hgot->root.u.def.value
+ < htab->elf.hgot->root.u.def.section->size);
+ bfd_put_32 (output_bfd, val, p);
+ }
}
else
{
(*_bfd_error_handler) (_("%s not defined in linker created %s"),
htab->elf.hgot->root.root.string,
- htab->got->name);
+ (htab->sgotplt != NULL
+ ? htab->sgotplt->name : htab->got->name));
bfd_set_error (bfd_error_bad_value);
ret = FALSE;
}