ports/devel/llvm12/files/patch-lld-be-compressed-debug
Brooks Davis f4fb63c060 devel/llvm12: lld fix compressed input sections
Apply upstream lld fix for compressed input sections on BE targets

  [LLD] Support compressed input sections on big-endian targets

  This patch enables compressed input sections on big-endian targets by
  checking the target endianness and selecting an appropriate `Chdr`
  structure.

  Fixes PR51369

  Differential Revision: https://reviews.llvm.org/D107635

MFH:		2021Q3
Sponsored by:	DARPA
2021-08-10 21:42:12 +01:00

154 lines
5.7 KiB
Text

commit c6ebc651b6fac9cf1d9f8c00ea49d29093003f85
Author: Simon Atanasyan <simon@atanasyan.com>
Date: Fri Aug 6 13:29:47 2021 +0300
[LLD] Support compressed input sections on big-endian targets
This patch enables compressed input sections on big-endian targets by
checking the target endianness and selecting an appropriate `Chdr`
structure.
Fixes PR51369
Differential Revision: https://reviews.llvm.org/D107635
diff --git lld/ELF/InputSection.cpp lld/ELF/InputSection.cpp
index 1f9fa961fc2..7d952e9037f 100644
--- lld/ELF/InputSection.cpp
+++ lld/ELF/InputSection.cpp
@@ -88,7 +88,22 @@ InputSectionBase::InputSectionBase(InputFile *file, uint64_t flags,
if (!zlib::isAvailable())
error(toString(file) + ": contains a compressed section, " +
"but zlib is not available");
- parseCompressedHeader();
+ switch (config->ekind) {
+ case ELF32LEKind:
+ parseCompressedHeader<ELF32LE>();
+ break;
+ case ELF32BEKind:
+ parseCompressedHeader<ELF32BE>();
+ break;
+ case ELF64LEKind:
+ parseCompressedHeader<ELF64LE>();
+ break;
+ case ELF64BEKind:
+ parseCompressedHeader<ELF64BE>();
+ break;
+ default:
+ llvm_unreachable("unknown ELFT");
+ }
}
}
@@ -210,10 +225,7 @@ OutputSection *SectionBase::getOutputSection() {
// When a section is compressed, `rawData` consists with a header followed
// by zlib-compressed data. This function parses a header to initialize
// `uncompressedSize` member and remove the header from `rawData`.
-void InputSectionBase::parseCompressedHeader() {
- using Chdr64 = typename ELF64LE::Chdr;
- using Chdr32 = typename ELF32LE::Chdr;
-
+template <typename ELFT> void InputSectionBase::parseCompressedHeader() {
// Old-style header
if (name.startswith(".zdebug")) {
if (!toStringRef(rawData).startswith("ZLIB")) {
@@ -239,32 +251,13 @@ void InputSectionBase::parseCompressedHeader() {
assert(flags & SHF_COMPRESSED);
flags &= ~(uint64_t)SHF_COMPRESSED;
- // New-style 64-bit header
- if (config->is64) {
- if (rawData.size() < sizeof(Chdr64)) {
- error(toString(this) + ": corrupted compressed section");
- return;
- }
-
- auto *hdr = reinterpret_cast<const Chdr64 *>(rawData.data());
- if (hdr->ch_type != ELFCOMPRESS_ZLIB) {
- error(toString(this) + ": unsupported compression type");
- return;
- }
-
- uncompressedSize = hdr->ch_size;
- alignment = std::max<uint32_t>(hdr->ch_addralign, 1);
- rawData = rawData.slice(sizeof(*hdr));
- return;
- }
-
- // New-style 32-bit header
- if (rawData.size() < sizeof(Chdr32)) {
+ // New-style header
+ if (rawData.size() < sizeof(typename ELFT::Chdr)) {
error(toString(this) + ": corrupted compressed section");
return;
}
- auto *hdr = reinterpret_cast<const Chdr32 *>(rawData.data());
+ auto *hdr = reinterpret_cast<const typename ELFT::Chdr *>(rawData.data());
if (hdr->ch_type != ELFCOMPRESS_ZLIB) {
error(toString(this) + ": unsupported compression type");
return;
diff --git lld/ELF/InputSection.h lld/ELF/InputSection.h
index 5b91c1c90bd..c914d0b4215 100644
--- lld/ELF/InputSection.h
+++ lld/ELF/InputSection.h
@@ -238,6 +238,7 @@ public:
}
protected:
+ template <typename ELFT>
void parseCompressedHeader();
void uncompress() const;
diff --git lld/test/ELF/compressed-debug-input-err.s lld/test/ELF/compressed-debug-input-err.s
index 89773eca59d..0495a9eaa08 100644
--- lld/test/ELF/compressed-debug-input-err.s
+++ lld/test/ELF/compressed-debug-input-err.s
@@ -3,6 +3,9 @@
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
# RUN: not ld.lld %t.o -o /dev/null -shared 2>&1 | FileCheck %s
+# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-unknown %s -o %t-be.o
+# RUN: not ld.lld %t-be.o -o /dev/null -shared 2>&1 | FileCheck %s
+
## Check we are able to report zlib uncompress errors.
# CHECK: error: {{.*}}.o:(.debug_str): uncompress failed: zlib error: Z_DATA_ERROR
diff --git lld/test/ELF/compressed-debug-input.s lld/test/ELF/compressed-debug-input.s
index c9bfd3e5162..5b61ea8b384 100644
--- lld/test/ELF/compressed-debug-input.s
+++ lld/test/ELF/compressed-debug-input.s
@@ -1,7 +1,9 @@
# REQUIRES: zlib, x86
# RUN: llvm-mc -compress-debug-sections=zlib -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: llvm-mc -compress-debug-sections=zlib -filetype=obj -triple=powerpc64-unknown-unknown %s -o %t-be
# RUN: llvm-readobj --sections %t | FileCheck -check-prefix=ZLIB %s
+# RUN: llvm-readobj --sections %t-be | FileCheck -check-prefix=ZLIB %s
# ZLIB: Section {
# ZLIB: Index: 2
# ZLIB: Name: .debug_str
@@ -21,7 +23,9 @@
# ZLIB-NEXT: }
# RUN: llvm-mc -compress-debug-sections=zlib-gnu -filetype=obj -triple=x86_64-unknown-linux %s -o %t2
+# RUN: llvm-mc -compress-debug-sections=zlib-gnu -filetype=obj -triple=powerpc64-unknown-unknown %s -o %t2-be
# RUN: llvm-readobj --sections %t2 | FileCheck -check-prefix=GNU %s
+# RUN: llvm-readobj --sections %t2-be | FileCheck -check-prefix=GNU %s
# GNU: Section {
# GNU: Index: 2
# GNU: Name: .zdebug_str
@@ -41,9 +45,13 @@
# RUN: ld.lld --hash-style=sysv %t -o %t.so -shared
# RUN: llvm-readobj --sections --section-data %t.so | FileCheck -check-prefix=DATA %s
+# RUN: ld.lld --hash-style=sysv %t-be -o %t-be.so -shared
+# RUN: llvm-readobj --sections --section-data %t-be.so | FileCheck -check-prefix=DATA %s
# RUN: ld.lld --hash-style=sysv %t2 -o %t2.so -shared
# RUN: llvm-readobj --sections --section-data %t2.so | FileCheck -check-prefix=DATA %s
+# RUN: ld.lld --hash-style=sysv %t2-be -o %t2-be.so -shared
+# RUN: llvm-readobj --sections --section-data %t2-be.so | FileCheck -check-prefix=DATA %s
# DATA: Section {
# DATA: Index: 6