Add x86 size relocation support to bfd

* bfd-in2.h: Regenerated.
	* libbfd.h: Likewise.

	* elf32-i386.c (elf_howto_table): Fill R_386_SIZE32 entry.
	(elf_i386_reloc_type_lookup): Support BFD_RELOC_SIZE32.
	(elf_i386_check_relocs): Handle R_386_SIZE32.
	(elf_i386_gc_sweep_hook): Likewise.
	(elf_i386_relocate_section): Likewise.

	* elf64-x86-64.c (x86_64_elf_howto_table): Fill R_X86_64_SIZE32
	and R_X86_64_SIZE64 entries.
	(x86_64_reloc_map): Add BFD_RELOC_SIZE32 and BFD_RELOC_SIZE64,
	(elf_x86_64_rtype_to_howto): Handle R_X86_64_SIZE32 for x32.
	(elf_x86_64_reloc_name_lookup): Likewise.
	(elf_x86_64_check_relocs): Handle R_X86_64_SIZE32 and
	R_X86_64_SIZE64.
	(elf_x86_64_gc_sweep_hook): Likewise.
	(elf_x86_64_relocate_section): Likewise.

	* reloc.c (bfd_reloc_code_type): Add BFD_RELOC_SIZE32 and
	BFD_RELOC_SIZE64.
This commit is contained in:
H.J. Lu 2013-01-16 21:34:46 +00:00
parent e1ec603fec
commit 1788fc08f7
6 changed files with 123 additions and 12 deletions

View File

@ -1,3 +1,27 @@
2013-01-16 H.J. Lu <hongjiu.lu@intel.com>
* bfd-in2.h: Regenerated.
* libbfd.h: Likewise.
* elf32-i386.c (elf_howto_table): Fill R_386_SIZE32 entry.
(elf_i386_reloc_type_lookup): Support BFD_RELOC_SIZE32.
(elf_i386_check_relocs): Handle R_386_SIZE32.
(elf_i386_gc_sweep_hook): Likewise.
(elf_i386_relocate_section): Likewise.
* elf64-x86-64.c (x86_64_elf_howto_table): Fill R_X86_64_SIZE32
and R_X86_64_SIZE64 entries.
(x86_64_reloc_map): Add BFD_RELOC_SIZE32 and BFD_RELOC_SIZE64,
(elf_x86_64_rtype_to_howto): Handle R_X86_64_SIZE32 for x32.
(elf_x86_64_reloc_name_lookup): Likewise.
(elf_x86_64_check_relocs): Handle R_X86_64_SIZE32 and
R_X86_64_SIZE64.
(elf_x86_64_gc_sweep_hook): Likewise.
(elf_x86_64_relocate_section): Likewise.
* reloc.c (bfd_reloc_code_type): Add BFD_RELOC_SIZE32 and
BFD_RELOC_SIZE64.
2013-01-15 H.J. Lu <hongjiu.lu@intel.com>
* elf64-x86-64.c (R_X86_64_standard): Replace R_X86_64_IRELATIVE

View File

@ -2523,6 +2523,10 @@ The 24-bit relocation is used in some Intel 960 configurations. */
BFD_RELOC_HI16_S_PLTOFF,
BFD_RELOC_8_PLTOFF,
/* Size relocations. */
BFD_RELOC_SIZE32,
BFD_RELOC_SIZE64,
/* Relocations used by 68K ELF. */
BFD_RELOC_68K_GLOB_DAT,
BFD_RELOC_68K_JMP_SLOT,

View File

