diff options
author | Jeff Law <law@redhat.com> | 1999-09-10 15:46:37 +0000 |
---|---|---|
committer | Jeff Law <law@redhat.com> | 1999-09-10 15:46:37 +0000 |
commit | e48c661ee6b7d8a850acd122a7a17076d3c1dc33 (patch) | |
tree | 513119b57075c2dcf7bce7ae0c6d509aeee51f91 /bfd/elf-hppa.h | |
parent | e5b08bf0d38e0446d5fd37b7ba307dd995996c8a (diff) | |
download | gdb-e48c661ee6b7d8a850acd122a7a17076d3c1dc33.zip gdb-e48c661ee6b7d8a850acd122a7a17076d3c1dc33.tar.gz gdb-e48c661ee6b7d8a850acd122a7a17076d3c1dc33.tar.bz2 |
* elf-hppa.h (elf_hppa_final_link_relocate): Create .opd entries
for FPTR relocs involving local symbols.
Diffstat (limited to 'bfd/elf-hppa.h')
-rw-r--r-- | bfd/elf-hppa.h | 104 |
1 files changed, 96 insertions, 8 deletions
diff --git a/bfd/elf-hppa.h b/bfd/elf-hppa.h index 53a50ab..dfc754e 100644 --- a/bfd/elf-hppa.h +++ b/bfd/elf-hppa.h @@ -1220,12 +1220,41 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd, to the local symbol's value). So, if this is a local symbol (h == NULL), then we need to - fill in its DLT entry. */ + fill in its DLT entry. + + Similarly we may still need to set up an entry in .opd for + 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. */ + if (r_type == R_PARISC_LTOFF_FPTR14R + || r_type == R_PARISC_LTOFF_FPTR14DR + || r_type == R_PARISC_LTOFF_FPTR14WR + || r_type == R_PARISC_LTOFF_FPTR21L + || r_type == R_PARISC_LTOFF_FPTR16F + || r_type == R_PARISC_LTOFF_FPTR16WF + || r_type == R_PARISC_LTOFF_FPTR16DF) + { + /* The first two words of an .opd entry are zero. */ + 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, + (hppa_info->opd_sec->contents + + dyn_h->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 + + dyn_h->opd_offset + 24)); + } } /* We want the value of the DLT offset for this symbol, not @@ -1353,6 +1382,25 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd, case R_PARISC_LTOFF_FPTR32: { + /* We may still need to create the FPTR itself if it was for + a local symbol. */ + if (dyn_h->h == NULL) + { + /* The first two words of an .opd entry are zero. */ + 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, + (hppa_info->opd_sec->contents + + dyn_h->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 + dyn_h->opd_offset + 24); + } + /* We want the value of the DLT offset for this symbol, not the symbol's actual address. */ value = dyn_h->dlt_offset + hppa_info->dlt_sec->output_offset; @@ -1363,6 +1411,25 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd, case R_PARISC_LTOFF_FPTR64: case R_PARISC_LTOFF_TP64: { + /* We may still need to create the FPTR itself if it was for + a local symbol. */ + if (dyn_h->h == NULL && r_type == R_PARISC_LTOFF_FPTR64) + { + /* The first two words of an .opd entry are zero. */ + 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, + (hppa_info->opd_sec->contents + + dyn_h->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 + dyn_h->opd_offset + 24); + } + /* We want the value of the DLT offset for this symbol, not the symbol's actual address. */ value = dyn_h->dlt_offset + hppa_info->dlt_sec->output_offset; @@ -1433,14 +1500,35 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd, case R_PARISC_FPTR64: - /* We want the value of the OPD offset for this symbol, not - the symbol's actual address. */ - value = (dyn_h->opd_offset - + hppa_info->opd_sec->output_offset - + hppa_info->opd_sec->output_section->vma); + { + /* We may still need to create the FPTR itself if it was for + a local symbol. */ + if (dyn_h->h == NULL) + { + /* The first two words of an .opd entry are zero. */ + 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, + (hppa_info->opd_sec->contents + + dyn_h->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 + dyn_h->opd_offset + 24); + } + + /* We want the value of the OPD offset for this symbol, not + the symbol's actual address. */ + value = (dyn_h->opd_offset + + hppa_info->opd_sec->output_offset + + hppa_info->opd_sec->output_section->vma); - bfd_put_64 (input_bfd, value + addend, hit_data); - return bfd_reloc_ok; + bfd_put_64 (input_bfd, value + addend, hit_data); + return bfd_reloc_ok; + } /* Something we don't know how to handle. */ default: |