aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2020-04-01 14:31:47 -0700
committerH.J. Lu <hjl.tools@gmail.com>2020-04-01 14:31:47 -0700
commit382aae06322799a25ea52fe61b243cbca4db8d66 (patch)
treebc60e7b2d1d5acc2622c393933788146f8b1c291 /bfd
parent6b4a335bf7b7996e904e895b3fdc35443c40cfca (diff)
downloadgdb-382aae06322799a25ea52fe61b243cbca4db8d66.zip
gdb-382aae06322799a25ea52fe61b243cbca4db8d66.tar.gz
gdb-382aae06322799a25ea52fe61b243cbca4db8d66.tar.bz2
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')
-rw-r--r--bfd/ChangeLog38
-rw-r--r--bfd/elf32-i386.c40
-rw-r--r--bfd/elf64-x86-64.c81
-rw-r--r--bfd/elfxx-x86.c103
-rw-r--r--bfd/elfxx-x86.h29
5 files changed, 260 insertions, 31 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index bea9526..2ed1046 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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>
PR ld/16017
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index eb7e1f8..51c3e86 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 90e2702..4c9ad78 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 108e04a..0fc75fb 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 bef17dc..6e91f24 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 *);