diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2013-01-16 21:34:46 +0000 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2013-01-16 21:34:46 +0000 |
commit | 1788fc08f7a091f246a41cd14d2b612d4253e55b (patch) | |
tree | a37e3ac15f14e718ac1248bc5eb66a5ade07d527 /bfd/elf64-x86-64.c | |
parent | e1ec603fec5191034dd56f4e417c89054b5f61b9 (diff) | |
download | gdb-1788fc08f7a091f246a41cd14d2b612d4253e55b.zip gdb-1788fc08f7a091f246a41cd14d2b612d4253e55b.tar.gz gdb-1788fc08f7a091f246a41cd14d2b612d4253e55b.tar.bz2 |
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.
Diffstat (limited to 'bfd/elf64-x86-64.c')
-rw-r--r-- | bfd/elf64-x86-64.c | 64 |
1 files changed, 54 insertions, 10 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 3f45776..8fae5fc 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -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 |