/* Support for HPPA 64-bit ELF
- Copyright (C) 1999-2018 Free Software Foundation, Inc.
+ Copyright (C) 1999-2021 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
/* Shortcuts to get to the various linker defined sections. */
asection *dlt_sec;
asection *dlt_rel_sec;
- asection *plt_sec;
- asection *plt_rel_sec;
asection *opd_sec;
asection *opd_rel_sec;
asection *other_rel_sec;
};
#define hppa_link_hash_table(p) \
- (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
- == HPPA64_ELF_DATA ? ((struct elf64_hppa_link_hash_table *) ((p)->hash)) : NULL)
+ ((is_elf_hash_table ((p)->hash) \
+ && elf_hash_table_id (elf_hash_table (p)) == HPPA64_ELF_DATA) \
+ ? (struct elf64_hppa_link_hash_table *) (p)->hash : NULL)
#define hppa_elf_hash_entry(ent) \
((struct elf64_hppa_link_hash_entry *)(ent))
static bfd_boolean elf64_hppa_object_p
(bfd *);
-static void elf64_hppa_post_process_headers
- (bfd *, struct bfd_link_info *);
-
static bfd_boolean elf64_hppa_create_dynamic_sections
(bfd *, struct bfd_link_info *);
elf64_hppa_hash_table_create (bfd *abfd)
{
struct elf64_hppa_link_hash_table *htab;
- bfd_size_type amt = sizeof (*htab);
+ size_t amt = sizeof (*htab);
htab = bfd_zmalloc (amt);
if (htab == NULL)
return NULL;
}
+ htab->root.dt_pltgot_required = TRUE;
htab->text_segment_base = (bfd_vma) -1;
htab->data_segment_base = (bfd_vma) -1;
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
return FALSE;
- return TRUE;
+ return ((hdr->sh_flags & SHF_PARISC_SHORT) == 0
+ || bfd_set_section_flags (hdr->bfd_section,
+ hdr->bfd_section->flags | SEC_SMALL_DATA));
}
/* SEC is a section containing relocs for an input BFD when linking; return
| SEC_LINKER_CREATED
| SEC_READONLY));
if (srel == NULL
- || !bfd_set_section_alignment (dynobj, srel, 3))
+ || !bfd_set_section_alignment (srel, 3))
return FALSE;
}
?!? Note we leak the last section_syms array. Presumably we
could free it in one of the later routines in this file. */
- if (hppa_info->section_syms)
- free (hppa_info->section_syms);
+ free (hppa_info->section_syms);
/* Read this BFD's local symbols. */
if (symtab_hdr->sh_info != 0)
if (need_entry & NEED_PLT)
{
- if (! hppa_info->plt_sec
+ if (! hppa_info->root.splt
&& ! get_plt (abfd, info, hppa_info))
goto err_out;
/* HP requires the EI_OSABI field to be filled in. The assignment to
EI_ABIVERSION may not be strictly necessary. */
-static void
-elf64_hppa_post_process_headers (bfd *abfd,
- struct bfd_link_info *link_info ATTRIBUTE_UNUSED)
+static bfd_boolean
+elf64_hppa_init_file_header (bfd *abfd, struct bfd_link_info *info)
{
- Elf_Internal_Ehdr * i_ehdrp;
+ Elf_Internal_Ehdr *i_ehdrp;
- i_ehdrp = elf_elfheader (abfd);
+ if (!_bfd_elf_init_file_header (abfd, info))
+ return FALSE;
+ i_ehdrp = elf_elfheader (abfd);
i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
i_ehdrp->e_ident[EI_ABIVERSION] = 1;
+ return TRUE;
}
/* Create function descriptor section (.opd). This section is called .opd
| SEC_IN_MEMORY
| SEC_LINKER_CREATED));
if (!opd
- || !bfd_set_section_alignment (abfd, opd, 3))
+ || !bfd_set_section_alignment (opd, 3))
{
BFD_ASSERT (0);
return FALSE;
asection *plt;
bfd *dynobj;
- plt = hppa_info->plt_sec;
+ plt = hppa_info->root.splt;
if (!plt)
{
dynobj = hppa_info->root.dynobj;
| SEC_IN_MEMORY
| SEC_LINKER_CREATED));
if (!plt
- || !bfd_set_section_alignment (abfd, plt, 3))
+ || !bfd_set_section_alignment (plt, 3))
{
BFD_ASSERT (0);
return FALSE;
}
- hppa_info->plt_sec = plt;
+ hppa_info->root.splt = plt;
}
return TRUE;
| SEC_IN_MEMORY
| SEC_LINKER_CREATED));
if (!dlt
- || !bfd_set_section_alignment (abfd, dlt, 3))
+ || !bfd_set_section_alignment (dlt, 3))
{
BFD_ASSERT (0);
return FALSE;
| SEC_READONLY
| SEC_LINKER_CREATED));
if (!stub
- || !bfd_set_section_alignment (abfd, stub, 3))
+ || !bfd_set_section_alignment (stub, 3))
{
BFD_ASSERT (0);
return FALSE;
| SEC_READONLY
| SEC_LINKER_CREATED));
if (s == NULL
- || !bfd_set_section_alignment (abfd, s, 3))
+ || !bfd_set_section_alignment (s, 3))
return FALSE;
hppa_info->dlt_rel_sec = s;
| SEC_READONLY
| SEC_LINKER_CREATED));
if (s == NULL
- || !bfd_set_section_alignment (abfd, s, 3))
+ || !bfd_set_section_alignment (s, 3))
return FALSE;
- hppa_info->plt_rel_sec = s;
+ hppa_info->root.srelplt = s;
s = bfd_make_section_anyway_with_flags (abfd, ".rela.data",
(SEC_ALLOC | SEC_LOAD
| SEC_READONLY
| SEC_LINKER_CREATED));
if (s == NULL
- || !bfd_set_section_alignment (abfd, s, 3))
+ || !bfd_set_section_alignment (s, 3))
return FALSE;
hppa_info->other_rel_sec = s;
| SEC_READONLY
| SEC_LINKER_CREATED));
if (s == NULL
- || !bfd_set_section_alignment (abfd, s, 3))
+ || !bfd_set_section_alignment (s, 3))
return FALSE;
hppa_info->opd_rel_sec = s;
else if (shared)
t = 2 * sizeof (Elf64_External_Rela);
- hppa_info->plt_rel_sec->size += t;
+ hppa_info->root.srelplt->size += t;
}
return TRUE;
bfd *dynobj;
bfd *ibfd;
asection *sec;
- bfd_boolean plt;
bfd_boolean relocs;
- bfd_boolean reltext;
hppa_info = hppa_link_hash_table (info);
if (hppa_info == NULL)
}
else
{
- sec = hppa_info->plt_sec;
- srel = hppa_info->plt_rel_sec;
+ sec = hppa_info->root.splt;
+ srel = hppa_info->root.srelplt;
for (; local_plt < end_local_plt; ++local_plt)
{
if (*local_plt > 0)
hppa_info->dlt_sec->size = data.ofs;
}
- if (hppa_info->plt_sec)
+ if (hppa_info->root.splt)
{
- data.ofs = hppa_info->plt_sec->size;
+ data.ofs = hppa_info->root.splt->size;
elf_link_hash_traverse (&hppa_info->root,
allocate_global_data_plt, &data);
- hppa_info->plt_sec->size = data.ofs;
+ hppa_info->root.splt->size = data.ofs;
}
if (hppa_info->stub_sec)
allocate_dynrel_entries, &data);
/* The sizes of all the sections are set. Allocate memory for them. */
- plt = FALSE;
relocs = FALSE;
- reltext = FALSE;
for (sec = dynobj->sections; sec != NULL; sec = sec->next)
{
const char *name;
/* It's OK to base decisions on the section name, because none
of the dynobj section names depend upon the input files. */
- name = bfd_get_section_name (dynobj, sec);
+ name = bfd_section_name (sec);
if (strcmp (name, ".plt") == 0)
{
/* Remember whether there is a PLT. */
- plt = sec->size != 0;
+ ;
}
else if (strcmp (name, ".opd") == 0
|| CONST_STRNEQ (name, ".dlt")
{
if (sec->size != 0)
{
- asection *target;
-
/* Remember whether there are any reloc sections other
than .rela.plt. */
if (strcmp (name, ".rela.plt") != 0)
- {
- const char *outname;
-
- relocs = TRUE;
-
- /* If this relocation section applies to a read only
- section, then we probably need a DT_TEXTREL
- entry. The entries in the .rela.plt section
- really apply to the .got section, which we
- created ourselves and so know is not readonly. */
- outname = bfd_get_section_name (output_bfd,
- sec->output_section);
- target = bfd_get_section_by_name (output_bfd, outname + 4);
- if (target != NULL
- && (target->flags & SEC_READONLY) != 0
- && (target->flags & SEC_ALLOC) != 0)
- reltext = TRUE;
- }
+ relocs = TRUE;
/* We use the reloc_count field as a counter if we need
to copy relocs into the output file. */
#define add_dynamic_entry(TAG, VAL) \
_bfd_elf_add_dynamic_entry (info, TAG, VAL)
- if (!add_dynamic_entry (DT_HP_DLD_FLAGS, 0)
- || !add_dynamic_entry (DT_PLTGOT, 0))
+ if (!add_dynamic_entry (DT_HP_DLD_FLAGS, 0))
return FALSE;
/* Add some entries to the .dynamic section. We fill in the
dynamic linker and used by the debugger. */
if (! bfd_link_pic (info))
{
- if (!add_dynamic_entry (DT_DEBUG, 0)
- || !add_dynamic_entry (DT_HP_DLD_HOOK, 0)
+ if (!add_dynamic_entry (DT_HP_DLD_HOOK, 0)
|| !add_dynamic_entry (DT_HP_LOAD_MAP, 0))
return FALSE;
}
Required by HPUX 11.00 patch PHSS_26559. */
if (!add_dynamic_entry (DT_FLAGS, (info)->flags))
return FALSE;
-
- if (plt)
- {
- if (!add_dynamic_entry (DT_PLTRELSZ, 0)
- || !add_dynamic_entry (DT_PLTREL, DT_RELA)
- || !add_dynamic_entry (DT_JMPREL, 0))
- return FALSE;
- }
-
- if (relocs)
- {
- if (!add_dynamic_entry (DT_RELA, 0)
- || !add_dynamic_entry (DT_RELASZ, 0)
- || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela)))
- return FALSE;
- }
-
- if (reltext)
- {
- if (!add_dynamic_entry (DT_TEXTREL, 0))
- return FALSE;
- info->flags |= DF_TEXTREL;
- }
}
#undef add_dynamic_entry
- return TRUE;
+ return _bfd_elf_add_dynamic_tags (output_bfd, info, relocs);
}
/* Called after we have output the symbol into the dynamic symbol
return FALSE;
stub = hppa_info->stub_sec;
- splt = hppa_info->plt_sec;
+ splt = hppa_info->root.splt;
sopd = hppa_info->opd_sec;
- spltrel = hppa_info->plt_rel_sec;
+ spltrel = hppa_info->root.srelplt;
/* Incredible. It is actually necessary to NOT use the symbol's real
value when building the dynamic symbol table for a shared library.
in the output_offset of the PLT section. */
bfd_put_64 (splt->owner, value, splt->contents + hh->plt_offset);
- value = _bfd_get_gp_value (splt->output_section->owner);
+ value = _bfd_get_gp_value (info->output_bfd);
bfd_put_64 (splt->owner, value, splt->contents + hh->plt_offset + 0x8);
/* Create a dynamic IPLT relocation for this entry.
loc = spltrel->contents;
loc += spltrel->reloc_count++ * sizeof (Elf64_External_Rela);
- bfd_elf64_swap_reloca_out (splt->output_section->owner, &rel, loc);
+ bfd_elf64_swap_reloca_out (info->output_bfd, &rel, loc);
}
/* Initialize an external call stub entry if requested. */
bfd_put_64 (sopd->owner, value, sopd->contents + hh->opd_offset + 16);
/* The last word is our local __gp value. */
- value = _bfd_get_gp_value (sopd->output_section->owner);
+ value = _bfd_get_gp_value (info->output_bfd);
bfd_put_64 (sopd->owner, value, sopd->contents + hh->opd_offset + 24);
}
loc = sopdrel->contents;
loc += sopdrel->reloc_count++ * sizeof (Elf64_External_Rela);
- bfd_elf64_swap_reloca_out (sopd->output_section->owner, &rel, loc);
+ bfd_elf64_swap_reloca_out (info->output_bfd, &rel, loc);
}
return TRUE;
}
loc = sdltrel->contents;
loc += sdltrel->reloc_count++ * sizeof (Elf64_External_Rela);
- bfd_elf64_swap_reloca_out (sdlt->output_section->owner, &rel, loc);
+ bfd_elf64_swap_reloca_out (info->output_bfd, &rel, loc);
}
return TRUE;
}
loc = hppa_info->other_rel_sec->contents;
loc += (hppa_info->other_rel_sec->reloc_count++
* sizeof (Elf64_External_Rela));
- bfd_elf64_swap_reloca_out (hppa_info->other_rel_sec->output_section->owner,
- &rel, loc);
+ bfd_elf64_swap_reloca_out (info->output_bfd, &rel, loc);
}
}
break;
case DT_JMPREL:
- s = hppa_info->plt_rel_sec;
+ s = hppa_info->root.srelplt;
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
break;
case DT_PLTRELSZ:
- s = hppa_info->plt_rel_sec;
+ s = hppa_info->root.srelplt;
dyn.d_un.d_val = s->size;
bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
break;
/* There is some question about whether or not the size of
the PLT relocs should be included here. HP's tools do
it, so we'll emulate them. */
- s = hppa_info->plt_rel_sec;
+ s = hppa_info->root.srelplt;
dyn.d_un.d_val += s->size;
bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
break;
that order) and set __gp to the base address of whichever
section is found first. */
- sec = hppa_info->plt_sec;
+ sec = hppa_info->root.splt;
if (sec && ! (sec->flags & SEC_EXCLUDE))
gp_val = (sec->output_offset
+ sec->output_section->vma
/* Do not attempt to sort non-regular files. This is here
especially for configure scripts and kernel builds which run
tests with "ld [...] -o /dev/null". */
- if (stat (abfd->filename, &buf) != 0
+ if (stat (bfd_get_filename (abfd), &buf) != 0
|| !S_ISREG(buf.st_mode))
return TRUE;
(hppa_info->opd_sec->contents + off + 16));
/* The last word is our local __gp value. */
- value = _bfd_get_gp_value
- (hppa_info->opd_sec->output_section->owner);
+ value = _bfd_get_gp_value (info->output_bfd);
bfd_put_64 (hppa_info->opd_sec->owner, value,
(hppa_info->opd_sec->contents + off + 24));
}
to the start of the DLT, so we have to compute the absolute
address, then subtract out the value of __gp. */
value = (hh->plt_offset
- + hppa_info->plt_sec->output_offset
- + hppa_info->plt_sec->output_section->vma);
+ + hppa_info->root.splt->output_offset
+ + hppa_info->root.splt->output_section->vma);
value -= _bfd_get_gp_value (output_bfd);
/* All PLTOFF relocations are basically the same at this point,
case R_PARISC_LTOFF_FPTR32:
{
- /* We may still need to create the FPTR itself if it was for
- a local symbol. */
- if (hh == NULL)
- {
- /* The first two words of an .opd entry are zero. */
- memset (hppa_info->opd_sec->contents + hh->opd_offset, 0, 16);
-
- /* The next word is the address of the function. */
- bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
- (hppa_info->opd_sec->contents
- + hh->opd_offset + 16));
-
- /* The last word is our local __gp value. */
- value = _bfd_get_gp_value
- (hppa_info->opd_sec->output_section->owner);
- bfd_put_64 (hppa_info->opd_sec->owner, value,
- hppa_info->opd_sec->contents + hh->opd_offset + 24);
-
- /* The DLT value is the address of the .opd entry. */
- value = (hh->opd_offset
- + hppa_info->opd_sec->output_offset
- + hppa_info->opd_sec->output_section->vma);
-
- bfd_put_64 (hppa_info->dlt_sec->owner,
- value,
- hppa_info->dlt_sec->contents + hh->dlt_offset);
- }
+ /* FIXME: There used to be code here to create the FPTR itself if
+ the relocation was against a local symbol. But the code could
+ never have worked. If the assert below is ever triggered then
+ the code will need to be reinstated and fixed so that it does
+ what is needed. */
+ BFD_ASSERT (hh != NULL);
/* We want the value of the DLT offset for this symbol, not
the symbol's actual address. Note that __gp may not point
+ hh->opd_offset + 16));
/* The last word is our local __gp value. */
- value = _bfd_get_gp_value
- (hppa_info->opd_sec->output_section->owner);
+ value = _bfd_get_gp_value (info->output_bfd);
bfd_put_64 (hppa_info->opd_sec->owner, value,
hppa_info->opd_sec->contents + hh->opd_offset + 24);
(hppa_info->opd_sec->contents + off + 16));
/* The last word is our local __gp value. */
- value = _bfd_get_gp_value
- (hppa_info->opd_sec->output_section->owner);
+ value = _bfd_get_gp_value (info->output_bfd);
bfd_put_64 (hppa_info->opd_sec->owner, value,
hppa_info->opd_sec->contents + off + 24);
}
}
case R_PARISC_SECREL32:
- if (sym_sec)
+ if (sym_sec && sym_sec->output_section)
value -= sym_sec->output_section->vma;
bfd_put_32 (input_bfd, value + addend, hit_data);
return bfd_reloc_ok;
else if (!bfd_link_relocatable (info))
{
bfd_boolean err;
- err = (info->unresolved_syms_in_objects == RM_GENERATE_ERROR
- || ELF_ST_VISIBILITY (eh->other) != STV_DEFAULT);
- (*info->callbacks->undefined_symbol) (info,
- eh->root.root.string,
- input_bfd,
- input_section,
- rel->r_offset, err);
+
+ err = (info->unresolved_syms_in_objects == RM_DIAGNOSE
+ && !info->warn_unresolved_syms)
+ || ELF_ST_VISIBILITY (eh->other) != STV_DEFAULT;
+
+ info->callbacks->undefined_symbol
+ (info, eh->root.root.string, input_bfd,
+ input_section, rel->r_offset, err);
}
if (!bfd_link_relocatable (info)
if (info->unresolved_syms_in_objects == RM_IGNORE
&& ELF_ST_VISIBILITY (eh->other) == STV_DEFAULT
&& eh->type == STT_PARISC_MILLI)
- (*info->callbacks->undefined_symbol)
+ info->callbacks->undefined_symbol
(info, eh_name (eh), input_bfd,
input_section, rel->r_offset, FALSE);
}
if (sym_name == NULL)
return FALSE;
if (*sym_name == '\0')
- sym_name = bfd_section_name (input_bfd, sym_sec);
+ sym_name = bfd_section_name (sym_sec);
}
(*info->callbacks->reloc_overflow)
static const struct bfd_elf_special_section elf64_hppa_special_sections[] =
{
+ { STRING_COMMA_LEN (".tbss"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_HP_TLS },
{ STRING_COMMA_LEN (".fini"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".init"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".plt"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
{ STRING_COMMA_LEN (".dlt"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
{ STRING_COMMA_LEN (".sdata"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
{ STRING_COMMA_LEN (".sbss"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
- { STRING_COMMA_LEN (".tbss"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_HP_TLS },
{ NULL, 0, 0, 0, 0 }
};
#define elf_backend_create_dynamic_sections \
elf64_hppa_create_dynamic_sections
-#define elf_backend_post_process_headers elf64_hppa_post_process_headers
+#define elf_backend_init_file_header elf64_hppa_init_file_header
#define elf_backend_omit_section_dynsym _bfd_elf_omit_section_dynsym_all
#define ELF_OSABI ELFOSABI_GNU
#undef elf64_bed
#define elf64_bed elf64_hppa_linux_bed
+#undef elf_backend_special_sections
+#define elf_backend_special_sections (elf64_hppa_special_sections + 1)
#include "elf64-target.h"