[LLD][COFF] Ensure .bss is merged at the end of a section. (#137677)
Because it is full of zeros, it is expected that as much of it as possible is elided from the actual image, and that cannot happen if there is initialized data in the section after it.
This commit is contained in:
parent
08f0aa4800
commit
bb2f7596a8
@ -215,6 +215,7 @@ private:
|
||||
void appendImportThunks();
|
||||
void locateImportTables();
|
||||
void createExportTable();
|
||||
void mergeSection(const std::map<StringRef, StringRef>::value_type &p);
|
||||
void mergeSections();
|
||||
void sortECChunks();
|
||||
void appendECImportTables();
|
||||
@ -1566,6 +1567,30 @@ void Writer::createSymbolAndStringTable() {
|
||||
fileSize = alignTo(fileOff, ctx.config.fileAlign);
|
||||
}
|
||||
|
||||
void Writer::mergeSection(const std::map<StringRef, StringRef>::value_type &p) {
|
||||
StringRef toName = p.second;
|
||||
if (p.first == toName)
|
||||
return;
|
||||
StringSet<> names;
|
||||
while (true) {
|
||||
if (!names.insert(toName).second)
|
||||
Fatal(ctx) << "/merge: cycle found for section '" << p.first << "'";
|
||||
auto i = ctx.config.merge.find(toName);
|
||||
if (i == ctx.config.merge.end())
|
||||
break;
|
||||
toName = i->second;
|
||||
}
|
||||
OutputSection *from = findSection(p.first);
|
||||
OutputSection *to = findSection(toName);
|
||||
if (!from)
|
||||
return;
|
||||
if (!to) {
|
||||
from->name = toName;
|
||||
return;
|
||||
}
|
||||
to->merge(from);
|
||||
}
|
||||
|
||||
void Writer::mergeSections() {
|
||||
llvm::TimeTraceScope timeScope("Merge sections");
|
||||
if (!pdataSec->chunks.empty()) {
|
||||
@ -1594,28 +1619,16 @@ void Writer::mergeSections() {
|
||||
}
|
||||
|
||||
for (auto &p : ctx.config.merge) {
|
||||
StringRef toName = p.second;
|
||||
if (p.first == toName)
|
||||
continue;
|
||||
StringSet<> names;
|
||||
while (true) {
|
||||
if (!names.insert(toName).second)
|
||||
Fatal(ctx) << "/merge: cycle found for section '" << p.first << "'";
|
||||
auto i = ctx.config.merge.find(toName);
|
||||
if (i == ctx.config.merge.end())
|
||||
break;
|
||||
toName = i->second;
|
||||
}
|
||||
OutputSection *from = findSection(p.first);
|
||||
OutputSection *to = findSection(toName);
|
||||
if (!from)
|
||||
continue;
|
||||
if (!to) {
|
||||
from->name = toName;
|
||||
continue;
|
||||
}
|
||||
to->merge(from);
|
||||
if (p.first != ".bss")
|
||||
mergeSection(p);
|
||||
}
|
||||
|
||||
// Because .bss contains all zeros, it should be merged at the end of
|
||||
// whatever section it is being merged into (usually .data) so that the image
|
||||
// need not actually contain all of the zeros.
|
||||
auto it = ctx.config.merge.find(".bss");
|
||||
if (it != ctx.config.merge.end())
|
||||
mergeSection(*it);
|
||||
}
|
||||
|
||||
// EC targets may have chunks of various architectures mixed together at this
|
||||
|
92
lld/test/COFF/merge-data-bss.test
Normal file
92
lld/test/COFF/merge-data-bss.test
Normal file
@ -0,0 +1,92 @@
|
||||
# RUN: yaml2obj %s -o %t.obj
|
||||
# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /force \
|
||||
# RUN: /merge:.other=.data %t.obj /debug
|
||||
# RUN: llvm-readobj --sections %t.exe | FileCheck %s
|
||||
|
||||
# CHECK: Name: .data
|
||||
# CHECK-NEXT: VirtualSize: 0x2018
|
||||
# CHECK-NEXT: VirtualAddress: 0x3000
|
||||
# CHECK-NEXT: RawDataSize: 512
|
||||
# CHECK-NOT: Name: .other
|
||||
|
||||
--- !COFF
|
||||
header:
|
||||
Machine: IMAGE_FILE_MACHINE_AMD64
|
||||
Characteristics: [ ]
|
||||
sections:
|
||||
- Name: .text
|
||||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 4
|
||||
SectionData: '90'
|
||||
SizeOfRawData: 1
|
||||
- Name: .data
|
||||
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
|
||||
Alignment: 4
|
||||
SectionData: '010000000000000002'
|
||||
SizeOfRawData: 9
|
||||
- Name: .bss
|
||||
Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
|
||||
Alignment: 4
|
||||
SectionData: ''
|
||||
SizeOfRawData: 8192
|
||||
- Name: .other
|
||||
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
|
||||
Alignment: 4
|
||||
SectionData: '030000000000000004'
|
||||
SizeOfRawData: 9
|
||||
symbols:
|
||||
- Name: .text
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 1
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 4027552580
|
||||
Number: 1
|
||||
- Name: .data
|
||||
Value: 0
|
||||
SectionNumber: 2
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 9
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 4185224559
|
||||
Number: 2
|
||||
- Name: .bss
|
||||
Value: 0
|
||||
SectionNumber: 3
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 8192
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 3
|
||||
- Name: .other
|
||||
Value: 0
|
||||
SectionNumber: 4
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 9
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 1054931164
|
||||
Number: 4
|
||||
- Name: main
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
...
|
Loading…
x
Reference in New Issue
Block a user