bfd *abfd ATTRIBUTE_UNUSED;
bfd_reloc_code_real_type code;
{
- switch (code)
+ switch (code)
{
case BFD_RELOC_NONE:
return &elf_howto_table[(int) R_390_NONE];
asection *srelplt;
asection *sdynbss;
asection *srelbss;
+
+ /* Small local sym to section mapping cache. */
+ struct sym_sec_cache sym_sec;
};
/* Get the s390 ELF linker hash table from a link_info structure. */
if (entry == NULL)
return entry;
}
-
+
/* Call the allocation method of the superclass. */
entry = _bfd_elf_link_hash_newfunc (entry, table, string);
if (entry != NULL)
{
struct elf_s390_link_hash_entry *eh;
-
+
eh = (struct elf_s390_link_hash_entry *) entry;
eh->dyn_relocs = NULL;
}
ret->srelplt = NULL;
ret->sdynbss = NULL;
ret->srelbss = NULL;
+ ret->sym_sec.abfd = NULL;
return &ret->elf.root;
}
Tentatively set the flag for now, and correct in
adjust_dynamic_symbol. */
h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
-
+
/* We may need a .plt entry if the function this reloc
refers to is in a shared lib. */
h->plt.refcount += 1;
symbol. */
if ((info->shared
&& (sec->flags & SEC_ALLOC) != 0
- && ((ELF32_R_TYPE (rel->r_info) != R_390_PC16
+ && ((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_PC32)
|| (h != NULL
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)))
{
+ struct elf_s390_dyn_relocs *p;
+ struct elf_s390_dyn_relocs **head;
+
/* We must copy these reloc types into the output file.
Create a reloc section in dynobj and make room for
this reloc. */
{
const char *name;
bfd *dynobj;
-
+
name = (bfd_elf_string_from_elf_section
(abfd,
elf_elfheader (abfd)->e_shstrndx,
relocations we need for this symbol. */
if (h != NULL)
{
- struct elf_s390_link_hash_entry *eh;
- struct elf_s390_dyn_relocs *p;
-
- eh = (struct elf_s390_link_hash_entry *) h;
- p = eh->dyn_relocs;
-
- if (p == NULL || p->sec != sec)
- {
- bfd_size_type amt = sizeof *p;
- p = ((struct elf_s390_dyn_relocs *)
- bfd_alloc (htab->elf.dynobj, amt));
- if (p == NULL)
- return false;
- p->next = eh->dyn_relocs;
- eh->dyn_relocs = p;
- p->sec = sec;
- p->count = 0;
- p->pc_count = 0;
- }
-
- 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_PC32)
- p->pc_count += 1;
+ head = &((struct elf_s390_link_hash_entry *) h)->dyn_relocs;
}
else
{
- /* Track dynamic relocs needed for local syms too. */
- elf_section_data (sec)->local_dynrel += 1;
+ /* Track dynamic relocs needed for local syms too.
+ We really need local syms available to do this
+ easily. Oh well. */
+
+ asection *s;
+ s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
+ sec, r_symndx);
+ if (s == NULL)
+ return false;
+
+ head = ((struct elf_s390_dyn_relocs **)
+ &elf_section_data (s)->local_dynrel);
+ }
+
+ p = *head;
+ if (p == NULL || p->sec != sec)
+ {
+ bfd_size_type amt = sizeof *p;
+ p = ((struct elf_s390_dyn_relocs *)
+ bfd_alloc (htab->elf.dynobj, amt));
+ if (p == NULL)
+ return false;
+ p->next = *head;
+ *head = p;
+ p->sec = sec;
+ p->count = 0;
+ p->pc_count = 0;
}
+
+ 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_PC32)
+ p->pc_count += 1;
}
break;
-
+
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_390_GNU_VTINHERIT:
if (!_bfd_elf32_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_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;
-
+
default:
break;
}
}
else
{
- if (!(elf_bad_symtab (abfd)
- && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
- && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
- && sym->st_shndx != SHN_COMMON))
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (abfd, sym->st_shndx);
}
return NULL;
const Elf_Internal_Rela *rel, *relend;
unsigned long r_symndx;
struct elf_link_hash_entry *h;
- bfd *dynobj;
-
- elf_section_data (sec)->local_dynrel = 0;
- dynobj = elf_hash_table (info)->dynobj;
- if (dynobj == NULL)
- return true;
+ elf_section_data (sec)->local_dynrel = NULL;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
}
/* If we didn't find any dynamic relocs in read-only sections, then
- we'll be keeping the dynamic relocs and avoiding the copy reloc. */
+ 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->root.u.def.section = s;
h->root.u.def.value = h->plt.offset;
}
-
+
/* Make room for this entry. */
s->_raw_size += PLT_ENTRY_SIZE;
-
+
/* 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->_raw_size += GOT_ENTRY_SIZE;
h->plt.offset = (bfd_vma) -1;
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
}
- }
+ }
else
{
h->plt.offset = (bfd_vma) -1;
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
- }
-
+ }
+
if (h->got.refcount > 0)
{
asection *s;
eh->dyn_relocs = NULL;
- keep:
+ keep: ;
}
/* Finally, allocate space. */
for (s = ibfd->sections; s != NULL; s = s->next)
{
- bfd_size_type count = elf_section_data (s)->local_dynrel;
+ struct elf_s390_dyn_relocs *p;
- if (count != 0)
+ for (p = *((struct elf_s390_dyn_relocs **)
+ &elf_section_data (s)->local_dynrel);
+ p != NULL;
+ p = p->next)
{
- srela = elf_section_data (s)->sreloc;
- srela->_raw_size += count * sizeof (Elf32_External_Rela);
+ if (!bfd_is_abs_section (p->sec)
+ && bfd_is_abs_section (p->sec->output_section))
+ {
+ /* Input section has been discarded, either because
+ it is a copy of a linkonce section or due to
+ linker script /DISCARD/, so we'll be discarding
+ the relocs too. */
+ }
+ else
+ {
+ srela = elf_section_data (p->sec)->sreloc;
+ srela->_raw_size += p->count * sizeof (Elf32_External_Rela);
+ }
}
}
{
if (s->_raw_size != 0 && s != htab->srelplt)
relocs = true;
-
+
/* We use the reloc_count field as a counter if we need
to copy relocs into the output file. */
s->reloc_count = 0;
if (s->contents == NULL)
return false;
}
-
+
if (htab->elf.dynamic_sections_created)
{
/* Add some entries to the .dynamic section. We fill in the
dynamic linker and used by the debugger. */
#define add_dynamic_entry(TAG, VAL) \
bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
-
+
if (! info->shared)
{
if (!add_dynamic_entry (DT_DEBUG, 0))
return false;
}
-
+
if (htab->splt->_raw_size != 0)
{
if (!add_dynamic_entry (DT_PLTGOT, 0)
|| !add_dynamic_entry (DT_JMPREL, 0))
return false;
}
-
+
if (relocs)
{
if (!add_dynamic_entry (DT_RELA, 0)
/* 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)
{
if (!add_dynamic_entry (DT_TEXTREL, 0))
}
}
#undef add_dynamic_entry
-
+
return true;
}
bfd_vma relocation;
boolean unresolved_reloc;
bfd_reloc_status_type r;
-
+
r_type = ELF32_R_TYPE (rel->r_info);
if (r_type == (int) R_390_GNU_VTINHERIT
|| r_type == (int) R_390_GNU_VTENTRY)
return false;
}
howto = elf_howto_table + r_type;
-
+
r_symndx = ELF32_R_SYM (rel->r_info);
-
+
if (info->relocateable)
{
/* This is a relocateable link. We don't have to change
rel->r_addend += sec->output_offset + sym->st_value;
}
}
-
+
continue;
}
-
+
/* This is a final link. */
h = NULL;
sym = NULL;
{
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
- relocation = (sec->output_section->vma
- + sec->output_offset
- + sym->st_value);
+ relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
}
else
{
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
+
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
sec = h->root.u.def.section;
- if (r_type == R_390_GOTPC
- || ((r_type == R_390_PLT16DBL
- || r_type == R_390_PLT32)
- && htab->splt != NULL
- && h->plt.offset != (bfd_vma) -1)
- || ((r_type == R_390_GOT12
- || r_type == R_390_GOT16
- || r_type == R_390_GOT32)
- && elf_hash_table (info)->dynamic_sections_created
- && (! info->shared
- || (! info->symbolic && h->dynindx != -1)
- || (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0))
- || (info->shared
- && ((! info->symbolic && h->dynindx != -1)
- || (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0)
- && (r_type == R_390_8
- || r_type == R_390_16
- || r_type == R_390_32
- || r_type == R_390_PC16
- || r_type == R_390_PC16DBL
- || r_type == R_390_PC32)
- && ((input_section->flags & SEC_ALLOC) != 0
- /* DWARF will emit R_390_32 relocations in its
- sections against symbols defined externally
- in shared libraries. We can't do anything
- with them here. */
- || ((input_section->flags & SEC_DEBUGGING) != 0
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_DYNAMIC) != 0))))
- {
- /* In these cases, we don't need the relocation
- value. We check specially because in some
- obscure cases sec->output_section will be NULL. */
- relocation = 0;
- }
- else if (sec->output_section == NULL)
+ if (sec->output_section == NULL)
{
/* Set a flag that will be cleared later if we find a
relocation value for this symbol. output_section
relocation = 0;
}
}
-
+
switch (r_type)
{
case R_390_GOT12:
offset table. */
if (htab->sgot == NULL)
abort ();
-
+
if (h != NULL)
{
boolean dyn;
-
+
off = h->got.offset;
dyn = htab->elf.dynamic_sections_created;
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
case R_390_PC16:
case R_390_PC16DBL:
case R_390_PC32:
+ /* r_symndx will be zero only for relocs against symbols
+ from removed linkonce sections, or sections discarded by
+ a linker script. */
+ if (r_symndx == 0
+ || (input_section->flags & SEC_ALLOC) == 0)
+ break;
+
if ((info->shared
- && (input_section->flags & SEC_ALLOC) != 0
&& ((r_type != R_390_PC16
&& r_type != R_390_PC16DBL
&& r_type != R_390_PC32)
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0))))
|| (!info->shared
- && (input_section->flags & SEC_ALLOC) != 0
&& h != NULL
&& h->dynindx != -1
&& (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
boolean skip, relocate;
asection *sreloc;
Elf32_External_Rela *loc;
-
+
/* When generating a shared object, these relocations
are copied into the output file to be resolved at run
time. */
-
+
skip = false;
-
- if (elf_section_data (input_section)->stab_info == NULL)
- outrel.r_offset = rel->r_offset;
- else
- {
- off = (_bfd_stab_section_offset
- (output_bfd, htab->elf.stab_info, input_section,
- &elf_section_data (input_section)->stab_info,
- rel->r_offset));
- if (off == (bfd_vma) -1)
- skip = true;
- outrel.r_offset = off;
- }
-
+
+ outrel.r_offset =
+ _bfd_elf_section_offset (output_bfd, info, input_section,
+ rel->r_offset);
+ if (outrel.r_offset == (bfd_vma) -1)
+ skip = true;
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
-
+
if (skip)
{
memset (&outrel, 0, sizeof outrel);
{
relocate = false;
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
- outrel.r_addend = relocation + rel->r_addend;
+ outrel.r_addend = rel->r_addend;
}
else
{
outrel.r_info = ELF32_R_INFO (0, R_390_RELATIVE);
outrel.r_addend = relocation + rel->r_addend;
}
-
+
sreloc = elf_section_data (input_section)->sreloc;
if (sreloc == NULL)
abort ();
-
+
loc = (Elf32_External_Rela *) sreloc->contents;
loc += sreloc->reloc_count++;
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
-
+
/* If this reloc is against an external symbol, we do
not want to fiddle with the addend. Otherwise, we
need to include the symbol value so that it becomes
if (! relocate)
continue;
}
-
break;
-
+
default:
break;
}
-
+
if (unresolved_reloc
&& !(info->shared
&& (input_section->flags & SEC_DEBUGGING) != 0
bfd_get_section_name (input_bfd, input_section),
(long) rel->r_offset,
h->root.root.string);
-
+
r = _bfd_final_link_relocate (howto, input_bfd, input_section,
contents, rel->r_offset,
relocation, rel->r_addend);
-
+
if (r != bfd_reloc_ok)
{
const char *name;
-
+
if (h != NULL)
name = h->root.root.string;
else
if (*name == '\0')
name = bfd_section_name (input_bfd, sec);
}
-
+
if (r == bfd_reloc_overflow)
{
-
+
if (! ((*info->callbacks->reloc_overflow)
(info, name, howto->name, (bfd_vma) 0,
input_bfd, input_section, rel->r_offset)))
}
}
}
-
+
return true;
}
Elf_Internal_Sym *sym;
{
struct elf_s390_link_hash_table *htab;
-
+
htab = elf_s390_hash_table (info);
-
+
if (h->plt.offset != (bfd_vma) -1)
{
bfd_vma plt_index;
Elf_Internal_Rela rela;
Elf32_External_Rela *loc;
bfd_vma relative_offset;
-
+
/* This symbol has an entry in the procedure linkage table. Set
it up. */
-
+
if (h->dynindx == -1
|| htab->splt == NULL
|| htab->sgotplt == NULL
rela.r_addend = 0;
loc = (Elf32_External_Rela *) htab->srelplt->contents + plt_index;
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
-
+
if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
{
/* Mark the symbol as undefined, rather than as defined in
the .plt section. Leave the value alone. This is a clue
for the dynamic linker, to make function pointer
comparisons work between an application and shared
- library. */
+ library. */
sym->st_shndx = SHN_UNDEF;
}
}
-
+
if (h->got.offset != (bfd_vma) -1)
{
Elf_Internal_Rela rela;
{
Elf_Internal_Dyn dyn;
asection *s;
-
+
bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
-
+
switch (dyn.d_tag)
{
default:
continue;
-
+
case DT_PLTGOT:
dyn.d_un.d_ptr = htab->sgot->output_section->vma;
break;
-
+
case DT_JMPREL:
dyn.d_un.d_ptr = htab->srelplt->output_section->vma;
break;
return bfd_default_set_arch_mach (abfd, bfd_arch_s390, bfd_mach_s390_esa);
}
+static boolean
+elf_s390_grok_prstatus (abfd, note)
+ bfd * abfd;
+ Elf_Internal_Note * note;
+{
+ int offset;
+ unsigned int raw_size;
+
+ switch (note->descsz)
+ {
+ default:
+ return false;
+
+ case 224: /* S/390 Linux. */
+ /* pr_cursig */
+ elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
+
+ /* pr_pid */
+ elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
+
+ /* pr_reg */
+ offset = 72;
+ raw_size = 144;
+ break;
+ }
+
+ /* Make a ".reg/999" section. */
+ return _bfd_elfcore_make_pseudosection (abfd, ".reg",
+ raw_size, note->descpos + offset);
+}
+
#define TARGET_BIG_SYM bfd_elf32_s390_vec
#define TARGET_BIG_NAME "elf32-s390"
#define ELF_ARCH bfd_arch_s390
#define elf_backend_relocate_section elf_s390_relocate_section
#define elf_backend_size_dynamic_sections elf_s390_size_dynamic_sections
#define elf_backend_reloc_type_class elf_s390_reloc_type_class
+#define elf_backend_grok_prstatus elf_s390_grok_prstatus
#define elf_backend_object_p elf_s390_object_p