@ -133,7 +133,9 @@ static reloc_howto_type elf_howto_table[]=
HOWTO(R_386_TLS_TPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_TLS_TPOFF32",
TRUE, 0xffffffff, 0xffffffff, FALSE),
EMPTY_HOWTO (38),
HOWTO(R_386_SIZE32, 0, 2, 32, FALSE, 0, complain_overflow_unsigned,
bfd_elf_generic_reloc, "R_386_SIZE32",
TRUE, 0xffffffff, 0xffffffff, FALSE),
HOWTO(R_386_TLS_GOTDESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_TLS_GOTDESC",
TRUE, 0xffffffff, 0xffffffff, FALSE),
@ -312,6 +314,10 @@ elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
TRACE ("BFD_RELOC_386_TLS_TPOFF32");
return &elf_howto_table[R_386_TLS_TPOFF32 - R_386_tls_offset];
case BFD_RELOC_SIZE32:
TRACE ("BFD_RELOC_SIZE32");
return &elf_howto_table[R_386_SIZE32 - R_386_tls_offset];
case BFD_RELOC_386_TLS_GOTDESC:
TRACE ("BFD_RELOC_386_TLS_GOTDESC");
return &elf_howto_table[R_386_TLS_GOTDESC - R_386_tls_offset];
@ -1680,6 +1686,7 @@ elf_i386_check_relocs (bfd *abfd,
case R_386_32:
case R_386_PC32:
case R_386_SIZE32:
if (h != NULL && info->executable)
{
/* If this reloc is in a read-only section, we might
@ -1959,6 +1966,7 @@ elf_i386_gc_sweep_hook (bfd *abfd,
case R_386_32:
case R_386_PC32:
case R_386_SIZE32:
if (info->shared
&& (h == NULL || h->type != STT_GNU_IFUNC))
break;
@ -3185,6 +3193,7 @@ elf_i386_relocate_section (bfd *output_bfd,
bfd_reloc_status_type r;
unsigned int indx;
int tls_type;
bfd_vma st_size;
r_type = ELF32_R_TYPE (rel->r_info);
if (r_type == R_386_GNU_VTINHERIT
@ -3217,6 +3226,7 @@ elf_i386_relocate_section (bfd *output_bfd,
relocation = (sec->output_section->vma
+ sec->output_offset
+ sym->st_value);
st_size = sym->st_size;
if (ELF_ST_TYPE (sym->st_info) == STT_SECTION
&& ((sec->flags & SEC_MERGE) != 0
@ -3309,6 +3319,7 @@ elf_i386_relocate_section (bfd *output_bfd,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
unresolved_reloc, warned);
st_size = h->size;
}
if (sec != NULL && discarded_section (sec))
@ -3670,6 +3681,25 @@ elf_i386_relocate_section (bfd *output_bfd,
unresolved_reloc = FALSE;
break;
case R_386_SIZE32:
if (h
&& h->type == STT_TLS
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& h->root.u.def.section->output_section != NULL
&& htab->elf.tls_sec == NULL)
{
(*_bfd_error_handler)
(_("%B: `%s' accessed both as normal and thread local symbol"),
input_bfd, h->root.root.string);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
/* Set to symbol size. */
relocation = st_size;
/* Fall through. */
case R_386_32:
case R_386_PC32:
if ((input_section->flags & SEC_ALLOC) == 0
@ -3680,7 +3710,7 @@ elf_i386_relocate_section (bfd *output_bfd,
&& (h == NULL
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak)
&& (r_type != R_386_PC32
&& ((r_type != R_386_PC32 && r_type != R_386_SIZE32)
|| !SYMBOL_CALLS_LOCAL (info, h)))
|| (ELIMINATE_COPY_RELOCS
&& !info->shared

View File

@ -148,8 +148,12 @@ static reloc_howto_type x86_64_elf_howto_table[] =
HOWTO(R_X86_64_PLTOFF64, 0, 4, 64, FALSE, 0, complain_overflow_signed,
bfd_elf_generic_reloc, "R_X86_64_PLTOFF64", FALSE, MINUS_ONE,
MINUS_ONE, FALSE),
EMPTY_HOWTO (32),
EMPTY_HOWTO (33),
HOWTO(R_X86_64_SIZE32, 0, 2, 32, FALSE, 0, complain_overflow_unsigned,
bfd_elf_generic_reloc, "R_X86_64_SIZE32", FALSE, 0xffffffff, 0xffffffff,
FALSE),
HOWTO(R_X86_64_SIZE64, 0, 4, 64, FALSE, 0, complain_overflow_unsigned,
bfd_elf_generic_reloc, "R_X86_64_SIZE64", FALSE, MINUS_ONE, MINUS_ONE,
FALSE),
HOWTO(R_X86_64_GOTPC32_TLSDESC, 0, 2, 32, TRUE, 0,
complain_overflow_bitfield, bfd_elf_generic_reloc,
"R_X86_64_GOTPC32_TLSDESC",
@ -238,6 +242,8 @@ static const struct elf_reloc_map x86_64_reloc_map[] =
{ BFD_RELOC_X86_64_GOTPC64, R_X86_64_GOTPC64, },
{ BFD_RELOC_X86_64_GOTPLT64, R_X86_64_GOTPLT64, },
{ BFD_RELOC_X86_64_PLTOFF64, R_X86_64_PLTOFF64, },
{ BFD_RELOC_SIZE32, R_X86_64_SIZE32, },
{ BFD_RELOC_SIZE64, R_X86_64_SIZE64, },
{ BFD_RELOC_X86_64_GOTPC32_TLSDESC, R_X86_64_GOTPC32_TLSDESC, },
{ BFD_RELOC_X86_64_TLSDESC_CALL, R_X86_64_TLSDESC_CALL, },
{ BFD_RELOC_X86_64_TLSDESC, R_X86_64_TLSDESC, },
@ -1731,6 +1737,8 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_X86_64_PC32:
case R_X86_64_PC64:
case R_X86_64_64:
case R_X86_64_SIZE32:
case R_X86_64_SIZE64:
pointer:
if (h != NULL && info->executable)
{
@ -2027,6 +2035,8 @@ elf_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
case R_X86_64_PC16:
case R_X86_64_PC32:
case R_X86_64_PC64:
case R_X86_64_SIZE32:
case R_X86_64_SIZE64:
if (info->shared
&& (h == NULL || h->type != STT_GNU_IFUNC))
break;
@ -3202,6 +3212,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
bfd_reloc_status_type r;
int tls_type;
asection *base_got;
bfd_vma st_size;
r_type = ELF32_R_TYPE (rel->r_info);
if (r_type == (int) R_X86_64_GNU_VTINHERIT
@ -3235,6 +3246,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
relocation = _bfd_elf_rela_local_sym (output_bfd, sym,
&sec, rel);
st_size = sym->st_size;
/* Relocate against local STT_GNU_IFUNC symbol. */
if (!info->relocatable
@ -3258,6 +3270,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
unresolved_reloc, warned);
st_size = h->size;
}
if (sec != NULL && discarded_section (sec))
@ -3267,14 +3280,22 @@ elf_x86_64_relocate_section (bfd *output_bfd,
if (info->relocatable)
continue;
if (rel->r_addend == 0
&& r_type == R_X86_64_64
&& !ABI_64_P (output_bfd))
if (rel->r_addend == 0 && !ABI_64_P (output_bfd))
{
/* For x32, treat R_X86_64_64 like R_X86_64_32 and zero-extend
it to 64bit if addend is zero. */
r_type = R_X86_64_32;
memset (contents + rel->r_offset + 4, 0, 4);
if (r_type == R_X86_64_64)
{
/* For x32, treat R_X86_64_64 like R_X86_64_32 and
zero-extend it to 64bit if addend is zero. */
r_type = R_X86_64_32;
memset (contents + rel->r_offset + 4, 0, 4);
}
else if (r_type == R_X86_64_SIZE64)
{
/* For x32, treat R_X86_64_SIZE64 like R_X86_64_SIZE32 and
zero-extend it to 64bit if addend is zero. */
r_type = R_X86_64_SIZE32;
memset (contents + rel->r_offset + 4, 0, 4);
}
}
/* Since STT_GNU_IFUNC symbol must go through PLT, we handle
@ -3655,6 +3676,26 @@ elf_x86_64_relocate_section (bfd *output_bfd,
unresolved_reloc = FALSE;
break;
case R_X86_64_SIZE32:
case R_X86_64_SIZE64:
if (h
&& h->type == STT_TLS
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& h->root.u.def.section->output_section != NULL
&& htab->elf.tls_sec == NULL)
{
(*_bfd_error_handler)
(_("%B: `%s' accessed both as normal and thread local symbol"),
input_bfd, h->root.root.string);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
/* Set to symbol size. */
relocation = st_size;
goto direct;
case R_X86_64_PC8:
case R_X86_64_PC16:
case R_X86_64_PC32:
@ -3727,6 +3768,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
/* FIXME: The ABI says the linker should make sure the value is
the same when it's zeroextended to 64 bit. */
direct:
if ((input_section->flags & SEC_ALLOC) == 0)
break;
@ -3734,7 +3776,9 @@ elf_x86_64_relocate_section (bfd *output_bfd,
&& (h == NULL
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak)
&& (! IS_X86_64_PCREL_TYPE (r_type)
&& ((! IS_X86_64_PCREL_TYPE (r_type)
&& r_type != R_X86_64_SIZE32
&& r_type != R_X86_64_SIZE64)
|| ! SYMBOL_CALLS_LOCAL (info, h)))
|| (ELIMINATE_COPY_RELOCS
&& !info->shared

View File

@ -940,6 +940,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_HI16_PLTOFF",
"BFD_RELOC_HI16_S_PLTOFF",
"BFD_RELOC_8_PLTOFF",
"BFD_RELOC_SIZE32",
"BFD_RELOC_SIZE64",
"BFD_RELOC_68K_GLOB_DAT",
"BFD_RELOC_68K_JMP_SLOT",
"BFD_RELOC_68K_RELATIVE",

View File

@ -1736,6 +1736,13 @@ ENUMX
ENUMDOC
For ELF.
ENUM
BFD_RELOC_SIZE32
ENUMX
BFD_RELOC_SIZE64
ENUMDOC
Size relocations.
ENUM
BFD_RELOC_68K_GLOB_DAT
ENUMX