From 382aae06322799a25ea52fe61b243cbca4db8d66 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 1 Apr 2020 14:31:47 -0700 Subject: [PATCH] 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. --- bfd/ChangeLog | 38 +++++++ bfd/elf32-i386.c | 40 +++++-- bfd/elf64-x86-64.c | 81 +++++++++++--- bfd/elfxx-x86.c | 103 ++++++++++++++++- bfd/elfxx-x86.h | 29 ++++- ld/ChangeLog | 32 ++++++ ld/testsuite/ld-elf/linux-x86.exp | 167 ++++++++++++++++++++++++++++ ld/testsuite/ld-elf/pr25749-1.c | 12 ++ ld/testsuite/ld-elf/pr25749-1a.c | 11 ++ ld/testsuite/ld-elf/pr25749-1b.c | 9 ++ ld/testsuite/ld-elf/pr25749-1b.err | 3 + ld/testsuite/ld-elf/pr25749-1c.c | 9 ++ ld/testsuite/ld-elf/pr25749-1d.c | 19 ++++ ld/testsuite/ld-elf/pr25749-2.c | 12 ++ ld/testsuite/ld-elf/pr25749-2a.s | 6 + ld/testsuite/ld-elf/pr25749-2b.s | 7 ++ ld/testsuite/ld-elf/pr25749.rd | 4 + ld/testsuite/ld-elf/pr25754-1a.c | 19 ++++ ld/testsuite/ld-elf/pr25754-1b.s | 3 + ld/testsuite/ld-elf/pr25754-2a.c | 20 ++++ ld/testsuite/ld-elf/pr25754-2b.s | 3 + ld/testsuite/ld-elf/pr25754-3a.c | 19 ++++ ld/testsuite/ld-elf/pr25754-3b.s | 3 + ld/testsuite/ld-elf/pr25754-4a.c | 12 ++ ld/testsuite/ld-elf/pr25754-4b.s | 23 ++++ ld/testsuite/ld-elf/pr25754-4c.s | 12 ++ ld/testsuite/ld-elf/pr25754-5a.c | 12 ++ ld/testsuite/ld-elf/pr25754-5b.s | 23 ++++ ld/testsuite/ld-elf/pr25754-5c.s | 12 ++ ld/testsuite/ld-elf/pr25754-6a.c | 12 ++ ld/testsuite/ld-elf/pr25754-6b.s | 12 ++ ld/testsuite/ld-x86-64/pr19609-6a.d | 11 +- 32 files changed, 746 insertions(+), 32 deletions(-) create mode 100644 ld/testsuite/ld-elf/pr25749-1.c create mode 100644 ld/testsuite/ld-elf/pr25749-1a.c create mode 100644 ld/testsuite/ld-elf/pr25749-1b.c create mode 100644 ld/testsuite/ld-elf/pr25749-1b.err create mode 100644 ld/testsuite/ld-elf/pr25749-1c.c create mode 100644 ld/testsuite/ld-elf/pr25749-1d.c create mode 100644 ld/testsuite/ld-elf/pr25749-2.c create mode 100644 ld/testsuite/ld-elf/pr25749-2a.s create mode 100644 ld/testsuite/ld-elf/pr25749-2b.s create mode 100644 ld/testsuite/ld-elf/pr25749.rd create mode 100644 ld/testsuite/ld-elf/pr25754-1a.c create mode 100644 ld/testsuite/ld-elf/pr25754-1b.s create mode 100644 ld/testsuite/ld-elf/pr25754-2a.c create mode 100644 ld/testsuite/ld-elf/pr25754-2b.s create mode 100644 ld/testsuite/ld-elf/pr25754-3a.c create mode 100644 ld/testsuite/ld-elf/pr25754-3b.s create mode 100644 ld/testsuite/ld-elf/pr25754-4a.c create mode 100644 ld/testsuite/ld-elf/pr25754-4b.s create mode 100644 ld/testsuite/ld-elf/pr25754-4c.s create mode 100644 ld/testsuite/ld-elf/pr25754-5a.c create mode 100644 ld/testsuite/ld-elf/pr25754-5b.s create mode 100644 ld/testsuite/ld-elf/pr25754-5c.s create mode 100644 ld/testsuite/ld-elf/pr25754-6a.c create mode 100644 ld/testsuite/ld-elf/pr25754-6b.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index bea9526d2a1..2ed10465791 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,41 @@ +2020-04-01 H.J. Lu + + 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. + 2020-04-01 Tamar Christina PR ld/16017 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))) { diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 90e27023343..4c9ad78dd74 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -196,9 +196,6 @@ static reloc_howto_type x86_64_elf_howto_table[] = FALSE) }; -/* Set if a relocation is converted from a GOTPCREL relocation. */ -#define R_X86_64_converted_reloc_bit (1 << 7) - #define X86_PCREL_TYPE_P(TYPE) \ ( ((TYPE) == R_X86_64_PC8) \ || ((TYPE) == R_X86_64_PC16) \ @@ -1509,6 +1506,8 @@ elf_x86_64_convert_load_reloc (bfd *abfd, bfd_boolean no_overflow; bfd_boolean relocx; bfd_boolean to_reloc_pc32; + bfd_boolean abs_symbol; + bfd_boolean local_ref; asection *tsec; bfd_signed_vma raddend; unsigned int opcode; @@ -1516,6 +1515,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd, unsigned int r_type = *r_type_p; unsigned int r_symndx; bfd_vma roff = irel->r_offset; + bfd_vma abs_relocation; if (roff < (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2)) return TRUE; @@ -1559,6 +1559,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd, || no_overflow || is_pic); + abs_symbol = FALSE; + abs_relocation = 0; + /* Get the symbol referred to by the reloc. */ if (h == NULL) { @@ -1569,8 +1572,13 @@ elf_x86_64_convert_load_reloc (bfd *abfd, if (isym->st_shndx == SHN_UNDEF) return TRUE; + local_ref = TRUE; if (isym->st_shndx == SHN_ABS) - tsec = bfd_abs_section_ptr; + { + tsec = bfd_abs_section_ptr; + abs_symbol = TRUE; + abs_relocation = isym->st_value; + } else if (isym->st_shndx == SHN_COMMON) tsec = bfd_com_section_ptr; else if (isym->st_shndx == SHN_X86_64_LCOMMON) @@ -1586,9 +1594,11 @@ elf_x86_64_convert_load_reloc (bfd *abfd, GOTPCRELX relocations since we need to modify REX byte. It is OK convert mov with R_X86_64_GOTPCREL to R_X86_64_PC32. */ - bfd_boolean local_ref; struct elf_x86_link_hash_entry *eh = elf_x86_hash_entry (h); + abs_symbol = ABS_SYMBOL_P (h); + abs_relocation = h->root.u.def.value; + /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P. */ local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h); if ((relocx || opcode == 0x8b) @@ -1728,6 +1738,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd, if (opcode == 0x8b) { + if (abs_symbol && local_ref) + to_reloc_pc32 = FALSE; + if (to_reloc_pc32) { /* Convert "mov foo@GOTPCREL(%rip), %reg" to @@ -1788,6 +1801,21 @@ elf_x86_64_convert_load_reloc (bfd *abfd, r_type = (rex & REX_W) != 0 ? R_X86_64_32S : R_X86_64_32; rewrite_modrm_rex: + if (abs_relocation) + { + /* Check if R_X86_64_32S/R_X86_64_32 fits. */ + if (r_type == R_X86_64_32S) + { + if ((abs_relocation + 0x80000000) > 0xffffffff) + return TRUE; + } + else + { + if (abs_relocation > 0xffffffff) + return TRUE; + } + } + bfd_put_8 (abfd, modrm, contents + roff - 1); if (rex) @@ -1879,6 +1907,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, const char *name; bfd_boolean size_reloc; bfd_boolean converted_reloc; + bfd_boolean no_dynreloc; r_symndx = htab->r_sym (rel->r_info); r_type = ELF32_R_TYPE (rel->r_info); @@ -1983,6 +2012,10 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, converted = TRUE; } + if (!_bfd_elf_x86_valid_reloc_p (sec, info, htab, rel, h, isym, + symtab_hdr, &no_dynreloc)) + return FALSE; + if (! elf_x86_64_tls_transition (info, abfd, sec, contents, symtab_hdr, sym_hashes, &r_type, GOT_UNKNOWN, @@ -2029,12 +2062,26 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, switch (r_type) { - default: tls_type = GOT_NORMAL; break; - case R_X86_64_TLSGD: tls_type = GOT_TLS_GD; break; - case R_X86_64_GOTTPOFF: tls_type = GOT_TLS_IE; break; + default: + tls_type = GOT_NORMAL; + if (h) + { + if (ABS_SYMBOL_P (h)) + tls_type = GOT_ABS; + } + else if (isym->st_shndx == SHN_ABS) + tls_type = GOT_ABS; + break; + case R_X86_64_TLSGD: + tls_type = GOT_TLS_GD; + break; + case R_X86_64_GOTTPOFF: + tls_type = GOT_TLS_IE; + break; case R_X86_64_GOTPC32_TLSDESC: case R_X86_64_TLSDESC_CALL: - tls_type = GOT_TLS_GDESC; break; + tls_type = GOT_TLS_GDESC; + break; } if (h != NULL) @@ -2245,8 +2292,9 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, size_reloc = FALSE; do_size: - if (NEED_DYNAMIC_RELOCATION_P (info, TRUE, h, sec, r_type, - htab->pointer_r_type)) + if (!no_dynreloc + && NEED_DYNAMIC_RELOCATION_P (info, TRUE, h, sec, r_type, + htab->pointer_r_type)) { struct elf_dyn_relocs *p; struct elf_dyn_relocs **head; @@ -2880,7 +2928,14 @@ elf_x86_64_relocate_section (bfd *output_bfd, base_got->contents + off); local_got_offsets[r_symndx] |= 1; - if (bfd_link_pic (info)) + /* NB: GOTPCREL relocations against local absolute + symbol store relocation value in the GOT slot + without relative relocation. */ + if (bfd_link_pic (info) + && !(sym->st_shndx == SHN_ABS + && (r_type == R_X86_64_GOTPCREL + || r_type == R_X86_64_GOTPCRELX + || r_type == R_X86_64_REX_GOTPCRELX))) relative_reloc = TRUE; } } @@ -3175,7 +3230,7 @@ elf_x86_64_relocate_section (bfd *output_bfd, && (X86_PCREL_TYPE_P (r_type) || X86_SIZE_TYPE_P (r_type))); - if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, + if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, sec, need_copy_reloc_in_pie, resolved_to_zero, FALSE)) { diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index 108e04a1588..0fc75fbedfb 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -347,7 +347,8 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) (but if both R_386_TLS_IE_32 and R_386_TLS_IE is present, we need two), R_386_TLS_GD and R_X86_64_TLSGD need one if local symbol and two if global. No dynamic relocation against - resolved undefined weak symbol in executable. */ + resolved undefined weak symbol in executable. No dynamic + relocation against non-preemptible absolute symbol. */ if (tls_type == GOT_TLS_IE_BOTH) htab->elf.srelgot->size += 2 * htab->sizeof_reloc; else if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1) @@ -359,7 +360,9 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) && ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT && !resolved_to_zero) || h->root.type != bfd_link_hash_undefweak) - && (bfd_link_pic (info) + && ((bfd_link_pic (info) + && !(h->dynindx == -1 + && ABS_SYMBOL_P (h))) || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))) htab->elf.srelgot->size += htab->sizeof_reloc; if (GOT_TLS_GDESC_P (tls_type)) @@ -952,6 +955,100 @@ _bfd_x86_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info) return _bfd_elf_link_check_relocs (abfd, info); } +bfd_boolean +_bfd_elf_x86_valid_reloc_p (asection *input_section, + struct bfd_link_info *info, + struct elf_x86_link_hash_table *htab, + const Elf_Internal_Rela *rel, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym, + Elf_Internal_Shdr *symtab_hdr, + bfd_boolean *no_dynreloc_p) +{ + bfd_boolean valid_p = TRUE; + + *no_dynreloc_p = FALSE; + + /* Check If relocation against non-preemptible absolute symbol is + valid in PIC. FIXME: Can't use SYMBOL_REFERENCES_LOCAL_P since + it may call _bfd_elf_link_hide_sym_by_version and result in + ld-elfvers/ vers21 test failure. */ + if (bfd_link_pic (info) + && (h == NULL || SYMBOL_REFERENCES_LOCAL (info, h))) + { + const struct elf_backend_data *bed; + unsigned int r_type; + Elf_Internal_Rela irel; + + /* Skip non-absolute symbol. */ + if (h) + { + if (!ABS_SYMBOL_P (h)) + return valid_p; + } + else if (sym->st_shndx != SHN_ABS) + return valid_p; + + bed = get_elf_backend_data (input_section->owner); + r_type = ELF32_R_TYPE (rel->r_info); + irel = *rel; + + /* Only allow relocations against absolute symbol, which can be + resolved as absolute value + addend. GOTPCREL relocations + are allowed since absolute value + addend is stored in the + GOT slot. */ + if (bed->target_id == X86_64_ELF_DATA) + { + r_type &= ~R_X86_64_converted_reloc_bit; + valid_p = (r_type == R_X86_64_64 + || r_type == R_X86_64_32 + || r_type == R_X86_64_32S + || r_type == R_X86_64_16 + || r_type == R_X86_64_8 + || r_type == R_X86_64_GOTPCREL + || r_type == R_X86_64_GOTPCRELX + || r_type == R_X86_64_REX_GOTPCRELX); + if (!valid_p) + { + unsigned int r_symndx = htab->r_sym (rel->r_info); + irel.r_info = htab->r_info (r_symndx, r_type); + } + } + else + valid_p = (r_type == R_386_32 + || r_type == R_386_16 + || r_type == R_386_8); + + if (valid_p) + *no_dynreloc_p = TRUE; + else + { + const char *name; + arelent internal_reloc; + + if (!bed->elf_info_to_howto (input_section->owner, + &internal_reloc, &irel) + || internal_reloc.howto == NULL) + abort (); + + if (h) + name = h->root.root.string; + else + name = bfd_elf_sym_name (input_section->owner, symtab_hdr, + sym, NULL); + info->callbacks->einfo + /* xgettext:c-format */ + (_("%F%P: %pB: relocation %s against absolute symbol " + "`%s' in section `%pA' is disallowed\n"), + input_section->owner, internal_reloc.howto->name, name, + input_section); + bfd_set_error (bfd_error_bad_value); + } + } + + return valid_p; +} + /* Set the sizes of the dynamic sections. */ bfd_boolean @@ -1065,7 +1162,7 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, || *local_tls_type == GOT_TLS_IE_BOTH) s->size += htab->got_entry_size; } - if (bfd_link_pic (info) + if ((bfd_link_pic (info) && *local_tls_type != GOT_ABS) || GOT_TLS_GD_ANY_P (*local_tls_type) || (*local_tls_type & GOT_TLS_IE)) { diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h index bef17dc2bac..6e91f242622 100644 --- a/bfd/elfxx-x86.h +++ b/bfd/elfxx-x86.h @@ -119,11 +119,15 @@ Copy dynamic function pointer relocations. Don't generate dynamic relocations against resolved undefined weak symbols in PIE, except when PC32_RELOC is TRUE. Undefined weak symbol is bound locally - when PIC is false. */ -#define GENERATE_DYNAMIC_RELOCATION_P(INFO, EH, R_TYPE, \ + when PIC is false. Don't generate dynamic relocations against + non-preemptible absolute symbol. */ +#define GENERATE_DYNAMIC_RELOCATION_P(INFO, EH, R_TYPE, SEC, \ NEED_COPY_RELOC_IN_PIE, \ RESOLVED_TO_ZERO, PC32_RELOC) \ ((bfd_link_pic (INFO) \ + && !(bfd_is_abs_section (SEC) \ + && ((EH) == NULL \ + || SYMBOL_REFERENCES_LOCAL (INFO, &(EH)->elf))) \ && !(NEED_COPY_RELOC_IN_PIE) \ && ((EH) == NULL \ || ((ELF_ST_VISIBILITY ((EH)->elf.other) == STV_DEFAULT \ @@ -170,17 +174,25 @@ || ((struct elf_x86_link_hash_entry *) (H))->linker_def \ || ELF_COMMON_DEF_P (H)) +/* Return TRUE if the symbol described by a linker hash entry H is + going to be absolute. Similar to bfd_is_abs_symbol, but excluding + all linker-script defined symbols. */ +#define ABS_SYMBOL_P(H) \ + (bfd_is_abs_symbol (&(H)->root) && !(H)->root.ldscript_def) + /* TRUE if relative relocation should be generated. GOT reference to global symbol in PIC will lead to dynamic symbol. It becomes a problem when "time" or "times" is defined as a variable in an executable, clashing with functions of the same name in libc. If a symbol isn't undefined weak symbol, don't make it dynamic in PIC and - generate relative relocation. */ + generate relative relocation. Don't generate relative relocation + against non-preemptible absolute symbol. */ #define GENERATE_RELATIVE_RELOC_P(INFO, H) \ ((H)->dynindx == -1 \ && !(H)->forced_local \ && (H)->root.type != bfd_link_hash_undefweak \ - && bfd_link_pic (INFO)) + && bfd_link_pic (INFO) \ + && !ABS_SYMBOL_P (H)) /* TRUE if this is a pointer reference to a local IFUNC. */ #define POINTER_LOCAL_IFUNC_P(INFO, H) \ @@ -414,6 +426,7 @@ struct elf_x86_plt_layout #define GOT_TLS_IE_NEG 6 #define GOT_TLS_IE_BOTH 7 #define GOT_TLS_GDESC 8 +#define GOT_ABS 9 #define GOT_TLS_GD_BOTH_P(type) \ ((type) == (GOT_TLS_GD | GOT_TLS_GDESC)) #define GOT_TLS_GD_P(type) \ @@ -601,6 +614,9 @@ struct elf_x86_plt long count; }; +/* Set if a relocation is converted from a GOTPCREL relocation. */ +#define R_X86_64_converted_reloc_bit (1 << 7) + #define elf_x86_tdata(abfd) \ ((struct elf_x86_obj_tdata *) (abfd)->tdata.any) @@ -652,6 +668,11 @@ extern int _bfd_x86_elf_compare_relocs extern bfd_boolean _bfd_x86_elf_link_check_relocs (bfd *, struct bfd_link_info *); +extern bfd_boolean _bfd_elf_x86_valid_reloc_p + (asection *, struct bfd_link_info *, struct elf_x86_link_hash_table *, + const Elf_Internal_Rela *, struct elf_link_hash_entry *, + Elf_Internal_Sym *, Elf_Internal_Shdr *, bfd_boolean *); + extern bfd_boolean _bfd_x86_elf_size_dynamic_sections (bfd *, struct bfd_link_info *); diff --git a/ld/ChangeLog b/ld/ChangeLog index 1395fb24dc8..6c95224f0ba 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,35 @@ +2020-04-01 H.J. Lu + + 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. + 2020-04-01 Tamar Christina PR ld/16017 diff --git a/ld/testsuite/ld-elf/linux-x86.exp b/ld/testsuite/ld-elf/linux-x86.exp index 63a321b9668..7186dede711 100644 --- a/ld/testsuite/ld-elf/linux-x86.exp +++ b/ld/testsuite/ld-elf/linux-x86.exp @@ -115,3 +115,170 @@ elfedit_test "--disable-x86-feature shstk" x86-feature-1 x86-feature-1c elfedit_test "--disable-x86-feature ibt" x86-feature-1 x86-feature-1d elfedit_test "--enable-x86-feature ibt --enable-x86-feature shstk" \ x86-feature-1 x86-feature-1e + +proc check_pr25749a {testname srcfilea srcfileb cflags ldflags lderror} { + global objcopy + global srcdir + global subdir + + if { [istarget "i?86-*-linux*"] } { + set output_arch "i386:i386" + set output_target "elf32-i386" + } else { + set output_arch "i386:x86-64" + if {[istarget "x86_64-*-linux*-gnux32"]} { + set output_target "elf32-x86-64" + } else { + set output_target "elf64-x86-64" + } + } + + exec cp $srcdir/$subdir/$srcfilea $srcfilea + set pr25749_bin "$objcopy -B $output_arch -I binary -O $output_target $srcfilea tmpdir/pr25749-bin.o" + send_log "$pr25749_bin\n" + set got [remote_exec host "$pr25749_bin"] + if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then { + send_log "$got\n" + fail "Convert $srcfilea to $output_target" + return + } + + if {"$lderror" == ""} { + run_cc_link_tests [list \ + [list \ + "Build $testname ($ldflags $cflags)" \ + "$ldflags tmpdir/pr25749-bin.o" \ + "$cflags" \ + [list $srcfilea $srcfileb]\ + {{readelf {-Wr} pr25749.rd}} \ + "${testname}a" \ + ] \ + ] + run_ld_link_exec_tests [list \ + [list \ + "Run ${testname}a ($ldflags $cflags)" \ + "$ldflags tmpdir/pr25749-bin.o" \ + "" \ + [list $srcfilea $srcfileb]\ + "${testname}a" \ + "pass.out" \ + "$cflags" \ + ] \ + ] + } else { + run_cc_link_tests [list \ + [list \ + "Build $testname ($ldflags $cflags)" \ + "$ldflags tmpdir/pr25749-bin.o" \ + "$cflags" \ + [list $srcfilea $srcfileb]\ + [list [list error_output $lderror]] \ + "$testname" \ + ] \ + ] + } +} + +check_pr25749a "pr25749-1a" "pr25749-1.c" "pr25749-1a.c" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" "" +check_pr25749a "pr25749-1a" "pr25749-1.c" "pr25749-1a.c" "-fPIE" "-pie" "" +check_pr25749a "pr25749-1b" "pr25749-1.c" "pr25749-1b.c" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" "" +if { [istarget "i?86-*-linux*"] } { + check_pr25749a "pr25749-1b" "pr25749-1.c" "pr25749-1b.c" "-fPIE" "-pie" "" +} else { + check_pr25749a "pr25749-1b" "pr25749-1.c" "pr25749-1b.c" "-fPIE" "-pie" "pr25749-1b.err" +} +check_pr25749a "pr25749-1c" "pr25749-1.c" "pr25749-1c.c" "-fPIC" "-shared" "pr25749-1b.err" +check_pr25749a "pr25749-2a" "pr25749-2.c" "pr25749-2a.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" "" +check_pr25749a "pr25749-2a" "pr25749-2.c" "pr25749-2a.s" "-fPIE" "-pie" "" +check_pr25749a "pr25749-2b" "pr25749-2.c" "pr25749-2b.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" "" +check_pr25749a "pr25749-2b" "pr25749-2.c" "pr25749-2b.s" "-fPIE" "-pie" "" +check_pr25749a "pr25754-1a" "pr25754-1a.c" "pr25754-1b.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" "" +check_pr25749a "pr25754-1b" "pr25754-1a.c" "pr25754-1b.s" "-fPIE" "$NOPIE_LDFLAGS" "" +check_pr25749a "pr25754-1c" "pr25754-1a.c" "pr25754-1b.s" "-fPIC" "$NOPIE_LDFLAGS" "" +check_pr25749a "pr25754-1d" "pr25754-1a.c" "pr25754-1b.s" "-fPIC" "-pie" "" +if { [istarget "i?86-*-linux*"] || [istarget "x86_64-*-linux*-gnux32"]} { + check_pr25749a "pr25754-2a" "pr25754-2a.c" "pr25754-2b.s" "-fPIC" "$NOPIE_LDFLAGS" "" + check_pr25749a "pr25754-2b" "pr25754-2a.c" "pr25754-2b.s" "-fPIC" "-pie" "" +} else { + check_pr25749a "pr25754-3a" "pr25754-3a.c" "pr25754-3b.s" "-fPIC" "$NOPIE_LDFLAGS" "" + check_pr25749a "pr25754-3b" "pr25754-3a.c" "pr25754-3b.s" "-fPIC" "-pie" "" +} +if { [istarget "i?86-*-linux*"] } { + check_pr25749a "pr25754-4a" "pr25754-4a.c" "pr25754-4b.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" "" + check_pr25749a "pr25754-4b" "pr25754-4a.c" "pr25754-4b.s" "-fpie" "-pie" "" + check_pr25749a "pr25754-5a" "pr25754-5a.c" "pr25754-5b.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" "" + check_pr25749a "pr25754-5b" "pr25754-5a.c" "pr25754-5b.s" "-fpie" "-pie" "" +} else { + check_pr25749a "pr25754-4a" "pr25754-4a.c" "pr25754-4c.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" "" + check_pr25749a "pr25754-4b" "pr25754-4a.c" "pr25754-4c.s" "-fpie" "-pie" "" + check_pr25749a "pr25754-5a" "pr25754-5a.c" "pr25754-5c.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" "" + check_pr25749a "pr25754-5b" "pr25754-5a.c" "pr25754-5c.s" "-fpie" "-pie" "" + if { ![istarget "x86_64-*-linux*-gnux32"]} { + check_pr25749a "pr25754-6a" "pr25754-6a.c" "pr25754-6b.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" "" + check_pr25749a "pr25754-6b" "pr25754-6a.c" "pr25754-6b.s" "-fpie" "-pie" "" + } +} + +proc check_pr25749b {testname srcfilea srcfileb cflags ldflags dsoldflags} { + global objcopy + global srcdir + global subdir + + if { [istarget "i?86-*-linux*"] } { + set output_arch "i386:i386" + set output_target "elf32-i386" + } else { + set output_arch "i386:x86-64" + if {[istarget "x86_64-*-linux*-gnux32"]} { + set output_target "elf32-x86-64" + } else { + set output_target "elf64-x86-64" + } + } + + exec cp $srcdir/$subdir/$srcfilea $srcfilea + set pr25749_bin "$objcopy -B $output_arch -I binary -O $output_target $srcfilea tmpdir/pr25749-bin.o" + send_log "$pr25749_bin\n" + set got [remote_exec host "$pr25749_bin"] + if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then { + send_log "$got\n" + fail "Convert $srcfilea to $output_target" + return + } + + run_cc_link_tests [list \ + [list \ + "Build lib${testname}.so ($dsoldflags)" \ + "-shared $dsoldflags tmpdir/pr25749-bin.o" \ + "-fPIC" \ + [list $srcfileb] \ + {{readelf {-Wr} pr25749.rd}} \ + "lib${testname}.so" \ + ] \ + ] + run_ld_link_exec_tests [list \ + [list \ + "Run ${testname}b ($ldflags $cflags)" \ + "$ldflags -Wl,--no-as-needed tmpdir/lib${testname}.so" \ + "" \ + [list $srcfilea]\ + "${testname}b" \ + "pass.out" \ + "$cflags" \ + ] \ + ] +} + +check_pr25749b "pr25749-1a" "pr25749-1.c" "pr25749-1a.c" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" "" +check_pr25749b "pr25749-1a" "pr25749-1.c" "pr25749-1a.c" "-fPIE" "-pie" "" +check_pr25749b "pr25749-1a" "pr25749-1.c" "pr25749-1a.c" "-fPIE" "-pie" "-Wl,-Bsymbolic" +check_pr25749b "pr25749-1b" "pr25749-1.c" "pr25749-1b.c" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" "" +check_pr25749b "pr25749-1b" "pr25749-1.c" "pr25749-1b.c" "-fPIE" "-pie" "" +check_pr25749b "pr25749-1b" "pr25749-1.c" "pr25749-1b.c" "-fPIE" "-pie" "-Wl,-Bsymbolic" +check_pr25749b "pr25749-1d" "pr25749-1.c" "pr25749-1d.c" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" "-Wl,-defsym=_begin=0" +check_pr25749b "pr25749-1d" "pr25749-1.c" "pr25749-1d.c" "-fPIE" "-pie" "-Wl,-defsym=_begin=0" +check_pr25749b "pr25749-1d" "pr25749-1.c" "pr25749-1d.c" "-fPIE" "-pie" "-Wl,-Bsymbolic -Wl,-defsym=_begin=0" +check_pr25749b "pr25749-2a" "pr25749-2.c" "pr25749-2a.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" "" +check_pr25749b "pr25749-2a" "pr25749-2.c" "pr25749-2a.s" "-fPIE" "-pie" "" +check_pr25749b "pr25749-2b" "pr25749-2.c" "pr25749-2b.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" "" +check_pr25749b "pr25749-2b" "pr25749-2.c" "pr25749-2b.s" "-fPIE" "-pie" "" diff --git a/ld/testsuite/ld-elf/pr25749-1.c b/ld/testsuite/ld-elf/pr25749-1.c new file mode 100644 index 00000000000..5b37af08c69 --- /dev/null +++ b/ld/testsuite/ld-elf/pr25749-1.c @@ -0,0 +1,12 @@ +#include +#include + +extern intptr_t size (void); + +int +main () +{ + if (size () == 147) + printf ("PASS\n"); + return 0; +} diff --git a/ld/testsuite/ld-elf/pr25749-1a.c b/ld/testsuite/ld-elf/pr25749-1a.c new file mode 100644 index 00000000000..775623b8c9c --- /dev/null +++ b/ld/testsuite/ld-elf/pr25749-1a.c @@ -0,0 +1,11 @@ +#include + +extern void *_binary_pr25749_1_c_start; +extern void *_binary_pr25749_1_c_end; + +intptr_t +size (void) +{ + return ((intptr_t) &_binary_pr25749_1_c_end + - (intptr_t) &_binary_pr25749_1_c_start); +} diff --git a/ld/testsuite/ld-elf/pr25749-1b.c b/ld/testsuite/ld-elf/pr25749-1b.c new file mode 100644 index 00000000000..f02a4087004 --- /dev/null +++ b/ld/testsuite/ld-elf/pr25749-1b.c @@ -0,0 +1,9 @@ +#include + +extern void *_binary_pr25749_1_c_size; + +intptr_t +size (void) +{ + return (intptr_t) &_binary_pr25749_1_c_size; +} diff --git a/ld/testsuite/ld-elf/pr25749-1b.err b/ld/testsuite/ld-elf/pr25749-1b.err new file mode 100644 index 00000000000..bb389172f16 --- /dev/null +++ b/ld/testsuite/ld-elf/pr25749-1b.err @@ -0,0 +1,3 @@ +#... +.*: .* against absolute symbol `_binary_pr25749_1_c_size' .* is disallowed +#pass diff --git a/ld/testsuite/ld-elf/pr25749-1c.c b/ld/testsuite/ld-elf/pr25749-1c.c new file mode 100644 index 00000000000..f2847d7f623 --- /dev/null +++ b/ld/testsuite/ld-elf/pr25749-1c.c @@ -0,0 +1,9 @@ +#include + +extern void *_binary_pr25749_1_c_size __attribute__ ((visibility("hidden"))); + +intptr_t +size (void) +{ + return (intptr_t) &_binary_pr25749_1_c_size; +} diff --git a/ld/testsuite/ld-elf/pr25749-1d.c b/ld/testsuite/ld-elf/pr25749-1d.c new file mode 100644 index 00000000000..33b869deb5d --- /dev/null +++ b/ld/testsuite/ld-elf/pr25749-1d.c @@ -0,0 +1,19 @@ +#include + +extern void *_binary_pr25749_1_c_start; +extern void *_binary_pr25749_1_c_end; + +intptr_t +size (void) +{ + return ((intptr_t) &_binary_pr25749_1_c_end + - (intptr_t) &_binary_pr25749_1_c_start); +} + +extern void *_begin __attribute__ ((visibility("hidden"))); + +intptr_t +size_p (void) +{ + return (intptr_t) &_begin; +} diff --git a/ld/testsuite/ld-elf/pr25749-2.c b/ld/testsuite/ld-elf/pr25749-2.c new file mode 100644 index 00000000000..820bebc1673 --- /dev/null +++ b/ld/testsuite/ld-elf/pr25749-2.c @@ -0,0 +1,12 @@ +#include +#include + +extern intptr_t size; + +int +main () +{ + if (size == 137) + printf ("PASS\n"); + return 0; +} diff --git a/ld/testsuite/ld-elf/pr25749-2a.s b/ld/testsuite/ld-elf/pr25749-2a.s new file mode 100644 index 00000000000..df486fe3294 --- /dev/null +++ b/ld/testsuite/ld-elf/pr25749-2a.s @@ -0,0 +1,6 @@ + .data + .globl size + .type size, %object +size: + .dc.a _binary_pr25749_2_c_size + .size size, .-size diff --git a/ld/testsuite/ld-elf/pr25749-2b.s b/ld/testsuite/ld-elf/pr25749-2b.s new file mode 100644 index 00000000000..ba82c450bc2 --- /dev/null +++ b/ld/testsuite/ld-elf/pr25749-2b.s @@ -0,0 +1,7 @@ + .data + .hidden _binary_pr25749_2_c_size + .globl size + .type size, %object +size: + .dc.a _binary_pr25749_2_c_size + .size size, .-size diff --git a/ld/testsuite/ld-elf/pr25749.rd b/ld/testsuite/ld-elf/pr25749.rd new file mode 100644 index 00000000000..fbc68bf2688 --- /dev/null +++ b/ld/testsuite/ld-elf/pr25749.rd @@ -0,0 +1,4 @@ +#failif +#... +[0-9a-f ]+R_.*_NONE.* +#... diff --git a/ld/testsuite/ld-elf/pr25754-1a.c b/ld/testsuite/ld-elf/pr25754-1a.c new file mode 100644 index 00000000000..2b048ec09bb --- /dev/null +++ b/ld/testsuite/ld-elf/pr25754-1a.c @@ -0,0 +1,19 @@ +#include +#include + +extern uintptr_t bar; + +uintptr_t * +__attribute__ ((noinline, noclone)) +get_bar (void) +{ + return &bar; +} + +int +main () +{ + if ((uintptr_t) get_bar () == 42) + printf ("PASS\n"); + return 0; +} diff --git a/ld/testsuite/ld-elf/pr25754-1b.s b/ld/testsuite/ld-elf/pr25754-1b.s new file mode 100644 index 00000000000..99d585d6b5f --- /dev/null +++ b/ld/testsuite/ld-elf/pr25754-1b.s @@ -0,0 +1,3 @@ + .data + .global bar + bar = 42 diff --git a/ld/testsuite/ld-elf/pr25754-2a.c b/ld/testsuite/ld-elf/pr25754-2a.c new file mode 100644 index 00000000000..7c9f58116e7 --- /dev/null +++ b/ld/testsuite/ld-elf/pr25754-2a.c @@ -0,0 +1,20 @@ +#include +#include + +extern uintptr_t bar; + +uintptr_t * +__attribute__ ((noinline, noclone)) +get_bar (void) +{ + return &bar; +} + +int +main () +{ + if ((uintptr_t) get_bar () == 0xfffffff0U) + printf ("PASS\n"); + return 0; +} +#include diff --git a/ld/testsuite/ld-elf/pr25754-2b.s b/ld/testsuite/ld-elf/pr25754-2b.s new file mode 100644 index 00000000000..9cab99303ee --- /dev/null +++ b/ld/testsuite/ld-elf/pr25754-2b.s @@ -0,0 +1,3 @@ + .data + .global bar + bar = 0xfffffff0 diff --git a/ld/testsuite/ld-elf/pr25754-3a.c b/ld/testsuite/ld-elf/pr25754-3a.c new file mode 100644 index 00000000000..2d4f02abe5a --- /dev/null +++ b/ld/testsuite/ld-elf/pr25754-3a.c @@ -0,0 +1,19 @@ +#include +#include + +extern uintptr_t bar; + +uintptr_t * +__attribute__ ((noinline, noclone)) +get_bar (void) +{ + return &bar; +} + +int +main () +{ + if ((uintptr_t) get_bar () == -0x80000001LL) + printf ("PASS\n"); + return 0; +} diff --git a/ld/testsuite/ld-elf/pr25754-3b.s b/ld/testsuite/ld-elf/pr25754-3b.s new file mode 100644 index 00000000000..aad3e45e0f6 --- /dev/null +++ b/ld/testsuite/ld-elf/pr25754-3b.s @@ -0,0 +1,3 @@ + .data + .global bar + bar = -0x80000001 diff --git a/ld/testsuite/ld-elf/pr25754-4a.c b/ld/testsuite/ld-elf/pr25754-4a.c new file mode 100644 index 00000000000..e2c2f8d54d0 --- /dev/null +++ b/ld/testsuite/ld-elf/pr25754-4a.c @@ -0,0 +1,12 @@ +#include +#include + +extern uintptr_t *get_bar (void); + +int +main () +{ + if ((uintptr_t) get_bar () == 0x7fffffffULL) + printf ("PASS\n"); + return 0; +} diff --git a/ld/testsuite/ld-elf/pr25754-4b.s b/ld/testsuite/ld-elf/pr25754-4b.s new file mode 100644 index 00000000000..448406dff89 --- /dev/null +++ b/ld/testsuite/ld-elf/pr25754-4b.s @@ -0,0 +1,23 @@ + .text + .p2align 4 + .globl get_bar + .type get_bar, @function +get_bar: + .cfi_startproc + call __x86.get_pc_thunk.ax + addl $_GLOBAL_OFFSET_TABLE_, %eax + movl bar@GOT(%eax), %eax + ret + .cfi_endproc + .size get_bar, .-get_bar + bar = 0x7fffffff + .section .text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat + .globl __x86.get_pc_thunk.ax + .hidden __x86.get_pc_thunk.ax + .type __x86.get_pc_thunk.ax, @function +__x86.get_pc_thunk.ax: + .cfi_startproc + movl (%esp), %eax + ret + .cfi_endproc + .section .note.GNU-stack,"",@progbits diff --git a/ld/testsuite/ld-elf/pr25754-4c.s b/ld/testsuite/ld-elf/pr25754-4c.s new file mode 100644 index 00000000000..de450fe081e --- /dev/null +++ b/ld/testsuite/ld-elf/pr25754-4c.s @@ -0,0 +1,12 @@ + .text + .p2align 4 + .globl get_bar + .type get_bar, @function +get_bar: + .cfi_startproc + movq bar@GOTPCREL(%rip), %rax + ret + .cfi_endproc + .size get_bar, .-get_bar + bar = 0x7fffffff + .section .note.GNU-stack,"",@progbits diff --git a/ld/testsuite/ld-elf/pr25754-5a.c b/ld/testsuite/ld-elf/pr25754-5a.c new file mode 100644 index 00000000000..cb791dd56f7 --- /dev/null +++ b/ld/testsuite/ld-elf/pr25754-5a.c @@ -0,0 +1,12 @@ +#include +#include + +extern uintptr_t *get_bar (void); + +int +main () +{ + if ((uintptr_t) get_bar () == 0xfffffff0ULL) + printf ("PASS\n"); + return 0; +} diff --git a/ld/testsuite/ld-elf/pr25754-5b.s b/ld/testsuite/ld-elf/pr25754-5b.s new file mode 100644 index 00000000000..2923c32ee9f --- /dev/null +++ b/ld/testsuite/ld-elf/pr25754-5b.s @@ -0,0 +1,23 @@ + .text + .p2align 4 + .globl get_bar + .type get_bar, @function +get_bar: + .cfi_startproc + call __x86.get_pc_thunk.ax + addl $_GLOBAL_OFFSET_TABLE_, %eax + movl bar@GOT(%eax), %eax + ret + .cfi_endproc + .size get_bar, .-get_bar + bar = 0xfffffff0 + .section .text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat + .globl __x86.get_pc_thunk.ax + .hidden __x86.get_pc_thunk.ax + .type __x86.get_pc_thunk.ax, @function +__x86.get_pc_thunk.ax: + .cfi_startproc + movl (%esp), %eax + ret + .cfi_endproc + .section .note.GNU-stack,"",@progbits diff --git a/ld/testsuite/ld-elf/pr25754-5c.s b/ld/testsuite/ld-elf/pr25754-5c.s new file mode 100644 index 00000000000..0195f19165d --- /dev/null +++ b/ld/testsuite/ld-elf/pr25754-5c.s @@ -0,0 +1,12 @@ + .text + .p2align 4 + .globl get_bar + .type get_bar, @function +get_bar: + .cfi_startproc + movq bar@GOTPCREL(%rip), %rax + ret + .cfi_endproc + .size get_bar, .-get_bar + bar = 0xfffffff0 + .section .note.GNU-stack,"",@progbits diff --git a/ld/testsuite/ld-elf/pr25754-6a.c b/ld/testsuite/ld-elf/pr25754-6a.c new file mode 100644 index 00000000000..59633a3b4dd --- /dev/null +++ b/ld/testsuite/ld-elf/pr25754-6a.c @@ -0,0 +1,12 @@ +#include +#include + +extern uintptr_t *get_bar (void); + +int +main () +{ + if ((uintptr_t) get_bar () == 0xffffffffffffff0ULL) + printf ("PASS\n"); + return 0; +} diff --git a/ld/testsuite/ld-elf/pr25754-6b.s b/ld/testsuite/ld-elf/pr25754-6b.s new file mode 100644 index 00000000000..2532480e5f0 --- /dev/null +++ b/ld/testsuite/ld-elf/pr25754-6b.s @@ -0,0 +1,12 @@ + .text + .p2align 4 + .globl get_bar + .type get_bar, @function +get_bar: + .cfi_startproc + movq bar@GOTPCREL(%rip), %rax + ret + .cfi_endproc + .size get_bar, .-get_bar + bar = 0xffffffffffffff0 + .section .note.GNU-stack,"",@progbits diff --git a/ld/testsuite/ld-x86-64/pr19609-6a.d b/ld/testsuite/ld-x86-64/pr19609-6a.d index 3c011d9b057..b340287f48b 100644 --- a/ld/testsuite/ld-x86-64/pr19609-6a.d +++ b/ld/testsuite/ld-x86-64/pr19609-6a.d @@ -1,4 +1,13 @@ #source: pr19609-6.s #as: --64 -mrelax-relocations=yes #ld: -melf_x86_64 --defsym foobar=0x80000000 -#error: failed to convert GOTPCREL relocation; relink with --no-relax +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .text: + +[a-f0-9]+ <_start>: +[ ]*[a-f0-9]+: 48 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <.got> +#pass -- 2.30.2