Eliminate the generation of incorrect dynamic copy relocations on AArch64.

Relates: #1452170
This commit is contained in:
Nick Clifton 2017-06-08 09:34:56 +01:00
parent da381ca746
commit 54f319436b
3 changed files with 331 additions and 1 deletions

View File

@ -0,0 +1,139 @@
diff -rupN binutils.orig/bfd/elfnn-aarch64.c binutils-2.28/bfd/elfnn-aarch64.c
--- binutils.orig/bfd/elfnn-aarch64.c 2017-06-08 09:11:46.364977859 +0100
+++ binutils-2.28/bfd/elfnn-aarch64.c 2017-06-08 09:15:46.901961364 +0100
@@ -246,7 +246,7 @@
|| (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC \
|| (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_OFF_G1)
-#define ELIMINATE_COPY_RELOCS 0
+#define ELIMINATE_COPY_RELOCS 1
/* Return size of a relocation entry. HTAB is the bfd's
elf_aarch64_link_hash_entry. */
@@ -5152,12 +5152,25 @@ elfNN_aarch64_final_link_relocate (reloc
/* When generating a shared object or relocatable executable, these
relocations are copied into the output file to be resolved at
run time. */
- if (((bfd_link_pic (info) == TRUE)
- || globals->root.is_relocatable_executable)
- && (input_section->flags & SEC_ALLOC)
- && (h == NULL
- || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
- || h->root.type != bfd_link_hash_undefweak))
+ if (((bfd_link_pic (info)
+ || globals->root.is_relocatable_executable)
+ && (input_section->flags & SEC_ALLOC)
+ && (h == NULL
+ || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ || h->root.type != bfd_link_hash_undefweak))
+ /* Or we are creating an executable, we may need to keep relocations
+ for symbols satisfied by a dynamic library if we manage to avoid
+ copy relocs for the symbol. */
+ || (ELIMINATE_COPY_RELOCS
+ && !bfd_link_pic (info)
+ && h != NULL
+ && (input_section->flags & SEC_ALLOC)
+ && h->dynindx != -1
+ && !h->non_got_ref
+ && ((h->def_dynamic
+ && !h->def_regular)
+ || h->root.type == bfd_link_hash_undefweak
+ || h->root.type == bfd_link_hash_undefined)))
{
Elf_Internal_Rela outrel;
bfd_byte *loc;
@@ -6822,6 +6835,25 @@ elfNN_aarch64_gc_sweep_hook (bfd *abfd,
return TRUE;
}
+/* Return true if we have dynamic relocs against EH or any of its weak
+ aliases, that apply to read-only sections. */
+
+static bfd_boolean
+alias_readonly_dynrelocs (struct elf_aarch64_link_hash_entry *eh)
+{
+ struct elf_dyn_relocs *p;
+ asection *s;
+
+ for (p = eh->dyn_relocs; p != NULL; p = p->next)
+ {
+ s = p->sec->output_section;
+ if (s != NULL && (s->flags & SEC_READONLY) != 0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
/* Adjust a symbol defined by a dynamic object and referenced by a
regular object. The current definition is in some section of the
dynamic object, but we're not including those sections. We have to
@@ -6895,6 +6927,19 @@ elfNN_aarch64_adjust_dynamic_symbol (str
return TRUE;
}
+ if (ELIMINATE_COPY_RELOCS)
+ {
+ struct elf_aarch64_link_hash_entry *eh;
+ /* If we didn't find any dynamic relocs in read-only sections, then
+ we'll be keeping the dynamic relocs and avoiding the copy reloc. */
+ eh = (struct elf_aarch64_link_hash_entry *) h;
+ if (eh->dyn_relocs && !alias_readonly_dynrelocs (eh))
+ {
+ h->non_got_ref = 0;
+ return TRUE;
+ }
+ }
+
/* We must allocate the symbol in our .dynbss section, which will
become part of the .bss section of the executable. There will be
an entry for this symbol in the .dynsym section. The dynamic
@@ -7167,7 +7212,16 @@ elfNN_aarch64_check_relocs (bfd *abfd, s
/* No need to do anything if we're not creating a shared
object. */
- if (! bfd_link_pic (info))
+ if (!(bfd_link_pic (info)
+ /* If on the other hand, we are creating an executable, we
+ may need to keep relocations for symbols satisfied by a
+ dynamic library if we manage to avoid copy relocs for the
+ symbol. */
+ || (ELIMINATE_COPY_RELOCS
+ && !bfd_link_pic (info)
+ && h != NULL
+ && (h->root.type == bfd_link_hash_defweak
+ || !h->def_regular))))
break;
{
diff -rupN binutils.orig/ld/testsuite/ld-aarch64/aarch64-elf.exp binutils-2.28/ld/testsuite/ld-aarch64/aarch64-elf.exp
--- binutils.orig/ld/testsuite/ld-aarch64/aarch64-elf.exp 2017-06-08 09:11:54.845871503 +0100
+++ binutils-2.28/ld/testsuite/ld-aarch64/aarch64-elf.exp 2017-06-08 09:16:34.984358379 +0100
@@ -323,6 +323,8 @@ set aarch64elflinktests {
{} "copy-reloc-so.so"}
{"ld-aarch64/exe with copy relocation" "-e0 tmpdir/copy-reloc-so.so" "" ""
{copy-reloc-exe.s} {{objdump -R copy-reloc.d}} "copy-reloc"}
+ {"ld-aarch64/exe with copy relocation elimination" "-e0 tmpdir/copy-reloc-so.so" "" ""
+ {copy-reloc-exe-eliminate.s} {{objdump -R copy-reloc-eliminate.d}} "copy-reloc-elimination"}
}
run_ld_link_tests $aarch64elflinktests
diff -rupN binutils.orig/ld/testsuite/ld-aarch64/copy-reloc-eliminate.d binutils-2.28/ld/testsuite/ld-aarch64/copy-reloc-eliminate.d
--- binutils.orig/ld/testsuite/ld-aarch64/copy-reloc-eliminate.d 1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.28/ld/testsuite/ld-aarch64/copy-reloc-eliminate.d 2017-06-08 09:12:10.191679056 +0100
@@ -0,0 +1,4 @@
+.*
+DYNAMIC RELOCATION RECORDS
+OFFSET.*TYPE.*VALUE.*
+.*R_AARCH64_ABS64.*global_a
diff -rupN binutils.orig/ld/testsuite/ld-aarch64/copy-reloc-exe-eliminate.s binutils-2.28/ld/testsuite/ld-aarch64/copy-reloc-exe-eliminate.s
--- binutils.orig/ld/testsuite/ld-aarch64/copy-reloc-exe-eliminate.s 1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.28/ld/testsuite/ld-aarch64/copy-reloc-exe-eliminate.s 2017-06-08 09:12:10.191679056 +0100
@@ -0,0 +1,7 @@
+ .global p
+ .section .data.rel.ro,"aw",%progbits
+ .align 3
+ .type p, %object
+ .size p, 8
+p:
+ .xword global_a

View File

@ -1462,3 +1462,187 @@ diff -rup binutils.orig/include/elf/common.h binutils-2.28/include/elf/common.h
+ .popsection
+
+
diff -rup binutils.orig/binutils/readelf.c binutils-2.28/binutils/readelf.c
--- binutils.orig/binutils/readelf.c 2017-05-15 17:12:12.760814593 +0100
+++ binutils-2.28/binutils/readelf.c 2017-05-15 17:26:46.142293641 +0100
@@ -4130,7 +4130,18 @@ get_section_type_name (unsigned int sh_t
if (elf_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
result = get_solaris_section_type (sh_type);
else
- result = NULL;
+ {
+ switch (sh_type)
+ {
+ case SHT_GNU_INCREMENTAL_INPUTS: result = "GNU_INCREMENTAL_INPUTS"; break;
+ case SHT_GNU_ATTRIBUTES: result = "GNU_ATTRIBUTES"; break;
+ case SHT_GNU_HASH: result = "GNU_HASH"; break;
+ case SHT_GNU_LIBLIST: result = "GNU_LIBLIST"; break;
+ default:
+ result = NULL;
+ break;
+ }
+ }
break;
}
@@ -15928,8 +15939,8 @@ print_gnu_note (Elf_Internal_Note *pnote
printf (_(" Hardware Capabilities: "));
if (pnote->descsz < 8)
{
- printf (_("<corrupt GNU_HWCAP>\n"));
- break;
+ error (_("<corrupt GNU_HWCAP>\n"));
+ return 0;
}
num_entries = byte_get ((unsigned char *) pnote->descdata, 4);
mask = byte_get ((unsigned char *) pnote->descdata + 4, 4);
@@ -16347,7 +16358,8 @@ print_symbol_for_build_attribute (FILE *
Elf_Internal_Sym * saved_sym = NULL;
Elf_Internal_Sym * sym;
- if (saved_file == NULL || file != saved_file)
+ if (section_headers != NULL
+ && (saved_file == NULL || file != saved_file))
{
Elf_Internal_Shdr * symsec;
@@ -16497,9 +16509,12 @@ print_gnu_build_attribute_description (E
static bfd_boolean
print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
{
+ static const char string_expected [2] = { GNU_BUILD_ATTRIBUTE_TYPE_STRING, 0 };
+ static const char number_expected [2] = { GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC, 0 };
+ static const char bool_expected [3] = { GNU_BUILD_ATTRIBUTE_TYPE_BOOL_TRUE, GNU_BUILD_ATTRIBUTE_TYPE_BOOL_FALSE, 0 };
char name_type;
char name_attribute;
- char * expected_types;
+ const char * expected_types;
const char * name = pnote->namedata;
const char * text;
int left;
@@ -16507,7 +16522,7 @@ print_gnu_build_attribute_name (Elf_Inte
if (name == NULL || pnote->namesz < 2)
{
error (_("corrupt name field in GNU build attribute note: size = %ld\n"), pnote->namesz);
- print_symbol (-20, _(" <corrupt name field>"));
+ print_symbol (-20, _(" <corrupt name>"));
return FALSE;
}
@@ -16533,7 +16548,7 @@ print_gnu_build_attribute_name (Elf_Inte
{
case GNU_BUILD_ATTRIBUTE_VERSION:
text = _("<version>");
- expected_types = "$";
+ expected_types = string_expected;
++ name;
break;
case GNU_BUILD_ATTRIBUTE_STACK_PROT:
@@ -16543,17 +16558,17 @@ print_gnu_build_attribute_name (Elf_Inte
break;
case GNU_BUILD_ATTRIBUTE_RELRO:
text = _("<relro>");
- expected_types = "!+";
+ expected_types = bool_expected;
++ name;
break;
case GNU_BUILD_ATTRIBUTE_STACK_SIZE:
text = _("<stack size>");
- expected_types = "*";
+ expected_types = number_expected;
++ name;
break;
case GNU_BUILD_ATTRIBUTE_TOOL:
text = _("<tool>");
- expected_types = "$";
+ expected_types = string_expected;
++ name;
break;
case GNU_BUILD_ATTRIBUTE_ABI:
@@ -16563,12 +16578,12 @@ print_gnu_build_attribute_name (Elf_Inte
break;
case GNU_BUILD_ATTRIBUTE_PIC:
text = _("<PIC>");
- expected_types = "*";
+ expected_types = number_expected;
++ name;
break;
case GNU_BUILD_ATTRIBUTE_SHORT_ENUM:
text = _("<short enum>");
- expected_types = "!+";
+ expected_types = bool_expected;
++ name;
break;
@@ -16585,9 +16600,11 @@ print_gnu_build_attribute_name (Elf_Inte
}
else
{
- error (_("unexpected character in name field\n"));
- print_symbol (- left, _("<unknown attribute>"));
- return 0;
+ static char tmpbuf [128];
+ error (_("unrecognised byte in name field: %d\n"), * name);
+ sprintf (tmpbuf, _("<unknown:_%d>"), * name);
+ text = tmpbuf;
+ name ++;
}
expected_types = "*$!+";
break;
@@ -16617,11 +16634,29 @@ print_gnu_build_attribute_name (Elf_Inte
{
case GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC:
{
- unsigned int bytes = pnote->namesz - (name - pnote->namedata);
- unsigned long val = 0;
+ unsigned int bytes;
+ unsigned long long val = 0;
unsigned int shift = 0;
char * decoded = NULL;
+ bytes = pnote->namesz - (name - pnote->namedata);
+ if (bytes > 0)
+ /* The -1 is because the name field is always 0 terminated, and we
+ want to be able to ensure that the shift in the while loop below
+ will not overflow. */
+ -- bytes;
+
+ if (bytes > sizeof (val))
+ {
+ fprintf (stderr, "namesz %lx name %p namedata %p\n",
+ pnote->namesz, name, pnote->namedata);
+ error (_("corrupt numeric name field: too many bytes in the value: %x\n"),
+ bytes);
+ bytes = sizeof (val);
+ }
+ /* We do not bother to warn if bytes == 0 as this can
+ happen with some early versions of the gcc plugin. */
+
while (bytes --)
{
unsigned long byte = (* name ++) & 0xff;
@@ -16660,13 +16695,21 @@ print_gnu_build_attribute_name (Elf_Inte
}
if (decoded != NULL)
- print_symbol (-left, decoded);
+ {
+ print_symbol (-left, decoded);
+ left = 0;
+ }
+ else if (val == 0)
+ {
+ printf ("0x0");
+ left -= 3;
+ }
else
{
if (do_wide)
- left -= printf ("0x%lx", val);
+ left -= printf ("0x%llx", val);
else
- left -= printf ("0x%-.*lx", left, val);
+ left -= printf ("0x%-.*llx", left, val);
}
}
break;

View File

@ -43,7 +43,7 @@
Summary: A GNU collection of binary utilities
Name: %{?cross}binutils%{?_with_debug:-debug}
Version: 2.28
Release: 6%{?dist}
Release: 7%{?dist}
License: GPLv3+
Group: Development/Tools
URL: http://sources.redhat.com/binutils
@ -89,6 +89,8 @@ Patch18: binutils-2.28-gas-comp_dir.patch
Patch19: binutils-2.28-ppc-dynamic-relocs.patch
# Have readelf skip checks of the dynamic section when its type is SHT_NOBITS.
Patch20: binutils-2.28-dynamic-section-warning.patch
# Fix incorrect generation of copy relocs on AArch64.
Patch21: binutils-2.28-aarch64-copy-relocs.patch
Provides: bundled(libiberty)
@ -230,6 +232,7 @@ using libelf instead of BFD.
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
# We cannot run autotools as there is an exact requirement of autoconf-2.59.
@ -596,6 +599,10 @@ exit 0
%endif # %{isnative}
%changelog
* Thu Jun 08 2017 Nick Clifton <nickc@redhat.com> 2.28-7
- Eliminate the generation of incorrect dynamic copy relocations on AArch64.
(#1452170)
* Mon May 15 2017 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.28-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_27_Mass_Rebuild