diff options
-rw-r--r-- | bfd/ChangeLog | 5 | ||||
-rw-r--r-- | bfd/elf-hppa.h | 69 |
2 files changed, 66 insertions, 8 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 597bd5d..964c7b6 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,10 @@ Mon Sep 13 20:01:47 1999 Jeffrey A Law (law@cygnus.com) + * elf-hppa.h (elf_hppa_record_segment_addrs): New function. + (elf_hppa_final_link): Initialize text_segment_base and + data_segment_base. + (elf_hppa_final_link_relocate): Handle SEGREL relocations. + * elf-hppa.h (elf_hppa_final_link): Remove unused variables. (elf_hppa_final_link_relocate): Likewise. (elf_hppa_relocate_insn): Likewise. diff --git a/bfd/elf-hppa.h b/bfd/elf-hppa.h index 65c0091..95d9724 100644 --- a/bfd/elf-hppa.h +++ b/bfd/elf-hppa.h @@ -69,6 +69,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 void elf_hppa_record_segment_addrs + PARAMS ((bfd *, asection *, PTR)); + /* ELF/PA relocation howto entries. */ static reloc_howto_type elf_hppa_howto_table[ELF_HOWTO_TABLE_SIZE] = @@ -810,6 +813,30 @@ elf_hppa_remark_useless_dynamic_symbols (h, data) return true; } +/* Record the lowest address for the data and text segments. */ +static void +elf_hppa_record_segment_addrs (abfd, section, data) + bfd *abfd ATTRIBUTE_UNUSED; + asection *section; + PTR data; +{ + struct elf64_hppa_link_hash_table *hppa_info; + bfd_vma value; + + hppa_info = (struct elf64_hppa_link_hash_table *)data; + + value = section->vma - section->filepos; + + if ((section->flags & (SEC_ALLOC | SEC_LOAD | SEC_READONLY) + == (SEC_ALLOC | SEC_LOAD | SEC_READONLY)) + && value < hppa_info->text_segment_base) + hppa_info->text_segment_base = value; + else if ((section->flags & (SEC_ALLOC | SEC_LOAD | SEC_READONLY) + == (SEC_ALLOC | SEC_LOAD)) + && value < hppa_info->data_segment_base) + hppa_info->data_segment_base = value; +} + /* Called after we have seen all the input files/sections, but before final symbol resolution and section placement has been determined. @@ -852,6 +879,12 @@ elf_hppa_final_link (abfd, info) _bfd_set_gp_value (abfd, gp_val); } + /* We need to know the base of the text and data segments so that we + can perform SEGREL relocations. We will recore the base addresses + when we encounter the first SEGREL relocation. */ + elf64_hppa_hash_table (info)->text_segment_base = (bfd_vma)-1; + elf64_hppa_hash_table (info)->data_segment_base = (bfd_vma)-1; + /* HP's shared libraries have references to symbols that are not defined anywhere. The generic ELF BFD linker code will complaim about such symbols. @@ -1097,13 +1130,6 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd, insn = bfd_get_32 (input_bfd, hit_data); -/* For reference here a quick summary of the relocations found in the - HPUX 11.00 PA64 .o and .a files, but not yet implemented. This is mostly - a guide to help prioritize what relocation support is worked on first. - The list will be deleted eventually. - - 27210 R_PARISC_SEGREL32 */ - switch (r_type) { case R_PARISC_NONE: @@ -1534,7 +1560,34 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd, return bfd_reloc_ok; case R_PARISC_SEGREL32: - return bfd_reloc_ok; + case R_PARISC_SEGREL64: + { + /* If this is the first SEGREL relocation, then initialize + the segment base values. */ + if (hppa_info->text_segment_base == (bfd_vma) -1) + bfd_map_over_sections (output_bfd, elf_hppa_record_segment_addrs, + elf64_hppa_hash_table (info)); + + /* VALUE holds the absolute address. We want to include the + addend, then turn it into a segment relative address. + + The segment is derived from SYM_SEC. We assume that there are + only two segments of note in the resulting executable/shlib. + A readonly segment (.text) and a readwrite segment (.data). */ + value += addend; + + if (sym_sec->flags & SEC_CODE) + value -= hppa_info->text_segment_base; + else + value -= hppa_info->data_segment_base; + + if (r_type == R_PARISC_SEGREL32) + bfd_put_32 (input_bfd, value, hit_data); + else + bfd_put_64 (input_bfd, value, hit_data); + return bfd_reloc_ok; + } + /* Something we don't know how to handle. */ default: |