Add TLS support for hppa-linux

This commit is contained in:
Nick Clifton 2006-05-24 11:05:42 +00:00
parent 9dd728f1af
commit 9b52905e69
8 changed files with 3537 additions and 3004 deletions

View file

@ -1,3 +1,34 @@
2006-05-24 Carlos O'Donell <carlos@systemhalted.org>
Randolph Chung <tausq@debian.org>
* elf-hppa.h (reloc_hppa_howto_table): Check bitfield for
TPREL21L/TPREL14R relocations. Handle LTOFF_TP14R relocations.
Add handling for TLS relocations.
(elf_hpp_reloc_final_type): Handle TLS relocs.
* elf32-hppa.c: Add authors for cleanup and TLS support.
(hppa_elf_local_got_tls_type, hh_name, eh_name): Define.
(elf32_hppa_link_hash_entry): Add tls_type.
(elf32_hppa_link_hash_table): Add tld_ldm_got.
(hppa_link_has_newfunc): Set tls_type.
(elf32_hppa_link_hash_table_create): Set tls_ldm_got refcount.
(hppa_stub_name): Use hh_name macro.
(elf32_hppa_copy_indirect_symbol): Copy TLS information.
(elf32_hppa_check_relocs): Call elf32_hppa_optimized_tls_reloc.
Handle TLS relocs.
(elf32_hppa_gc_sweep_hook): Likewise.
(allocate_dynrelocs): Handle TLS relocs.
(elf32_hppa_size_dynamic_sections): Count space required by TLS
relocs. Use hh_name macro.
(dtpoff_base): New function.
(tpoff): Likewise.
(elf32_hppa_optimized_tls_reloc): Likewise.
(final_link_relocate): Handle TLS relocs.
(elf32_hppa_relocate_section): Handle TLS relocs. Use eh_name
and hh_name macros.
(elf32_hppa_finish_dynamic_symbol): Setup TLS got entries. Use
hh_name and eh_name macros.
(elf32_hppa_reloc_type_clas): Handle TLS relocs.
2006-05-24 Bjoern Haase <bjoern.m.haase@web.de>
* archures.c: Add bfd_mach_avr6.

View file

