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.
This commit is contained in:
H.J. Lu 2020-04-01 14:31:47 -07:00
parent 6b4a335bf7
commit 382aae0632
32 changed files with 746 additions and 32 deletions

View File

@ -1,3 +1,41 @@
2020-04-01 H.J. Lu <hongjiu.lu@intel.com>
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 <tamar.christina@arm.com> 2020-04-01 Tamar Christina <tamar.christina@arm.com>
PR ld/16017 PR ld/16017

View File

@ -1226,6 +1226,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
bfd_vma nop_offset; bfd_vma nop_offset;
bfd_boolean is_pic; bfd_boolean is_pic;
bfd_boolean to_reloc_32; bfd_boolean to_reloc_32;
bfd_boolean abs_symbol;
unsigned int r_type; unsigned int r_type;
unsigned int r_symndx; unsigned int r_symndx;
bfd_vma roff = irel->r_offset; 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); modrm = bfd_get_8 (abfd, contents + roff - 1);
baseless = (modrm & 0xc7) == 0x5; 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) if (baseless && is_pic)
{ {
/* For PIC, disallow R_386_GOT32X without a base register /* 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; const char *name;
if (h == NULL) if (h == NULL)
{ name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd,
r_symndx);
name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
}
else else
name = h->root.root.string; name = h->root.root.string;
@ -1294,9 +1306,6 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
goto convert_load; 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 /* Undefined weak symbol is only bound locally in executable
and its reference is resolved as 0. */ and its reference is resolved as 0. */
if (h->root.type == bfd_link_hash_undefweak 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: convert_load:
if (opcode == 0x8b) if (opcode == 0x8b)
{ {
if (abs_symbol && local_ref)
to_reloc_32 = TRUE;
if (to_reloc_32) if (to_reloc_32)
{ {
/* Convert "mov foo@GOT[(%reg1)], %reg2" to /* Convert "mov foo@GOT[(%reg1)], %reg2" to
@ -1519,6 +1531,7 @@ elf_i386_check_relocs (bfd *abfd,
Elf_Internal_Sym *isym; Elf_Internal_Sym *isym;
const char *name; const char *name;
bfd_boolean size_reloc; bfd_boolean size_reloc;
bfd_boolean no_dynreloc;
r_symndx = ELF32_R_SYM (rel->r_info); r_symndx = ELF32_R_SYM (rel->r_info);
r_type = ELF32_R_TYPE (rel->r_info); r_type = ELF32_R_TYPE (rel->r_info);
@ -1587,6 +1600,10 @@ elf_i386_check_relocs (bfd *abfd,
goto error_return; 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, if (! elf_i386_tls_transition (info, abfd, sec, contents,
symtab_hdr, sym_hashes, symtab_hdr, sym_hashes,
&r_type, GOT_UNKNOWN, &r_type, GOT_UNKNOWN,
@ -1827,8 +1844,9 @@ elf_i386_check_relocs (bfd *abfd,
size_reloc = FALSE; size_reloc = FALSE;
do_size: do_size:
if (NEED_DYNAMIC_RELOCATION_P (info, FALSE, h, sec, r_type, if (!no_dynreloc
R_386_32)) && NEED_DYNAMIC_RELOCATION_P (info, FALSE, h, sec, r_type,
R_386_32))
{ {
struct elf_dyn_relocs *p; struct elf_dyn_relocs *p;
struct elf_dyn_relocs **head; struct elf_dyn_relocs **head;
@ -2704,7 +2722,7 @@ elf_i386_relocate_section (bfd *output_bfd,
|| is_vxworks_tls) || is_vxworks_tls)
break; break;
if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, sec,
FALSE, resolved_to_zero, FALSE, resolved_to_zero,
(r_type == R_386_PC32))) (r_type == R_386_PC32)))
{ {

View File

@ -196,9 +196,6 @@ static reloc_howto_type x86_64_elf_howto_table[] =
FALSE) 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) \ #define X86_PCREL_TYPE_P(TYPE) \
( ((TYPE) == R_X86_64_PC8) \ ( ((TYPE) == R_X86_64_PC8) \
|| ((TYPE) == R_X86_64_PC16) \ || ((TYPE) == R_X86_64_PC16) \
@ -1509,6 +1506,8 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
bfd_boolean no_overflow; bfd_boolean no_overflow;
bfd_boolean relocx; bfd_boolean relocx;
bfd_boolean to_reloc_pc32; bfd_boolean to_reloc_pc32;
bfd_boolean abs_symbol;
bfd_boolean local_ref;
asection *tsec; asection *tsec;
bfd_signed_vma raddend; bfd_signed_vma raddend;
unsigned int opcode; 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_type = *r_type_p;
unsigned int r_symndx; unsigned int r_symndx;
bfd_vma roff = irel->r_offset; bfd_vma roff = irel->r_offset;
bfd_vma abs_relocation;
if (roff < (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2)) if (roff < (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2))
return TRUE; return TRUE;
@ -1559,6 +1559,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
|| no_overflow || no_overflow
|| is_pic); || is_pic);
abs_symbol = FALSE;
abs_relocation = 0;
/* Get the symbol referred to by the reloc. */ /* Get the symbol referred to by the reloc. */
if (h == NULL) if (h == NULL)
{ {
@ -1569,8 +1572,13 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
if (isym->st_shndx == SHN_UNDEF) if (isym->st_shndx == SHN_UNDEF)
return TRUE; return TRUE;
local_ref = TRUE;
if (isym->st_shndx == SHN_ABS) 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) else if (isym->st_shndx == SHN_COMMON)
tsec = bfd_com_section_ptr; tsec = bfd_com_section_ptr;
else if (isym->st_shndx == SHN_X86_64_LCOMMON) 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. GOTPCRELX relocations since we need to modify REX byte.
It is OK convert mov with R_X86_64_GOTPCREL to It is OK convert mov with R_X86_64_GOTPCREL to
R_X86_64_PC32. */ R_X86_64_PC32. */
bfd_boolean local_ref;
struct elf_x86_link_hash_entry *eh = elf_x86_hash_entry (h); 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. */ /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P. */
local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h); local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h);
if ((relocx || opcode == 0x8b) if ((relocx || opcode == 0x8b)
@ -1728,6 +1738,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
if (opcode == 0x8b) if (opcode == 0x8b)
{ {
if (abs_symbol && local_ref)
to_reloc_pc32 = FALSE;
if (to_reloc_pc32) if (to_reloc_pc32)
{ {
/* Convert "mov foo@GOTPCREL(%rip), %reg" to /* 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; r_type = (rex & REX_W) != 0 ? R_X86_64_32S : R_X86_64_32;
rewrite_modrm_rex: 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); bfd_put_8 (abfd, modrm, contents + roff - 1);
if (rex) if (rex)
@ -1879,6 +1907,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
const char *name; const char *name;
bfd_boolean size_reloc; bfd_boolean size_reloc;
bfd_boolean converted_reloc; bfd_boolean converted_reloc;
bfd_boolean no_dynreloc;
r_symndx = htab->r_sym (rel->r_info); r_symndx = htab->r_sym (rel->r_info);
r_type = ELF32_R_TYPE (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; 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, if (! elf_x86_64_tls_transition (info, abfd, sec, contents,
symtab_hdr, sym_hashes, symtab_hdr, sym_hashes,
&r_type, GOT_UNKNOWN, &r_type, GOT_UNKNOWN,
@ -2029,12 +2062,26 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
switch (r_type) switch (r_type)
{ {
default: tls_type = GOT_NORMAL; break; default:
case R_X86_64_TLSGD: tls_type = GOT_TLS_GD; break; tls_type = GOT_NORMAL;
case R_X86_64_GOTTPOFF: tls_type = GOT_TLS_IE; break; 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_GOTPC32_TLSDESC:
case R_X86_64_TLSDESC_CALL: case R_X86_64_TLSDESC_CALL:
tls_type = GOT_TLS_GDESC; break; tls_type = GOT_TLS_GDESC;
break;
} }
if (h != NULL) if (h != NULL)
@ -2245,8 +2292,9 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
size_reloc = FALSE; size_reloc = FALSE;
do_size: do_size:
if (NEED_DYNAMIC_RELOCATION_P (info, TRUE, h, sec, r_type, if (!no_dynreloc
htab->pointer_r_type)) && NEED_DYNAMIC_RELOCATION_P (info, TRUE, h, sec, r_type,
htab->pointer_r_type))
{ {
struct elf_dyn_relocs *p; struct elf_dyn_relocs *p;
struct elf_dyn_relocs **head; struct elf_dyn_relocs **head;
@ -2880,7 +2928,14 @@ elf_x86_64_relocate_section (bfd *output_bfd,
base_got->contents + off); base_got->contents + off);
local_got_offsets[r_symndx] |= 1; 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; relative_reloc = TRUE;
} }
} }
@ -3175,7 +3230,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
&& (X86_PCREL_TYPE_P (r_type) && (X86_PCREL_TYPE_P (r_type)
|| X86_SIZE_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, need_copy_reloc_in_pie,
resolved_to_zero, FALSE)) resolved_to_zero, FALSE))
{ {

View File

@ -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 (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 need two), R_386_TLS_GD and R_X86_64_TLSGD need one if local
symbol and two if global. No dynamic relocation against 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) if (tls_type == GOT_TLS_IE_BOTH)
htab->elf.srelgot->size += 2 * htab->sizeof_reloc; htab->elf.srelgot->size += 2 * htab->sizeof_reloc;
else if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1) 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 && ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
&& !resolved_to_zero) && !resolved_to_zero)
|| h->root.type != bfd_link_hash_undefweak) || 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))) || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
htab->elf.srelgot->size += htab->sizeof_reloc; htab->elf.srelgot->size += htab->sizeof_reloc;
if (GOT_TLS_GDESC_P (tls_type)) 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); 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. */ /* Set the sizes of the dynamic sections. */
bfd_boolean bfd_boolean
@ -1065,7 +1162,7 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd,
|| *local_tls_type == GOT_TLS_IE_BOTH) || *local_tls_type == GOT_TLS_IE_BOTH)
s->size += htab->got_entry_size; 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) || GOT_TLS_GD_ANY_P (*local_tls_type)
|| (*local_tls_type & GOT_TLS_IE)) || (*local_tls_type & GOT_TLS_IE))
{ {

View File

@ -119,11 +119,15 @@
Copy dynamic function pointer relocations. Don't generate dynamic Copy dynamic function pointer relocations. Don't generate dynamic
relocations against resolved undefined weak symbols in PIE, except relocations against resolved undefined weak symbols in PIE, except
when PC32_RELOC is TRUE. Undefined weak symbol is bound locally when PC32_RELOC is TRUE. Undefined weak symbol is bound locally
when PIC is false. */ when PIC is false. Don't generate dynamic relocations against
#define GENERATE_DYNAMIC_RELOCATION_P(INFO, EH, R_TYPE, \ non-preemptible absolute symbol. */
#define GENERATE_DYNAMIC_RELOCATION_P(INFO, EH, R_TYPE, SEC, \
NEED_COPY_RELOC_IN_PIE, \ NEED_COPY_RELOC_IN_PIE, \
RESOLVED_TO_ZERO, PC32_RELOC) \ RESOLVED_TO_ZERO, PC32_RELOC) \
((bfd_link_pic (INFO) \ ((bfd_link_pic (INFO) \
&& !(bfd_is_abs_section (SEC) \
&& ((EH) == NULL \
|| SYMBOL_REFERENCES_LOCAL (INFO, &(EH)->elf))) \
&& !(NEED_COPY_RELOC_IN_PIE) \ && !(NEED_COPY_RELOC_IN_PIE) \
&& ((EH) == NULL \ && ((EH) == NULL \
|| ((ELF_ST_VISIBILITY ((EH)->elf.other) == STV_DEFAULT \ || ((ELF_ST_VISIBILITY ((EH)->elf.other) == STV_DEFAULT \
@ -170,17 +174,25 @@
|| ((struct elf_x86_link_hash_entry *) (H))->linker_def \ || ((struct elf_x86_link_hash_entry *) (H))->linker_def \
|| ELF_COMMON_DEF_P (H)) || 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 /* TRUE if relative relocation should be generated. GOT reference to
global symbol in PIC will lead to dynamic symbol. It becomes a global symbol in PIC will lead to dynamic symbol. It becomes a
problem when "time" or "times" is defined as a variable in an problem when "time" or "times" is defined as a variable in an
executable, clashing with functions of the same name in libc. If a 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 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) \ #define GENERATE_RELATIVE_RELOC_P(INFO, H) \
((H)->dynindx == -1 \ ((H)->dynindx == -1 \
&& !(H)->forced_local \ && !(H)->forced_local \
&& (H)->root.type != bfd_link_hash_undefweak \ && (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. */ /* TRUE if this is a pointer reference to a local IFUNC. */
#define POINTER_LOCAL_IFUNC_P(INFO, H) \ #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_NEG 6
#define GOT_TLS_IE_BOTH 7 #define GOT_TLS_IE_BOTH 7
#define GOT_TLS_GDESC 8 #define GOT_TLS_GDESC 8
#define GOT_ABS 9
#define GOT_TLS_GD_BOTH_P(type) \ #define GOT_TLS_GD_BOTH_P(type) \
((type) == (GOT_TLS_GD | GOT_TLS_GDESC)) ((type) == (GOT_TLS_GD | GOT_TLS_GDESC))
#define GOT_TLS_GD_P(type) \ #define GOT_TLS_GD_P(type) \
@ -601,6 +614,9 @@ struct elf_x86_plt
long count; 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) \ #define elf_x86_tdata(abfd) \
((struct elf_x86_obj_tdata *) (abfd)->tdata.any) ((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 extern bfd_boolean _bfd_x86_elf_link_check_relocs
(bfd *, struct bfd_link_info *); (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 extern bfd_boolean _bfd_x86_elf_size_dynamic_sections
(bfd *, struct bfd_link_info *); (bfd *, struct bfd_link_info *);

View File

@ -1,3 +1,35 @@
2020-04-01 H.J. Lu <hongjiu.lu@intel.com>
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 <tamar.christina@arm.com> 2020-04-01 Tamar Christina <tamar.christina@arm.com>
PR ld/16017 PR ld/16017

View File

@ -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 "--disable-x86-feature ibt" x86-feature-1 x86-feature-1d
elfedit_test "--enable-x86-feature ibt --enable-x86-feature shstk" \ elfedit_test "--enable-x86-feature ibt --enable-x86-feature shstk" \
x86-feature-1 x86-feature-1e 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" ""

View File

@ -0,0 +1,12 @@
#include <stdio.h>
#include <bfd_stdint.h>
extern intptr_t size (void);
int
main ()
{
if (size () == 147)
printf ("PASS\n");
return 0;
}

View File

@ -0,0 +1,11 @@
#include <bfd_stdint.h>
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);
}

View File

@ -0,0 +1,9 @@
#include <bfd_stdint.h>
extern void *_binary_pr25749_1_c_size;
intptr_t
size (void)
{
return (intptr_t) &_binary_pr25749_1_c_size;
}

View File

@ -0,0 +1,3 @@
#...
.*: .* against absolute symbol `_binary_pr25749_1_c_size' .* is disallowed
#pass

View File

@ -0,0 +1,9 @@
#include <bfd_stdint.h>
extern void *_binary_pr25749_1_c_size __attribute__ ((visibility("hidden")));
intptr_t
size (void)
{
return (intptr_t) &_binary_pr25749_1_c_size;
}

View File

@ -0,0 +1,19 @@
#include <bfd_stdint.h>
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;
}

View File

@ -0,0 +1,12 @@
#include <stdio.h>
#include <bfd_stdint.h>
extern intptr_t size;
int
main ()
{
if (size == 137)
printf ("PASS\n");
return 0;
}

View File

@ -0,0 +1,6 @@
.data
.globl size
.type size, %object
size:
.dc.a _binary_pr25749_2_c_size
.size size, .-size

View File

@ -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

View File

@ -0,0 +1,4 @@
#failif
#...
[0-9a-f ]+R_.*_NONE.*
#...

View File

@ -0,0 +1,19 @@
#include <stdio.h>
#include <bfd_stdint.h>
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;
}

View File

@ -0,0 +1,3 @@
.data
.global bar
bar = 42

View File

@ -0,0 +1,20 @@
#include <stdio.h>
#include <bfd_stdint.h>
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 <stdio.h>

View File

@ -0,0 +1,3 @@
.data
.global bar
bar = 0xfffffff0

View File

@ -0,0 +1,19 @@
#include <stdio.h>
#include <bfd_stdint.h>
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;
}

View File

@ -0,0 +1,3 @@
.data
.global bar
bar = -0x80000001

View File

@ -0,0 +1,12 @@
#include <stdio.h>
#include <bfd_stdint.h>
extern uintptr_t *get_bar (void);
int
main ()
{
if ((uintptr_t) get_bar () == 0x7fffffffULL)
printf ("PASS\n");
return 0;
}

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,12 @@
#include <stdio.h>
#include <bfd_stdint.h>
extern uintptr_t *get_bar (void);
int
main ()
{
if ((uintptr_t) get_bar () == 0xfffffff0ULL)
printf ("PASS\n");
return 0;
}

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,12 @@
#include <stdio.h>
#include <bfd_stdint.h>
extern uintptr_t *get_bar (void);
int
main ()
{
if ((uintptr_t) get_bar () == 0xffffffffffffff0ULL)
printf ("PASS\n");
return 0;
}

View File

@ -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

View File

@ -1,4 +1,13 @@
#source: pr19609-6.s #source: pr19609-6.s
#as: --64 -mrelax-relocations=yes #as: --64 -mrelax-relocations=yes
#ld: -melf_x86_64 --defsym foobar=0x80000000 #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