diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2020-04-01 14:31:47 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2020-04-01 14:31:47 -0700 |
commit | 382aae06322799a25ea52fe61b243cbca4db8d66 (patch) | |
tree | bc60e7b2d1d5acc2622c393933788146f8b1c291 /bfd/elf32-i386.c | |
parent | 6b4a335bf7b7996e904e895b3fdc35443c40cfca (diff) | |
download | binutils-gdb-382aae06322799a25ea52fe61b243cbca4db8d66.tar.gz |
x86: Only allow S + A relocations against absolute symbol
Since value of non-preemptible absolute symbol (SHN_ABS) won't change,
only relocations, which can be resolved as absolute value + addend, and
GOTPCREL relocations, where absolute value + addend is stored in the GOT
slot, against non-preemptible absolute symbol are allowed in PIE and
shared library.
Also convert load relocation to R_386_32, R_X86_64_32S or R_X86_64_32 for
relocation against non-preemptible absolute symbol. Don't convert to
R_X86_64_32S nor R_X86_64_32 for non-preemptible absolute symbol if they
overflow.
bfd/
PR ld/25749
PR ld/25754
* elf32-i386.c (elf_i386_convert_load_reloc): Convert load
relocation to R_386_32 for relocation against non-preemptible
absolute symbol.
(elf_i386_check_relocs): Call _bfd_elf_x86_valid_reloc_p. Don't
allocate dynamic relocation for non-preemptible absolute symbol.
(elf_i386_relocate_section): Pass sec to
GENERATE_DYNAMIC_RELOCATION_P.
* elf64-x86-64.c (R_X86_64_converted_reloc_bit): Moved.
(elf_x86_64_convert_load_reloc): Covert load relocation to
R_X86_64_32S or R_X86_64_32 for relocation against non-preemptible
absolute symbol. Don't convert to R_X86_64_32S nor R_X86_64_32
for non-preemptible absolute symbol if they overflow.
(elf_x86_64_check_relocs): Call _bfd_elf_x86_valid_reloc_p. Set
tls_type for GOT slot to GOT_ABS for non-preemptible absolute
symbol. Don't allocate dynamic relocation for non-preemptible
absolute symbol.
(elf_x86_64_relocate_section): Don't generate relative relocation
for GOTPCREL relocations aganst local absolute symbol. Pass sec
to GENERATE_DYNAMIC_RELOCATION_P.
* elfxx-x86.c (elf_x86_allocate_dynrelocs): No dynamic relocation
against non-preemptible absolute symbol.
(_bfd_elf_x86_valid_reloc_p): New function.
(_bfd_x86_elf_size_dynamic_sections): No dynamic relocation for
GOT_ABS GOT slot.
* elfxx-x86.h (GENERATE_DYNAMIC_RELOCATION_P): Add an SEC
argument. Don't generate dynamic relocation against
non-preemptible absolute symbol.
(ABS_SYMBOL_P): New.
(GENERATE_RELATIVE_RELOC_P): Don't generate relative relocation
against non-preemptible absolute symbol.
(GOT_ABS): New.
(R_X86_64_converted_reloc_bit): New. Moved from elf64-x86-64.c.
(_bfd_elf_x86_valid_reloc_p): New.
ld/
PR ld/25749
PR ld/25754
* testsuite/ld-elf/linux-x86.exp: Run ld/25749 tests.
* testsuite/ld-elf/pr25749-1.c: New file.
* testsuite/ld-elf/pr25749-1a.c: Likewise.
* testsuite/ld-elf/pr25749-1b.c: Likewise.
* testsuite/ld-elf/pr25749-1b.err: Likewise.
* testsuite/ld-elf/pr25749-1c.c: Likewise.
* testsuite/ld-elf/pr25749-1d.c: Likewise.
* testsuite/ld-elf/pr25749-2.c: Likewise.
* testsuite/ld-elf/pr25749-2a.s: Likewise.
* testsuite/ld-elf/pr25749-2b.s: Likewise.
* testsuite/ld-elf/pr25749.rd: Likewise.
* testsuite/ld-elf/pr25754-1a.c: Likewise.
* testsuite/ld-elf/pr25754-1b.s: Likewise.
* testsuite/ld-elf/pr25754-2a.c: Likewise.
* testsuite/ld-elf/pr25754-2b.err: Likewise.
* testsuite/ld-elf/pr25754-2b.s: Likewise.
* testsuite/ld-elf/pr25754-3a.c: Likewise.
* testsuite/ld-elf/pr25754-3b.s: Likewise.
* testsuite/ld-elf/pr25754-4a.c: Likewise.
* testsuite/ld-elf/pr25754-4b.s: Likewise.
* testsuite/ld-elf/pr25754-4c.s: Likewise.
* testsuite/ld-elf/pr25754-5a.c: Likewise.
* testsuite/ld-elf/pr25754-5b.s: Likewise.
* testsuite/ld-elf/pr25754-5c.s: Likewise.
* testsuite/ld-elf/pr25754-6a.c: Likewise.
* testsuite/ld-elf/pr25754-6b.s: Likewise.
* testsuite/ld-x86-64/pr19609-6a.d: Don't expect linker error.
Diffstat (limited to 'bfd/elf32-i386.c')
-rw-r--r-- | bfd/elf32-i386.c | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index eb7e1f8b34e..51c3e863044 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1226,6 +1226,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, bfd_vma nop_offset; bfd_boolean is_pic; bfd_boolean to_reloc_32; + bfd_boolean abs_symbol; unsigned int r_type; unsigned int r_symndx; bfd_vma roff = irel->r_offset; @@ -1249,6 +1250,21 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, modrm = bfd_get_8 (abfd, contents + roff - 1); baseless = (modrm & 0xc7) == 0x5; + if (h) + { + /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P. */ + local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h); + isym = NULL; + abs_symbol = ABS_SYMBOL_P (h); + } + else + { + local_ref = TRUE; + isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd, + r_symndx); + abs_symbol = isym->st_shndx == SHN_ABS; + } + if (baseless && is_pic) { /* For PIC, disallow R_386_GOT32X without a base register @@ -1256,11 +1272,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, const char *name; if (h == NULL) - { - isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd, - r_symndx); - name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL); - } + name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL); else name = h->root.root.string; @@ -1294,9 +1306,6 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, goto convert_load; } - /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P. */ - local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h); - /* Undefined weak symbol is only bound locally in executable and its reference is resolved as 0. */ if (h->root.type == bfd_link_hash_undefweak @@ -1396,6 +1405,9 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, convert_load: if (opcode == 0x8b) { + if (abs_symbol && local_ref) + to_reloc_32 = TRUE; + if (to_reloc_32) { /* Convert "mov foo@GOT[(%reg1)], %reg2" to @@ -1519,6 +1531,7 @@ elf_i386_check_relocs (bfd *abfd, Elf_Internal_Sym *isym; const char *name; bfd_boolean size_reloc; + bfd_boolean no_dynreloc; r_symndx = ELF32_R_SYM (rel->r_info); r_type = ELF32_R_TYPE (rel->r_info); @@ -1587,6 +1600,10 @@ elf_i386_check_relocs (bfd *abfd, goto error_return; } + if (!_bfd_elf_x86_valid_reloc_p (sec, info, htab, rel, h, isym, + symtab_hdr, &no_dynreloc)) + return FALSE; + if (! elf_i386_tls_transition (info, abfd, sec, contents, symtab_hdr, sym_hashes, &r_type, GOT_UNKNOWN, @@ -1827,8 +1844,9 @@ elf_i386_check_relocs (bfd *abfd, size_reloc = FALSE; do_size: - if (NEED_DYNAMIC_RELOCATION_P (info, FALSE, h, sec, r_type, - R_386_32)) + if (!no_dynreloc + && NEED_DYNAMIC_RELOCATION_P (info, FALSE, h, sec, r_type, + R_386_32)) { struct elf_dyn_relocs *p; struct elf_dyn_relocs **head; @@ -2704,7 +2722,7 @@ elf_i386_relocate_section (bfd *output_bfd, || is_vxworks_tls) break; - if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, + if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, sec, FALSE, resolved_to_zero, (r_type == R_386_PC32))) { |