Skip to content

Commit c6ebc65

Browse files
committed
[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
1 parent 4c2e012 commit c6ebc65

File tree

4 files changed

+32
-27
lines changed

4 files changed

+32
-27
lines changed

lld/ELF/InputSection.cpp

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,22 @@ InputSectionBase::InputSectionBase(InputFile *file, uint64_t flags,
8888
if (!zlib::isAvailable())
8989
error(toString(file) + ": contains a compressed section, " +
9090
"but zlib is not available");
91-
parseCompressedHeader();
91+
switch (config->ekind) {
92+
case ELF32LEKind:
93+
parseCompressedHeader<ELF32LE>();
94+
break;
95+
case ELF32BEKind:
96+
parseCompressedHeader<ELF32BE>();
97+
break;
98+
case ELF64LEKind:
99+
parseCompressedHeader<ELF64LE>();
100+
break;
101+
case ELF64BEKind:
102+
parseCompressedHeader<ELF64BE>();
103+
break;
104+
default:
105+
llvm_unreachable("unknown ELFT");
106+
}
92107
}
93108
}
94109

@@ -210,10 +225,7 @@ OutputSection *SectionBase::getOutputSection() {
210225
// When a section is compressed, `rawData` consists with a header followed
211226
// by zlib-compressed data. This function parses a header to initialize
212227
// `uncompressedSize` member and remove the header from `rawData`.
213-
void InputSectionBase::parseCompressedHeader() {
214-
using Chdr64 = typename ELF64LE::Chdr;
215-
using Chdr32 = typename ELF32LE::Chdr;
216-
228+
template <typename ELFT> void InputSectionBase::parseCompressedHeader() {
217229
// Old-style header
218230
if (name.startswith(".zdebug")) {
219231
if (!toStringRef(rawData).startswith("ZLIB")) {
@@ -239,32 +251,13 @@ void InputSectionBase::parseCompressedHeader() {
239251
assert(flags & SHF_COMPRESSED);
240252
flags &= ~(uint64_t)SHF_COMPRESSED;
241253

242-
// New-style 64-bit header
243-
if (config->is64) {
244-
if (rawData.size() < sizeof(Chdr64)) {
245-
error(toString(this) + ": corrupted compressed section");
246-
return;
247-
}
248-
249-
auto *hdr = reinterpret_cast<const Chdr64 *>(rawData.data());
250-
if (hdr->ch_type != ELFCOMPRESS_ZLIB) {
251-
error(toString(this) + ": unsupported compression type");
252-
return;
253-
}
254-
255-
uncompressedSize = hdr->ch_size;
256-
alignment = std::max<uint32_t>(hdr->ch_addralign, 1);
257-
rawData = rawData.slice(sizeof(*hdr));
258-
return;
259-
}
260-
261-
// New-style 32-bit header
262-
if (rawData.size() < sizeof(Chdr32)) {
254+
// New-style header
255+
if (rawData.size() < sizeof(typename ELFT::Chdr)) {
263256
error(toString(this) + ": corrupted compressed section");
264257
return;
265258
}
266259

267-
auto *hdr = reinterpret_cast<const Chdr32 *>(rawData.data());
260+
auto *hdr = reinterpret_cast<const typename ELFT::Chdr *>(rawData.data());
268261
if (hdr->ch_type != ELFCOMPRESS_ZLIB) {
269262
error(toString(this) + ": unsupported compression type");
270263
return;

lld/ELF/InputSection.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ class InputSectionBase : public SectionBase {
238238
}
239239

240240
protected:
241+
template <typename ELFT>
241242
void parseCompressedHeader();
242243
void uncompress() const;
243244

lld/test/ELF/compressed-debug-input-err.s

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
44
# RUN: not ld.lld %t.o -o /dev/null -shared 2>&1 | FileCheck %s
55

6+
# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-unknown %s -o %t-be.o
7+
# RUN: not ld.lld %t-be.o -o /dev/null -shared 2>&1 | FileCheck %s
8+
69
## Check we are able to report zlib uncompress errors.
710
# CHECK: error: {{.*}}.o:(.debug_str): uncompress failed: zlib error: Z_DATA_ERROR
811

lld/test/ELF/compressed-debug-input.s

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# REQUIRES: zlib, x86
22

33
# RUN: llvm-mc -compress-debug-sections=zlib -filetype=obj -triple=x86_64-unknown-linux %s -o %t
4+
# RUN: llvm-mc -compress-debug-sections=zlib -filetype=obj -triple=powerpc64-unknown-unknown %s -o %t-be
45
# RUN: llvm-readobj --sections %t | FileCheck -check-prefix=ZLIB %s
6+
# RUN: llvm-readobj --sections %t-be | FileCheck -check-prefix=ZLIB %s
57
# ZLIB: Section {
68
# ZLIB: Index: 2
79
# ZLIB: Name: .debug_str
@@ -21,7 +23,9 @@
2123
# ZLIB-NEXT: }
2224

2325
# RUN: llvm-mc -compress-debug-sections=zlib-gnu -filetype=obj -triple=x86_64-unknown-linux %s -o %t2
26+
# RUN: llvm-mc -compress-debug-sections=zlib-gnu -filetype=obj -triple=powerpc64-unknown-unknown %s -o %t2-be
2427
# RUN: llvm-readobj --sections %t2 | FileCheck -check-prefix=GNU %s
28+
# RUN: llvm-readobj --sections %t2-be | FileCheck -check-prefix=GNU %s
2529
# GNU: Section {
2630
# GNU: Index: 2
2731
# GNU: Name: .zdebug_str
@@ -41,9 +45,13 @@
4145

4246
# RUN: ld.lld --hash-style=sysv %t -o %t.so -shared
4347
# RUN: llvm-readobj --sections --section-data %t.so | FileCheck -check-prefix=DATA %s
48+
# RUN: ld.lld --hash-style=sysv %t-be -o %t-be.so -shared
49+
# RUN: llvm-readobj --sections --section-data %t-be.so | FileCheck -check-prefix=DATA %s
4450

4551
# RUN: ld.lld --hash-style=sysv %t2 -o %t2.so -shared
4652
# RUN: llvm-readobj --sections --section-data %t2.so | FileCheck -check-prefix=DATA %s
53+
# RUN: ld.lld --hash-style=sysv %t2-be -o %t2-be.so -shared
54+
# RUN: llvm-readobj --sections --section-data %t2-be.so | FileCheck -check-prefix=DATA %s
4755

4856
# DATA: Section {
4957
# DATA: Index: 6

0 commit comments

Comments
 (0)