version 1.6, 2020/04/03 17:51:04 |
version 1.7, 2022/12/23 17:09:18 |
|
|
/* Support for HPPA 64-bit ELF |
/* Support for HPPA 64-bit ELF |
Copyright (C) 1999-2018 Free Software Foundation, Inc. |
Copyright (C) 1999-2020 Free Software Foundation, Inc. |
|
|
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
|
|
Line 169 static struct bfd_link_hash_table *elf64 |
|
Line 169 static struct bfd_link_hash_table *elf64 |
|
static bfd_boolean elf64_hppa_object_p |
static bfd_boolean elf64_hppa_object_p |
(bfd *); |
(bfd *); |
|
|
static void elf64_hppa_post_process_headers |
|
(bfd *, struct bfd_link_info *); |
|
|
|
static bfd_boolean elf64_hppa_create_dynamic_sections |
static bfd_boolean elf64_hppa_create_dynamic_sections |
(bfd *, struct bfd_link_info *); |
(bfd *, struct bfd_link_info *); |
|
|
Line 422 get_reloc_section (bfd *abfd, |
|
Line 419 get_reloc_section (bfd *abfd, |
|
| SEC_LINKER_CREATED |
| SEC_LINKER_CREATED |
| SEC_READONLY)); |
| SEC_READONLY)); |
if (srel == NULL |
if (srel == NULL |
|| !bfd_set_section_alignment (dynobj, srel, 3)) |
|| !bfd_set_section_alignment (srel, 3)) |
return FALSE; |
return FALSE; |
} |
} |
|
|
Line 1120 allocate_global_data_opd (struct elf_lin |
|
Line 1117 allocate_global_data_opd (struct elf_lin |
|
/* HP requires the EI_OSABI field to be filled in. The assignment to |
/* HP requires the EI_OSABI field to be filled in. The assignment to |
EI_ABIVERSION may not be strictly necessary. */ |
EI_ABIVERSION may not be strictly necessary. */ |
|
|
static void |
static bfd_boolean |
elf64_hppa_post_process_headers (bfd *abfd, |
elf64_hppa_init_file_header (bfd *abfd, struct bfd_link_info *info) |
struct bfd_link_info *link_info ATTRIBUTE_UNUSED) |
|
{ |
{ |
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_OSABI] = get_elf_backend_data (abfd)->elf_osabi; |
i_ehdrp->e_ident[EI_ABIVERSION] = 1; |
i_ehdrp->e_ident[EI_ABIVERSION] = 1; |
|
return TRUE; |
} |
} |
|
|
/* Create function descriptor section (.opd). This section is called .opd |
/* Create function descriptor section (.opd). This section is called .opd |
Line 1159 get_opd (bfd *abfd, |
|
Line 1158 get_opd (bfd *abfd, |
|
| SEC_IN_MEMORY |
| SEC_IN_MEMORY |
| SEC_LINKER_CREATED)); |
| SEC_LINKER_CREATED)); |
if (!opd |
if (!opd |
|| !bfd_set_section_alignment (abfd, opd, 3)) |
|| !bfd_set_section_alignment (opd, 3)) |
{ |
{ |
BFD_ASSERT (0); |
BFD_ASSERT (0); |
return FALSE; |
return FALSE; |
Line 1195 get_plt (bfd *abfd, |
|
Line 1194 get_plt (bfd *abfd, |
|
| SEC_IN_MEMORY |
| SEC_IN_MEMORY |
| SEC_LINKER_CREATED)); |
| SEC_LINKER_CREATED)); |
if (!plt |
if (!plt |
|| !bfd_set_section_alignment (abfd, plt, 3)) |
|| !bfd_set_section_alignment (plt, 3)) |
{ |
{ |
BFD_ASSERT (0); |
BFD_ASSERT (0); |
return FALSE; |
return FALSE; |
Line 1231 get_dlt (bfd *abfd, |
|
Line 1230 get_dlt (bfd *abfd, |
|
| SEC_IN_MEMORY |
| SEC_IN_MEMORY |
| SEC_LINKER_CREATED)); |
| SEC_LINKER_CREATED)); |
if (!dlt |
if (!dlt |
|| !bfd_set_section_alignment (abfd, dlt, 3)) |
|| !bfd_set_section_alignment (dlt, 3)) |
{ |
{ |
BFD_ASSERT (0); |
BFD_ASSERT (0); |
return FALSE; |
return FALSE; |
Line 1267 get_stub (bfd *abfd, |
|
Line 1266 get_stub (bfd *abfd, |
|
| SEC_READONLY |
| SEC_READONLY |
| SEC_LINKER_CREATED)); |
| SEC_LINKER_CREATED)); |
if (!stub |
if (!stub |
|| !bfd_set_section_alignment (abfd, stub, 3)) |
|| !bfd_set_section_alignment (stub, 3)) |
{ |
{ |
BFD_ASSERT (0); |
BFD_ASSERT (0); |
return FALSE; |
return FALSE; |
Line 1347 elf64_hppa_create_dynamic_sections (bfd |
|
Line 1346 elf64_hppa_create_dynamic_sections (bfd |
|
| SEC_READONLY |
| SEC_READONLY |
| SEC_LINKER_CREATED)); |
| SEC_LINKER_CREATED)); |
if (s == NULL |
if (s == NULL |
|| !bfd_set_section_alignment (abfd, s, 3)) |
|| !bfd_set_section_alignment (s, 3)) |
return FALSE; |
return FALSE; |
hppa_info->dlt_rel_sec = s; |
hppa_info->dlt_rel_sec = s; |
|
|
Line 1358 elf64_hppa_create_dynamic_sections (bfd |
|
Line 1357 elf64_hppa_create_dynamic_sections (bfd |
|
| SEC_READONLY |
| SEC_READONLY |
| SEC_LINKER_CREATED)); |
| SEC_LINKER_CREATED)); |
if (s == NULL |
if (s == NULL |
|| !bfd_set_section_alignment (abfd, s, 3)) |
|| !bfd_set_section_alignment (s, 3)) |
return FALSE; |
return FALSE; |
hppa_info->plt_rel_sec = s; |
hppa_info->plt_rel_sec = s; |
|
|
Line 1369 elf64_hppa_create_dynamic_sections (bfd |
|
Line 1368 elf64_hppa_create_dynamic_sections (bfd |
|
| SEC_READONLY |
| SEC_READONLY |
| SEC_LINKER_CREATED)); |
| SEC_LINKER_CREATED)); |
if (s == NULL |
if (s == NULL |
|| !bfd_set_section_alignment (abfd, s, 3)) |
|| !bfd_set_section_alignment (s, 3)) |
return FALSE; |
return FALSE; |
hppa_info->other_rel_sec = s; |
hppa_info->other_rel_sec = s; |
|
|
Line 1380 elf64_hppa_create_dynamic_sections (bfd |
|
Line 1379 elf64_hppa_create_dynamic_sections (bfd |
|
| SEC_READONLY |
| SEC_READONLY |
| SEC_LINKER_CREATED)); |
| SEC_LINKER_CREATED)); |
if (s == NULL |
if (s == NULL |
|| !bfd_set_section_alignment (abfd, s, 3)) |
|| !bfd_set_section_alignment (s, 3)) |
return FALSE; |
return FALSE; |
hppa_info->opd_rel_sec = s; |
hppa_info->opd_rel_sec = s; |
|
|
Line 1750 elf64_hppa_size_dynamic_sections (bfd *o |
|
Line 1749 elf64_hppa_size_dynamic_sections (bfd *o |
|
|
|
/* It's OK to base decisions on the section name, because none |
/* It's OK to base decisions on the section name, because none |
of the dynobj section names depend upon the input files. */ |
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) |
if (strcmp (name, ".plt") == 0) |
{ |
{ |
Line 1783 elf64_hppa_size_dynamic_sections (bfd *o |
|
Line 1782 elf64_hppa_size_dynamic_sections (bfd *o |
|
entry. The entries in the .rela.plt section |
entry. The entries in the .rela.plt section |
really apply to the .got section, which we |
really apply to the .got section, which we |
created ourselves and so know is not readonly. */ |
created ourselves and so know is not readonly. */ |
outname = bfd_get_section_name (output_bfd, |
outname = bfd_section_name (sec->output_section); |
sec->output_section); |
|
target = bfd_get_section_by_name (output_bfd, outname + 4); |
target = bfd_get_section_by_name (output_bfd, outname + 4); |
if (target != NULL |
if (target != NULL |
&& (target->flags & SEC_READONLY) != 0 |
&& (target->flags & SEC_READONLY) != 0 |
Line 2011 elf64_hppa_finish_dynamic_symbol (bfd *o |
|
Line 2009 elf64_hppa_finish_dynamic_symbol (bfd *o |
|
in the output_offset of the PLT section. */ |
in the output_offset of the PLT section. */ |
|
|
bfd_put_64 (splt->owner, value, splt->contents + hh->plt_offset); |
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); |
bfd_put_64 (splt->owner, value, splt->contents + hh->plt_offset + 0x8); |
|
|
/* Create a dynamic IPLT relocation for this entry. |
/* Create a dynamic IPLT relocation for this entry. |
Line 2027 elf64_hppa_finish_dynamic_symbol (bfd *o |
|
Line 2025 elf64_hppa_finish_dynamic_symbol (bfd *o |
|
|
|
loc = spltrel->contents; |
loc = spltrel->contents; |
loc += spltrel->reloc_count++ * sizeof (Elf64_External_Rela); |
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. */ |
/* Initialize an external call stub entry if requested. */ |
Line 2143 elf64_hppa_finalize_opd (struct elf_link |
|
Line 2141 elf64_hppa_finalize_opd (struct elf_link |
|
bfd_put_64 (sopd->owner, value, sopd->contents + hh->opd_offset + 16); |
bfd_put_64 (sopd->owner, value, sopd->contents + hh->opd_offset + 16); |
|
|
/* The last word is our local __gp value. */ |
/* 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); |
bfd_put_64 (sopd->owner, value, sopd->contents + hh->opd_offset + 24); |
} |
} |
|
|
Line 2220 elf64_hppa_finalize_opd (struct elf_link |
|
Line 2218 elf64_hppa_finalize_opd (struct elf_link |
|
|
|
loc = sopdrel->contents; |
loc = sopdrel->contents; |
loc += sopdrel->reloc_count++ * sizeof (Elf64_External_Rela); |
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; |
return TRUE; |
} |
} |
Line 2315 elf64_hppa_finalize_dlt (struct elf_link |
|
Line 2313 elf64_hppa_finalize_dlt (struct elf_link |
|
|
|
loc = sdltrel->contents; |
loc = sdltrel->contents; |
loc += sdltrel->reloc_count++ * sizeof (Elf64_External_Rela); |
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; |
return TRUE; |
} |
} |
Line 2431 elf64_hppa_finalize_dynreloc (struct elf |
|
Line 2429 elf64_hppa_finalize_dynreloc (struct elf |
|
loc = hppa_info->other_rel_sec->contents; |
loc = hppa_info->other_rel_sec->contents; |
loc += (hppa_info->other_rel_sec->reloc_count++ |
loc += (hppa_info->other_rel_sec->reloc_count++ |
* sizeof (Elf64_External_Rela)); |
* sizeof (Elf64_External_Rela)); |
bfd_elf64_swap_reloca_out (hppa_info->other_rel_sec->output_section->owner, |
bfd_elf64_swap_reloca_out (info->output_bfd, &rel, loc); |
&rel, loc); |
|
} |
} |
} |
} |
|
|
Line 3381 elf_hppa_final_link_relocate (Elf_Intern |
|
Line 3378 elf_hppa_final_link_relocate (Elf_Intern |
|
(hppa_info->opd_sec->contents + off + 16)); |
(hppa_info->opd_sec->contents + off + 16)); |
|
|
/* The last word is our local __gp value. */ |
/* The last word is our local __gp value. */ |
value = _bfd_get_gp_value |
value = _bfd_get_gp_value (info->output_bfd); |
(hppa_info->opd_sec->output_section->owner); |
|
bfd_put_64 (hppa_info->opd_sec->owner, value, |
bfd_put_64 (hppa_info->opd_sec->owner, value, |
(hppa_info->opd_sec->contents + off + 24)); |
(hppa_info->opd_sec->contents + off + 24)); |
} |
} |
Line 3556 elf_hppa_final_link_relocate (Elf_Intern |
|
Line 3552 elf_hppa_final_link_relocate (Elf_Intern |
|
|
|
case R_PARISC_LTOFF_FPTR32: |
case R_PARISC_LTOFF_FPTR32: |
{ |
{ |
/* We may still need to create the FPTR itself if it was for |
/* FIXME: There used to be code here to create the FPTR itself if |
a local symbol. */ |
the relocation was against a local symbol. But the code could |
if (hh == NULL) |
never have worked. If the assert below is ever triggered then |
{ |
the code will need to be reinstated and fixed so that it does |
/* The first two words of an .opd entry are zero. */ |
what is needed. */ |
memset (hppa_info->opd_sec->contents + hh->opd_offset, 0, 16); |
BFD_ASSERT (hh != NULL); |
|
|
/* 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); |
|
} |
|
|
|
/* We want the value of the DLT offset for this symbol, not |
/* We want the value of the DLT offset for this symbol, not |
the symbol's actual address. Note that __gp may not point |
the symbol's actual address. Note that __gp may not point |
Line 3612 elf_hppa_final_link_relocate (Elf_Intern |
|
Line 3587 elf_hppa_final_link_relocate (Elf_Intern |
|
+ hh->opd_offset + 16)); |
+ hh->opd_offset + 16)); |
|
|
/* The last word is our local __gp value. */ |
/* The last word is our local __gp value. */ |
value = _bfd_get_gp_value |
value = _bfd_get_gp_value (info->output_bfd); |
(hppa_info->opd_sec->output_section->owner); |
|
bfd_put_64 (hppa_info->opd_sec->owner, value, |
bfd_put_64 (hppa_info->opd_sec->owner, value, |
hppa_info->opd_sec->contents + hh->opd_offset + 24); |
hppa_info->opd_sec->contents + hh->opd_offset + 24); |
|
|
Line 3739 elf_hppa_final_link_relocate (Elf_Intern |
|
Line 3713 elf_hppa_final_link_relocate (Elf_Intern |
|
(hppa_info->opd_sec->contents + off + 16)); |
(hppa_info->opd_sec->contents + off + 16)); |
|
|
/* The last word is our local __gp value. */ |
/* The last word is our local __gp value. */ |
value = _bfd_get_gp_value |
value = _bfd_get_gp_value (info->output_bfd); |
(hppa_info->opd_sec->output_section->owner); |
|
bfd_put_64 (hppa_info->opd_sec->owner, value, |
bfd_put_64 (hppa_info->opd_sec->owner, value, |
hppa_info->opd_sec->contents + off + 24); |
hppa_info->opd_sec->contents + off + 24); |
} |
} |
Line 3963 elf64_hppa_relocate_section (bfd *output |
|
Line 3936 elf64_hppa_relocate_section (bfd *output |
|
if (sym_name == NULL) |
if (sym_name == NULL) |
return FALSE; |
return FALSE; |
if (*sym_name == '\0') |
if (*sym_name == '\0') |
sym_name = bfd_section_name (input_bfd, sym_sec); |
sym_name = bfd_section_name (sym_sec); |
} |
} |
|
|
(*info->callbacks->reloc_overflow) |
(*info->callbacks->reloc_overflow) |
Line 3979 elf64_hppa_relocate_section (bfd *output |
|
Line 3952 elf64_hppa_relocate_section (bfd *output |
|
|
|
static const struct bfd_elf_special_section elf64_hppa_special_sections[] = |
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 (".fini"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, |
{ STRING_COMMA_LEN (".init"), 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 (".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 (".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 (".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 (".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 } |
{ NULL, 0, 0, 0, 0 } |
}; |
}; |
|
|
Line 4050 const struct elf_size_info hppa64_elf_si |
|
Line 4023 const struct elf_size_info hppa64_elf_si |
|
|
|
#define elf_backend_create_dynamic_sections \ |
#define elf_backend_create_dynamic_sections \ |
elf64_hppa_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_backend_omit_section_dynsym _bfd_elf_omit_section_dynsym_all |
|
|
Line 4113 const struct elf_size_info hppa64_elf_si |
|
Line 4086 const struct elf_size_info hppa64_elf_si |
|
#define ELF_OSABI ELFOSABI_GNU |
#define ELF_OSABI ELFOSABI_GNU |
#undef elf64_bed |
#undef elf64_bed |
#define elf64_bed elf64_hppa_linux_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" |
#include "elf64-target.h" |