summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejas Belagod <tejas.belagod@arm.com>2014-11-25 14:51:24 +0800
committerAndrew Hsieh <andrewhsieh@google.com>2014-12-02 08:29:41 +0800
commit5387e7a81fcd3e033a29eccece64e02f96e7f960 (patch)
treec0d69c3b5b2175172278bad40b1a644dda3a1d2a
parente2b060be9823f53d2acd7bc7b5fe06cc4d940063 (diff)
downloadtoolchain_binutils-5387e7a81fcd3e033a29eccece64e02f96e7f960.tar.gz
toolchain_binutils-5387e7a81fcd3e033a29eccece64e02f96e7f960.tar.bz2
toolchain_binutils-5387e7a81fcd3e033a29eccece64e02f96e7f960.zip
Fixed Cortex-A53 Erratum 835769 -- LD segfaults with unordered maps.
The BFD/LD patch for Cortex-A53 erratum 835769 (https://sourceware.org/ml/binutils/2014-10/msg00199.html) does not handle a particular case of the AArch64 ELF ABI where mapping symbols are allowed to be unordered in the symbol table (not in address order). The unordering causes section maps to be traversed with incorrect span boundaries (in the erratum scanning function) which causes memory faults. The attached patch fixes this issue by ordering the section maps by their 'vma' before starting to traverse them. While this is not an issue with a the GNU toolchain, it is a potential issue with Clang/LLVM. We have observed at least one case where LLVM generates an ELF object with mapping symbols unordered in the symbol table and causes a fault. We have been unable to construct a test case with the GNU toolchain. We have verified by manual inspection the correctness of the traversal with this patch for an LLVM-generated ELF object which triggered this issue. This patch has been bootstrapped on aarch64-linux and regressed. Change-Id: I75622055b01eeb3038d5600c9eea395585e54aca
-rw-r--r--binutils-2.24/bfd/elfnn-aarch64.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/binutils-2.24/bfd/elfnn-aarch64.c b/binutils-2.24/bfd/elfnn-aarch64.c
index 90addb5b..dfd7b019 100644
--- a/binutils-2.24/bfd/elfnn-aarch64.c
+++ b/binutils-2.24/bfd/elfnn-aarch64.c
@@ -2936,6 +2936,29 @@ aarch64_erratum_sequence (uint32_t insn_1, uint32_t insn_2)
return FALSE;
}
+/* Used to order a list of mapping symbols by address. */
+
+static int
+elf_aarch64_compare_mapping (const void *a, const void *b)
+{
+ const elf_aarch64_section_map *amap = (const elf_aarch64_section_map *) a;
+ const elf_aarch64_section_map *bmap = (const elf_aarch64_section_map *) b;
+
+ if (amap->vma > bmap->vma)
+ return 1;
+ else if (amap->vma < bmap->vma)
+ return -1;
+ else if (amap->type > bmap->type)
+ /* Ensure results do not depend on the host qsort for objects with
+ multiple mapping symbols at the same address by sorting on type
+ after vma. */
+ return 1;
+ else if (amap->type < bmap->type)
+ return -1;
+ else
+ return 0;
+}
+
static bfd_boolean
erratum_835769_scan (bfd *input_bfd,
struct bfd_link_info *info,
@@ -2973,6 +2996,10 @@ erratum_835769_scan (bfd *input_bfd,
return TRUE;
sec_data = elf_aarch64_section_data (section);
+
+ qsort (sec_data->map, sec_data->mapcount,
+ sizeof (elf_aarch64_section_map), elf_aarch64_compare_mapping);
+
for (span = 0; span < sec_data->mapcount; span++)
{
unsigned int span_start = sec_data->map[span].vma;