From d79bbf4474d52ca2dd6c87b0b51fb4d819f65c9c Mon Sep 17 00:00:00 2001 From: Shoaib Meenai Date: Thu, 11 Jan 2018 06:57:01 +0000 Subject: [PATCH] [ELF] Fix SysV hash tables with --no-rosegment When setting up the chain, we copy over the bucket's previous symbol index, assuming that this index will be 0 (STN_UNDEF) for an unused bucket (marking the end of the chain). When linking with --no-rosegment, however, unused buckets will in fact contain the padding value, and so the hash table will end up containing invalid chains. Zero out the hash table section explicitly to avoid this, similar to what's already done for GNU hash sections. Differential Revision: https://reviews.llvm.org/D41928 llvm-svn: 322259 --- lld/ELF/SyntheticSections.cpp | 3 +++ lld/test/ELF/sysv-hash-no-rosegment.s | 13 +++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 lld/test/ELF/sysv-hash-no-rosegment.s diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index c83afcf72e49..36e3ffa284ef 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1836,6 +1836,9 @@ void HashTableSection::finalizeContents() { } void HashTableSection::writeTo(uint8_t *Buf) { + // See comment in GnuHashTableSection::writeTo. + memset(Buf, 0, Size); + unsigned NumSymbols = InX::DynSymTab->getNumSymbols(); uint32_t *P = reinterpret_cast(Buf); diff --git a/lld/test/ELF/sysv-hash-no-rosegment.s b/lld/test/ELF/sysv-hash-no-rosegment.s new file mode 100644 index 000000000000..31b9d2fbec05 --- /dev/null +++ b/lld/test/ELF/sysv-hash-no-rosegment.s @@ -0,0 +1,13 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: ld.lld -shared --no-rosegment -o %t %t.o +# RUN: llvm-readobj -hash-table %t | FileCheck %s + +# CHECK: HashTable { +# CHECK-NEXT: Num Buckets: 2 +# CHECK-NEXT: Num Chains: 2 +# CHECK-NEXT: Buckets: [1, 0] +# CHECK-NEXT: Chains: [0, 0] +# CHECK-NEXT: } + +callq undef@PLT