X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf-hppa.h;h=99a66f4e1807397e46eb892fa3beec20b55b5e2a;hb=86fb1dece37497b267579ed4f062d280cd5760cd;hp=cca760dad3499072391f0eaad87112a3a72d8059;hpb=f8df10f4f595488c4b6a8e49ffc99721d5aefdba;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf-hppa.h b/bfd/elf-hppa.h index cca760dad3..99a66f4e18 100644 --- a/bfd/elf-hppa.h +++ b/bfd/elf-hppa.h @@ -1,5 +1,5 @@ /* Common code for PA ELF implementations. - Copyright 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -29,6 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define ELF_R_TYPE(X) ELF64_R_TYPE(X) #define ELF_R_SYM(X) ELF64_R_SYM(X) #define elf_hppa_internal_shdr Elf64_Internal_Shdr +#define elf_hppa_reloc_final_type elf64_hppa_reloc_final_type #define _bfd_elf_hppa_gen_reloc_type _bfd_elf64_hppa_gen_reloc_type #define elf_hppa_relocate_section elf64_hppa_relocate_section #define bfd_elf_bfd_final_link bfd_elf64_bfd_final_link @@ -38,15 +39,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define ELF_R_TYPE(X) ELF32_R_TYPE(X) #define ELF_R_SYM(X) ELF32_R_SYM(X) #define elf_hppa_internal_shdr Elf32_Internal_Shdr +#define elf_hppa_reloc_final_type elf32_hppa_reloc_final_type #define _bfd_elf_hppa_gen_reloc_type _bfd_elf32_hppa_gen_reloc_type #define elf_hppa_relocate_section elf32_hppa_relocate_section #define bfd_elf_bfd_final_link bfd_elf32_bfd_final_link #define elf_hppa_final_link elf32_hppa_final_link #endif -elf_hppa_reloc_type ** _bfd_elf_hppa_gen_reloc_type - PARAMS ((bfd *, elf_hppa_reloc_type, int, unsigned int, int, asymbol *)); - static void elf_hppa_info_to_howto PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); @@ -65,6 +64,12 @@ static boolean elf_hppa_fake_sections static void elf_hppa_final_write_processing PARAMS ((bfd *, boolean)); +static int hppa_unwind_entry_compare + PARAMS ((const PTR, const PTR)); + +static boolean elf_hppa_sort_unwind + PARAMS ((bfd *)); + #if ARCH_SIZE == 64 static boolean elf_hppa_add_symbol_hook PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *, @@ -76,6 +81,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)); @@ -84,12 +92,12 @@ static boolean elf_hppa_final_link static boolean elf_hppa_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, - bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); + bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); static bfd_reloc_status_type elf_hppa_final_link_relocate PARAMS ((Elf_Internal_Rela *, bfd *, bfd *, asection *, - bfd_byte *, bfd_vma, struct bfd_link_info *, - asection *, struct elf_link_hash_entry *, + bfd_byte *, bfd_vma, struct bfd_link_info *, + asection *, struct elf_link_hash_entry *, struct elf64_hppa_dyn_hash_entry *)); static int elf_hppa_relocate_insn @@ -605,40 +613,17 @@ static reloc_howto_type elf_hppa_howto_table[ELF_HOWTO_TABLE_SIZE] = #define OFFSET_14R_FROM_21L 4 #define OFFSET_14F_FROM_21L 5 -/* Return one (or more) BFD relocations which implement the base - relocation with modifications based on format and field. */ +/* Return the final relocation type for the given base type, instruction + format, and field selector. */ -elf_hppa_reloc_type ** -_bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym) +elf_hppa_reloc_type +elf_hppa_reloc_final_type (abfd, base_type, format, field) bfd *abfd; elf_hppa_reloc_type base_type; int format; unsigned int field; - int ignore ATTRIBUTE_UNUSED; - asymbol *sym ATTRIBUTE_UNUSED; { - elf_hppa_reloc_type *finaltype; - elf_hppa_reloc_type **final_types; - bfd_size_type amt = sizeof (elf_hppa_reloc_type *) * 2; - - /* Allocate slots for the BFD relocation. */ - final_types = (elf_hppa_reloc_type **) bfd_alloc (abfd, amt); - if (final_types == NULL) - return NULL; - - /* Allocate space for the relocation itself. */ - amt = sizeof (elf_hppa_reloc_type); - finaltype = (elf_hppa_reloc_type *) bfd_alloc (abfd, amt); - if (finaltype == NULL) - return NULL; - - /* Some reasonable defaults. */ - final_types[0] = finaltype; - final_types[1] = NULL; - -#define final_type finaltype[0] - - final_type = base_type; + elf_hppa_reloc_type final_type = base_type; /* Just a tangle of nested switch statements to deal with the braindamage that a different field selector means a completely different relocation @@ -677,7 +662,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym) final_type = R_PARISC_PLABEL14R; break; default: - return NULL; + return R_PARISC_NONE; } break; @@ -693,7 +678,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym) final_type = R_PARISC_DIR17R; break; default: - return NULL; + return R_PARISC_NONE; } break; @@ -717,7 +702,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym) final_type = R_PARISC_PLABEL21L; break; default: - return NULL; + return R_PARISC_NONE; } break; @@ -730,13 +715,13 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym) be a section relative relocation. Dwarf2 (for example) uses 32bit section relative relocations. */ if (bfd_get_arch_info (abfd)->bits_per_address != 32) - final_type = R_PARISC_SECREL32; + final_type = R_PARISC_SECREL32; break; case e_psel: final_type = R_PARISC_PLABEL32; break; default: - return NULL; + return R_PARISC_NONE; } break; @@ -750,12 +735,12 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym) final_type = R_PARISC_FPTR64; break; default: - return NULL; + return R_PARISC_NONE; } break; default: - return NULL; + return R_PARISC_NONE; } break; @@ -776,7 +761,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym) final_type = base_type + OFFSET_14F_FROM_21L; break; default: - return NULL; + return R_PARISC_NONE; } break; @@ -792,12 +777,12 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym) final_type = base_type; break; default: - return NULL; + return R_PARISC_NONE; } break; default: - return NULL; + return R_PARISC_NONE; } break; @@ -811,7 +796,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym) final_type = R_PARISC_PCREL12F; break; default: - return NULL; + return R_PARISC_NONE; } break; @@ -829,7 +814,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym) final_type = R_PARISC_PCREL14F; break; default: - return NULL; + return R_PARISC_NONE; } break; @@ -845,7 +830,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym) final_type = R_PARISC_PCREL17F; break; default: - return NULL; + return R_PARISC_NONE; } break; @@ -860,7 +845,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym) final_type = R_PARISC_PCREL21L; break; default: - return NULL; + return R_PARISC_NONE; } break; @@ -871,12 +856,12 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym) final_type = R_PARISC_PCREL22F; break; default: - return NULL; + return R_PARISC_NONE; } break; default: - return NULL; + return R_PARISC_NONE; } break; @@ -888,9 +873,45 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym) break; default: - return NULL; + return R_PARISC_NONE; } + return final_type; +} + +/* Return one (or more) BFD relocations which implement the base + relocation with modifications based on format and field. */ + +elf_hppa_reloc_type ** +_bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym) + bfd *abfd; + elf_hppa_reloc_type base_type; + int format; + unsigned int field; + int ignore ATTRIBUTE_UNUSED; + asymbol *sym ATTRIBUTE_UNUSED; +{ + elf_hppa_reloc_type *finaltype; + elf_hppa_reloc_type **final_types; + bfd_size_type amt = sizeof (elf_hppa_reloc_type *) * 2; + + /* Allocate slots for the BFD relocation. */ + final_types = (elf_hppa_reloc_type **) bfd_alloc (abfd, amt); + if (final_types == NULL) + return NULL; + + /* Allocate space for the relocation itself. */ + amt = sizeof (elf_hppa_reloc_type); + finaltype = (elf_hppa_reloc_type *) bfd_alloc (abfd, amt); + if (finaltype == NULL) + return NULL; + + /* Some reasonable defaults. */ + final_types[0] = finaltype; + final_types[1] = NULL; + + *finaltype = elf_hppa_reloc_final_type (abfd, base_type, format, field); + return final_types; } @@ -1022,6 +1043,64 @@ elf_hppa_final_write_processing (abfd, linker) | EF_PARISC_TRAPNIL); } +/* Comparison function for qsort to sort unwind section during a + final link. */ + +static int +hppa_unwind_entry_compare (a, b) + const PTR a; + const PTR b; +{ + const bfd_byte *ap, *bp; + unsigned long av, bv; + + ap = (const bfd_byte *) a; + av = (unsigned long) ap[0] << 24; + av |= (unsigned long) ap[1] << 16; + av |= (unsigned long) ap[2] << 8; + av |= (unsigned long) ap[3]; + + bp = (const bfd_byte *) b; + bv = (unsigned long) bp[0] << 24; + bv |= (unsigned long) bp[1] << 16; + bv |= (unsigned long) bp[2] << 8; + bv |= (unsigned long) bp[3]; + + return av < bv ? -1 : av > bv ? 1 : 0; +} + +static boolean elf_hppa_sort_unwind (abfd) + bfd *abfd; +{ + asection *s; + + /* Magic section names, but this is much safer than having + relocate_section remember where SEGREL32 relocs occurred. + Consider what happens if someone inept creates a linker script + that puts unwind information in .text. */ + s = bfd_get_section_by_name (abfd, ".PARISC.unwind"); + if (s != NULL) + { + bfd_size_type size; + char *contents; + + size = s->_raw_size; + contents = bfd_malloc (size); + if (contents == NULL) + return false; + + if (! bfd_get_section_contents (abfd, s, contents, (file_ptr) 0, size)) + return false; + + qsort (contents, (size_t) (size / 16), 16, hppa_unwind_entry_compare); + + if (! bfd_set_section_contents (abfd, s, contents, (file_ptr) 0, size)) + return false; + } + + return true; +} + #if ARCH_SIZE == 64 /* Hook called by the linker routine which adds symbols from an object file. HP's libraries define symbols with HP specific section @@ -1064,6 +1143,9 @@ elf_hppa_unmark_useless_dynamic_symbols (h, data) { struct bfd_link_info *info = (struct bfd_link_info *)data; + if (h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + /* If we are not creating a shared library, and this symbol is referenced by a shared library but is not defined anywhere, then the generic code will warn that it is undefined. @@ -1097,6 +1179,9 @@ elf_hppa_remark_useless_dynamic_symbols (h, data) { struct bfd_link_info *info = (struct bfd_link_info *)data; + if (h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + /* If we are not creating a shared library, and this symbol is referenced by a shared library but is not defined anywhere, then the generic code will warn that it is undefined. @@ -1124,6 +1209,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) @@ -1246,6 +1348,11 @@ elf_hppa_final_link (abfd, info) elf_hppa_remark_useless_dynamic_symbols, info); + /* If we're producing a final executable, sort the contents of the + unwind section. */ + if (retval) + retval = elf_hppa_sort_unwind (abfd); + return retval; } @@ -1378,7 +1485,7 @@ elf_hppa_relocate_section (output_bfd, info, input_bfd, input_section, relocation = 0; } /* Allow undefined symbols in shared libraries. */ - else if (info->shared && !info->no_undefined + else if (info->shared && !info->no_undefined && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) { if (info->symbolic) @@ -1407,11 +1514,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; + } } } @@ -1608,11 +1721,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 @@ -1626,7 +1735,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)); @@ -1636,7 +1745,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 @@ -1654,7 +1773,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 @@ -1665,9 +1784,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; @@ -1792,7 +1911,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)); @@ -1801,6 +1920,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 @@ -1826,7 +1954,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)); @@ -1835,6 +1963,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 @@ -1926,7 +2063,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)); @@ -1938,12 +2075,12 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd, } /* We want the value of the OPD offset for this symbol, not - the symbol's actual address. */ + 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); + bfd_put_64 (input_bfd, value, hit_data); return bfd_reloc_ok; } @@ -1979,7 +2116,7 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd, bfd_put_32 (input_bfd, value, hit_data); else bfd_put_64 (input_bfd, value, hit_data); - return bfd_reloc_ok; + return bfd_reloc_ok; } /* Something we don't know how to handle. */