Skip to content

Commit e168968

Browse files
committedJan 8, 2018
[ELF] Compress debug sections after assignAddresses and support custom layout
Previously, in r320472, I moved the calculation of section offsets and sizes for compressed debug sections into maybeCompress, which happens before assignAddresses, so that the compression had the required information. However, I failed to take account of relocations that patch such sections. This had two effects: 1. A race condition existed when a debug section referred to a different debug section (see PR35788). 2. References to symbols in non-debug sections would be patched incorrectly. This is because the addresses of such symbols are not calculated until after assignAddresses (this was a partial regression caused by r320472, but they could still have been broken before, in the event that a custom layout was used in a linker script). assignAddresses does not need to know about the output section size of non-allocatable sections, because they do not affect the value of Dot. This means that there is no longer a reason not to support custom layout of compressed debug sections, as far as I'm aware. These two points allow for delaying when maybeCompress can be called, removing the need for the loop I previously added to calculate the section size, and therefore the race condition. Furthermore, by delaying, we fix the issues of relocations getting incorrect symbol values, because they have now all been finalized. llvm-svn: 321986
1 parent f090e8a commit e168968

File tree

6 files changed

+68
-15
lines changed

6 files changed

+68
-15
lines changed
 

‎lld/ELF/LinkerScript.cpp

-5
Original file line numberDiff line numberDiff line change
@@ -669,11 +669,6 @@ void LinkerScript::assignOffsets(OutputSection *Sec) {
669669

670670
switchTo(Sec);
671671

672-
// We do not support custom layout for compressed debug sectons.
673-
// At this point we already know their size and have compressed content.
674-
if (Ctx->OutSec->Flags & SHF_COMPRESSED)
675-
return;
676-
677672
// The Size previously denoted how many InputSections had been added to this
678673
// section, and was used for sorting SHF_LINK_ORDER sections. Reset it to
679674
// compute the actual size value.

‎lld/ELF/OutputSections.cpp

-9
Original file line numberDiff line numberDiff line change
@@ -183,15 +183,6 @@ template <class ELFT> void OutputSection::maybeCompress() {
183183
!Name.startswith(".debug_"))
184184
return;
185185

186-
// Calculate the section offsets and size pre-compression.
187-
Size = 0;
188-
for (BaseCommand *Cmd : SectionCommands)
189-
if (auto *ISD = dyn_cast<InputSectionDescription>(Cmd))
190-
for (InputSection *IS : ISD->Sections) {
191-
IS->OutSecOff = alignTo(Size, IS->Alignment);
192-
this->Size = IS->OutSecOff + IS->getSize();
193-
}
194-
195186
// Create a section header.
196187
ZDebugHeader.resize(sizeof(Elf_Chdr));
197188
auto *Hdr = reinterpret_cast<Elf_Chdr *>(ZDebugHeader.data());

‎lld/ELF/Writer.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -427,13 +427,14 @@ template <class ELFT> void Writer<ELFT>::run() {
427427
if (errorCount())
428428
return;
429429

430+
Script->assignAddresses();
431+
430432
// If -compressed-debug-sections is specified, we need to compress
431433
// .debug_* sections. Do it right now because it changes the size of
432434
// output sections.
433435
parallelForEach(OutputSections,
434436
[](OutputSection *Sec) { Sec->maybeCompress<ELFT>(); });
435437

436-
Script->assignAddresses();
437438
Script->allocateHeaders(Phdrs);
438439

439440
// Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a

‎lld/test/ELF/Inputs/compress-debug.s

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.text
2+
.fill 0x44
3+
4+
.section .debug_info,"",@progbits
5+
.fill 0x43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# REQUIRES: x86, zlib
2+
3+
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
4+
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/compress-debug.s -o %t2.o
5+
# RUN: ld.lld %t2.o %t.o -o %t1 --compress-debug-sections=zlib -Ttext=0
6+
# RUN: llvm-dwarfdump %t1 -debug-str | FileCheck %s
7+
# These two checks correspond to the patched values of a_sym and a_debug_sym.
8+
# D = 0x44 - address of .text input section for this file (the start address of
9+
# .text is 0 as requested on the command line, and the size of the
10+
# preceding .text in the other input file is 0x44).
11+
# C = 0x43 - offset of .debug_info section for this file (the size of
12+
# the preceding .debug_info from the other input file is 0x43).
13+
# CHECK: 0x00000000: "D"
14+
# CHECK: 0x00000004: "C"
15+
16+
.text
17+
a_sym:
18+
nop
19+
20+
.section .debug_str,"",@progbits
21+
.long a_sym
22+
.long a_debug_sym
23+
24+
.section .debug_info,"",@progbits
25+
a_debug_sym:
26+
.long 0x88776655
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# REQUIRES: x86, zlib
2+
3+
# RUN: echo "SECTIONS { \
4+
# RUN: .text : { . += 0x10; *(.text) } \
5+
# RUN: .debug_str : { . += 0x10; *(.debug_str) } \
6+
# RUN: .debug_info : { . += 0x10; *(.debug_info) } \
7+
# RUN: }" > %t.script
8+
9+
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
10+
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/../Inputs/compress-debug.s -o %t2.o
11+
# RUN: ld.lld %t2.o %t.o -o %t1 --compress-debug-sections=zlib -T %t.script
12+
# RUN: llvm-dwarfdump %t1 -debug-str | FileCheck %s
13+
# These two checks correspond to the patched values of a_sym and a_debug_sym.
14+
# T = 0x54 - address of .text input section for this file (the start address of
15+
# .text is 0 by default, the size of the preceding .text in the other input
16+
# file is 0x44, and the linker script adds an additional 0x10).
17+
# S = 0x53 - offset of .debug_info section for this file (the size of
18+
# the preceding .debug_info from the other input file is 0x43, and the
19+
# linker script adds an additional 0x10).
20+
# Also note that the .debug_str offsets are also offset by 0x10, as directed by
21+
# the linker script.
22+
# CHECK: 0x00000010: "T"
23+
# CHECK: 0x00000014: "S"
24+
25+
.text
26+
a_sym:
27+
nop
28+
29+
.section .debug_str,"",@progbits
30+
.long a_sym
31+
.long a_debug_sym
32+
33+
.section .debug_info,"",@progbits
34+
a_debug_sym:
35+
.long 0x88776655

0 commit comments

Comments
 (0)