2002-02-26 John David Anglin <dave@hiauly1.hia.nrc.ca>

* bfd/elf-hppa.h (elf_hppa_is_dynamic_loader_symbol): New function.
	(elf_hppa_relocate_section): Ignore undefined dynamic loader symbols.
	(elf_hppa_final_link_relocate): Correct relocations for indirect
	references to local data through the DLT.  Fix .opd creation for
	local symbols using R_PARISC_LTOFF_FPTR32 and R_PARISC_FPTR64
	relocations.  Use e_lsel selector for R_PARISC_DLTIND21L,
	R_PARISC_LTOFF_FPTR21L and R_PARISC_LTOFF_TP21L as per
	"Processor-Specific ELF for PA_RISC, Version 1.43" document.
	Similarly, use e_rsel for DLT and LTOFF 'R' relocations.
	* bfd/elf32-hppa.c (final_link_relocate): Revise relocation selectors
	as per "Processor-Specific ELF for PA_RISC, Version 1.43" document.
This commit is contained in:
Jeff Law 2002-03-05 17:55:55 +00:00
parent 86eaf01e5d
commit 1bf425384c
3 changed files with 95 additions and 25 deletions

View file

@ -1,3 +1,17 @@
2002-03-05 John David Anglin <dave@hiauly1.hia.nrc.ca>
* elf-hppa.h (elf_hppa_is_dynamic_loader_symbol): New function.
(elf_hppa_relocate_section): Ignore undefined dynamic loader symbols.
(elf_hppa_final_link_relocate): Correct relocations for indirect
references to local data through the DLT. Fix .opd creation for
local symbols using R_PARISC_LTOFF_FPTR32 and R_PARISC_FPTR64
relocations. Use e_lsel selector for R_PARISC_DLTIND21L,
R_PARISC_LTOFF_FPTR21L and R_PARISC_LTOFF_TP21L as per
"Processor-Specific ELF for PA_RISC, Version 1.43" document.
Similarly, use e_rsel for DLT and LTOFF 'R' relocations.
* elf32-hppa.c (final_link_relocate): Revise relocation selectors
as per "Processor-Specific ELF for PA_RISC, Version 1.43" document.
2002-03-05 Jakub Jelinek <jakub@redhat.com>
* merge.c (_bfd_merge_sections): Don't segfault if there

View file