@ -1,22 +1,22 @@
/* Common code for PA ELF implementations.
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
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.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
#define ELF_HOWTO_TABLE_SIZE R_PARISC_UNIMPLEMENTED + 1
@ -27,30 +27,20 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
external constraints require 32 or 64 bit specific code. We remap
the definitions/functions as necessary here. */
#if ARCH_SIZE == 64
#define ELF_R_TYPE(X) ELF64_R_TYPE(X)
#define ELF_R_SYM(X) ELF64_R_SYM(X)
#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 elf_hppa_final_link elf64_hppa_final_link
#define ELF_R_TYPE(X) ELF64_R_TYPE(X)
#define ELF_R_SYM(X) ELF64_R_SYM(X)
#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 elf_hppa_final_link elf64_hppa_final_link
#endif
#if ARCH_SIZE == 32
#define ELF_R_TYPE(X) ELF32_R_TYPE(X)
#define ELF_R_SYM(X) ELF32_R_SYM(X)
#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 elf_hppa_final_link elf32_hppa_final_link
#endif
#if ARCH_SIZE == 64
static bfd_reloc_status_type elf_hppa_final_link_relocate
(Elf_Internal_Rela *, bfd *, bfd *, asection *, 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
(int, int, unsigned int);
#define ELF_R_TYPE(X) ELF32_R_TYPE(X)
#define ELF_R_SYM(X) ELF32_R_SYM(X)
#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 elf_hppa_final_link elf32_hppa_final_link
#endif
/* ELF/PA relocation howto entries. */
@ -387,7 +377,7 @@ static reloc_howto_type elf_hppa_howto_table[ELF_HOWTO_TABLE_SIZE] =
bfd_elf_generic_reloc, "R_PARISC_UNIMPLEMENTED", FALSE, 0, 0, FALSE },
{ R_PARISC_TPREL32, 0, 0, 32, FALSE, 0, complain_overflow_dont,
bfd_elf_generic_reloc, "R_PARISC_TPREL32", FALSE, 0, 0, FALSE },
{ R_PARISC_TPREL21L, 0, 0, 21, FALSE, 0, complain_overflow_dont,
{ R_PARISC_TPREL21L, 0, 0, 21, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_TPREL21L", FALSE, 0, 0, FALSE },
{ R_PARISC_UNIMPLEMENTED, 0, 0, 0, FALSE, 0, complain_overflow_dont,
bfd_elf_generic_reloc, "R_PARISC_UNIMPLEMENTED", FALSE, 0, 0, FALSE },
@ -395,7 +385,7 @@ static reloc_howto_type elf_hppa_howto_table[ELF_HOWTO_TABLE_SIZE] =
bfd_elf_generic_reloc, "R_PARISC_UNIMPLEMENTED", FALSE, 0, 0, FALSE },
{ R_PARISC_UNIMPLEMENTED, 0, 0, 0, FALSE, 0, complain_overflow_dont,
bfd_elf_generic_reloc, "R_PARISC_UNIMPLEMENTED", FALSE, 0, 0, FALSE },
{ R_PARISC_TPREL14R, 0, 0, 14, FALSE, 0, complain_overflow_dont,
{ R_PARISC_TPREL14R, 0, 0, 14, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_TPREL14R", FALSE, 0, 0, FALSE },
{ R_PARISC_UNIMPLEMENTED, 0, 0, 0, FALSE, 0, complain_overflow_dont,
bfd_elf_generic_reloc, "R_PARISC_UNIMPLEMENTED", FALSE, 0, 0, FALSE },
@ -413,7 +403,7 @@ static reloc_howto_type elf_hppa_howto_table[ELF_HOWTO_TABLE_SIZE] =
{ R_PARISC_UNIMPLEMENTED, 0, 0, 0, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_UNIMPLEMENTED", FALSE, 0, 0, FALSE },
{ R_PARISC_LTOFF_TP14R, 0, 0, 14, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_UNIMPLEMENTED", FALSE, 0, 0, FALSE },
bfd_elf_generic_reloc, "R_PARISC_LTOFF_TP14R", FALSE, 0, 0, FALSE },
{ R_PARISC_LTOFF_TP14F, 0, 0, 14, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_LTOFF_TP14F", FALSE, 0, 0, FALSE },
/* 168 */
@ -557,6 +547,31 @@ static reloc_howto_type elf_hppa_howto_table[ELF_HOWTO_TABLE_SIZE] =
bfd_elf_generic_reloc, "R_PARISC_GNU_VTENTRY", FALSE, 0, 0, FALSE },
{ R_PARISC_GNU_VTINHERIT, 0, 0, 0, FALSE, 0, complain_overflow_dont,
bfd_elf_generic_reloc, "R_PARISC_GNU_VTINHERIT", FALSE, 0, 0, FALSE },
{ R_PARISC_TLS_GD21L, 0, 0, 21, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_TLS_GD21L", FALSE, 0, 0, FALSE },
{ R_PARISC_TLS_GD14R, 0, 0, 14, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_TLS_GD14R", FALSE, 0, 0, FALSE },
{ R_PARISC_TLS_GDCALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
bfd_elf_generic_reloc, "R_PARISC_TLS_GDCALL", FALSE, 0, 0, FALSE },
{ R_PARISC_TLS_LDM21L, 0, 0, 21, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_TLS_LDM21L", FALSE, 0, 0, FALSE },
{ R_PARISC_TLS_LDM14R, 0, 0, 14, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_TLS_LDM14R", FALSE, 0, 0, FALSE },
{ R_PARISC_TLS_LDMCALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
bfd_elf_generic_reloc, "R_PARISC_TLS_LDMCALL", FALSE, 0, 0, FALSE },
/* 240 */
{ R_PARISC_TLS_LDO21L, 0, 0, 21, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_TLS_LDO21L", FALSE, 0, 0, FALSE },
{ R_PARISC_TLS_LDO14R, 0, 0, 14, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_TLS_LDO14R", FALSE, 0, 0, FALSE },
{ R_PARISC_TLS_DTPMOD32, 0, 0, 32, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_TLS_DTPMOD32", FALSE, 0, 0, FALSE },
{ R_PARISC_TLS_DTPMOD64, 0, 0, 64, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_TLS_DTPMOD64", FALSE, 0, 0, FALSE },
{ R_PARISC_TLS_DTPOFF32, 0, 0, 32, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_TLS_DTPOFF32", FALSE, 0, 0, FALSE },
{ R_PARISC_TLS_DTPOFF64, 0, 0, 64, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_TLS_DTPOFF64", FALSE, 0, 0, FALSE },
};
#define OFFSET_14R_FROM_21L 4
@ -578,9 +593,9 @@ elf_hppa_reloc_final_type (bfd *abfd,
for PA ELF. */
switch (base_type)
{
/* We have been using generic relocation types. However, that may not
really make sense. Anyway, we need to support both R_PARISC_DIR64
and R_PARISC_DIR32 here. */
/* We have been using generic relocation types. However, that may not
really make sense. Anyway, we need to support both R_PARISC_DIR64
and R_PARISC_DIR32 here. */
case R_PARISC_DIR32:
case R_PARISC_DIR64:
case R_HPPA_ABS_CALL:
@ -701,11 +716,11 @@ elf_hppa_reloc_final_type (bfd *abfd,
case e_rsel:
case e_rrsel:
case e_rdsel:
/* R_PARISC_DLTREL14R for elf64, R_PARISC_DPREL14R for elf32 */
/* R_PARISC_DLTREL14R for elf64, R_PARISC_DPREL14R for elf32. */
final_type = base_type + OFFSET_14R_FROM_21L;
break;
case e_fsel:
/* R_PARISC_DLTREL14F for elf64, R_PARISC_DPREL14F for elf32 */
/* R_PARISC_DLTREL14F for elf64, R_PARISC_DPREL14F for elf32. */
final_type = base_type + OFFSET_14F_FROM_21L;
break;
default:
@ -721,7 +736,7 @@ elf_hppa_reloc_final_type (bfd *abfd,
case e_ldsel:
case e_nlsel:
case e_nlrsel:
/* R_PARISC_DLTREL21L for elf64, R_PARISC_DPREL21L for elf32 */
/* R_PARISC_DLTREL21L for elf64, R_PARISC_DPREL21L for elf32. */
final_type = base_type;
break;
default:
@ -838,6 +853,82 @@ elf_hppa_reloc_final_type (bfd *abfd,
}
break;
case R_PARISC_TLS_GD21L:
switch (field)
{
case e_ltsel:
case e_lrsel:
final_type = R_PARISC_TLS_GD21L;
break;
case e_rtsel:
case e_rrsel:
final_type = R_PARISC_TLS_GD14R;
break;
default:
return R_PARISC_NONE;
}
break;
case R_PARISC_TLS_LDM21L:
switch (field)
{
case e_ltsel:
case e_lrsel:
final_type = R_PARISC_TLS_LDM21L;
break;
case e_rtsel:
case e_rrsel:
final_type = R_PARISC_TLS_LDM14R;
break;
default:
return R_PARISC_NONE;
}
break;
case R_PARISC_TLS_LDO21L:
switch (field)
{
case e_lrsel:
final_type = R_PARISC_TLS_LDO21L;
break;
case e_rrsel:
final_type = R_PARISC_TLS_LDO14R;
break;
default:
return R_PARISC_NONE;
}
break;
case R_PARISC_TLS_IE21L:
switch (field)
{
case e_ltsel:
case e_lrsel:
final_type = R_PARISC_TLS_IE21L;
break;
case e_rtsel:
case e_rrsel:
final_type = R_PARISC_TLS_IE14R;
break;
default:
return R_PARISC_NONE;
}
break;
case R_PARISC_TLS_LE21L:
switch (field)
{
case e_lrsel:
final_type = R_PARISC_TLS_LE21L;
break;
case e_rrsel:
final_type = R_PARISC_TLS_LE14R;
break;
default:
return R_PARISC_NONE;
}
break;
case R_PARISC_GNU_VTENTRY:
case R_PARISC_GNU_VTINHERIT:
case R_PARISC_SEGREL32:
@ -906,7 +997,7 @@ elf_hppa_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
arelent *bfd_reloc,
Elf_Internal_Rela *elf_reloc)
{
BFD_ASSERT (ELF_R_TYPE(elf_reloc->r_info)
BFD_ASSERT (ELF_R_TYPE (elf_reloc->r_info)
< (unsigned int) R_PARISC_UNIMPLEMENTED);
bfd_reloc->howto = &elf_hppa_howto_table[ELF_R_TYPE (elf_reloc->r_info)];
}
@ -932,7 +1023,7 @@ static bfd_boolean
elf_hppa_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, const char *name)
{
if (name[0] == 'L' && name[1] == '$')
return 1;
return TRUE;
return _bfd_elf_is_local_label_name (abfd, name);
}
@ -950,6 +1041,7 @@ elf_hppa_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec)
{
int indx;
asection *asec;
#if ARCH_SIZE == 64
hdr->sh_type = SHT_LOPROC + 1;
#else
@ -1030,7 +1122,8 @@ hppa_unwind_entry_compare (const void *a, const void *b)
return av < bv ? -1 : av > bv ? 1 : 0;
}
static bfd_boolean elf_hppa_sort_unwind (bfd *abfd)
static bfd_boolean
elf_hppa_sort_unwind (bfd *abfd)
{
asection *s;
@ -1315,208 +1408,116 @@ elf_hppa_final_link (bfd *abfd, struct bfd_link_info *info)
return retval;
}
/* Relocate an HPPA ELF section. */
/* Relocate the given INSN. VALUE should be the actual value we want
to insert into the instruction, ie by this point we should not be
concerned with computing an offset relative to the DLT, PC, etc.
Instead this routine is meant to handle the bit manipulations needed
to insert the relocation into the given instruction. */
static bfd_boolean
elf_hppa_relocate_section (bfd *output_bfd,
struct bfd_link_info *info,
bfd *input_bfd,
asection *input_section,
bfd_byte *contents,
Elf_Internal_Rela *relocs,
Elf_Internal_Sym *local_syms,
asection **local_sections)
static int
elf_hppa_relocate_insn (int insn, int sym_value, unsigned int r_type)
{
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
struct elf64_hppa_link_hash_table *hppa_info;
if (info->relocatable)
return TRUE;
hppa_info = elf64_hppa_hash_table (info);
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
rel = relocs;
relend = relocs + input_section->reloc_count;
for (; rel < relend; rel++)
switch (r_type)
{
int r_type;
reloc_howto_type *howto = elf_hppa_howto_table + ELF_R_TYPE (rel->r_info);
unsigned long r_symndx;
struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
asection *sym_sec;
bfd_vma relocation;
bfd_reloc_status_type r;
const char *dyn_name;
char *dynh_buf = NULL;
size_t dynh_buflen = 0;
struct elf64_hppa_dyn_hash_entry *dyn_h = NULL;
/* This is any 22 bit branch. In PA2.0 syntax it corresponds to
the "B" instruction. */
case R_PARISC_PCREL22F:
case R_PARISC_PCREL22C:
return (insn & ~0x3ff1ffd) | re_assemble_22 (sym_value);
r_type = ELF_R_TYPE (rel->r_info);
if (r_type < 0 || r_type >= (int) R_PARISC_UNIMPLEMENTED)
{
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
/* This is any 12 bit branch. */
case R_PARISC_PCREL12F:
return (insn & ~0x1ffd) | re_assemble_12 (sym_value);
/* This is a final link. */
r_symndx = ELF_R_SYM (rel->r_info);
h = NULL;
sym = NULL;
sym_sec = NULL;
if (r_symndx < symtab_hdr->sh_info)
{
/* This is a local symbol. */
sym = local_syms + r_symndx;
sym_sec = local_sections[r_symndx];
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sym_sec, rel);
/* This is any 17 bit branch. In PA2.0 syntax it also corresponds
to the "B" instruction as well as BE. */
case R_PARISC_PCREL17F:
case R_PARISC_DIR17F:
case R_PARISC_DIR17R:
case R_PARISC_PCREL17C:
case R_PARISC_PCREL17R:
return (insn & ~0x1f1ffd) | re_assemble_17 (sym_value);
/* If this symbol has an entry in the PA64 dynamic hash
table, then get it. */
dyn_name = get_dyn_name (input_bfd, h, rel,
&dynh_buf, &dynh_buflen);
dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
dyn_name, FALSE, FALSE);
/* ADDIL or LDIL instructions. */
case R_PARISC_DLTREL21L:
case R_PARISC_DLTIND21L:
case R_PARISC_LTOFF_FPTR21L:
case R_PARISC_PCREL21L:
case R_PARISC_LTOFF_TP21L:
case R_PARISC_DPREL21L:
case R_PARISC_PLTOFF21L:
case R_PARISC_DIR21L:
return (insn & ~0x1fffff) | re_assemble_21 (sym_value);
}
else
{
/* This is not a local symbol. */
long indx;
/* LDO and integer loads/stores with 14 bit displacements. */
case R_PARISC_DLTREL14R:
case R_PARISC_DLTREL14F:
case R_PARISC_DLTIND14R:
case R_PARISC_DLTIND14F:
case R_PARISC_LTOFF_FPTR14R:
case R_PARISC_PCREL14R:
case R_PARISC_PCREL14F:
case R_PARISC_LTOFF_TP14R:
case R_PARISC_LTOFF_TP14F:
case R_PARISC_DPREL14R:
case R_PARISC_DPREL14F:
case R_PARISC_PLTOFF14R:
case R_PARISC_PLTOFF14F:
case R_PARISC_DIR14R:
case R_PARISC_DIR14F:
return (insn & ~0x3fff) | low_sign_unext (sym_value, 14);
indx = r_symndx - symtab_hdr->sh_info;
h = elf_sym_hashes (input_bfd)[indx];
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
sym_sec = h->root.u.def.section;
/* PA2.0W LDO and integer loads/stores with 16 bit displacements. */
case R_PARISC_LTOFF_FPTR16F:
case R_PARISC_PCREL16F:
case R_PARISC_LTOFF_TP16F:
case R_PARISC_GPREL16F:
case R_PARISC_PLTOFF16F:
case R_PARISC_DIR16F:
case R_PARISC_LTOFF16F:
return (insn & ~0xffff) | re_assemble_16 (sym_value);
/* If this symbol has an entry in the PA64 dynamic hash
table, then get it. */
dyn_name = get_dyn_name (input_bfd, h, rel,
&dynh_buf, &dynh_buflen);
dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
dyn_name, FALSE, FALSE);
/* Doubleword loads and stores with a 14 bit displacement. */
case R_PARISC_DLTREL14DR:
case R_PARISC_DLTIND14DR:
case R_PARISC_LTOFF_FPTR14DR:
case R_PARISC_LTOFF_FPTR16DF:
case R_PARISC_PCREL14DR:
case R_PARISC_PCREL16DF:
case R_PARISC_LTOFF_TP14DR:
case R_PARISC_LTOFF_TP16DF:
case R_PARISC_DPREL14DR:
case R_PARISC_GPREL16DF:
case R_PARISC_PLTOFF14DR:
case R_PARISC_PLTOFF16DF:
case R_PARISC_DIR14DR:
case R_PARISC_DIR16DF:
case R_PARISC_LTOFF16DF:
return (insn & ~0x3ff1) | (((sym_value & 0x2000) >> 13)
| ((sym_value & 0x1ff8) << 1));
/* If we have a relocation against a symbol defined in a
shared library and we have not created an entry in the
PA64 dynamic symbol hash table for it, then we lose. */
if (sym_sec->output_section == NULL && dyn_h == NULL)
{
(*_bfd_error_handler)
(_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
input_bfd,
input_section,
(long) rel->r_offset,
howto->name,
h->root.root.string);
relocation = 0;
}
else if (sym_sec->output_section)
relocation = (h->root.u.def.value
+ sym_sec->output_offset
+ sym_sec->output_section->vma);
/* Value will be provided via one of the offsets in the
dyn_h hash table entry. */
else
relocation = 0;
}
else if (info->unresolved_syms_in_objects == RM_IGNORE
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
{
/* If this symbol has an entry in the PA64 dynamic hash
table, then get it. */
dyn_name = get_dyn_name (input_bfd, h, rel,
&dynh_buf, &dynh_buflen);
dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
dyn_name, FALSE, FALSE);
/* Floating point single word load/store instructions. */
case R_PARISC_DLTREL14WR:
case R_PARISC_DLTIND14WR:
case R_PARISC_LTOFF_FPTR14WR:
case R_PARISC_LTOFF_FPTR16WF:
case R_PARISC_PCREL14WR:
case R_PARISC_PCREL16WF:
case R_PARISC_LTOFF_TP14WR:
case R_PARISC_LTOFF_TP16WF:
case R_PARISC_DPREL14WR:
case R_PARISC_GPREL16WF:
case R_PARISC_PLTOFF14WR:
case R_PARISC_PLTOFF16WF:
case R_PARISC_DIR16WF:
case R_PARISC_DIR14WR:
case R_PARISC_LTOFF16WF:
return (insn & ~0x3ff9) | (((sym_value & 0x2000) >> 13)
| ((sym_value & 0x1ffc) << 1));
if (dyn_h == NULL)
{
(*_bfd_error_handler)
(_("%B(%A): warning: unresolvable relocation against symbol `%s'"),
input_bfd, input_section, h->root.root.string);
}
relocation = 0;
}
else if (h->root.type == bfd_link_hash_undefweak)
{
dyn_name = get_dyn_name (input_bfd, h, rel,
&dynh_buf, &dynh_buflen);
dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
dyn_name, FALSE, FALSE);
if (dyn_h == NULL)
{
(*_bfd_error_handler)
(_("%B(%A): warning: unresolvable relocation against symbol `%s'"),
input_bfd, input_section, h->root.root.string);
}
relocation = 0;
}
else
{
/* 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,
(info->unresolved_syms_in_objects == RM_GENERATE_ERROR
|| ELF_ST_VISIBILITY (h->other)))))
return FALSE;
break;
}
}
}
r = elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
input_section, contents,
relocation, info, sym_sec,
h, dyn_h);
if (r != bfd_reloc_ok)
{
switch (r)
{
default:
abort ();
case bfd_reloc_overflow:
{
const char *sym_name;
if (h != NULL)
sym_name = NULL;
else
{
sym_name = bfd_elf_string_from_elf_section (input_bfd,
symtab_hdr->sh_link,
sym->st_name);
if (sym_name == NULL)
return FALSE;
if (*sym_name == '\0')
sym_name = bfd_section_name (input_bfd, sym_sec);
}
if (!((*info->callbacks->reloc_overflow)
(info, (h ? &h->root : NULL), sym_name,
howto->name, (bfd_vma) 0, input_bfd,
input_section, rel->r_offset)))
return FALSE;
}
break;
}
}
default:
return insn;
}
return TRUE;
}
/* Compute the value for a relocation (REL) during a final link stage,
@ -1806,10 +1807,8 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
value = hppa_field_adjust (value, addend, e_rrsel);
if (r_type == R_PARISC_DIR17R || r_type == R_PARISC_DIR17F)
{
/* All branches are implicitly shifted by 2 places. */
value >>= 2;
}
/* All branches are implicitly shifted by 2 places. */
value >>= 2;
insn = elf_hppa_relocate_insn (insn, (int) value, r_type);
break;
@ -2081,115 +2080,208 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
return bfd_reloc_ok;
}
/* Relocate the given INSN. VALUE should be the actual value we want
to insert into the instruction, ie by this point we should not be
concerned with computing an offset relative to the DLT, PC, etc.
Instead this routine is meant to handle the bit manipulations needed
to insert the relocation into the given instruction. */
/* Relocate an HPPA ELF section. */
static int
elf_hppa_relocate_insn (int insn, int sym_value, unsigned int r_type)
static bfd_boolean
elf_hppa_relocate_section (bfd *output_bfd,
struct bfd_link_info *info,
bfd *input_bfd,
asection *input_section,
bfd_byte *contents,
Elf_Internal_Rela *relocs,
Elf_Internal_Sym *local_syms,
asection **local_sections)
{
switch (r_type)
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
struct elf64_hppa_link_hash_table *hppa_info;
if (info->relocatable)
return TRUE;
hppa_info = elf64_hppa_hash_table (info);
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
rel = relocs;
relend = relocs + input_section->reloc_count;
for (; rel < relend; rel++)
{
/* This is any 22 bit branch. In PA2.0 syntax it corresponds to
the "B" instruction. */
case R_PARISC_PCREL22F:
case R_PARISC_PCREL22C:
return (insn & ~0x3ff1ffd) | re_assemble_22 (sym_value);
int r_type;
reloc_howto_type *howto = elf_hppa_howto_table + ELF_R_TYPE (rel->r_info);
unsigned long r_symndx;
struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
asection *sym_sec;
bfd_vma relocation;
bfd_reloc_status_type r;
const char *dyn_name;
char *dynh_buf = NULL;
size_t dynh_buflen = 0;
struct elf64_hppa_dyn_hash_entry *dyn_h = NULL;
/* This is any 12 bit branch. */
case R_PARISC_PCREL12F:
return (insn & ~0x1ffd) | re_assemble_12 (sym_value);
r_type = ELF_R_TYPE (rel->r_info);
if (r_type < 0 || r_type >= (int) R_PARISC_UNIMPLEMENTED)
{
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
/* This is any 17 bit branch. In PA2.0 syntax it also corresponds
to the "B" instruction as well as BE. */
case R_PARISC_PCREL17F:
case R_PARISC_DIR17F:
case R_PARISC_DIR17R:
case R_PARISC_PCREL17C:
case R_PARISC_PCREL17R:
return (insn & ~0x1f1ffd) | re_assemble_17 (sym_value);
/* This is a final link. */
r_symndx = ELF_R_SYM (rel->r_info);
h = NULL;
sym = NULL;
sym_sec = NULL;
if (r_symndx < symtab_hdr->sh_info)
{
/* This is a local symbol. */
sym = local_syms + r_symndx;
sym_sec = local_sections[r_symndx];
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sym_sec, rel);
/* ADDIL or LDIL instructions. */
case R_PARISC_DLTREL21L:
case R_PARISC_DLTIND21L:
case R_PARISC_LTOFF_FPTR21L:
case R_PARISC_PCREL21L:
case R_PARISC_LTOFF_TP21L:
case R_PARISC_DPREL21L:
case R_PARISC_PLTOFF21L:
case R_PARISC_DIR21L:
return (insn & ~0x1fffff) | re_assemble_21 (sym_value);
/* If this symbol has an entry in the PA64 dynamic hash
table, then get it. */
dyn_name = get_dyn_name (input_bfd, h, rel,
&dynh_buf, &dynh_buflen);
dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
dyn_name, FALSE, FALSE);
/* LDO and integer loads/stores with 14 bit displacements. */
case R_PARISC_DLTREL14R:
case R_PARISC_DLTREL14F:
case R_PARISC_DLTIND14R:
case R_PARISC_DLTIND14F:
case R_PARISC_LTOFF_FPTR14R:
case R_PARISC_PCREL14R:
case R_PARISC_PCREL14F:
case R_PARISC_LTOFF_TP14R:
case R_PARISC_LTOFF_TP14F:
case R_PARISC_DPREL14R:
case R_PARISC_DPREL14F:
case R_PARISC_PLTOFF14R:
case R_PARISC_PLTOFF14F:
case R_PARISC_DIR14R:
case R_PARISC_DIR14F:
return (insn & ~0x3fff) | low_sign_unext (sym_value, 14);
}
else
{
/* This is not a local symbol. */
long indx;
/* PA2.0W LDO and integer loads/stores with 16 bit displacements. */
case R_PARISC_LTOFF_FPTR16F:
case R_PARISC_PCREL16F:
case R_PARISC_LTOFF_TP16F:
case R_PARISC_GPREL16F:
case R_PARISC_PLTOFF16F:
case R_PARISC_DIR16F:
case R_PARISC_LTOFF16F:
return (insn & ~0xffff) | re_assemble_16 (sym_value);
indx = r_symndx - symtab_hdr->sh_info;
h = elf_sym_hashes (input_bfd)[indx];
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
sym_sec = h->root.u.def.section;
/* Doubleword loads and stores with a 14 bit displacement. */
case R_PARISC_DLTREL14DR:
case R_PARISC_DLTIND14DR:
case R_PARISC_LTOFF_FPTR14DR:
case R_PARISC_LTOFF_FPTR16DF:
case R_PARISC_PCREL14DR:
case R_PARISC_PCREL16DF:
case R_PARISC_LTOFF_TP14DR:
case R_PARISC_LTOFF_TP16DF:
case R_PARISC_DPREL14DR:
case R_PARISC_GPREL16DF:
case R_PARISC_PLTOFF14DR:
case R_PARISC_PLTOFF16DF:
case R_PARISC_DIR14DR:
case R_PARISC_DIR16DF:
case R_PARISC_LTOFF16DF:
return (insn & ~0x3ff1) | (((sym_value & 0x2000) >> 13)
| ((sym_value & 0x1ff8) << 1));
/* If this symbol has an entry in the PA64 dynamic hash
table, then get it. */
dyn_name = get_dyn_name (input_bfd, h, rel,
&dynh_buf, &dynh_buflen);
dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
dyn_name, FALSE, FALSE);
/* Floating point single word load/store instructions. */
case R_PARISC_DLTREL14WR:
case R_PARISC_DLTIND14WR:
case R_PARISC_LTOFF_FPTR14WR:
case R_PARISC_LTOFF_FPTR16WF:
case R_PARISC_PCREL14WR:
case R_PARISC_PCREL16WF:
case R_PARISC_LTOFF_TP14WR:
case R_PARISC_LTOFF_TP16WF:
case R_PARISC_DPREL14WR:
case R_PARISC_GPREL16WF:
case R_PARISC_PLTOFF14WR:
case R_PARISC_PLTOFF16WF:
case R_PARISC_DIR16WF:
case R_PARISC_DIR14WR:
case R_PARISC_LTOFF16WF:
return (insn & ~0x3ff9) | (((sym_value & 0x2000) >> 13)
| ((sym_value & 0x1ffc) << 1));
/* If we have a relocation against a symbol defined in a
shared library and we have not created an entry in the
PA64 dynamic symbol hash table for it, then we lose. */
if (sym_sec->output_section == NULL && dyn_h == NULL)
{
(*_bfd_error_handler)
(_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
input_bfd,
input_section,
(long) rel->r_offset,
howto->name,
h->root.root.string);
relocation = 0;
}
else if (sym_sec->output_section)
relocation = (h->root.u.def.value
+ sym_sec->output_offset
+ sym_sec->output_section->vma);
/* Value will be provided via one of the offsets in the
dyn_h hash table entry. */
else
relocation = 0;
}
else if (info->unresolved_syms_in_objects == RM_IGNORE
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
{
/* If this symbol has an entry in the PA64 dynamic hash
table, then get it. */
dyn_name = get_dyn_name (input_bfd, h, rel,
&dynh_buf, &dynh_buflen);
dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
dyn_name, FALSE, FALSE);
default:
return insn;
if (dyn_h == NULL)
{
(*_bfd_error_handler)
(_("%B(%A): warning: unresolvable relocation against symbol `%s'"),
input_bfd, input_section, h->root.root.string);
}
relocation = 0;
}
else if (h->root.type == bfd_link_hash_undefweak)
{
dyn_name = get_dyn_name (input_bfd, h, rel,
&dynh_buf, &dynh_buflen);
dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
dyn_name, FALSE, FALSE);
if (dyn_h == NULL)
{
(*_bfd_error_handler)
(_("%B(%A): warning: unresolvable relocation against symbol `%s'"),
input_bfd, input_section, h->root.root.string);
}
relocation = 0;
}
else
{
/* 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,
(info->unresolved_syms_in_objects == RM_GENERATE_ERROR
|| ELF_ST_VISIBILITY (h->other)))))
return FALSE;
break;
}
}
}
r = elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
input_section, contents,
relocation, info, sym_sec,
h, dyn_h);
if (r != bfd_reloc_ok)
{
switch (r)
{
default:
abort ();
case bfd_reloc_overflow:
{
const char *sym_name;
if (h != NULL)
sym_name = NULL;
else
{
sym_name = bfd_elf_string_from_elf_section (input_bfd,
symtab_hdr->sh_link,
sym->st_name);
if (sym_name == NULL)
return FALSE;
if (*sym_name == '\0')
sym_name = bfd_section_name (input_bfd, sym_sec);
}
if (!((*info->callbacks->reloc_overflow)
(info, (h ? &h->root : NULL), sym_name,
howto->name, (bfd_vma) 0, input_bfd,
input_section, rel->r_offset)))
return FALSE;
}
break;
}
}
}
return TRUE;
}
#endif
#endif /* ARCH_SIZE == 64 */

View file

@ -7,7 +7,9 @@
Department of Computer Science
University of Utah
Largely rewritten by Alan Modra <alan@linuxcare.com.au>
Naming cleanup by Carlos O'Donell <carlos@systemhalted.org>
TLS support written by Randolph Chung <tausq@debian.org>
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
@ -168,7 +170,8 @@ static const bfd_byte plt_stub[] =
shared lib. */
#define ELIMINATE_COPY_RELOCS 1
enum elf32_hppa_stub_type {
enum elf32_hppa_stub_type
{
hppa_stub_long_branch,
hppa_stub_long_branch_shared,
hppa_stub_import,
@ -177,8 +180,8 @@ enum elf32_hppa_stub_type {
hppa_stub_none
};
struct elf32_hppa_stub_hash_entry {
struct elf32_hppa_stub_hash_entry
{
/* Base hash table entry structure. */
struct bfd_hash_entry bh_root;
@ -203,8 +206,8 @@ struct elf32_hppa_stub_hash_entry {
asection *id_sec;
};
struct elf32_hppa_link_hash_entry {
struct elf32_hppa_link_hash_entry
{
struct elf_link_hash_entry eh;
/* A pointer to the most recently used stub hash entry against this
@ -213,8 +216,8 @@ struct elf32_hppa_link_hash_entry {
/* Used to count relocations for delayed sizing of relocation
sections. */
struct elf32_hppa_dyn_reloc_entry {
struct elf32_hppa_dyn_reloc_entry
{
/* Next relocation in the chain. */
struct elf32_hppa_dyn_reloc_entry *hdh_next;
@ -230,12 +233,17 @@ struct elf32_hppa_link_hash_entry {
#endif
} *dyn_relocs;
enum
{
GOT_UNKNOWN = 0, GOT_NORMAL = 1, GOT_TLS_GD = 2, GOT_TLS_LDM = 4, GOT_TLS_IE = 8
} tls_type;
/* Set if this symbol is used by a plabel reloc. */
unsigned int plabel:1;
};
struct elf32_hppa_link_hash_table {
struct elf32_hppa_link_hash_table
{
/* The main hash table. */
struct elf_link_hash_table etab;
@ -251,7 +259,8 @@ struct elf32_hppa_link_hash_table {
/* Array to keep track of which stub sections have been created, and
information on stub grouping. */
struct map_stub {
struct map_stub
{
/* This is the section to which stubs in the group will be
attached. */
asection *link_sec;
@ -292,6 +301,13 @@ struct elf32_hppa_link_hash_table {
/* Small local sym to section mapping cache. */
struct sym_sec_cache sym_sec;
/* Data for LDM relocations. */
union
{
bfd_signed_vma refcount;
bfd_vma offset;
} tls_ldm_got;
};
/* Various hash macros and functions. */
@ -308,6 +324,15 @@ struct elf32_hppa_link_hash_table {
((struct elf32_hppa_stub_hash_entry *) \
bfd_hash_lookup ((table), (string), (create), (copy)))
#define hppa_elf_local_got_tls_type(abfd) \
((char *)(elf_local_got_offsets (abfd) + (elf_tdata (abfd)->symtab_hdr.sh_info * 2)))
#define hh_name(hh) \
(hh ? hh->eh.root.root.string : "<undef>")
#define eh_name(eh) \
(eh ? eh->root.root.string : "<undef>")
/* Assorted hash table functions. */
/* Initialize an entry in the stub hash table. */
@ -375,6 +400,7 @@ hppa_link_hash_newfunc (struct bfd_hash_entry *entry,
hh->hsh_cache = NULL;
hh->dyn_relocs = NULL;
hh->plabel = 0;
hh->tls_type = GOT_UNKNOWN;
}
return entry;
@ -390,7 +416,7 @@ elf32_hppa_link_hash_table_create (bfd *abfd)
struct elf32_hppa_link_hash_table *htab;
bfd_size_type amt = sizeof (*htab);
htab = (struct elf32_hppa_link_hash_table *) bfd_malloc (amt);
htab = bfd_malloc (amt);
if (htab == NULL)
return NULL;
@ -424,6 +450,7 @@ elf32_hppa_link_hash_table_create (bfd *abfd)
htab->has_22bit_branch = 0;
htab->need_plt_stub = 0;
htab->sym_sec.abfd = NULL;
htab->tls_ldm_got.refcount = 0;
return &htab->etab.root;
}
@ -453,28 +480,24 @@ hppa_stub_name (const asection *input_section,
if (hh)
{
len = 8 + 1 + strlen (hh->eh.root.root.string) + 1 + 8 + 1;
len = 8 + 1 + strlen (hh_name (hh)) + 1 + 8 + 1;
stub_name = bfd_malloc (len);
if (stub_name != NULL)
{
sprintf (stub_name, "%08x_%s+%x",
input_section->id & 0xffffffff,
hh->eh.root.root.string,
(int) rela->r_addend & 0xffffffff);
}
sprintf (stub_name, "%08x_%s+%x",
input_section->id & 0xffffffff,
hh_name (hh),
(int) rela->r_addend & 0xffffffff);
}
else
{
len = 8 + 1 + 8 + 1 + 8 + 1 + 8 + 1;
stub_name = bfd_malloc (len);
if (stub_name != NULL)
{
sprintf (stub_name, "%08x_%x:%x+%x",
input_section->id & 0xffffffff,
sym_sec->id & 0xffffffff,
(int) ELF32_R_SYM (rela->r_info) & 0xffffffff,
(int) rela->r_addend & 0xffffffff);
}
sprintf (stub_name, "%08x_%x:%x+%x",
input_section->id & 0xffffffff,
sym_sec->id & 0xffffffff,
(int) ELF32_R_SYM (rela->r_info) & 0xffffffff,
(int) rela->r_addend & 0xffffffff);
}
return stub_name;
}
@ -620,17 +643,13 @@ hppa_type_of_stub (asection *input_sec,
bytes on from the branch instruction location. The offset is
signed and counts in units of 4 bytes. */
if (r_type == (unsigned int) R_PARISC_PCREL17F)
{
max_branch_offset = (1 << (17-1)) << 2;
}
max_branch_offset = (1 << (17 - 1)) << 2;
else if (r_type == (unsigned int) R_PARISC_PCREL12F)
{
max_branch_offset = (1 << (12-1)) << 2;
}
max_branch_offset = (1 << (12 - 1)) << 2;
else /* R_PARISC_PCREL22F. */
{
max_branch_offset = (1 << (22-1)) << 2;
}
max_branch_offset = (1 << (22 - 1)) << 2;
if (branch_offset + max_branch_offset >= 2*max_branch_offset)
return hppa_stub_long_branch;
@ -1063,7 +1082,24 @@ elf32_hppa_copy_indirect_symbol (struct bfd_link_info *info,
eh_dir->needs_plt |= eh_ind->needs_plt;
}
else
_bfd_elf_link_hash_copy_indirect (info, eh_dir, eh_ind);
{
if (eh_ind->root.type == bfd_link_hash_indirect
&& eh_dir->got.refcount <= 0)
{
hh_dir->tls_type = hh_ind->tls_type;
hh_ind->tls_type = GOT_UNKNOWN;
}
_bfd_elf_link_hash_copy_indirect (info, eh_dir, eh_ind);
}
}
static int
elf32_hppa_optimized_tls_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED,
int r_type, int is_local ATTRIBUTE_UNUSED)
{
/* For now we don't support linker optimizations. */
return r_type;
}
/* Look through the relocs for a section during the first phase, and
@ -1084,6 +1120,7 @@ elf32_hppa_check_relocs (bfd *abfd,
struct elf32_hppa_link_hash_table *htab;
asection *sreloc;
asection *stubreloc;
int tls_type = GOT_UNKNOWN, old_tls_type = GOT_UNKNOWN;
if (info->relocatable)
return TRUE;
@ -1121,6 +1158,7 @@ elf32_hppa_check_relocs (bfd *abfd,
}
r_type = ELF32_R_TYPE (rela->r_info);
r_type = elf32_hppa_optimized_tls_reloc (info, r_type, hh == NULL);
switch (r_type)
{
@ -1243,6 +1281,20 @@ elf32_hppa_check_relocs (bfd *abfd,
return FALSE;
continue;
case R_PARISC_TLS_GD21L:
case R_PARISC_TLS_GD14R:
case R_PARISC_TLS_LDM21L:
case R_PARISC_TLS_LDM14R:
need_entry = NEED_GOT;
break;
case R_PARISC_TLS_IE21L:
case R_PARISC_TLS_IE14R:
if (info->shared)
info->flags |= DF_STATIC_TLS;
need_entry = NEED_GOT;
break;
default:
continue;
}
@ -1250,6 +1302,25 @@ elf32_hppa_check_relocs (bfd *abfd,
/* Now carry out our orders. */
if (need_entry & NEED_GOT)
{
switch (r_type)
{
default:
tls_type = GOT_NORMAL;
break;
case R_PARISC_TLS_GD21L:
case R_PARISC_TLS_GD14R:
tls_type |= GOT_TLS_GD;
break;
case R_PARISC_TLS_LDM21L:
case R_PARISC_TLS_LDM14R:
tls_type |= GOT_TLS_LDM;
break;
case R_PARISC_TLS_IE21L:
case R_PARISC_TLS_IE14R:
tls_type |= GOT_TLS_IE;
break;
}
/* Allocate space for a GOT entry, as well as a dynamic
relocation for this entry. */
if (htab->sgot == NULL)
@ -1260,31 +1331,56 @@ elf32_hppa_check_relocs (bfd *abfd,
return FALSE;
}
if (hh != NULL)
{
hh->eh.got.refcount += 1;
}
if (r_type == R_PARISC_TLS_LDM21L
|| r_type == R_PARISC_TLS_LDM14R)
hppa_link_hash_table (info)->tls_ldm_got.refcount += 1;
else
{
bfd_signed_vma *local_got_refcounts;
/* This is a global offset table entry for a local symbol. */
local_got_refcounts = elf_local_got_refcounts (abfd);
if (local_got_refcounts == NULL)
{
bfd_size_type size;
if (hh != NULL)
{
hh->eh.got.refcount += 1;
old_tls_type = hh->tls_type;
}
else
{
bfd_signed_vma *local_got_refcounts;
/* This is a global offset table entry for a local symbol. */
local_got_refcounts = elf_local_got_refcounts (abfd);
if (local_got_refcounts == NULL)
{
bfd_size_type size;
/* Allocate space for local got offsets and local
plt offsets. Done this way to save polluting
elf_obj_tdata with another target specific
pointer. */
size = symtab_hdr->sh_info;
size *= 2 * sizeof (bfd_signed_vma);
/* Add in space to store the local GOT TLS types. */
size += symtab_hdr->sh_info;
local_got_refcounts = bfd_zalloc (abfd, size);
if (local_got_refcounts == NULL)
return FALSE;
elf_local_got_refcounts (abfd) = local_got_refcounts;
memset (hppa_elf_local_got_tls_type (abfd),
GOT_UNKNOWN, symtab_hdr->sh_info);
}
local_got_refcounts[r_symndx] += 1;
old_tls_type = hppa_elf_local_got_tls_type (abfd) [r_symndx];
}
tls_type |= old_tls_type;
if (old_tls_type != tls_type)
{
if (hh != NULL)
hh->tls_type = tls_type;
else
hppa_elf_local_got_tls_type (abfd) [r_symndx] = tls_type;
}
/* Allocate space for local got offsets and local
plt offsets. Done this way to save polluting
elf_obj_tdata with another target specific
pointer. */
size = symtab_hdr->sh_info;
size *= 2 * sizeof (bfd_signed_vma);
local_got_refcounts = bfd_zalloc (abfd, size);
if (local_got_refcounts == NULL)
return FALSE;
elf_local_got_refcounts (abfd) = local_got_refcounts;
}
local_got_refcounts[r_symndx] += 1;
}
}
@ -1325,6 +1421,8 @@ elf32_hppa_check_relocs (bfd *abfd,
plt offsets. */
size = symtab_hdr->sh_info;
size *= 2 * sizeof (bfd_signed_vma);
/* Add in space to store the local GOT TLS types. */
size += symtab_hdr->sh_info;
local_got_refcounts = bfd_zalloc (abfd, size);
if (local_got_refcounts == NULL)
return FALSE;
@ -1578,11 +1676,17 @@ elf32_hppa_gc_sweep_hook (bfd *abfd,
}
r_type = ELF32_R_TYPE (rela->r_info);
r_type = elf32_hppa_optimized_tls_reloc (info, r_type, eh != NULL);
switch (r_type)
{
case R_PARISC_DLTIND14F:
case R_PARISC_DLTIND14R:
case R_PARISC_DLTIND21L:
case R_PARISC_TLS_GD21L:
case R_PARISC_TLS_GD14R:
case R_PARISC_TLS_IE21L:
case R_PARISC_TLS_IE14R:
if (eh != NULL)
{
if (eh->got.refcount > 0)
@ -1595,6 +1699,11 @@ elf32_hppa_gc_sweep_hook (bfd *abfd,
}
break;
case R_PARISC_TLS_LDM21L:
case R_PARISC_TLS_LDM14R:
hppa_link_hash_table (info)->tls_ldm_got.refcount -= 1;
break;
case R_PARISC_PCREL12F:
case R_PARISC_PCREL17C:
case R_PARISC_PCREL17F:
@ -1709,7 +1818,7 @@ elf32_hppa_hide_symbol (struct bfd_link_info *info,
}
}
if (! hppa_elf_hash_entry(eh)->plabel)
if (! hppa_elf_hash_entry (eh)->plabel)
{
eh->needs_plt = 0;
eh->plt = elf_hash_table (info)->init_plt_refcount;
@ -1882,7 +1991,7 @@ allocate_plt_static (struct elf_link_hash_entry *eh, void *inf)
eh = (struct elf_link_hash_entry *) eh->root.u.i.link;
info = (struct bfd_link_info *) inf;
hh = hppa_elf_hash_entry(eh);
hh = hppa_elf_hash_entry (eh);
htab = hppa_link_hash_table (info);
if (htab->etab.dynamic_sections_created
&& eh->plt.refcount > 0)
@ -1982,12 +2091,21 @@ allocate_dynrelocs (struct elf_link_hash_entry *eh, void *inf)
sec = htab->sgot;
eh->got.offset = sec->size;
sec->size += GOT_ENTRY_SIZE;
/* R_PARISC_TLS_GD* needs two GOT entries */
if ((hh->tls_type & (GOT_TLS_GD | GOT_TLS_IE)) == (GOT_TLS_GD | GOT_TLS_IE))
sec->size += GOT_ENTRY_SIZE * 2;
else if ((hh->tls_type & GOT_TLS_GD) == GOT_TLS_GD)
sec->size += GOT_ENTRY_SIZE;
if (htab->etab.dynamic_sections_created
&& (info->shared
|| (eh->dynindx != -1
&& !eh->forced_local)))
{
htab->srelgot->size += sizeof (Elf32_External_Rela);
if ((hh->tls_type & (GOT_TLS_GD | GOT_TLS_IE)) == (GOT_TLS_GD | GOT_TLS_IE))
htab->srelgot->size += 2 * sizeof (Elf32_External_Rela);
else if ((hh->tls_type & GOT_TLS_GD) == GOT_TLS_GD)
htab->srelgot->size += sizeof (Elf32_External_Rela);
}
}
else
@ -2181,6 +2299,7 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
bfd_size_type locsymcount;
Elf_Internal_Shdr *symtab_hdr;
asection *srel;
char *local_tls_type;
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
continue;
@ -2219,6 +2338,7 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
locsymcount = symtab_hdr->sh_info;
end_local_got = local_got + locsymcount;
local_tls_type = hppa_elf_local_got_tls_type (ibfd);
sec = htab->sgot;
srel = htab->srelgot;
for (; local_got < end_local_got; ++local_got)
@ -2227,11 +2347,23 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
{
*local_got = sec->size;
sec->size += GOT_ENTRY_SIZE;
if ((*local_tls_type & (GOT_TLS_GD | GOT_TLS_IE)) == (GOT_TLS_GD | GOT_TLS_IE))
sec->size += 2 * GOT_ENTRY_SIZE;
else if ((*local_tls_type & GOT_TLS_GD) == GOT_TLS_GD)
sec->size += GOT_ENTRY_SIZE;
if (info->shared)
srel->size += sizeof (Elf32_External_Rela);
{
srel->size += sizeof (Elf32_External_Rela);
if ((*local_tls_type & (GOT_TLS_GD | GOT_TLS_IE)) == (GOT_TLS_GD | GOT_TLS_IE))
srel->size += 2 * sizeof (Elf32_External_Rela);
else if ((*local_tls_type & GOT_TLS_GD) == GOT_TLS_GD)
srel->size += sizeof (Elf32_External_Rela);
}
}
else
*local_got = (bfd_vma) -1;
++local_tls_type;
}
local_plt = end_local_got;
@ -2260,6 +2392,17 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
}
}
}
if (htab->tls_ldm_got.refcount > 0)
{
/* Allocate 2 got entries and 1 dynamic reloc for
R_PARISC_TLS_DTPMOD32 relocs. */
htab->tls_ldm_got.offset = htab->sgot->size;
htab->sgot->size += (GOT_ENTRY_SIZE * 2);
htab->srelgot->size += sizeof (Elf32_External_Rela);
}
else
htab->tls_ldm_got.offset = -1;
/* Do all the .plt entries without relocs first. The dynamic linker
uses the last .plt reloc to find the end of the .plt (and hence
@ -2670,7 +2813,7 @@ get_local_syms (bfd *output_bfd, bfd *input_bfd, struct bfd_link_info *info)
struct elf32_hppa_stub_hash_entry *hsh;
sec = hh->eh.root.u.def.section;
stub_name = hh->eh.root.root.string;
stub_name = hh_name (hh);
hsh = hppa_stub_hash_lookup (&htab->bstab,
stub_name,
FALSE, FALSE);
@ -3104,6 +3247,35 @@ elf32_hppa_build_stubs (struct bfd_link_info *info)
return TRUE;
}
/* Return the base vma address which should be subtracted from the real
address when resolving a dtpoff relocation.
This is PT_TLS segment p_vaddr. */
static bfd_vma
dtpoff_base (struct bfd_link_info *info)
{
/* If tls_sec is NULL, we should have signalled an error already. */
if (elf_hash_table (info)->tls_sec == NULL)
return 0;
return elf_hash_table (info)->tls_sec->vma;
}
/* Return the relocation value for R_PARISC_TLS_TPOFF*.. */
static bfd_vma
tpoff (struct bfd_link_info *info, bfd_vma address)
{
struct elf_link_hash_table *htab = elf_hash_table (info);
/* If tls_sec is NULL, we should have signalled an error already. */
if (htab->tls_sec == NULL)
return 0;
/* hppa TLS ABI is variant I and static TLS block start just after
tcbhead structure which has 2 pointer fields. */
return (address - htab->tls_sec->vma
+ align_power ((bfd_vma) 8, htab->tls_sec->alignment_power));
}
/* Perform a final link. */
static bfd_boolean
@ -3315,6 +3487,12 @@ final_link_relocate (asection *input_section,
case R_PARISC_DLTIND21L:
case R_PARISC_DLTIND14R:
case R_PARISC_DLTIND14F:
case R_PARISC_TLS_GD21L:
case R_PARISC_TLS_GD14R:
case R_PARISC_TLS_LDM21L:
case R_PARISC_TLS_LDM14R:
case R_PARISC_TLS_IE21L:
case R_PARISC_TLS_IE14R:
value -= elf_gp (input_section->output_section->owner);
break;
@ -3342,6 +3520,9 @@ final_link_relocate (asection *input_section,
case R_PARISC_DLTIND14F:
case R_PARISC_SEGBASE:
case R_PARISC_SEGREL32:
case R_PARISC_TLS_DTPMOD32:
case R_PARISC_TLS_DTPOFF32:
case R_PARISC_TLS_TPREL32:
r_field = e_fsel;
break;
@ -3353,6 +3534,11 @@ final_link_relocate (asection *input_section,
case R_PARISC_DIR21L:
case R_PARISC_DPREL21L:
case R_PARISC_TLS_GD21L:
case R_PARISC_TLS_LDM21L:
case R_PARISC_TLS_LDO21L:
case R_PARISC_TLS_IE21L:
case R_PARISC_TLS_LE21L:
r_field = e_lrsel;
break;
@ -3366,6 +3552,11 @@ final_link_relocate (asection *input_section,
case R_PARISC_DIR17R:
case R_PARISC_DIR14R:
case R_PARISC_DPREL14R:
case R_PARISC_TLS_GD14R:
case R_PARISC_TLS_LDM14R:
case R_PARISC_TLS_LDO14R:
case R_PARISC_TLS_IE14R:
case R_PARISC_TLS_LE14R:
r_field = e_rrsel;
break;
@ -3546,7 +3737,7 @@ elf32_hppa_relocate_section (bfd *output_bfd,
&& eh->type == STT_PARISC_MILLI)
{
if (! info->callbacks->undefined_symbol
(info, eh->root.root.string, input_bfd,
(info, eh_name (eh), input_bfd,
input_section, rela->r_offset, FALSE))
return FALSE;
warned_undef = TRUE;
@ -3875,6 +4066,198 @@ elf32_hppa_relocate_section (bfd *output_bfd,
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
}
break;
case R_PARISC_TLS_LDM21L:
case R_PARISC_TLS_LDM14R:
{
bfd_vma off;
off = htab->tls_ldm_got.offset;
if (off & 1)
off &= ~1;
else
{
Elf_Internal_Rela outrel;
bfd_byte *loc;
outrel.r_offset = (off
+ htab->sgot->output_section->vma
+ htab->sgot->output_offset);
outrel.r_addend = 0;
outrel.r_info = ELF32_R_INFO (0, R_PARISC_TLS_DTPMOD32);
loc = htab->srelgot->contents;
loc += htab->srelgot->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
htab->tls_ldm_got.offset |= 1;
}
/* Add the base of the GOT to the relocation value. */
relocation = (off
+ htab->sgot->output_offset
+ htab->sgot->output_section->vma);
break;
}
case R_PARISC_TLS_LDO21L:
case R_PARISC_TLS_LDO14R:
relocation -= dtpoff_base (info);
break;
case R_PARISC_TLS_GD21L:
case R_PARISC_TLS_GD14R:
case R_PARISC_TLS_IE21L:
case R_PARISC_TLS_IE14R:
{
bfd_vma off;
int indx;
char tls_type;
indx = 0;
if (hh != NULL)
{
bfd_boolean dyn;
dyn = htab->etab.dynamic_sections_created;
if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, &hh->eh)
&& (!info->shared
|| !SYMBOL_REFERENCES_LOCAL (info, &hh->eh)))
{
indx = hh->eh.dynindx;
}
off = hh->eh.got.offset;
tls_type = hh->tls_type;
}
else
{
off = local_got_offsets[r_symndx];
tls_type = hppa_elf_local_got_tls_type (input_bfd)[r_symndx];
}
if (tls_type == GOT_UNKNOWN)
abort ();
if ((off & 1) != 0)
off &= ~1;
else
{
bfd_boolean need_relocs = FALSE;
Elf_Internal_Rela outrel;
bfd_byte *loc = NULL;
int cur_off = off;
/* The GOT entries have not been initialized yet. Do it
now, and emit any relocations. If both an IE GOT and a
GD GOT are necessary, we emit the GD first. */
if ((info->shared || indx != 0)
&& (hh == NULL
|| ELF_ST_VISIBILITY (hh->eh.other) == STV_DEFAULT
|| hh->eh.root.type != bfd_link_hash_undefweak))
{
need_relocs = TRUE;
loc = htab->srelgot->contents;
/* FIXME (CAO): Should this be reloc_count++ ? */
loc += htab->srelgot->reloc_count * sizeof (Elf32_External_Rela);
}
if (tls_type & GOT_TLS_GD)
{
if (need_relocs)
{
outrel.r_offset = (cur_off
+ htab->sgot->output_section->vma
+ htab->sgot->output_offset);
outrel.r_info = ELF32_R_INFO (indx,R_PARISC_TLS_DTPMOD32);
outrel.r_addend = 0;
bfd_put_32 (output_bfd, 0, htab->sgot->contents + cur_off);
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
htab->srelgot->reloc_count++;
loc += sizeof (Elf32_External_Rela);
if (indx == 0)
bfd_put_32 (output_bfd, relocation - dtpoff_base (info),
htab->sgot->contents + cur_off + 4);
else
{
bfd_put_32 (output_bfd, 0,
htab->sgot->contents + cur_off + 4);
outrel.r_info = ELF32_R_INFO (indx, R_PARISC_TLS_DTPOFF32);
outrel.r_offset += 4;
bfd_elf32_swap_reloca_out (output_bfd, &outrel,loc);
htab->srelgot->reloc_count++;
loc += sizeof (Elf32_External_Rela);
}
}
else
{
/* If we are not emitting relocations for a
general dynamic reference, then we must be in a
static link or an executable link with the
symbol binding locally. Mark it as belonging
to module 1, the executable. */
bfd_put_32 (output_bfd, 1,
htab->sgot->contents + cur_off);
bfd_put_32 (output_bfd, relocation - dtpoff_base (info),
htab->sgot->contents + cur_off + 4);
}
cur_off += 8;
}
if (tls_type & GOT_TLS_IE)
{
if (need_relocs)
{
outrel.r_offset = (cur_off
+ htab->sgot->output_section->vma
+ htab->sgot->output_offset);
outrel.r_info = ELF32_R_INFO (indx, R_PARISC_TLS_TPREL32);
if (indx == 0)
outrel.r_addend = relocation - dtpoff_base (info);
else
outrel.r_addend = 0;
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
htab->srelgot->reloc_count++;
loc += sizeof (Elf32_External_Rela);
}
else
bfd_put_32 (output_bfd, tpoff (info, relocation),
htab->sgot->contents + cur_off);
cur_off += 4;
}
if (hh != NULL)
hh->eh.got.offset |= 1;
else
local_got_offsets[r_symndx] |= 1;
}
if ((tls_type & GOT_TLS_GD)
&& r_type != R_PARISC_TLS_GD21L
&& r_type != R_PARISC_TLS_GD14R)
off += 2 * GOT_ENTRY_SIZE;
/* Add the base of the GOT to the relocation value. */
relocation = (off
+ htab->sgot->output_offset
+ htab->sgot->output_section->vma);
break;
}
case R_PARISC_TLS_LE21L:
case R_PARISC_TLS_LE14R:
{
relocation = tpoff (info, relocation);
break;
}
break;
default:
break;
@ -3887,7 +4270,7 @@ elf32_hppa_relocate_section (bfd *output_bfd,
continue;
if (hh != NULL)
sym_name = hh->eh.root.root.string;
sym_name = hh_name (hh);
else
{
sym_name = bfd_elf_string_from_elf_section (input_bfd,
@ -3996,7 +4379,9 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd,
}
}
if (eh->got.offset != (bfd_vma) -1)
if (eh->got.offset != (bfd_vma) -1
&& (hppa_elf_hash_entry (eh)->tls_type & GOT_TLS_GD) == 0
&& (hppa_elf_hash_entry (eh)->tls_type & GOT_TLS_IE) == 0)
{
/* This symbol has an entry in the global offset table. Set it
up. */
@ -4057,8 +4442,8 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd,
}
/* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
if (eh->root.root.string[0] == '_'
&& (strcmp (eh->root.root.string, "_DYNAMIC") == 0
if (eh_name (eh)[0] == '_'
&& (strcmp (eh_name (eh), "_DYNAMIC") == 0
|| eh == htab->etab.hgot))
{
sym->st_shndx = SHN_ABS;
@ -4073,6 +4458,17 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd,
static enum elf_reloc_type_class
elf32_hppa_reloc_type_class (const Elf_Internal_Rela *rela)
{
/* Handle TLS relocs first; we don't want them to be marked
relative by the "if (ELF32_R_SYM (rela->r_info) == 0)"
check below. */
switch ((int) ELF32_R_TYPE (rela->r_info))
{
case R_PARISC_TLS_DTPMOD32:
case R_PARISC_TLS_DTPOFF32:
case R_PARISC_TLS_TPREL32:
return reloc_class_normal;
}
if (ELF32_R_SYM (rela->r_info) == 0)
return reloc_class_relative;

View file

@ -1,3 +1,19 @@
2006-05-24 Nick Clifton <nickc@redhat.com>
* config/tc-hppa.c: Convert to ISO C90 format.
* config/tc-hppa.h: Likewise.
2006-05-24 Carlos O'Donell <carlos@systemhalted.org>
Randolph Chung <randolph@tausq.org>
* config/tc-hppa.c (is_tls_gdidx, is_tls_ldidx, is_tls_dtpoff,
is_tls_ieoff, is_tls_leoff): Define.
(fix_new_hppa): Handle TLS.
(cons_fix_new_hppa): Likewise.
(pa_ip): Likewise.
(md_apply_fix): Handle TLS relocs.
* config/tc-hppa.h (hppa_fix_adjustable): Handle TLS.
2006-05-24 Bjoern Haase <bjoern.m.haase@web.de>
* config/tc-avr.c: Add new cpu targets avr6, avr2560 and avr2561.

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/* tc-hppa.h -- Header file for the PA
Copyright 1989, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002,
2003, 2004, 2005 Free Software Foundation, Inc.
2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@ -90,15 +90,14 @@
#define ASEC_NULL (asection *)0
/* pa_define_label gets used outside of tc-hppa.c via tc_frob_label. */
extern void pa_define_label PARAMS ((symbolS *));
extern void parse_cons_expression_hppa PARAMS ((expressionS *));
extern void cons_fix_new_hppa PARAMS ((fragS *, int, int, expressionS *));
extern int hppa_force_relocation PARAMS ((struct fix *));
extern void pa_define_label (symbolS *);
extern void parse_cons_expression_hppa (expressionS *);
extern void cons_fix_new_hppa (fragS *, int, int, expressionS *);
extern int hppa_force_relocation (struct fix *);
/* This gets called before writing the object file to make sure
things like entry/exit and proc/procend pairs match. */
extern void pa_check_eof PARAMS ((void));
extern void pa_check_eof (void);
#define tc_frob_file pa_check_eof
#define tc_frob_label(sym) pa_define_label (sym)
@ -120,7 +119,7 @@ extern const char hppa_symbol_chars[];
When used in an instruction it will always follow a comma. */
#define TC_EOL_IN_INSN(PTR) (*(PTR) == '!' && (PTR)[-1] == ',')
int hppa_fix_adjustable PARAMS((struct fix *));
int hppa_fix_adjustable (struct fix *);
#define tc_fix_adjustable hppa_fix_adjustable
#define EXTERN_FORCE_RELOC 1
@ -170,17 +169,23 @@ int hppa_fix_adjustable PARAMS((struct fix *));
#define tc_frob_symbol(sym,punt) \
{ \
if ((S_GET_SEGMENT (sym) == &bfd_und_section && ! symbol_used_p (sym) && \
ELF_ST_VISIBILITY (S_GET_OTHER (sym)) == STV_DEFAULT) \
if ((S_GET_SEGMENT (sym) == &bfd_und_section \
&& ! symbol_used_p (sym) \
&& ELF_ST_VISIBILITY (S_GET_OTHER (sym)) == STV_DEFAULT) \
|| (S_GET_SEGMENT (sym) == &bfd_abs_section \
&& ! S_IS_EXTERNAL (sym)) \
|| strcmp (S_GET_NAME (sym), "$global$") == 0 \
|| strcmp (S_GET_NAME (sym), "$PIC_pcrel$0") == 0) \
|| strcmp (S_GET_NAME (sym), "$PIC_pcrel$0") == 0 \
|| strcmp (S_GET_NAME (sym), "$tls_gdidx$") == 0 \
|| strcmp (S_GET_NAME (sym), "$tls_ldidx$") == 0 \
|| strcmp (S_GET_NAME (sym), "$tls_dtpoff$") == 0 \
|| strcmp (S_GET_NAME (sym), "$tls_ieoff$") == 0 \
|| strcmp (S_GET_NAME (sym), "$tls_leoff$") == 0) \
punt = 1; \
}
#define elf_tc_final_processing elf_hppa_final_processing
void elf_hppa_final_processing PARAMS ((void));
void elf_hppa_final_processing (void);
#define DWARF2_LINE_MIN_INSN_LENGTH 4
#endif /* OBJ_ELF */
@ -191,8 +196,7 @@ void elf_hppa_final_processing PARAMS ((void));
A silly fudge required for backwards compatibility. */
#define md_optimize_expr hppa_force_reg_syms_absolute
int hppa_force_reg_syms_absolute
PARAMS ((expressionS *, operatorT, expressionS *));
int hppa_force_reg_syms_absolute (expressionS *, operatorT, expressionS *);
#define TC_FIX_TYPE PTR
#define TC_INIT_FIX_DATA(FIX) ((FIX)->tc_fix_data = NULL)

View file

@ -1,3 +1,14 @@
2006-05-24 Carlos O'Donell <carlos@systemhalted.org>
Randolph Chung <randolph@tausq.org>
* hppa.h (R_PARISC_TLS_GD21L, R_PARISC_TLS_GD14R, R_PARISC_TLS_GDCALL,
R_PARISC_TLS_LDM21L, R_PARISC_TLS_LDM14R, R_PARISC_TLS_LDMCALL,
R_PARISC_TLS_LDO21L, R_PARISC_TLS_LDO14R, R_PARISC_TLS_DTPMOD32,
R_PARISC_TLS_DTPMOD64, R_PARISC_TLS_DTPOFF32, R_PARISC_TLS_DTPOFF64):
New TLS relocs.
(R_PARISC_TLS_LE21L, R_PARISC_TLS_LE14R, R_PARISC_TLS_IE21L,
R_PARISC_TLS_IE14R, R_PARISC_TLS_TPREL32, R_PARISC_TLS_TPREL64):
Define TLS relocs using existing equivalents.
2006-05-24 Bjoern Haase <bjoern.m.haase@web.de>
* avr.h: Add E_AVR_MACH_AVR6, R_AVR_LO8_LDI_GS and R_AVR_HI8_LDI_GS.

View file

@ -1,22 +1,22 @@
/* HPPA ELF support for BFD.
Copyright 1993, 1994, 1995, 1998, 1999, 2000, 2005
Copyright 1993, 1994, 1995, 1998, 1999, 2000, 2005, 2006
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.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
/* This file holds definitions specific to the HPPA ELF ABI. Note
that most of this is not actually implemented by BFD. */
@ -80,10 +80,10 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
/* These are strictly for compatibility with the older elf32-hppa
implementation. Hopefully we can eliminate them in the future. */
/* Optional section holding argument location/relocation info. */
#define SHT_PARISC_SYMEXTN SHT_LOPROC+8
#define SHT_PARISC_SYMEXTN SHT_LOPROC + 8
/* Option section for linker stubs. */
#define SHT_PARISC_STUBS SHT_LOPROC+9
#define SHT_PARISC_STUBS SHT_LOPROC + 9
/* Processor specific section flags. */
@ -480,8 +480,28 @@ RELOC_NUMBER (R_PARISC_LTOFF_TP16DF, 231)
RELOC_NUMBER (R_PARISC_GNU_VTENTRY, 232)
RELOC_NUMBER (R_PARISC_GNU_VTINHERIT, 233)
RELOC_NUMBER (R_PARISC_TLS_GD21L, 234)
RELOC_NUMBER (R_PARISC_TLS_GD14R, 235)
RELOC_NUMBER (R_PARISC_TLS_GDCALL, 236)
RELOC_NUMBER (R_PARISC_TLS_LDM21L, 237)
RELOC_NUMBER (R_PARISC_TLS_LDM14R, 238)
RELOC_NUMBER (R_PARISC_TLS_LDMCALL, 239)
RELOC_NUMBER (R_PARISC_TLS_LDO21L, 240)
RELOC_NUMBER (R_PARISC_TLS_LDO14R, 241)
RELOC_NUMBER (R_PARISC_TLS_DTPMOD32, 242)
RELOC_NUMBER (R_PARISC_TLS_DTPMOD64, 243)
RELOC_NUMBER (R_PARISC_TLS_DTPOFF32, 244)
RELOC_NUMBER (R_PARISC_TLS_DTPOFF64, 245)
END_RELOC_NUMBERS (R_PARISC_UNIMPLEMENTED)
#define R_PARISC_TLS_LE21L R_PARISC_TPREL21L
#define R_PARISC_TLS_LE14R R_PARISC_TPREL14R
#define R_PARISC_TLS_IE21L R_PARISC_LTOFF_TP21L
#define R_PARISC_TLS_IE14R R_PARISC_LTOFF_TP14R
#define R_PARISC_TLS_TPREL32 R_PARISC_TPREL32
#define R_PARISC_TLS_TPREL64 R_PARISC_TPREL64
#ifndef RELOC_MACROS_GEN_FUNC
typedef enum elf_hppa_reloc_type elf_hppa_reloc_type;
#endif