[committed] hppa64: Improve relocation handling for local symbols and add gc_section support
John David Anglin
dave.anglin@bell.net
Tue Jan 20 19:47:34 GMT 2026
The attached change improves the ld testresults on hppa64 linux:
=== ld Summary ===
# of expected passes 629
# of unexpected failures 6
# of unexpected successes 23
# of expected failures 22
# of untested testcases 16
# of unsupported tests 204
./ld-new 2.45.50.20260119
Test results for gcc-16 on HP-UX can be found here:
https://gcc.gnu.org/pipermail/gcc-testresults/2026-January/867800.html
Although the above included some gcc hacks, this is the first time
that gcc has built with binutils ld in many years.
There are still issues with pthread support. The call stub support
still needs work to allow large applications. Probably there are
still issues with linkonce sections.
Linux still links and boots with this change.
Commited to trunk,
Dave
---
hppa64: Improve relocation handling for local symbols and add gc_section support
With this patch, gcc-16 can be built and there are significant
improvements in test results. I spent a lot of time trying to
fix the EH exception support. While there are still issues with
handling relocations in linkonce sessions, exception handling
mostly works if pc-relative and text relative encoding is used
in .eh_frame. The main problems are the HP-UX dynamic linker
relocates the text and data segements indpendently, and it does
not support unaligned dynamic relocations.
Due to a configure bug in libstdc++-v3, the lack of gc_section
support caused many test failures, so I added the gc_section
support form elf32-hppa.c.
I also move the HP_LOAD_MAP scratchpad to the end of the .bss
section and fixed a number of issues with the linker scripts.
2026-01-20 John David Anglin <danglin@gcc.gnu.org>
bfd/ChangeLog:
* elf64-hppa.c (elf64_hppa_check_relocs): Drop NEED_PLT
from R_PARISC_LTOFF_FPTR relocations. Revise R_PARISC_FPTR64
relocation to use maybe_dynamic. Add support for
R_PARISC_GNU_VTINHERIT and R_PARISC_GNU_VTENTRY relocations.
Add code to handle dynamic relocations of local symbols.
(elf64_hppa_gc_mark_hook): New.
(ensure_undef_dynamic): New.
(allocate_dynrel_entries): Revise checks to determine when
to discard relocs.
(elf64_hppa_late_size_sections): Revise allocation of local
PLT, DLT and OPD entries.
(elf64_hppa_finalize_opd): Remove assert.
(elf64_hppa_finalize_dlt): Change type of dynindx to long.
(elf64_hppa_finalize_dynreloc): Likewise. Add check for
discarded sections. Correct handling of R_PARISC_FPTR64
relocation. Remove assert. Add new assert to check that
we don't allocate more relocs in .rela.data than it can
hold.
(elf64_hppa_finish_dynamic_sections): Move allocation for
DT_HP_LOAD_MAP to end of .bss section. Only allocate on
HP-UX.
(elf_hppa_dlt_dynrel_reloc): Add dynrel_type argument.
Change type of dynindx. Drop use of value. Remove assert.
(elf_hppa_opd_dynrel_relocs): Rename to elf_hppa_opd_eplt_reloc.
Drop code to to emit R_PARISC_FPTR64 relocation.
(elf_hppa_opd_fptr_reloc): New.
(elf_hppa_final_link_relocate): Add SYM arguement. Move
check for SEC_DEBUGGING. Rework DLT, LTOFF, FPTR and DIR64
relocation handling.
(elf64_hppa_relocate_section): Add asserts to ensure symbol
isn't undefined and input_section hasn't been discarded.
(elf_backend_gc_mark_hook): Define.
(elf_backend_can_gc_sections): Define.
ld/ChangeLog:
* emulparams/elf64hppa.sh (DATA_ADDR): Revise value to match
HP-UX 11 value.
(SHLIB_DATA_ADDR): Likewise.
(NOP): Define.
(OTHER_READONLY_SECTIONS): Add .data.rel, .HP.init, .preinit,
.init and .fini sections to list.
(__SYSTEM_ID_D, __TLS_SIZE_D, __FPU_REVISION, __FPU_MODEL,
__CPU_REVISION, __CPU_KEYBITS_1, __LOAD_INFO, __ARGC, __ARGV,
__ENVP, __libdl_jmp_tbl, __systab): Provide.
(DATA_START_SYMBOLS, OTHER_SYMBOLS, INIT_START): Delete.
(PREINIT_START, PREINIT_END, INIT_START): Define.
emulparams/hppa64linux.sh (NOP): Define.
(DATA_START_SYMBOLS): Delete.
scripttempl/elf64hppa.sc: Delete .init and .fini sections
from script. Allocate 16 bytes at end of .bss for HP_LOAD_MAP.
diff --git a/bfd/elf64-hppa.c b/bfd/elf64-hppa.c
index 2df62923ee5..c35dcf02976 100644
--- a/bfd/elf64-hppa.c
+++ b/bfd/elf64-hppa.c
@@ -749,9 +749,9 @@ elf64_hppa_check_relocs (bfd *abfd,
case R_PARISC_LTOFF_FPTR16WF:
case R_PARISC_LTOFF_FPTR16DF:
if (bfd_link_pic (info) || maybe_dynamic)
- need_entry = (NEED_DLT | NEED_OPD | NEED_PLT | NEED_DYNREL);
+ need_entry = (NEED_DLT | NEED_OPD | NEED_DYNREL);
else
- need_entry = (NEED_DLT | NEED_OPD | NEED_PLT);
+ need_entry = (NEED_DLT | NEED_OPD);
dynrel_type = R_PARISC_FPTR64;
break;
@@ -760,13 +760,27 @@ elf64_hppa_check_relocs (bfd *abfd,
/* We need dynamic EPLT and FPTR64 relocations when building
a shared library. We also need these relocations if we have
a global symbol which is not defined in this executable. */
- if (bfd_link_pic (info) || hh)
+ if (bfd_link_pic (info) || maybe_dynamic)
need_entry = (NEED_OPD | NEED_DYNREL);
else
need_entry = (NEED_OPD);
dynrel_type = R_PARISC_FPTR64;
break;
+ /* This relocation describes the C++ object vtable hierarchy.
+ Reconstruct it for later use during GC. */
+ case R_PARISC_GNU_VTINHERIT:
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, &hh->eh, rel->r_offset))
+ return false;
+ continue;
+
+ /* This relocation describes which C++ vtable entries are actually
+ used. Record for later use during GC. */
+ case R_PARISC_GNU_VTENTRY:
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, &hh->eh, rel->r_addend))
+ return false;
+ continue;
+
/* Add more cases as needed. */
}
@@ -874,17 +888,57 @@ elf64_hppa_check_relocs (bfd *abfd,
sec_symndx, rel->r_offset, rel->r_addend))
goto err_out;
+ /* Add global symbol to dynamic symbol table. */
+ if (hh != NULL
+ && hh->eh.dynindx == -1
+ && ! (bfd_elf_link_record_dynamic_symbol (info, &hh->eh)))
+ goto err_out;
+
/* Add local symbol to local dynamic symbol table. */
if (hh == NULL
&& ! (bfd_elf_link_record_local_dynamic_symbol
(info, abfd, r_symndx)))
goto err_out;
- /* Add global symbol to dynamic symbol table. */
- if (hh != NULL
- && hh->eh.dynindx == -1
- && ! (bfd_elf_link_record_dynamic_symbol (info, &hh->eh)))
- goto err_out;
+ /* Handle dynamic relocation for a local symbol. */
+ if (hh == NULL)
+ {
+ struct elf64_hppa_dyn_reloc_entry *hdh_p;
+ struct elf64_hppa_dyn_reloc_entry **hdh_head;
+ asection *sr;
+ void *vpp;
+ Elf_Internal_Sym *isym;
+
+ isym = bfd_sym_from_r_symndx (&hppa_info->root.sym_cache,
+ abfd, r_symndx);
+ if (isym == NULL)
+ return false;
+
+ sr = bfd_section_from_elf_index (abfd, isym->st_shndx);
+ if (sr == NULL)
+ sr = sec;
+
+ vpp = &elf_section_data (sr)->local_dynrel;
+ hdh_head = (struct elf64_hppa_dyn_reloc_entry **) vpp;
+
+ hdh_p = *hdh_head;
+ if (hdh_p == NULL || hdh_p->sec != sec)
+ {
+ hdh_p = bfd_alloc (hppa_info->root.dynobj, sizeof *hdh_p);
+ if (hdh_p == NULL)
+ return false;
+ hdh_p->next = *hdh_head;
+ *hdh_head = hdh_p;
+ hdh_p->type = dynrel_type;
+ hdh_p->sec = sec;
+ hdh_p->count = 0;
+ hdh_p->sec_symndx = sec_symndx;
+ hdh_p->offset = rel->r_offset;
+ hdh_p->addend = rel->r_addend;
+ }
+
+ hdh_p->count += 1;
+ }
}
}
@@ -894,6 +948,27 @@ elf64_hppa_check_relocs (bfd *abfd,
return false;
}
+/* Return the section that should be marked against garbage collection
+ for a given relocation. */
+
+static asection *
+elf64_hppa_gc_mark_hook (asection *sec,
+ struct bfd_link_info *info,
+ struct elf_reloc_cookie *cookie,
+ struct elf_link_hash_entry *hh,
+ unsigned int symndx)
+{
+ if (hh != NULL)
+ switch (ELF64_R_TYPE (cookie->rel->r_info))
+ {
+ case R_PARISC_GNU_VTINHERIT:
+ case R_PARISC_GNU_VTENTRY:
+ return NULL;
+ }
+
+ return _bfd_elf_gc_mark_hook (sec, info, cookie, hh, symndx);
+}
+
struct elf64_hppa_allocate_data
{
struct bfd_link_info *info;
@@ -1347,6 +1422,30 @@ elf64_hppa_create_dynamic_sections (bfd *abfd,
return true;
}
+/* If EH is undefined, make it dynamic if that makes sense. */
+
+static bool
+ensure_undef_dynamic (struct bfd_link_info *info,
+ struct elf_link_hash_entry *eh)
+{
+ struct elf64_hppa_link_hash_table *hppa_info;
+
+ hppa_info = hppa_link_hash_table (info);
+ if (hppa_info == NULL)
+ return false;
+
+ if (hppa_info->root.dynamic_sections_created
+ && (eh->root.type == bfd_link_hash_undefweak
+ || eh->root.type == bfd_link_hash_undefined)
+ && eh->dynindx == -1
+ && !eh->forced_local
+ && eh->type != STT_PARISC_MILLI
+ && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh)
+ && ELF_ST_VISIBILITY (eh->other) == STV_DEFAULT)
+ return bfd_elf_link_record_dynamic_symbol (info, eh);
+ return true;
+}
+
/* Allocate dynamic relocations for those symbols that turned out
to be dynamic. */
@@ -1366,30 +1465,6 @@ allocate_dynrel_entries (struct elf_link_hash_entry *eh, void *data)
dynamic_symbol = elf64_hppa_dynamic_symbol_p (eh, x->info);
shared = bfd_link_pic (x->info);
- /* Take care of the normal data relocations. */
-
- for (rent = hh->reloc_entries; rent; rent = rent->next)
- {
- switch (rent->type)
- {
- case R_PARISC_FPTR64:
- /* Allocate one if we are building a shared library, or
- we don't want an OPD entry. Ignore text relocations. */
- if ((hh->want_opd && !shared)
- || (rent->sec->flags & SEC_READONLY))
- continue;
- break;
- case R_PARISC_DIR64:
- if (!dynamic_symbol && !shared)
- continue;
- break;
- default:
- abort();
- }
- if (!discarded_section (hppa_info->other_rel_sec))
- hppa_info->other_rel_sec->size += sizeof (Elf64_External_Rela);
- }
-
/* Take care of the GOT and PLT relocations. */
if ((dynamic_symbol || shared) && hh->want_dlt)
@@ -1416,6 +1491,66 @@ allocate_dynrel_entries (struct elf_link_hash_entry *eh, void *data)
hppa_info->root.srelplt->size += t;
}
+ /* If no dynamic sections we can't have dynamic relocs. */
+ if (!hppa_info->root.dynamic_sections_created)
+ hh->reloc_entries = NULL;
+
+ /* Discard relocs on undefined syms with non-default visibility. */
+ else if ((eh->root.type == bfd_link_hash_undefined
+ && ELF_ST_VISIBILITY (eh->other) != STV_DEFAULT)
+ || UNDEFWEAK_NO_DYNAMIC_RELOC (x->info, eh))
+ hh->reloc_entries = NULL;
+
+ if (hh->reloc_entries == NULL)
+ return true;
+
+ if (bfd_link_pic (x->info))
+ {
+ /* Discard space for relocs that have become local due to
+ symbol visibility changes. */
+ if (!ensure_undef_dynamic (x->info, eh))
+ return false;
+ }
+
+ /* Take care of the normal data relocations. */
+
+ for (rent = hh->reloc_entries; rent; rent = rent->next)
+ {
+ switch (rent->type)
+ {
+ case R_PARISC_FPTR64:
+ /* Allocate one if we are building a shared library, or
+ we don't want an OPD entry. Ignore text relocations. */
+ if ((hh->want_opd && !shared)
+ || (rent->sec->flags & SEC_READONLY))
+ continue;
+ break;
+ case R_PARISC_DIR64:
+ if (!dynamic_symbol && !shared)
+ continue;
+ break;
+ default:
+ abort();
+ }
+
+ if (discarded_section (rent->sec)
+ || discarded_section (hppa_info->other_rel_sec))
+ continue;
+
+ if (eh->dynindx == -1)
+ {
+ if (rent->type == R_PARISC_FPTR64)
+ {
+ if (!hh->want_opd)
+ continue;
+ }
+ else if (discarded_section (eh->root.u.def.section))
+ continue;
+ }
+
+ hppa_info->other_rel_sec->size += sizeof (Elf64_External_Rela);
+ }
+
return true;
}
@@ -1542,13 +1677,15 @@ elf64_hppa_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
bfd_signed_vma *start_local_dlt;
bfd_signed_vma *end_local_dlt;
bfd_signed_vma *local_plt;
+ bfd_signed_vma *start_local_plt;
bfd_signed_vma *end_local_plt;
bfd_signed_vma *local_opd;
bfd_signed_vma *start_local_opd;
bfd_signed_vma *end_local_opd;
bfd_size_type locsymcount;
Elf_Internal_Shdr *symtab_hdr;
- asection *srel, *srel_other;
+ asection *srel;
+ long indx;
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
continue;
@@ -1557,6 +1694,9 @@ elf64_hppa_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
{
struct elf64_hppa_dyn_reloc_entry *hdh_p;
+ if (discarded_section (sec))
+ continue;
+
for (hdh_p = ((struct elf64_hppa_dyn_reloc_entry *)
elf_section_data (sec)->local_dynrel);
hdh_p != NULL;
@@ -1572,7 +1712,7 @@ elf64_hppa_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
}
else if (hdh_p->count != 0)
{
- srel = elf_section_data (hdh_p->sec)->sreloc;
+ srel = hppa_info->other_rel_sec;
srel->size += hdh_p->count * sizeof (Elf64_External_Rela);
if ((hdh_p->sec->output_section->flags & SEC_READONLY) != 0)
info->flags |= DF_TEXTREL;
@@ -1586,44 +1726,45 @@ elf64_hppa_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
locsymcount = symtab_hdr->sh_info;
+
end_local_dlt = start_local_dlt + locsymcount;
+ start_local_plt = end_local_dlt;
+ end_local_plt = start_local_plt + locsymcount;
+ start_local_opd = end_local_plt;
+ end_local_opd = start_local_opd + locsymcount;
+
sec = hppa_info->dlt_sec;
srel = hppa_info->dlt_rel_sec;
- for (local_dlt = start_local_dlt;
+ for (local_dlt = start_local_dlt, indx = 0;
local_dlt < end_local_dlt;
- ++local_dlt)
+ ++local_dlt, ++indx)
{
if (*local_dlt > 0)
{
- long indx;
- long dynindx = -1;
-
- indx = local_dlt - start_local_dlt;
- if (!bfd_link_pic (info))
- dynindx = _bfd_elf_link_lookup_local_dynindx (info, ibfd,
- indx);
*local_dlt = sec->size;
sec->size += DLT_ENTRY_SIZE;
- if (bfd_link_pic (info) || dynindx != -1)
+ if (bfd_link_pic (info) || start_local_opd[indx] > 0)
srel->size += sizeof (Elf64_External_Rela);
}
else
*local_dlt = (bfd_vma) -1;
}
- local_plt = end_local_dlt;
- end_local_plt = local_plt + locsymcount;
if (! hppa_info->root.dynamic_sections_created)
{
/* Won't be used, but be safe. */
- for (; local_plt < end_local_plt; ++local_plt)
+ for (local_plt = start_local_plt;
+ local_plt < end_local_plt;
+ ++local_plt)
*local_plt = (bfd_vma) -1;
}
else
{
sec = hppa_info->root.splt;
srel = hppa_info->root.srelplt;
- for (; local_plt < end_local_plt; ++local_plt)
+ for (local_plt = start_local_plt;
+ local_plt < end_local_plt;
+ ++local_plt)
{
if (*local_plt > 0)
{
@@ -1637,8 +1778,6 @@ elf64_hppa_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
}
}
- start_local_opd = end_local_plt;
- end_local_opd = start_local_opd + locsymcount;
if (! hppa_info->root.dynamic_sections_created)
{
/* Won't be used, but be safe. */
@@ -1651,7 +1790,6 @@ elf64_hppa_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
{
sec = hppa_info->opd_sec;
srel = hppa_info->opd_rel_sec;
- srel_other = hppa_info->other_rel_sec;
for (local_opd = start_local_opd;
local_opd < end_local_opd;
++local_opd)
@@ -1663,12 +1801,10 @@ elf64_hppa_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
*local_opd = sec->size - OPD_ENTRY_SIZE;
sec->size += OPD_ENTRY_SIZE;
- /* We need EPLT and FPTR64 relocations. */
+ /* We need a EPLT relocation if we are building a
+ shared library. */
if (bfd_link_pic (info))
- {
- srel->size += sizeof (Elf64_External_Rela);
- srel_other->size += sizeof (Elf64_External_Rela);
- }
+ srel->size += sizeof (Elf64_External_Rela);
}
else
*local_opd = (bfd_vma) -1;
@@ -2144,7 +2280,7 @@ elf64_hppa_finalize_opd (struct elf_link_hash_entry *eh, void *data)
bfd_vma value, value2;
Elf_Internal_Rela rel;
bfd_byte *loc;
- int dynindx;
+ long dynindx;
asection *sec;
/* The offset of this relocation is the absolute address of the
@@ -2183,7 +2319,6 @@ elf64_hppa_finalize_opd (struct elf_link_hash_entry *eh, void *data)
rel.r_addend += value;
dynindx = hppa_info->text_hash_entry->dynindx;
- BFD_ASSERT (dynindx != -1);
rel.r_info = ELF64_R_INFO (dynindx, R_PARISC_EPLT);
loc = sopdrel->contents;
@@ -2254,7 +2389,7 @@ elf64_hppa_finalize_dlt (struct elf_link_hash_entry *eh, void *data)
{
Elf_Internal_Rela rel;
bfd_byte *loc;
- int dynindx;
+ long dynindx;
asection *sec;
bfd_vma value, value2;
@@ -2326,7 +2461,7 @@ elf64_hppa_finalize_dynreloc (struct elf_link_hash_entry *eh,
if (hh->reloc_entries)
{
struct elf64_hppa_dyn_reloc_entry *rent;
- int dynindx;
+ long dynindx;
for (rent = hh->reloc_entries; rent; rent = rent->next)
{
@@ -2350,6 +2485,10 @@ elf64_hppa_finalize_dynreloc (struct elf_link_hash_entry *eh,
abort();
}
+ if (discarded_section (rent->sec)
+ || discarded_section (hppa_info->other_rel_sec))
+ continue;
+
/* Create a dynamic relocation for this entry.
We need the output offset for the reloc's section because
@@ -2360,24 +2499,41 @@ elf64_hppa_finalize_dynreloc (struct elf_link_hash_entry *eh,
if (eh->dynindx == -1)
{
- asection *sec;
+ asection *sec, *sopd;
bfd_vma value, value2;
- value = (eh->root.u.def.value
- + eh->root.u.def.section->output_section->vma
- + eh->root.u.def.section->output_offset);
+ if (rent->type == R_PARISC_FPTR64)
+ {
+ if (!hh->want_opd)
+ continue;
+ sopd = hppa_info->opd_sec;
+ value = (hh->opd_offset + sopd->output_offset
+ + sopd->output_section->vma);
- if (eh->root.u.def.section->flags & SEC_READONLY)
- {
- sec = hppa_info->text_hash_entry->root.u.def.section;
+ sec = hppa_info->data_hash_entry->root.u.def.section;
value2 = sec->output_offset + sec->output_section->vma;
- dynindx = hppa_info->text_hash_entry->dynindx;
+ dynindx = hppa_info->data_hash_entry->dynindx;
}
else
{
- sec = hppa_info->data_hash_entry->root.u.def.section;
- value2 = sec->output_offset + sec->output_section->vma;
- dynindx = hppa_info->data_hash_entry->dynindx;
+ if (discarded_section (eh->root.u.def.section))
+ continue;
+ value = (eh->root.u.def.value
+ + eh->root.u.def.section->output_section->vma
+ + eh->root.u.def.section->output_offset);
+
+ if (eh->root.u.def.section->flags & SEC_READONLY)
+ {
+ sec = hppa_info->text_hash_entry->root.u.def.section;
+ value2 = sec->output_offset + sec->output_section->vma;
+ dynindx = hppa_info->text_hash_entry->dynindx;
+ }
+ else
+ {
+ sec = hppa_info->data_hash_entry->root.u.def.section;
+ value2 = sec->output_offset + sec->output_section->vma;
+ dynindx = hppa_info->data_hash_entry->dynindx;
+ }
}
rel.r_addend = value - value2;
}
@@ -2387,10 +2543,12 @@ elf64_hppa_finalize_dynreloc (struct elf_link_hash_entry *eh,
dynindx = eh->dynindx;
}
- BFD_ASSERT (dynindx != -1);
rel.r_info = ELF64_R_INFO (dynindx, rent->type);
loc = hppa_info->other_rel_sec->contents;
+ BFD_ASSERT ((hppa_info->other_rel_sec->reloc_count
+ * sizeof (Elf64_External_Rela))
+ < hppa_info->other_rel_sec->size);
loc += (hppa_info->other_rel_sec->reloc_count++
* sizeof (Elf64_External_Rela));
bfd_elf64_swap_reloca_out (info->output_bfd, &rel, loc);
@@ -2476,17 +2634,24 @@ elf64_hppa_finish_dynamic_sections (bfd *output_bfd,
break;
case DT_HP_LOAD_MAP:
- /* Compute the absolute address of 16byte scratchpad area
+ /* Compute the absolute address of 16-byte scratchpad area
for the dynamic linker.
By convention the linker script will allocate the scratchpad
- area at the start of the .data section. So all we have to
- to is find the start of the .data section. */
- s = bfd_get_section_by_name (output_bfd, ".data");
- if (!s)
- return false;
- dyn.d_un.d_ptr = s->vma;
- bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
+ area at the start of the .data section.
+
+ In HPUX 11.11, HP ld now allocates the region at the end
+ of the .bss section. This avoids adding 16 bytes to the
+ start of .data. This may affect relocation offsets. */
+ if (output_bfd->xvec == & hppa_elf64_vec
+ && ! bfd_link_pic (info))
+ {
+ s = bfd_get_section_by_name (output_bfd, ".bss");
+ if (!s)
+ break;
+ dyn.d_un.d_ptr = s->vma + s->size - 16;
+ bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
+ }
break;
case DT_PLTGOT:
@@ -3129,15 +3294,14 @@ elf_hppa_dlt_dynrel_reloc (Elf_Internal_Rela *rel,
bfd_vma relocation,
struct bfd_link_info *info,
asection *sym_sec,
- bfd_vma dlt_offset)
+ bfd_vma dlt_offset,
+ int dynrel_type)
{
Elf_Internal_Rela rela;
bfd_byte *loc;
- int dynindx;
+ long dynindx;
asection *sec;
asection *sdlt, *sdltrel;
- int dynrel_type;
- bfd_vma value;
bfd_signed_vma addend = rel->r_addend;
struct elf64_hppa_link_hash_table *hppa_info = hppa_link_hash_table (info);
@@ -3152,23 +3316,18 @@ elf_hppa_dlt_dynrel_reloc (Elf_Internal_Rela *rel,
{
sec = hppa_info->text_hash_entry->root.u.def.section;
dynindx = hppa_info->text_hash_entry->dynindx;
- dynrel_type = R_PARISC_FPTR64;
}
else
{
sec = hppa_info->data_hash_entry->root.u.def.section;
dynindx = hppa_info->data_hash_entry->dynindx;
- dynrel_type = R_PARISC_DIR64;
}
/* Adjust addend using the difference of the symbol's
location and the section symbol's address. */
- value = relocation + addend - sec->output_offset - sec->output_section->vma;
-
- /* The result becomes the addend of the relocation. */
- rela.r_addend = value;
+ rela.r_addend = (relocation + addend - sec->output_offset
+ - sec->output_section->vma);
- BFD_ASSERT (dynindx != -1);
rela.r_info = ELF64_R_INFO (dynindx, dynrel_type);
loc = sdltrel->contents;
@@ -3176,54 +3335,73 @@ elf_hppa_dlt_dynrel_reloc (Elf_Internal_Rela *rel,
bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc);
}
-/* Output OPD EPLT and FPTR64 relocations for a local symbol. */
+/* Output OPD EPLT relocation for a local symbol. */
static void
-elf_hppa_opd_dynrel_relocs (Elf_Internal_Rela *rel,
- asection *input_section,
- bfd_vma relocation,
- struct bfd_link_info *info,
- bfd_vma opd_offset)
+elf_hppa_opd_eplt_reloc (Elf_Internal_Rela *rel,
+ bfd_vma relocation,
+ struct bfd_link_info *info,
+ bfd_vma opd_offset)
{
Elf_Internal_Rela rela;
bfd_byte *loc;
- int dynindx;
+ long dynindx;
asection *sopd, *sopdrel;
- asection *sec, *s;
+ asection *sec;
bfd_vma value;
- bfd_vma offset = rel->r_offset;
bfd_signed_vma addend = rel->r_addend;
struct elf64_hppa_link_hash_table *hppa_info = hppa_link_hash_table (info);
sopd = hppa_info->opd_sec;
sopdrel = hppa_info->opd_rel_sec;
- /* The offset of the EPLT relocation is the absolute address
- of the .opd entry for this symbol. */
- rela.r_offset = opd_offset + sopd->output_offset + sopd->output_section->vma;
+ /* We need a EPLT relocation if we are building a shared library. */
+ if (bfd_link_pic (info))
+ {
+ /* The offset of the EPLT relocation is the absolute address
+ of the .opd entry for this symbol. */
+ rela.r_offset = (opd_offset + sopd->output_offset
+ + sopd->output_section->vma);
- /* Select text base segment and its dynindx. */
- sec = hppa_info->text_hash_entry->root.u.def.section;
- dynindx = hppa_info->text_hash_entry->dynindx;
+ /* Select text base segment and its dynindx. */
+ sec = hppa_info->text_hash_entry->root.u.def.section;
+ dynindx = hppa_info->text_hash_entry->dynindx;
- /* Adjust the addend with the difference between the
- symbol's address and the base segment's address. */
- value = relocation + addend - sec->output_offset - sec->output_section->vma;
+ /* Adjust the addend with the difference between the
+ symbol's address and the base segment's address. */
+ value = (relocation + addend - sec->output_offset
+ - sec->output_section->vma);
- /* The result becomes the addend of the relocation. */
- rela.r_addend = value;
+ /* The result becomes the addend of the relocation. */
+ rela.r_addend = value;
- BFD_ASSERT (dynindx != -1);
- rela.r_info = ELF64_R_INFO (dynindx, R_PARISC_EPLT);
+ rela.r_info = ELF64_R_INFO (dynindx, R_PARISC_EPLT);
- loc = sopdrel->contents;
- loc += sopdrel->reloc_count++ * sizeof (Elf64_External_Rela);
- bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc);
+ loc = sopdrel->contents;
+ loc += sopdrel->reloc_count++ * sizeof (Elf64_External_Rela);
+ bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc);
+ }
+}
- /* The offset of the FPTR relocation is the absolute address
- of this symbol. */
- rela.r_offset = (offset + input_section->output_offset
- + input_section->output_section->vma);
+/* Output OPD FPTR64 relocation for a local symbol. */
+
+static void
+elf_hppa_opd_fptr_reloc (struct bfd_link_info *info,
+ bfd_vma opd_offset,
+ bfd_vma fptr_offset)
+{
+ Elf_Internal_Rela rela;
+ bfd_byte *loc;
+ long dynindx;
+ asection *sopd;
+ asection *sec, *s;
+ bfd_vma value;
+ struct elf64_hppa_link_hash_table *hppa_info = hppa_link_hash_table (info);
+
+ sopd = hppa_info->opd_sec;
+
+ /* FPTR offset. */
+ rela.r_offset = fptr_offset;
/* OPD's address. */
value = opd_offset + sopd->output_offset + sopd->output_section->vma;
@@ -3239,11 +3417,11 @@ elf_hppa_opd_dynrel_relocs (Elf_Internal_Rela *rel,
/* The result becomes the addend of the relocation. */
rela.r_addend = value;
- BFD_ASSERT (dynindx != -1);
rela.r_info = ELF64_R_INFO (dynindx, R_PARISC_FPTR64);
s = hppa_info->other_rel_sec;
loc = s->contents;
+ BFD_ASSERT (s->reloc_count * sizeof (Elf64_External_Rela) < s->size);
loc += s->reloc_count++ * sizeof (Elf64_External_Rela);
bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc);
}
@@ -3269,6 +3447,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
bfd_byte *contents,
bfd_vma value,
struct bfd_link_info *info,
+ Elf_Internal_Sym *sym,
asection *sym_sec,
struct elf_link_hash_entry *eh)
{
@@ -3285,13 +3464,6 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
unsigned int r_type = howto->type;
bfd_byte *hit_data = contents + offset;
- /* Dynamic relocs are not propagated for SEC_DEBUGGING
- sections because such sections are not SEC_ALLOC and
- thus ld.so will not process them. */
- if (bfd_link_pic (info)
- && (input_section->flags & SEC_DEBUGGING) != 0)
- return bfd_reloc_ok;
-
if (hppa_info == NULL)
return bfd_reloc_notsupported;
@@ -3426,9 +3598,11 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
case R_PARISC_LTOFF16WF:
case R_PARISC_LTOFF16DF:
{
- bfd_vma off;
+ bfd_vma dlt_off, fptr_off, opd_off;
bfd_vma relocation = value;
asection *sopd;
+ bool need_dlt_reloc = false;
+ int dynrel_type = R_PARISC_NONE;
sopd = hppa_info->opd_sec;
@@ -3449,6 +3623,32 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
if (local_offsets == NULL)
abort ();
+ local_dlt_offsets = local_offsets;
+ dlt_off = local_dlt_offsets[r_symndx];
+
+ if ((dlt_off & 1) != 0)
+ {
+ BFD_ASSERT (dlt_off != (bfd_vma) -1);
+ dlt_off &= ~1;
+ }
+ else
+ {
+ local_dlt_offsets[r_symndx] |= 1;
+
+ if (bfd_link_pic (info))
+ {
+ if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
+ dynrel_type = R_PARISC_FPTR64;
+ else
+ dynrel_type = R_PARISC_DIR64;
+ need_dlt_reloc = true;
+ }
+
+ bfd_put_64 (hppa_info->dlt_sec->owner,
+ value + addend,
+ hppa_info->dlt_sec->contents + dlt_off);
+ }
+
/* Now do .opd creation if needed. */
if (r_type == R_PARISC_LTOFF_FPTR14R
|| r_type == R_PARISC_LTOFF_FPTR14DR
@@ -3459,66 +3659,72 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|| r_type == R_PARISC_LTOFF_FPTR16DF)
{
local_opd_offsets = local_offsets + 2 * symtab_hdr->sh_info;
- off = local_opd_offsets[r_symndx];
+ opd_off = local_opd_offsets[r_symndx];
/* The last bit records whether we've already initialised
this local .opd entry. */
- if ((off & 1) != 0)
+ if ((opd_off & 1) != 0)
{
- BFD_ASSERT (off != (bfd_vma) -1);
- off &= ~1;
+ BFD_ASSERT (opd_off != (bfd_vma) -1);
+ opd_off &= ~1;
}
else
{
local_opd_offsets[r_symndx] |= 1;
- /* If we are building a shared library, we need a EPLT
- and FPTR64 relocation for each OPD entry. */
- if (bfd_link_pic (info))
- elf_hppa_opd_dynrel_relocs (rel, input_section,
- relocation, info, off);
+ /* If we are building a shared library, we need an EPLT
+ relocation for each OPD entry. */
+ elf_hppa_opd_eplt_reloc (rel, relocation, info, opd_off);
+
+ /* Adjust the relocation to point to the OPD. */
+ relocation = (opd_off + sopd->output_offset
+ + sopd->output_section->vma);
+ sym_sec = sopd;
+ rel->r_addend = 0;
+ need_dlt_reloc = true;
+ dynrel_type = R_PARISC_FPTR64;
/* The third word is the address of the function. */
bfd_put_64 (sopd->owner, value + addend,
- sopd->contents + off + 16);
+ sopd->contents + opd_off + 16);
/* The last word is our local __gp value. */
value = _bfd_get_gp_value (info->output_bfd);
bfd_put_64 (sopd->owner, value,
- sopd->contents + off + 24);
+ sopd->contents + opd_off + 24);
}
- }
- local_dlt_offsets = local_offsets;
- off = local_dlt_offsets[r_symndx];
-
- if ((off & 1) != 0)
- {
- BFD_ASSERT (off != (bfd_vma) -1);
- off &= ~1;
- }
- else
- {
- local_dlt_offsets[r_symndx] |= 1;
+ /* Output a FPTR64 relocation for dynamic local symbols.
+ Note dynamic relocs are not propagated for SEC_DEBUGGING
+ sections because such sections are not SEC_ALLOC and thus
+ ld.so will not process them. */
if (bfd_link_pic (info)
- || _bfd_elf_link_lookup_local_dynindx (info, input_bfd,
+ && (input_section->flags & SEC_DEBUGGING) == 0
+ && _bfd_elf_link_lookup_local_dynindx (info, input_bfd,
r_symndx) != -1)
- elf_hppa_dlt_dynrel_reloc (rel, relocation, info,
- sym_sec, off);
+ {
+ /* FPTR offset is absolute address of DLT entry. */
+ fptr_off = (dlt_off
+ + hppa_info->dlt_sec->output_offset
+ + hppa_info->dlt_sec->output_section->vma);
- bfd_put_64 (hppa_info->dlt_sec->owner,
- value + addend,
- hppa_info->dlt_sec->contents + off);
+ /* Output FPTR64 relocation for local symbol. */
+ elf_hppa_opd_fptr_reloc (info, opd_off, fptr_off);
+ }
}
}
else
- off = hh->dlt_offset;
+ dlt_off = hh->dlt_offset;
+
+ if (need_dlt_reloc)
+ elf_hppa_dlt_dynrel_reloc (rel, relocation, info, sym_sec,
+ dlt_off, dynrel_type);
/* We want the value of the DLT offset for this symbol, not
the symbol's actual address. Note that __gp may not point
to the start of the DLT, so we have to compute the absolute
address, then subtract out the value of __gp. */
- value = (off
+ value = (dlt_off
+ hppa_info->dlt_sec->output_offset
+ hppa_info->dlt_sec->output_section->vma);
value -= _bfd_get_gp_value (output_bfd);
@@ -3681,11 +3887,34 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
{
bfd_vma relocation = value;
bfd_vma *local_opd_offsets, *local_dlt_offsets;
- bfd_vma dlt_off;
+ bfd_vma dlt_off, fptr_off;
bfd_vma opd_off = (bfd_vma) -1;
+ bool need_dlt_reloc = false;
+ int dynrel_type = R_PARISC_NONE;
if (eh == NULL)
{
+ local_dlt_offsets = local_offsets;
+ dlt_off = local_dlt_offsets[r_symndx];
+
+ if ((dlt_off & 1) != 0)
+ {
+ BFD_ASSERT (dlt_off != (bfd_vma) -1);
+ dlt_off &= ~1;
+ }
+ else
+ {
+ local_dlt_offsets[r_symndx] |= 1;
+ if (bfd_link_pic (info))
+ {
+ if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
+ dynrel_type = R_PARISC_FPTR64;
+ else
+ dynrel_type = R_PARISC_DIR64;
+ need_dlt_reloc = true;
+ }
+ }
+
if (r_type == R_PARISC_LTOFF_FPTR64)
{
local_opd_offsets = local_offsets + 2 * symtab_hdr->sh_info;
@@ -3700,32 +3929,40 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
}
else
{
+ asection *sopd = hppa_info->opd_sec;
+
local_opd_offsets[r_symndx] |= 1;
- /* If we are building a shared library, we need a EPLT
- and FPTR64 relocation for each OPD entry. */
- if (bfd_link_pic (info))
- elf_hppa_opd_dynrel_relocs (rel, input_section,
- relocation, info, opd_off);
+ /* If we are building a shared library, we need an EPLT
+ relocation for each OPD entry. */
+ elf_hppa_opd_eplt_reloc (rel, relocation, info, opd_off);
+
+ /* Adjust the DLT relocation to point to the OPD. */
+ relocation = (opd_off + sopd->output_offset
+ + sopd->output_section->vma);
+ sym_sec = sopd;
+ rel->r_addend = 0;
+ need_dlt_reloc = true;
+ dynrel_type = R_PARISC_FPTR64;
}
- }
- local_dlt_offsets = local_offsets;
- dlt_off = local_dlt_offsets[r_symndx];
-
- if ((dlt_off & 1) != 0)
- {
- BFD_ASSERT (dlt_off != (bfd_vma) -1);
- dlt_off &= ~1;
- }
- else
- {
- local_dlt_offsets[r_symndx] |= 1;
+ /* Output a FPTR64 relocation for dynamic local symbols.
+ Note dynamic relocs are not propagated for SEC_DEBUGGING
+ sections because such sections are not SEC_ALLOC and thus
+ ld.so will not process them. */
if (bfd_link_pic (info)
- || _bfd_elf_link_lookup_local_dynindx (info, input_bfd,
+ && (input_section->flags & SEC_DEBUGGING) == 0
+ && _bfd_elf_link_lookup_local_dynindx (info, input_bfd,
r_symndx) != -1)
- elf_hppa_dlt_dynrel_reloc (rel, relocation, info,
- sym_sec, dlt_off);
+ {
+ /* FPTR offset is absolute address of DLT entry. */
+ fptr_off = (dlt_off
+ + hppa_info->dlt_sec->output_offset
+ + hppa_info->dlt_sec->output_section->vma);
+
+ /* Output FPTR64 relocation for local symbol. */
+ elf_hppa_opd_fptr_reloc (info, opd_off, fptr_off);
+ }
}
}
else
@@ -3734,6 +3971,10 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
dlt_off = hh->dlt_offset;
}
+ if (need_dlt_reloc)
+ elf_hppa_dlt_dynrel_reloc (rel, relocation, info, sym_sec,
+ dlt_off, dynrel_type);
+
/* We may still need to create the FPTR itself if it was for
a local symbol. */
if (eh == NULL && r_type == R_PARISC_LTOFF_FPTR64)
@@ -3774,6 +4015,62 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
return bfd_reloc_ok;
case R_PARISC_DIR64:
+ if (hh == NULL)
+ {
+ long dynindx;
+ Elf_Internal_Rela rela;
+ bfd_byte *loc;
+ asection *s, *sec;
+
+ /* Output a DIR64 relocation for dynamic local symbols.
+ Note dynamic relocs are not propagated for SEC_DEBUGGING
+ sections because such sections are not SEC_ALLOC and thus
+ ld.so will not process them. */
+ if (bfd_link_pic (info)
+ && (input_section->flags & SEC_DEBUGGING) == 0
+ && _bfd_elf_link_lookup_local_dynindx (info, input_bfd,
+ r_symndx) != -1)
+ {
+ bfd_vma out_off;
+
+ out_off = _bfd_elf_section_offset (output_bfd, info,
+ input_section,
+ rel->r_offset);
+
+ BFD_ASSERT (out_off != (bfd_vma) -1 && out_off != (bfd_vma) -2);
+
+ /* This is the output relocation offset. */
+ rela.r_offset = (out_off
+ + input_section->output_offset
+ + input_section->output_section->vma);
+
+ /* Select base segment. */
+ if (sym_sec->flags & SEC_READONLY)
+ {
+ sec = hppa_info->text_hash_entry->root.u.def.section;
+ dynindx = hppa_info->text_hash_entry->dynindx;
+ }
+ else
+ {
+ sec = hppa_info->data_hash_entry->root.u.def.section;
+ dynindx = hppa_info->data_hash_entry->dynindx;
+ }
+
+ /* Adjust addend using the difference of the symbol's
+ location and the section symbol's address. */
+ rela.r_addend = (value + addend - sec->output_offset
+ - sec->output_section->vma);
+
+ /* We need a dynamic relocation for this symbol. */
+ rela.r_info = ELF64_R_INFO (dynindx, R_PARISC_DIR64);
+
+ s = hppa_info->other_rel_sec;
+ loc = s->contents;
+ loc += s->reloc_count++ * sizeof (Elf64_External_Rela);
+ bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc);
+ }
+ }
+
bfd_put_64 (output_bfd, value + addend, hit_data);
return bfd_reloc_ok;
@@ -3838,7 +4135,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
case R_PARISC_FPTR64:
{
- bfd_vma off;
+ bfd_vma fptr_off, opd_off;
bfd_vma relocation = value;
asection *sopd;
@@ -3854,40 +4151,68 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
abort ();
local_opd_offsets = local_offsets + 2 * symtab_hdr->sh_info;
- off = local_opd_offsets[r_symndx];
+ opd_off = local_opd_offsets[r_symndx];
/* The last bit records whether we've already initialised
this local .opd entry. */
- if ((off & 1) != 0)
+ if ((opd_off & 1) != 0)
{
- BFD_ASSERT (off != (bfd_vma) -1);
- off &= ~1;
+ BFD_ASSERT (opd_off != (bfd_vma) -1);
+ opd_off &= ~1;
}
else
{
local_opd_offsets[r_symndx] |= 1;
- /* If we are building a shared library, we need a EPLT
- and a FPTR64 relocation for each OPD entry. */
- if (bfd_link_pic (info))
- elf_hppa_opd_dynrel_relocs (rel, input_section,
- relocation, info, off);
+ if (input_section->flags & SEC_READONLY)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB(%pA+%#" PRIx64
+ "): R_PARISC_FPTR64 relocation in readonly section"),
+ input_bfd,
+ input_section,
+ (uint64_t) offset);
+ return bfd_reloc_notsupported;
+ }
+
+ /* If we are building a shared library, we need an EPLT
+ relocation for each OPD entry. */
+ elf_hppa_opd_eplt_reloc (rel, relocation, info, opd_off);
/* The third word is the address of the function. */
bfd_put_64 (sopd->owner, value + addend,
- (sopd->contents + off + 16));
+ (sopd->contents + opd_off + 16));
/* The last word is our local __gp value. */
value = _bfd_get_gp_value (info->output_bfd);
- bfd_put_64 (sopd->owner, value, sopd->contents + off + 24);
+ bfd_put_64 (sopd->owner, value, sopd->contents + opd_off + 24);
+ }
+
+ /* Output a FPTR64 relocation for dynamic local symbols.
+ Note dynamic relocs are not propagated for SEC_DEBUGGING
+ sections because such sections are not SEC_ALLOC and thus
+ ld.so will not process them. */
+ if (bfd_link_pic (info)
+ && (input_section->flags & SEC_DEBUGGING) == 0
+ && _bfd_elf_link_lookup_local_dynindx (info, input_bfd,
+ r_symndx) != -1)
+ {
+ /* The offset of the FPTR relocation is the absolute address
+ of this relocation. */
+ fptr_off = (rel->r_offset + input_section->output_offset
+ + input_section->output_section->vma);
+
+ /* Output FPTR64 relocation for local symbol. */
+ elf_hppa_opd_fptr_reloc (info, opd_off, fptr_off);
}
}
else
- off = hh->opd_offset;
+ opd_off = hh->opd_offset;
if (hh == NULL || hh->want_opd)
/* We want the value of the OPD offset for this symbol. */
- value = off + sopd->output_offset + sopd->output_section->vma;
+ value = opd_off + sopd->output_offset + sopd->output_section->vma;
else
/* We want the address of the symbol. */
value += addend;
@@ -4066,6 +4391,12 @@ elf64_hppa_relocate_section (bfd *output_bfd,
}
}
+ /* Ensure symbol isn't undefined. */
+ BFD_ASSERT (r_symndx != STN_UNDEF);
+
+ /* Ensure input section hasn't been discarded. */
+ BFD_ASSERT (!discarded_section (input_section));
+
if (sym_sec != NULL && discarded_section (sym_sec))
RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
rel, 1, relend, R_PARISC_NONE,
@@ -4076,7 +4407,7 @@ elf64_hppa_relocate_section (bfd *output_bfd,
r = elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
input_section, contents,
- relocation, info, sym_sec,
+ relocation, info, sym, sym_sec,
eh);
if (r != bfd_reloc_ok)
@@ -4202,6 +4533,7 @@ static const struct elf_size_info hppa64_elf_size_info =
elf64_hppa_finish_dynamic_sections
#define elf_backend_grok_prstatus elf64_hppa_grok_prstatus
#define elf_backend_grok_psinfo elf64_hppa_grok_psinfo
+#define elf_backend_gc_mark_hook elf64_hppa_gc_mark_hook
/* Stuff for the BFD linker: */
#define bfd_elf64_bfd_link_hash_table_create \
@@ -4225,6 +4557,7 @@ static const struct elf_size_info hppa64_elf_size_info =
#define elf_backend_link_output_symbol_hook \
elf64_hppa_link_output_symbol_hook
+#define elf_backend_can_gc_sections 1
#define elf_backend_want_got_plt 0
#define elf_backend_plt_readonly 0
#define elf_backend_want_plt_sym 0
diff --git a/ld/emulparams/elf64hppa.sh b/ld/emulparams/elf64hppa.sh
index b0b43f7ecde..5afe0e2714a 100644
--- a/ld/emulparams/elf64hppa.sh
+++ b/ld/emulparams/elf64hppa.sh
@@ -3,7 +3,7 @@ ELFSIZE=64
OUTPUT_FORMAT="elf64-hppa"
NO_REL_RELOCS=yes
TEXT_START_ADDR=0x4000000000001000
-DATA_ADDR=0x8000000000001000
+DATA_ADDR=0x8000000100000000
TARGET_PAGE_SIZE=4096
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
LIB_PATH="=/usr/lib/pa20_64:=/opt/langtools/lib/pa20_64"
@@ -12,10 +12,11 @@ LIB_PATH="=/usr/lib/pa20_64:=/opt/langtools/lib/pa20_64"
# data to some reasonable value. Of course nobody knows what reasoanble
# really is, so we just use the same values that HP's linker uses.
SHLIB_TEXT_START_ADDR=0x4000000000001000
-SHLIB_DATA_ADDR=0x8000000000001000
+SHLIB_DATA_ADDR=0x8000000100000000
ARCH=hppa
MACHINE=hppa2.0w
+NOP=0x08000240
ENTRY="main"
TEMPLATE_NAME=elf
GENERATE_SHLIB_SCRIPT=yes
@@ -30,7 +31,33 @@ OTHER_READONLY_SECTIONS="
OTHER_READWRITE_SECTIONS="
.PARISC.pfa_count ${RELOCATING-0} : { *(.PARISC.pfa_count) }
.PARISC.global ${RELOCATING-0} : { *(.PARISC.global) }
+ .data.rel ${RELOCATING-0} : { *(.data.rel.local*) }
.opd ${RELOCATING-0} : { *(.opd) }
+ .HP.init ${RELOCATING-0} :
+ {
+ KEEP (*(SORT_NONE(.HP.init)))
+ }
+ .preinit ${RELOCATING-0} :
+ {
+ ${RELOCATING+${PREINIT_START}}
+ KEEP (*(SORT_NONE(.preinit)))
+ ${RELOCATING+${PREINIT_END}}
+ }
+
+# HP messed up the .init and .fini sections and they are expected
+# to contain arrays of function pointers.
+ .init ${RELOCATING-0} :
+ {
+ ${RELOCATING+${INIT_START}}
+ KEEP (*(SORT_NONE(.init)))
+ ${RELOCATING+${INIT_END}}
+ }
+ .fini ${RELOCATING-0} :
+ {
+ ${RELOCATING+${FINI_START}}
+ KEEP (*(SORT_NONE(.fini)))
+ ${RELOCATING+${FINI_END}}
+ }
${RELOCATING+PROVIDE (__gp = .);}
.plt ${RELOCATING-0} : { *(.plt) }
.dlt ${RELOCATING-0} : { *(.dlt) }"
@@ -42,35 +69,46 @@ OTHER_BSS_SECTIONS="
.hbss ${RELOCATING-0} : { *(.hbss) }
.tbss ${RELOCATING-0} : { *(.tbss) }"
-#OTHER_SYMBOLS='PROVIDE (__TLS_SIZE = SIZEOF (.tbss));'
+# OTHER_SYMBOLS='PROVIDE (__TLS_SIZE = SIZEOF (.tbss));'
+
+# These symbols need to be provided in final relocations.
OTHER_SYMBOLS='
+ PROVIDE (__SYSTEM_ID = 0x214);
+ PROVIDE (_FPU_STATUS = 0x0);
PROVIDE (__TLS_SIZE = 0);
PROVIDE (__TLS_INIT_SIZE = 0);
PROVIDE (__TLS_INIT_START = 0);
PROVIDE (__TLS_INIT_A = 0);
- PROVIDE (__TLS_PREALLOC_DTV_A = 0);'
+ PROVIDE (__TLS_PREALLOC_DTV_A = 0);
+ PROVIDE (__SYSTEM_ID_D = 0);
+ PROVIDE (__TLS_SIZE_D = 0);
+ PROVIDE (__FPU_REVISION = 0);
+ PROVIDE (__FPU_MODEL = 0);
+ PROVIDE (__CPU_REVISION = 0);
+ PROVIDE (__CPU_KEYBITS_1 = 0);
+ PROVIDE (__LOAD_INFO = 0);
+ PROVIDE (__ARGC = 0);
+ PROVIDE (__ARGV = 0);
+ PROVIDE (__ENVP = 0);
+ PROVIDE (__libdl_jmp_tbl = 0);
+ PROVIDE (__systab = 0);'
# HPs use .dlt where systems use .got. Sigh.
OTHER_GOT_RELOC_SECTIONS="
.rela.dlt ${RELOCATING-0} : { *(.rela.dlt) }
.rela.opd ${RELOCATING-0} : { *(.rela.opd) }"
-# We're not actually providing a symbol anymore (due to the inability to be
-# safe in regards to shared libraries). So we just allocate the hunk of space
-# unconditionally, but do not mess around with the symbol table.
-DATA_START_SYMBOLS='. += 16;'
-
DATA_PLT=
PLT_BEFORE_GOT=
# .dynamic should be at the start of the .text segment.
TEXT_DYNAMIC=
-# The linker is required to define these two symbols.
-OTHER_SYMBOLS='PROVIDE (__SYSTEM_ID = 0x214); PROVIDE (_FPU_STATUS = 0x0);'
# The PA64 ELF port needs two additional initializer sections and also wants
# a start/end symbol pair for the .init and .fini sections.
-INIT_START='KEEP (*(.HP.init)); PROVIDE (__preinit_start = .); KEEP (*(.preinit)); PROVIDE (__preinit_end = .); PROVIDE (__init_start = .);'
+PREINIT_START='PROVIDE (__preinit_start = .);'
+PREINIT_END='PROVIDE (__preinit_end = .);'
+INIT_START='PROVIDE (__init_start = .);'
INIT_END='PROVIDE (__init_end = .);'
FINI_START='PROVIDE (__fini_start = .);'
FINI_END='PROVIDE (__fini_end = .);'
diff --git a/ld/emulparams/hppa64linux.sh b/ld/emulparams/hppa64linux.sh
index 3caad892dbf..d72c6bb9a84 100644
--- a/ld/emulparams/hppa64linux.sh
+++ b/ld/emulparams/hppa64linux.sh
@@ -7,6 +7,7 @@ TARGET_PAGE_SIZE=0x10000
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
ARCH=hppa
MACHINE=hppa2.0w
+NOP=0x08000240
ENTRY="main"
TEMPLATE_NAME=elf
GENERATE_SHLIB_SCRIPT=yes
@@ -40,11 +41,6 @@ OTHER_GOT_RELOC_SECTIONS="
.rela.dlt ${RELOCATING-0} : { *(.rela.dlt) }
.rela.opd ${RELOCATING-0} : { *(.rela.opd) }"
-# We're not actually providing a symbol anymore (due to the inability to be
-# safe in regards to shared libraries). So we just allocate the hunk of space
-# unconditionally, but do not mess around with the symbol table.
-DATA_START_SYMBOLS='. += 16;'
-
DATA_PLT=
PLT_BEFORE_GOT=
diff --git a/ld/scripttempl/elf64hppa.sc b/ld/scripttempl/elf64hppa.sc
index 6b92ba58f5a..d742675fb8c 100644
--- a/ld/scripttempl/elf64hppa.sc
+++ b/ld/scripttempl/elf64hppa.sc
@@ -12,7 +12,7 @@
# SMALL_DATA_DTOR - .dtors contains small data.
# DATA_ADDR - if end-of-text-plus-one-page isn't right for data start
# INITIAL_READONLY_SECTIONS - at start of text segment
-# OTHER_READONLY_SECTIONS - other than .text .init .rodata ...
+# OTHER_READONLY_SECTIONS - other than .text .rodata ...
# (e.g., .PARISC.milli)
# OTHER_TEXT_SECTIONS - these get put in .text when relocating
# OTHER_READWRITE_SECTIONS - other than .data .bss .ctors .sdata ...
@@ -400,13 +400,6 @@ if test -z "${NON_ALLOC_DYN}"; then
fi
cat <<EOF
- .init ${RELOCATING-0} :
- {
- ${RELOCATING+${INIT_START}}
- KEEP (*(SORT_NONE(.init)))
- ${RELOCATING+${INIT_END}}
- } =${NOP-0}
-
${TEXT_PLT+${PLT}}
${TINY_READONLY_SECTION}
.text ${RELOCATING-0} :
@@ -417,12 +410,6 @@ cat <<EOF
*(.gnu.warning)
${RELOCATING+${OTHER_TEXT_SECTIONS}}
} =${NOP-0}
- .fini ${RELOCATING-0} :
- {
- ${RELOCATING+${FINI_START}}
- KEEP (*(SORT_NONE(.fini)))
- ${RELOCATING+${FINI_END}}
- } =${NOP-0}
${RELOCATING+PROVIDE (__${ETEXT_NAME} = .);}
${RELOCATING+PROVIDE (_${ETEXT_NAME} = .);}
${RELOCATING+PROVIDE (${ETEXT_NAME} = .);}
@@ -500,6 +487,8 @@ cat <<EOF
${RELOCATING+*(.dynbss)}
*(.bss${RELOCATING+ .bss.* .gnu.linkonce.b.*})
${RELOCATING+*(COMMON)
+ /* Provide 16 bytes for HP_LOAD map. */
+ . += 16;
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/binutils/attachments/20260120/d97c470f/attachment-0001.sig>
More information about the Binutils
mailing list