@ -75,6 +75,9 @@ static boolean elf_hppa_unmark_useless_dynamic_symbols
static boolean elf_hppa_remark_useless_dynamic_symbols
PARAMS ((struct elf_link_hash_entry *, PTR));
static boolean elf_hppa_is_dynamic_loader_symbol
PARAMS ((const char *));
static void elf_hppa_record_segment_addrs
PARAMS ((bfd *, asection *, PTR));
@ -1136,6 +1139,23 @@ elf_hppa_remark_useless_dynamic_symbols (h, data)
return true;
}
static boolean
elf_hppa_is_dynamic_loader_symbol (name)
const char * name;
{
return (! strcmp (name, "__CPU_REVISION")
|| ! strcmp (name, "__CPU_KEYBITS_1")
|| ! strcmp (name, "__SYSTEM_ID_D")
|| ! strcmp (name, "__FPU_MODEL")
|| ! strcmp (name, "__FPU_REVISION")
|| ! strcmp (name, "__ARGC")
|| ! strcmp (name, "__ARGV")
|| ! strcmp (name, "__ENVP")
|| ! strcmp (name, "__TLS_SIZE_D")
|| ! strcmp (name, "__LOAD_INFO")
|| ! strcmp (name, "__systab"));
}
/* Record the lowest address for the data and text segments. */
static void
elf_hppa_record_segment_addrs (abfd, section, data)
@ -1419,11 +1439,17 @@ elf_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
relocation = 0;
else
{
if (!((*info->callbacks->undefined_symbol)
(info, h->root.root.string, input_bfd,
input_section, rel->r_offset, true)))
return false;
break;
/* Ignore dynamic loader defined symbols. */
if (elf_hppa_is_dynamic_loader_symbol (h->root.root.string))
relocation = 0;
else
{
if (!((*info->callbacks->undefined_symbol)
(info, h->root.root.string, input_bfd,
input_section, rel->r_offset, true)))
return false;
break;
}
}
}
@ -1620,11 +1646,7 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
a local function which had its address taken. */
if (dyn_h->h == NULL)
{
bfd_put_64 (hppa_info->dlt_sec->owner,
value,
hppa_info->dlt_sec->contents + dyn_h->dlt_offset);
/* Now handle .opd creation if needed. */
/* Now do .opd creation if needed. */
if (r_type == R_PARISC_LTOFF_FPTR14R
|| r_type == R_PARISC_LTOFF_FPTR14DR
|| r_type == R_PARISC_LTOFF_FPTR14WR
@ -1638,7 +1660,7 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
0, 16);
/* The next word is the address of the function. */
bfd_put_64 (hppa_info->opd_sec->owner, value,
bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
(hppa_info->opd_sec->contents
+ dyn_h->opd_offset + 16));
@ -1648,7 +1670,17 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
bfd_put_64 (hppa_info->opd_sec->owner, value,
(hppa_info->opd_sec->contents
+ dyn_h->opd_offset + 24));
/* The DLT value is the address of the .opd entry. */
value = (dyn_h->opd_offset
+ hppa_info->opd_sec->output_offset
+ hppa_info->opd_sec->output_section->vma);
addend = 0;
}
bfd_put_64 (hppa_info->dlt_sec->owner,
value + addend,
hppa_info->dlt_sec->contents + dyn_h->dlt_offset);
}
/* We want the value of the DLT offset for this symbol, not
@ -1666,7 +1698,7 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
if (r_type == R_PARISC_DLTIND21L
|| r_type == R_PARISC_LTOFF_FPTR21L
|| r_type == R_PARISC_LTOFF_TP21L)
value = hppa_field_adjust (value, addend, e_lrsel);
value = hppa_field_adjust (value, 0, e_lsel);
else if (r_type == R_PARISC_DLTIND14F
|| r_type == R_PARISC_LTOFF_FPTR16F
|| r_type == R_PARISC_LTOFF_FPTR16WF
@ -1677,9 +1709,9 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
|| r_type == R_PARISC_LTOFF_TP16F
|| r_type == R_PARISC_LTOFF_TP16WF
|| r_type == R_PARISC_LTOFF_TP16DF)
value = hppa_field_adjust (value, addend, e_fsel);
value = hppa_field_adjust (value, 0, e_fsel);
else
value = hppa_field_adjust (value, addend, e_rrsel);
value = hppa_field_adjust (value, 0, e_rsel);
insn = elf_hppa_relocate_insn (insn, (int) value, r_type);
break;
@ -1804,7 +1836,7 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
memset (hppa_info->opd_sec->contents + dyn_h->opd_offset, 0, 16);
/* The next word is the address of the function. */
bfd_put_64 (hppa_info->opd_sec->owner, value,
bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
(hppa_info->opd_sec->contents
+ dyn_h->opd_offset + 16));
@ -1813,6 +1845,15 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
(hppa_info->opd_sec->output_section->owner);
bfd_put_64 (hppa_info->opd_sec->owner, value,
hppa_info->opd_sec->contents + dyn_h->opd_offset + 24);
/* The DLT value is the address of the .opd entry. */
value = (dyn_h->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 + dyn_h->dlt_offset);
}
/* We want the value of the DLT offset for this symbol, not
@ -1838,7 +1879,7 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
memset (hppa_info->opd_sec->contents + dyn_h->opd_offset, 0, 16);
/* The next word is the address of the function. */
bfd_put_64 (hppa_info->opd_sec->owner, value,
bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
(hppa_info->opd_sec->contents
+ dyn_h->opd_offset + 16));
@ -1847,6 +1888,15 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
(hppa_info->opd_sec->output_section->owner);
bfd_put_64 (hppa_info->opd_sec->owner, value,
hppa_info->opd_sec->contents + dyn_h->opd_offset + 24);
/* The DLT value is the address of the .opd entry. */
value = (dyn_h->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 + dyn_h->dlt_offset);
}
/* We want the value of the DLT offset for this symbol, not
@ -1938,7 +1988,7 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
memset (hppa_info->opd_sec->contents + dyn_h->opd_offset, 0, 16);
/* The next word is the address of the function. */
bfd_put_64 (hppa_info->opd_sec->owner, value,
bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
(hppa_info->opd_sec->contents
+ dyn_h->opd_offset + 16));
@ -1955,7 +2005,7 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
+ hppa_info->opd_sec->output_offset
+ hppa_info->opd_sec->output_section->vma);
bfd_put_64 (input_bfd, value + addend, hit_data);
bfd_put_64 (input_bfd, value, hit_data);
return bfd_reloc_ok;
}

View file

@ -3471,21 +3471,27 @@ final_link_relocate (input_section, contents, rel, value, htab, sym_sec, h)
r_field = e_fsel;
break;
case R_PARISC_DIR21L:
case R_PARISC_PCREL21L:
case R_PARISC_DPREL21L:
case R_PARISC_PLABEL21L:
case R_PARISC_DLTIND21L:
case R_PARISC_PCREL21L:
case R_PARISC_PLABEL21L:
r_field = e_lsel;
break;
case R_PARISC_DIR21L:
case R_PARISC_DPREL21L:
r_field = e_lrsel;
break;
case R_PARISC_DIR17R:
case R_PARISC_PCREL17R:
case R_PARISC_DIR14R:
case R_PARISC_PCREL14R:
case R_PARISC_DPREL14R:
case R_PARISC_PLABEL14R:
case R_PARISC_DLTIND14R:
r_field = e_rsel;
break;
case R_PARISC_DIR17R:
case R_PARISC_DIR14R:
case R_PARISC_DPREL14R:
r_field = e_rrsel;
break;