/* IBM S/390-specific support for 64-bit ELF
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
- 2010 Free Software Foundation, Inc.
+ 2010, 2011, 2012 Free Software Foundation, Inc.
Contributed Martin Schwidefsky (schwidefsky@de.ibm.com).
This file is part of BFD, the Binary File Descriptor library.
/* The name of the dynamic interpreter. This is put in the .interp
section. */
-#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
+#define ELF_DYNAMIC_INTERPRETER "/lib/ld64.so.1"
/* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid
copying dynamic variables from a shared lib into an app's dynbss
RET1: BASR 1,0 # 2 bytes Return from GOT 1st time
LGF 1,12(1) # 6 bytes Load offset in symbl table in r1
BRCL 15,-x # 6 bytes Jump to start of PLT
- .long ? # 4 bytes offset into symbol table
+ .long ? # 4 bytes offset into .rela.plt
Total = 32 bytes per PLT entry
Fixup at offset 2: relative address to GOT entry
Fixup at offset 22: relative branch to PLT0
- Fixup at offset 28: 32 bit offset into symbol table
-
- A 32 bit offset into the symbol table is enough. It allows for symbol
- tables up to a size of 2 gigabyte. A single dynamic object (the main
- program, any shared library) is limited to 4GB in size and I want to see
- the program that manages to have a symbol table of more than 2 GB with a
- total size of at max 4 GB. */
-
-#define PLT_ENTRY_WORD0 (bfd_vma) 0xc0100000
-#define PLT_ENTRY_WORD1 (bfd_vma) 0x0000e310
-#define PLT_ENTRY_WORD2 (bfd_vma) 0x10000004
-#define PLT_ENTRY_WORD3 (bfd_vma) 0x07f10d10
-#define PLT_ENTRY_WORD4 (bfd_vma) 0xe310100c
-#define PLT_ENTRY_WORD5 (bfd_vma) 0x0014c0f4
-#define PLT_ENTRY_WORD6 (bfd_vma) 0x00000000
-#define PLT_ENTRY_WORD7 (bfd_vma) 0x00000000
+ Fixup at offset 28: 32 bit offset into .rela.plt
+
+ A 32 bit offset into the symbol table is enough. It allows for
+ .rela.plt sections up to a size of 2 gigabyte. A single dynamic
+ object (the main program, any shared library) is limited to 4GB in
+ size. Having a .rela.plt of 2GB would already make the .plt
+ section bigger than 8GB. */
+
+static const bfd_byte elf_s390x_plt_entry[PLT_ENTRY_SIZE] =
+ {
+ 0xc0, 0x10, 0x00, 0x00, 0x00, 0x00, /* larl %r1,. */
+ 0xe3, 0x10, 0x10, 0x00, 0x00, 0x04, /* lg %r1,0(%r1) */
+ 0x07, 0xf1, /* br %r1 */
+ 0x0d, 0x10, /* basr %r1,%r0 */
+ 0xe3, 0x10, 0x10, 0x0c, 0x00, 0x14, /* lgf %r1,12(%r1) */
+ 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg first plt */
+ 0x00, 0x00, 0x00, 0x00 /* .long 0x00000000 */
+ };
/* The first PLT entry pushes the offset into the symbol table
- from R1 onto the stack at 8(15) and the loader object info
- at 12(15), loads the loader address in R1 and jumps to it. */
+ from R1 onto the stack at 56(15) and the loader object info
+ at 48(15), loads the loader address in R1 and jumps to it. */
/* The first entry in the PLT:
Fixup at offset 8: relative address to start of GOT. */
-#define PLT_FIRST_ENTRY_WORD0 (bfd_vma) 0xe310f038
-#define PLT_FIRST_ENTRY_WORD1 (bfd_vma) 0x0024c010
-#define PLT_FIRST_ENTRY_WORD2 (bfd_vma) 0x00000000
-#define PLT_FIRST_ENTRY_WORD3 (bfd_vma) 0xd207f030
-#define PLT_FIRST_ENTRY_WORD4 (bfd_vma) 0x1008e310
-#define PLT_FIRST_ENTRY_WORD5 (bfd_vma) 0x10100004
-#define PLT_FIRST_ENTRY_WORD6 (bfd_vma) 0x07f10700
-#define PLT_FIRST_ENTRY_WORD7 (bfd_vma) 0x07000700
-
-/* The s390 linker needs to keep track of the number of relocs that it
- decides to copy as dynamic relocs in check_relocs for each symbol.
- This is so that it can later discard them if they are found to be
- unnecessary. We store the information in a field extending the
- regular ELF linker hash table. */
-
-struct elf_s390_dyn_relocs
-{
- struct elf_s390_dyn_relocs *next;
-
- /* The input section of the reloc. */
- asection *sec;
+static const bfd_byte elf_s390x_first_plt_entry[PLT_FIRST_ENTRY_SIZE] =
+ {
+ 0xe3, 0x10, 0xf0, 0x38, 0x00, 0x24, /* stg %r1,56(%r15) */
+ 0xc0, 0x10, 0x00, 0x00, 0x00, 0x00, /* larl %r1,. */
+ 0xd2, 0x07, 0xf0, 0x30, 0x10, 0x08, /* mvc 48(8,%r15),8(%r1) */
+ 0xe3, 0x10, 0x10, 0x10, 0x00, 0x04, /* lg %r1,16(%r1) */
+ 0x07, 0xf1, /* br %r1 */
+ 0x07, 0x00, /* nopr %r0 */
+ 0x07, 0x00, /* nopr %r0 */
+ 0x07, 0x00 /* nopr %r0 */
+ };
- /* Total number of relocs copied for the input section. */
- bfd_size_type count;
-
- /* Number of pc-relative relocs copied for the input section. */
- bfd_size_type pc_count;
-};
/* s390 ELF linker hash entry. */
struct elf_link_hash_entry elf;
/* Track dynamic relocs copied for this symbol. */
- struct elf_s390_dyn_relocs *dyn_relocs;
+ struct elf_dyn_relocs *dyn_relocs;
/* Number of GOTPLT references for a function. */
bfd_signed_vma gotplt_refcount;
struct elf_link_hash_table elf;
/* Short-cuts to get to dynamic linker sections. */
- asection *sgot;
- asection *sgotplt;
- asection *srelgot;
- asection *splt;
- asection *srelplt;
asection *sdynbss;
asection *srelbss;
return NULL;
}
- ret->sgot = NULL;
- ret->sgotplt = NULL;
- ret->srelgot = NULL;
- ret->splt = NULL;
- ret->srelplt = NULL;
+ ret->elf.sgot = NULL;
+ ret->elf.sgotplt = NULL;
+ ret->elf.srelgot = NULL;
+ ret->elf.splt = NULL;
+ ret->elf.srelplt = NULL;
ret->sdynbss = NULL;
ret->srelbss = NULL;
ret->tls_ldm_got.refcount = 0;
if (htab == NULL)
return FALSE;
- htab->sgot = bfd_get_section_by_name (dynobj, ".got");
- htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
- htab->srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
- if (!htab->sgot || !htab->sgotplt || !htab->srelgot)
+ htab->elf.sgot = bfd_get_linker_section (dynobj, ".got");
+ htab->elf.sgotplt = bfd_get_linker_section (dynobj, ".got.plt");
+ htab->elf.srelgot = bfd_get_linker_section (dynobj, ".rela.got");
+ if (!htab->elf.sgot || !htab->elf.sgotplt || !htab->elf.srelgot)
abort ();
return TRUE;
}
if (htab == NULL)
return FALSE;
- if (!htab->sgot && !create_got_section (dynobj, info))
+ if (!htab->elf.sgot && !create_got_section (dynobj, info))
return FALSE;
if (!_bfd_elf_create_dynamic_sections (dynobj, info))
return FALSE;
- htab->splt = bfd_get_section_by_name (dynobj, ".plt");
- htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
- htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
+ htab->elf.splt = bfd_get_linker_section (dynobj, ".plt");
+ htab->elf.srelplt = bfd_get_linker_section (dynobj, ".rela.plt");
+ htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
if (!info->shared)
- htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss");
+ htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
- if (!htab->splt || !htab->srelplt || !htab->sdynbss
+ if (!htab->elf.splt || !htab->elf.srelplt || !htab->sdynbss
|| (!info->shared && !htab->srelbss))
abort ();
{
if (edir->dyn_relocs != NULL)
{
- struct elf_s390_dyn_relocs **pp;
- struct elf_s390_dyn_relocs *p;
+ struct elf_dyn_relocs **pp;
+ struct elf_dyn_relocs *p;
/* Add reloc counts against the indirect sym to the direct sym
list. Merge any entries against the same section. */
for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
{
- struct elf_s390_dyn_relocs *q;
+ struct elf_dyn_relocs *q;
for (q = edir->dyn_relocs; q != NULL; q = q->next)
if (q->sec == p->sec)
case R_390_GOTOFF64:
case R_390_GOTPC:
case R_390_GOTPCDBL:
- if (htab->sgot == NULL)
+ if (htab->elf.sgot == NULL)
{
if (htab->elf.dynobj == NULL)
htab->elf.dynobj = abfd;
&& (h->root.type == bfd_link_hash_defweak
|| !h->def_regular)))
{
- struct elf_s390_dyn_relocs *p;
- struct elf_s390_dyn_relocs **head;
+ struct elf_dyn_relocs *p;
+ struct elf_dyn_relocs **head;
/* We must copy these reloc types into the output file.
Create a reloc section in dynobj and make room for
s = sec;
vpp = &elf_section_data (s)->local_dynrel;
- head = (struct elf_s390_dyn_relocs **) vpp;
+ head = (struct elf_dyn_relocs **) vpp;
}
p = *head;
if (p == NULL || p->sec != sec)
{
bfd_size_type amt = sizeof *p;
- p = ((struct elf_s390_dyn_relocs *)
+ p = ((struct elf_dyn_relocs *)
bfd_alloc (htab->elf.dynobj, amt));
if (p == NULL)
return FALSE;
if (r_symndx >= symtab_hdr->sh_info)
{
struct elf_s390_link_hash_entry *eh;
- struct elf_s390_dyn_relocs **pp;
- struct elf_s390_dyn_relocs *p;
+ struct elf_dyn_relocs **pp;
+ struct elf_dyn_relocs *p;
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
while (h->root.type == bfd_link_hash_indirect
if (ELIMINATE_COPY_RELOCS)
{
struct elf_s390_link_hash_entry * eh;
- struct elf_s390_dyn_relocs *p;
+ struct elf_dyn_relocs *p;
eh = (struct elf_s390_link_hash_entry *) h;
for (p = eh->dyn_relocs; p != NULL; p = p->next)
}
}
- if (h->size == 0)
- {
- (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
- h->root.root.string);
- return TRUE;
- }
-
/* We must allocate the symbol in our .dynbss section, which will
become part of the .bss section of the executable. There will be
an entry for this symbol in the .dynsym section. The dynamic
/* We must generate a R_390_COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. */
- if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
htab->srelbss->size += sizeof (Elf64_External_Rela);
h->needs_copy = 1;
struct bfd_link_info *info;
struct elf_s390_link_hash_table *htab;
struct elf_s390_link_hash_entry *eh;
- struct elf_s390_dyn_relocs *p;
+ struct elf_dyn_relocs *p;
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
- if (h->root.type == bfd_link_hash_warning)
- /* When warning symbols are created, they **replace** the "real"
- entry in the hash table, thus we never get to see the real
- symbol in a hash traversal. So look at it now. */
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
info = (struct bfd_link_info *) inf;
htab = elf_s390_hash_table (info);
if (htab == NULL)
if (info->shared
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
{
- asection *s = htab->splt;
+ asection *s = htab->elf.splt;
/* If this is the first .plt entry, make room for the special
first entry. */
/* We also need to make an entry in the .got.plt section, which
will be placed in the .got section by the linker script. */
- htab->sgotplt->size += GOT_ENTRY_SIZE;
+ htab->elf.sgotplt->size += GOT_ENTRY_SIZE;
/* We also need to make an entry in the .rela.plt section. */
- htab->srelplt->size += sizeof (Elf64_External_Rela);
+ htab->elf.srelplt->size += sizeof (Elf64_External_Rela);
}
else
{
to be stored somewhere. The immediate value in the instruction
is not bit enough so the value is stored in the got. */
{
- h->got.offset = htab->sgot->size;
- htab->sgot->size += GOT_ENTRY_SIZE;
+ h->got.offset = htab->elf.sgot->size;
+ htab->elf.sgot->size += GOT_ENTRY_SIZE;
}
else
h->got.offset = (bfd_vma) -1;
return FALSE;
}
- s = htab->sgot;
+ s = htab->elf.sgot;
h->got.offset = s->size;
s->size += GOT_ENTRY_SIZE;
/* R_390_TLS_GD64 needs 2 consecutive GOT slots. */
R_390_TLS_GD64 needs one if local symbol and two if global. */
if ((tls_type == GOT_TLS_GD && h->dynindx == -1)
|| tls_type >= GOT_TLS_IE)
- htab->srelgot->size += sizeof (Elf64_External_Rela);
+ htab->elf.srelgot->size += sizeof (Elf64_External_Rela);
else if (tls_type == GOT_TLS_GD)
- htab->srelgot->size += 2 * sizeof (Elf64_External_Rela);
+ htab->elf.srelgot->size += 2 * sizeof (Elf64_External_Rela);
else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak)
&& (info->shared
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
- htab->srelgot->size += sizeof (Elf64_External_Rela);
+ htab->elf.srelgot->size += sizeof (Elf64_External_Rela);
}
else
h->got.offset = (bfd_vma) -1;
{
if (SYMBOL_CALLS_LOCAL (info, h))
{
- struct elf_s390_dyn_relocs **pp;
+ struct elf_dyn_relocs **pp;
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
{
PTR inf;
{
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;
+ struct elf_dyn_relocs *p;
eh = (struct elf_s390_link_hash_entry *) h;
for (p = eh->dyn_relocs; p != NULL; p = p->next)
/* Set the contents of the .interp section to the interpreter. */
if (info->executable)
{
- s = bfd_get_section_by_name (dynobj, ".interp");
+ s = bfd_get_linker_section (dynobj, ".interp");
if (s == NULL)
abort ();
s->size = sizeof ELF_DYNAMIC_INTERPRETER;
for (s = ibfd->sections; s != NULL; s = s->next)
{
- struct elf_s390_dyn_relocs *p;
+ struct elf_dyn_relocs *p;
for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
{
locsymcount = symtab_hdr->sh_info;
end_local_got = local_got + locsymcount;
local_tls_type = elf_s390_local_got_tls_type (ibfd);
- s = htab->sgot;
- srela = htab->srelgot;
+ s = htab->elf.sgot;
+ srela = htab->elf.srelgot;
for (; local_got < end_local_got; ++local_got, ++local_tls_type)
{
if (*local_got > 0)
{
/* Allocate 2 got entries and 1 dynamic reloc for R_390_TLS_LDM64
relocs. */
- htab->tls_ldm_got.offset = htab->sgot->size;
- htab->sgot->size += 2 * GOT_ENTRY_SIZE;
- htab->srelgot->size += sizeof (Elf64_External_Rela);
+ htab->tls_ldm_got.offset = htab->elf.sgot->size;
+ htab->elf.sgot->size += 2 * GOT_ENTRY_SIZE;
+ htab->elf.srelgot->size += sizeof (Elf64_External_Rela);
}
else
htab->tls_ldm_got.offset = -1;
if ((s->flags & SEC_LINKER_CREATED) == 0)
continue;
- if (s == htab->splt
- || s == htab->sgot
- || s == htab->sgotplt
+ if (s == htab->elf.splt
+ || s == htab->elf.sgot
+ || s == htab->elf.sgotplt
|| s == htab->sdynbss)
{
/* Strip this section if we don't need it; see the
}
else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela"))
{
- if (s->size != 0 && s != htab->srelplt)
+ if (s->size != 0 && s != htab->elf.srelplt)
relocs = TRUE;
/* We use the reloc_count field as a counter if we need
return FALSE;
}
- if (htab->splt->size != 0)
+ if (htab->elf.splt->size != 0)
{
if (!add_dynamic_entry (DT_PLTGOT, 0)
|| !add_dynamic_entry (DT_PLTRELSZ, 0)
unresolved_reloc, warned);
}
- if (sec != NULL && elf_discarded_section (sec))
- {
- /* For relocs against symbols from removed linkonce sections,
- or sections discarded by a linker script, we just want the
- section contents zeroed. Avoid any special processing. */
- _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
- rel->r_info = 0;
- rel->r_addend = 0;
- continue;
- }
+ if (sec != NULL && discarded_section (sec))
+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+ rel, 1, relend, howto, 0, contents);
if (info->relocatable)
continue;
unresolved_reloc = FALSE;
if (r_type == R_390_GOTPLTENT)
- relocation += htab->sgot->output_section->vma;
+ relocation += htab->elf.sgot->output_section->vma;
break;
}
/* Fall through. */
case R_390_GOTENT:
/* Relocation is to the entry for this symbol in the global
offset table. */
- if (htab->sgot == NULL)
+ if (htab->elf.sgot == NULL)
abort ();
if (h != NULL)
else
{
bfd_put_64 (output_bfd, relocation,
- htab->sgot->contents + off);
+ htab->elf.sgot->contents + off);
h->got.offset |= 1;
}
}
else
{
bfd_put_64 (output_bfd, relocation,
- htab->sgot->contents + off);
+ htab->elf.sgot->contents + off);
if (info->shared)
{
Elf_Internal_Rela outrel;
bfd_byte *loc;
- s = htab->srelgot;
+ s = htab->elf.srelgot;
if (s == NULL)
abort ();
- outrel.r_offset = (htab->sgot->output_section->vma
- + htab->sgot->output_offset
+ outrel.r_offset = (htab->elf.sgot->output_section->vma
+ + htab->elf.sgot->output_offset
+ off);
outrel.r_info = ELF64_R_INFO (0, R_390_RELATIVE);
outrel.r_addend = relocation;
if (off >= (bfd_vma) -2)
abort ();
- relocation = htab->sgot->output_offset + off;
+ relocation = htab->elf.sgot->output_offset + off;
/* For @GOTENT the relocation is against the offset between
the instruction and the symbols entry in the GOT and not
add the vma of the GOT to get the correct value. */
if ( r_type == R_390_GOTENT
|| r_type == R_390_GOTPLTENT)
- relocation += htab->sgot->output_section->vma;
+ relocation += htab->elf.sgot->output_section->vma;
break;
defined _GLOBAL_OFFSET_TABLE in a different way, as is
permitted by the ABI, we might have to change this
calculation. */
- relocation -= htab->sgot->output_section->vma;
+ relocation -= htab->elf.sgot->output_section->vma;
break;
case R_390_GOTPC:
case R_390_GOTPCDBL:
/* Use global offset table as symbol value. */
- relocation = htab->sgot->output_section->vma;
+ relocation = htab->elf.sgot->output_section->vma;
unresolved_reloc = FALSE;
break;
break;
if (h->plt.offset == (bfd_vma) -1
- || htab->splt == NULL)
+ || htab->elf.splt == NULL)
{
/* We didn't make a PLT entry for this symbol. This
happens when statically linking PIC code, or when
break;
}
- relocation = (htab->splt->output_section->vma
- + htab->splt->output_offset
+ relocation = (htab->elf.splt->output_section->vma
+ + htab->elf.splt->output_offset
+ h->plt.offset);
unresolved_reloc = FALSE;
break;
this symbol resolve the symbol directly. */
if ( h == NULL
|| h->plt.offset == (bfd_vma) -1
- || htab->splt == NULL)
+ || htab->elf.splt == NULL)
{
- relocation -= htab->sgot->output_section->vma;
+ relocation -= htab->elf.sgot->output_section->vma;
break;
}
- relocation = (htab->splt->output_section->vma
- + htab->splt->output_offset
+ relocation = (htab->elf.splt->output_section->vma
+ + htab->elf.splt->output_offset
+ h->plt.offset
- - htab->sgot->output_section->vma);
+ - htab->elf.sgot->output_section->vma);
unresolved_reloc = FALSE;
break;
continue;
}
- if (htab->sgot == NULL)
+ if (htab->elf.sgot == NULL)
abort ();
if (h != NULL)
bfd_byte *loc;
int dr_type, indx;
- if (htab->srelgot == NULL)
+ if (htab->elf.srelgot == NULL)
abort ();
- outrel.r_offset = (htab->sgot->output_section->vma
- + htab->sgot->output_offset + off);
+ outrel.r_offset = (htab->elf.sgot->output_section->vma
+ + htab->elf.sgot->output_offset + off);
indx = h && h->dynindx != -1 ? h->dynindx : 0;
if (r_type == R_390_TLS_GD64)
else
outrel.r_addend = 0;
outrel.r_info = ELF64_R_INFO (indx, dr_type);
- loc = htab->srelgot->contents;
- loc += htab->srelgot->reloc_count++
+ loc = htab->elf.srelgot->contents;
+ loc += htab->elf.srelgot->reloc_count++
* sizeof (Elf64_External_Rela);
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
BFD_ASSERT (! unresolved_reloc);
bfd_put_64 (output_bfd,
relocation - dtpoff_base (info),
- htab->sgot->contents + off + GOT_ENTRY_SIZE);
+ htab->elf.sgot->contents + off + GOT_ENTRY_SIZE);
}
else
{
outrel.r_info = ELF64_R_INFO (indx, R_390_TLS_DTPOFF);
outrel.r_offset += GOT_ENTRY_SIZE;
outrel.r_addend = 0;
- htab->srelgot->reloc_count++;
+ htab->elf.srelgot->reloc_count++;
loc += sizeof (Elf64_External_Rela);
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
}
abort ();
if (r_type == ELF64_R_TYPE (rel->r_info))
{
- relocation = htab->sgot->output_offset + off;
+ relocation = htab->elf.sgot->output_offset + off;
if (r_type == R_390_TLS_IE64 || r_type == R_390_TLS_IEENT)
- relocation += htab->sgot->output_section->vma;
+ relocation += htab->elf.sgot->output_section->vma;
unresolved_reloc = FALSE;
}
else
{
- bfd_put_64 (output_bfd, htab->sgot->output_offset + off,
+ bfd_put_64 (output_bfd, htab->elf.sgot->output_offset + off,
contents + rel->r_offset);
continue;
}
goto emit_tls_relocs;
}
- if (htab->sgot == NULL)
+ if (htab->elf.sgot == NULL)
abort ();
BFD_ASSERT (! unresolved_reloc);
bfd_put_64 (output_bfd, -tpoff (info, relocation),
- htab->sgot->contents + off);
- relocation = htab->sgot->output_offset + off;
+ htab->elf.sgot->contents + off);
+ relocation = htab->elf.sgot->output_offset + off;
if (r_type == R_390_TLS_IEENT)
- relocation += htab->sgot->output_section->vma;
+ relocation += htab->elf.sgot->output_section->vma;
unresolved_reloc = FALSE;
break;
and the value will turn out zero. */
continue;
- if (htab->sgot == NULL)
+ if (htab->elf.sgot == NULL)
abort ();
off = htab->tls_ldm_got.offset;
Elf_Internal_Rela outrel;
bfd_byte *loc;
- if (htab->srelgot == NULL)
+ if (htab->elf.srelgot == NULL)
abort ();
- outrel.r_offset = (htab->sgot->output_section->vma
- + htab->sgot->output_offset + off);
+ outrel.r_offset = (htab->elf.sgot->output_section->vma
+ + htab->elf.sgot->output_offset + off);
bfd_put_64 (output_bfd, 0,
- htab->sgot->contents + off + GOT_ENTRY_SIZE);
+ htab->elf.sgot->contents + off + GOT_ENTRY_SIZE);
outrel.r_info = ELF64_R_INFO (0, R_390_TLS_DTPMOD);
outrel.r_addend = 0;
- loc = htab->srelgot->contents;
- loc += htab->srelgot->reloc_count++
+ loc = htab->elf.srelgot->contents;
+ loc += htab->elf.srelgot->reloc_count++
* sizeof (Elf64_External_Rela);
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
htab->tls_ldm_got.offset |= 1;
}
- relocation = htab->sgot->output_offset + off;
+ relocation = htab->elf.sgot->output_offset + off;
unresolved_reloc = FALSE;
break;
continue;
case R_390_TLS_LDO64:
- if (info->shared)
+ if (info->shared || (input_section->flags & SEC_DEBUGGING))
relocation -= dtpoff_base (info);
else
/* When converting LDO to LE, we must negate. */
not process them. */
if (unresolved_reloc
&& !((input_section->flags & SEC_DEBUGGING) != 0
- && h->def_dynamic))
+ && h->def_dynamic)
+ && _bfd_elf_section_offset (output_bfd, info, input_section,
+ rel->r_offset) != (bfd_vma) -1)
(*_bfd_error_handler)
(_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
input_bfd,
it up. */
if (h->dynindx == -1
- || htab->splt == NULL
- || htab->sgotplt == NULL
- || htab->srelplt == NULL)
+ || htab->elf.splt == NULL
+ || htab->elf.sgotplt == NULL
+ || htab->elf.srelplt == NULL)
abort ();
/* Calc. index no.
got_offset = (plt_index + 3) * GOT_ENTRY_SIZE;
/* Fill in the blueprint of a PLT. */
- bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD0,
- htab->splt->contents + h->plt.offset);
- bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD1,
- htab->splt->contents + h->plt.offset + 4);
- bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD2,
- htab->splt->contents + h->plt.offset + 8);
- bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD3,
- htab->splt->contents + h->plt.offset + 12);
- bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD4,
- htab->splt->contents + h->plt.offset + 16);
- bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD5,
- htab->splt->contents + h->plt.offset + 20);
- bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD6,
- htab->splt->contents + h->plt.offset + 24);
- bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD7,
- htab->splt->contents + h->plt.offset + 28);
+ memcpy (htab->elf.splt->contents + h->plt.offset, elf_s390x_plt_entry,
+ PLT_ENTRY_SIZE);
+
/* Fixup the relative address to the GOT entry */
bfd_put_32 (output_bfd,
- (htab->sgotplt->output_section->vma +
- htab->sgotplt->output_offset + got_offset
- - (htab->splt->output_section->vma + h->plt.offset))/2,
- htab->splt->contents + h->plt.offset + 2);
+ (htab->elf.sgotplt->output_section->vma +
+ htab->elf.sgotplt->output_offset + got_offset
+ - (htab->elf.splt->output_section->vma + h->plt.offset))/2,
+ htab->elf.splt->contents + h->plt.offset + 2);
/* Fixup the relative branch to PLT 0 */
bfd_put_32 (output_bfd, - (PLT_FIRST_ENTRY_SIZE +
(PLT_ENTRY_SIZE * plt_index) + 22)/2,
- htab->splt->contents + h->plt.offset + 24);
- /* Fixup offset into symbol table */
+ htab->elf.splt->contents + h->plt.offset + 24);
+ /* Fixup offset into .rela.plt section. */
bfd_put_32 (output_bfd, plt_index * sizeof (Elf64_External_Rela),
- htab->splt->contents + h->plt.offset + 28);
+ htab->elf.splt->contents + h->plt.offset + 28);
/* Fill in the entry in the global offset table.
Points to instruction after GOT offset. */
bfd_put_64 (output_bfd,
- (htab->splt->output_section->vma
- + htab->splt->output_offset
+ (htab->elf.splt->output_section->vma
+ + htab->elf.splt->output_offset
+ h->plt.offset
+ 14),
- htab->sgotplt->contents + got_offset);
+ htab->elf.sgotplt->contents + got_offset);
/* Fill in the entry in the .rela.plt section. */
- rela.r_offset = (htab->sgotplt->output_section->vma
- + htab->sgotplt->output_offset
+ rela.r_offset = (htab->elf.sgotplt->output_section->vma
+ + htab->elf.sgotplt->output_offset
+ got_offset);
rela.r_info = ELF64_R_INFO (h->dynindx, R_390_JMP_SLOT);
rela.r_addend = 0;
- loc = htab->srelplt->contents + plt_index * sizeof (Elf64_External_Rela);
+ loc = htab->elf.srelplt->contents + plt_index * sizeof (Elf64_External_Rela);
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
if (!h->def_regular)
/* This symbol has an entry in the global offset table. Set it
up. */
- if (htab->sgot == NULL || htab->srelgot == NULL)
+ if (htab->elf.sgot == NULL || htab->elf.srelgot == NULL)
abort ();
- rela.r_offset = (htab->sgot->output_section->vma
- + htab->sgot->output_offset
+ rela.r_offset = (htab->elf.sgot->output_section->vma
+ + htab->elf.sgot->output_offset
+ (h->got.offset &~ (bfd_vma) 1));
/* If this is a static link, or it is a -Bsymbolic link and the
else
{
BFD_ASSERT((h->got.offset & 1) == 0);
- bfd_put_64 (output_bfd, (bfd_vma) 0, htab->sgot->contents + h->got.offset);
+ bfd_put_64 (output_bfd, (bfd_vma) 0, htab->elf.sgot->contents + h->got.offset);
rela.r_info = ELF64_R_INFO (h->dynindx, R_390_GLOB_DAT);
rela.r_addend = 0;
}
- loc = htab->srelgot->contents;
- loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela);
+ loc = htab->elf.srelgot->contents;
+ loc += htab->elf.srelgot->reloc_count++ * sizeof (Elf64_External_Rela);
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
}
return FALSE;
dynobj = htab->elf.dynobj;
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+ sdyn = bfd_get_linker_section (dynobj, ".dynamic");
if (htab->elf.dynamic_sections_created)
{
Elf64_External_Dyn *dyncon, *dynconend;
- if (sdyn == NULL || htab->sgot == NULL)
+ if (sdyn == NULL || htab->elf.sgot == NULL)
abort ();
dyncon = (Elf64_External_Dyn *) sdyn->contents;
continue;
case DT_PLTGOT:
- dyn.d_un.d_ptr = htab->sgot->output_section->vma;
+ dyn.d_un.d_ptr = htab->elf.sgot->output_section->vma;
break;
case DT_JMPREL:
- dyn.d_un.d_ptr = htab->srelplt->output_section->vma;
+ dyn.d_un.d_ptr = htab->elf.srelplt->output_section->vma;
break;
case DT_PLTRELSZ:
- s = htab->srelplt->output_section;
+ s = htab->elf.srelplt->output_section;
dyn.d_un.d_val = s->size;
break;
linker script arranges for .rela.plt to follow all
other relocation sections, we don't have to worry
about changing the DT_RELA entry. */
- s = htab->srelplt->output_section;
+ s = htab->elf.srelplt->output_section;
dyn.d_un.d_val -= s->size;
break;
}
}
/* Fill in the special first entry in the procedure linkage table. */
- if (htab->splt && htab->splt->size > 0)
+ if (htab->elf.splt && htab->elf.splt->size > 0)
{
/* fill in blueprint for plt 0 entry */
- bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD0,
- htab->splt->contents );
- bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD1,
- htab->splt->contents +4 );
- bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD3,
- htab->splt->contents +12 );
- bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD4,
- htab->splt->contents +16 );
- bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD5,
- htab->splt->contents +20 );
- bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD6,
- htab->splt->contents + 24);
- bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD7,
- htab->splt->contents + 28 );
+ memcpy (htab->elf.splt->contents, elf_s390x_first_plt_entry,
+ PLT_FIRST_ENTRY_SIZE);
/* Fixup relative address to start of GOT */
bfd_put_32 (output_bfd,
- (htab->sgotplt->output_section->vma +
- htab->sgotplt->output_offset
- - htab->splt->output_section->vma - 6)/2,
- htab->splt->contents + 8);
+ (htab->elf.sgotplt->output_section->vma +
+ htab->elf.sgotplt->output_offset
+ - htab->elf.splt->output_section->vma - 6)/2,
+ htab->elf.splt->contents + 8);
}
- elf_section_data (htab->splt->output_section)
+ elf_section_data (htab->elf.splt->output_section)
->this_hdr.sh_entsize = PLT_ENTRY_SIZE;
}
- if (htab->sgotplt)
+ if (htab->elf.sgotplt)
{
/* Fill in the first three entries in the global offset table. */
- if (htab->sgotplt->size > 0)
+ if (htab->elf.sgotplt->size > 0)
{
bfd_put_64 (output_bfd,
(sdyn == NULL ? (bfd_vma) 0
: sdyn->output_section->vma + sdyn->output_offset),
- htab->sgotplt->contents);
+ htab->elf.sgotplt->contents);
/* One entry for shared object struct ptr. */
- bfd_put_64 (output_bfd, (bfd_vma) 0, htab->sgotplt->contents + 8);
+ bfd_put_64 (output_bfd, (bfd_vma) 0, htab->elf.sgotplt->contents + 8);
/* One entry for _dl_runtime_resolve. */
- bfd_put_64 (output_bfd, (bfd_vma) 0, htab->sgotplt->contents + 12);
+ bfd_put_64 (output_bfd, (bfd_vma) 0, htab->elf.sgotplt->contents + 12);
}
- elf_section_data (htab->sgot->output_section)
+ elf_section_data (htab->elf.sgot->output_section)
->this_hdr.sh_entsize = 8;
}
return TRUE;