/* IBM S/390-specific support for 32-bit ELF
- Copyright 2000, 2001 Free Software Foundation, Inc.
+ Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Carl B. Pedersen and Martin Schwidefsky.
This file is part of BFD, the Binary File Descriptor library.
static boolean elf_s390_finish_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
static boolean elf_s390_object_p PARAMS ((bfd *));
+static boolean elf_s390_grok_prstatus PARAMS ((bfd *, Elf_Internal_Note *));
#define USE_RELA 1 /* We want RELA relocations, not REL. */
HOWTO(R_390_PC16, 0, 1, 16, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_390_PC16", false, 0,0x0000ffff, true),
HOWTO(R_390_PC16DBL, 1, 1, 16, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_390_PC16DBL", false, 0,0x0000ffff, true),
HOWTO(R_390_PLT16DBL, 1, 1, 16, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_390_PLT16DBL", false, 0,0x0000ffff, true),
+ HOWTO(R_390_PC32DBL, 1, 2, 32, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_390_PC32DBL", false, 0,0xffffffff, true),
+ HOWTO(R_390_PLT32DBL, 1, 2, 32, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_390_PLT32DBL", false, 0,0xffffffff, true),
+ HOWTO(R_390_GOTPCDBL, 1, 2, 32, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_390_GOTPCDBL", false, 0,0xffffffff, true),
+ HOWTO(R_390_GOTENT, 1, 2, 32, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_390_GOTENT", false, 0,0xffffffff, true),
};
/* GNU extension to record C++ vtable hierarchy. */
return &elf_howto_table[(int) R_390_PC16DBL];
case BFD_RELOC_390_PLT16DBL:
return &elf_howto_table[(int) R_390_PLT16DBL];
+ case BFD_RELOC_390_PC32DBL:
+ return &elf_howto_table[(int) R_390_PC32DBL];
+ case BFD_RELOC_390_PLT32DBL:
+ return &elf_howto_table[(int) R_390_PLT32DBL];
+ case BFD_RELOC_390_GOTPCDBL:
+ return &elf_howto_table[(int) R_390_GOTPCDBL];
+ case BFD_RELOC_390_GOTENT:
+ return &elf_howto_table[(int) R_390_GOTENT];
case BFD_RELOC_VTABLE_INHERIT:
return &elf32_s390_vtinherit_howto;
case BFD_RELOC_VTABLE_ENTRY:
case R_390_GOT12:
case R_390_GOT16:
case R_390_GOT32:
+ case R_390_GOTENT:
/* This symbol requires a global offset table entry. */
if (h != NULL)
{
case R_390_GOTOFF:
case R_390_GOTPC:
+ case R_390_GOTPCDBL:
if (htab->sgot == NULL)
{
if (htab->elf.dynobj == NULL)
break;
case R_390_PLT16DBL:
+ case R_390_PLT32DBL:
case R_390_PLT32:
/* This symbol requires a procedure linkage table entry. We
actually build the entry in adjust_dynamic_symbol,
case R_390_32:
case R_390_PC16:
case R_390_PC16DBL:
+ case R_390_PC32DBL:
case R_390_PC32:
if (h != NULL && !info->shared)
{
&& (sec->flags & SEC_ALLOC) != 0
&& ((ELF32_R_TYPE (rel->r_info) != R_390_PC16
&& ELF32_R_TYPE (rel->r_info) != R_390_PC16DBL
+ && ELF32_R_TYPE (rel->r_info) != R_390_PC32DBL
&& ELF32_R_TYPE (rel->r_info) != R_390_PC32)
|| (h != NULL
&& (! info->symbolic
p->count += 1;
if (ELF32_R_TYPE (rel->r_info) == R_390_PC16
|| ELF32_R_TYPE (rel->r_info) == R_390_PC16DBL
+ || ELF32_R_TYPE (rel->r_info) == R_390_PC32DBL
|| ELF32_R_TYPE (rel->r_info) == R_390_PC32)
p->pc_count += 1;
}
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_390_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+ if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return false;
break;
case R_390_GOT32:
case R_390_GOTOFF:
case R_390_GOTPC:
+ case R_390_GOTPCDBL:
+ case R_390_GOTENT:
r_symndx = ELF32_R_SYM (rel->r_info);
if (r_symndx >= symtab_hdr->sh_info)
{
case R_390_32:
case R_390_PC16:
case R_390_PC16DBL:
+ case R_390_PC32DBL:
case R_390_PC32:
r_symndx = ELF32_R_SYM (rel->r_info);
if (r_symndx >= symtab_hdr->sh_info)
{
if (ELF32_R_TYPE (rel->r_info) == R_390_PC16
|| ELF32_R_TYPE (rel->r_info) == R_390_PC16DBL
+ || ELF32_R_TYPE (rel->r_info) == R_390_PC32DBL
|| ELF32_R_TYPE (rel->r_info) == R_390_PC32)
p->pc_count -= 1;
p->count -= 1;
break;
case R_390_PLT16DBL:
+ case R_390_PLT32DBL:
case R_390_PLT32:
r_symndx = ELF32_R_SYM (rel->r_info);
if (r_symndx >= symtab_hdr->sh_info)
if (h->plt.refcount <= 0
|| (! info->shared
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0))
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0
+ && h->root.type != bfd_link_hash_undefweak
+ && h->root.type != bfd_link_hash_undefined))
{
/* This case can occur if we saw a PLT32 reloc in an input
file, but the symbol was never referred to by a dynamic
struct elf_s390_link_hash_entry *eh;
struct elf_s390_dyn_relocs *p;
- if (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
+ if (h->root.type == bfd_link_hash_indirect)
return true;
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
info = (struct bfd_link_info *) inf;
htab = elf_s390_hash_table (info);
struct elf_s390_link_hash_entry *eh;
struct elf_s390_dyn_relocs *p;
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
eh = (struct elf_s390_link_hash_entry *) h;
for (p = eh->dyn_relocs; p != NULL; p = p->next)
{
linker script /DISCARD/, so we'll be discarding
the relocs too. */
}
- else
+ else if (p->count != 0)
{
srela = elf_section_data (p->sec)->sreloc;
srela->_raw_size += p->count * sizeof (Elf32_External_Rela);
+ if ((p->sec->output_section->flags & SEC_READONLY) != 0)
+ info->flags |= DF_TEXTREL;
}
}
}
/* If any dynamic relocs apply to a read-only section,
then we need a DT_TEXTREL entry. */
- elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, (PTR) info);
+ if ((info->flags & DF_TEXTREL) == 0)
+ elf_link_hash_traverse (&htab->elf, readonly_dynrelocs,
+ (PTR) info);
if ((info->flags & DF_TEXTREL) != 0)
{
case R_390_GOT12:
case R_390_GOT16:
case R_390_GOT32:
+ case R_390_GOTENT:
/* Relocation is to the entry for this symbol in the global
offset table. */
if (htab->sgot == NULL)
abort ();
relocation = htab->sgot->output_offset + off;
+
+ /*
+ * For @GOTENT the relocation is against the offset between
+ * the instruction and the symbols entry in the GOT and not
+ * between the start of the GOT and the symbols entry. We
+ * add the vma of the GOT to get the correct value.
+ */
+ if (r_type == R_390_GOTENT)
+ relocation += htab->sgot->output_section->vma;
+
break;
case R_390_GOTOFF:
break;
case R_390_GOTPC:
+ case R_390_GOTPCDBL:
/* Use global offset table as symbol value. */
relocation = htab->sgot->output_section->vma;
unresolved_reloc = false;
break;
case R_390_PLT16DBL:
+ case R_390_PLT32DBL:
case R_390_PLT32:
/* Relocation is to the entry for this symbol in the
procedure linkage table. */
case R_390_32:
case R_390_PC16:
case R_390_PC16DBL:
+ case R_390_PC32DBL:
case R_390_PC32:
/* r_symndx will be zero only for relocs against symbols
from removed linkonce sections, or sections discarded by
if ((info->shared
&& ((r_type != R_390_PC16
&& r_type != R_390_PC16DBL
+ && r_type != R_390_PC32DBL
&& r_type != R_390_PC32)
|| (h != NULL
&& h->dynindx != -1
time. */
skip = false;
+ relocate = false;
outrel.r_offset =
_bfd_elf_section_offset (output_bfd, info, input_section,
rel->r_offset);
if (outrel.r_offset == (bfd_vma) -1)
skip = true;
+ else if (outrel.r_offset == (bfd_vma) -2)
+ skip = true, relocate = true;
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
if (skip)
- {
- memset (&outrel, 0, sizeof outrel);
- relocate = false;
- }
+ memset (&outrel, 0, sizeof outrel);
else if (h != NULL
&& h->dynindx != -1
&& (r_type == R_390_PC16
|| r_type == R_390_PC16DBL
+ || r_type == R_390_PC32DBL
|| r_type == R_390_PC32
|| !info->shared
|| !info->symbolic
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0))
{
- relocate = false;
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
outrel.r_addend = rel->r_addend;
}
elf_s390_object_p (abfd)
bfd *abfd;
{
- return bfd_default_set_arch_mach (abfd, bfd_arch_s390, bfd_mach_s390_esa);
+ return bfd_default_set_arch_mach (abfd, bfd_arch_s390, bfd_mach_s390_31);
}
static boolean