Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -105,8 +105,8 @@ llvm::Regex FileRe; SortKind SortOuter = SortNone; SortKind SortInner = SortNone; - llvm::Regex ExcludedFileRe; - llvm::Regex SectionRe; + // Pairs of section regex and files excluded. + std::vector> SectionsVec; }; struct AssertCommand : BaseCommand { Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -104,10 +104,10 @@ return false; } -static bool fileMatches(const InputSectionDescription *Desc, - StringRef Filename) { - return const_cast(Desc->FileRe).match(Filename) && - !const_cast(Desc->ExcludedFileRe).match(Filename); +static bool fileMatches(const llvm::Regex &FileRe, + const llvm::Regex &ExcludedFileRe, StringRef Filename) { + return const_cast(FileRe).match(Filename) && + !const_cast(ExcludedFileRe).match(Filename); } static bool comparePriority(InputSectionData *A, InputSectionData *B) { @@ -155,17 +155,21 @@ template std::vector *> LinkerScript::getInputSections(const InputSectionDescription *I) { - const Regex &Re = I->SectionRe; std::vector *> Ret; - for (ObjectFile *F : Symtab::X->getObjectFiles()) - if (fileMatches(I, sys::path::filename(F->getName()))) - for (InputSectionBase *S : F->getSections()) - if (!isDiscarded(S) && !S->OutSec && - const_cast(Re).match(S->Name)) - Ret.push_back(S); + for (const std::pair &V : I->SectionsVec) { + for (ObjectFile *F : Symtab::X->getObjectFiles()) { + if (fileMatches(I->FileRe, V.first, sys::path::filename(F->getName()))) { + + Regex &Re = const_cast(V.second); + for (InputSectionBase *S : F->getSections()) + if (!isDiscarded(S) && !S->OutSec && Re.match(S->Name)) + Ret.push_back(S); - if (const_cast(Re).match("COMMON")) - Ret.push_back(CommonInputSection::X); + if (Re.match("COMMON")) + Ret.push_back(CommonInputSection::X); + } + } + } return Ret; } @@ -687,6 +691,7 @@ std::vector readOutputSectionPhdrs(); InputSectionDescription *readInputSectionDescription(StringRef Tok); Regex readFilePatterns(); + void readSectionExcludes(InputSectionDescription *Cmd); InputSectionDescription *readInputSectionRules(StringRef FilePattern); unsigned readPhdrType(); SortKind readSortKind(); @@ -981,17 +986,38 @@ return SortNone; } +void ScriptParser::readSectionExcludes(InputSectionDescription *Cmd) { + llvm::Regex ExcludeFileRe; + std::vector V; + + while (!Error) { + if (skip(")")) { + Cmd->SectionsVec.push_back( + {std::move(ExcludeFileRe), compileGlobPatterns(V)}); + return; + } + + if (skip("EXCLUDE_FILE")) { + if (!V.empty()) { + Cmd->SectionsVec.push_back( + {std::move(ExcludeFileRe), compileGlobPatterns(V)}); + V.clear(); + } + + expect("("); + ExcludeFileRe = readFilePatterns(); + continue; + } + + V.push_back(next()); + } +} + InputSectionDescription * ScriptParser::readInputSectionRules(StringRef FilePattern) { auto *Cmd = new InputSectionDescription(FilePattern); expect("("); - // Read EXCLUDE_FILE(). - if (skip("EXCLUDE_FILE")) { - expect("("); - Cmd->ExcludedFileRe = readFilePatterns(); - } - // Read SORT(). if (SortKind K1 = readSortKind()) { Cmd->SortOuter = K1; @@ -999,16 +1025,16 @@ if (SortKind K2 = readSortKind()) { Cmd->SortInner = K2; expect("("); - Cmd->SectionRe = readFilePatterns(); + Cmd->SectionsVec.push_back({llvm::Regex(), readFilePatterns()}); expect(")"); } else { - Cmd->SectionRe = readFilePatterns(); + Cmd->SectionsVec.push_back({llvm::Regex(), readFilePatterns()}); } expect(")"); return Cmd; } - Cmd->SectionRe = readFilePatterns(); + readSectionExcludes(Cmd); return Cmd; } @@ -1021,7 +1047,8 @@ StringRef FilePattern = next(); InputSectionDescription *Cmd = readInputSectionRules(FilePattern); expect(")"); - Opt.KeptSections.push_back(&Cmd->SectionRe); + for (std::pair &Regex : Cmd->SectionsVec) + Opt.KeptSections.push_back(&Regex.second); return Cmd; } return readInputSectionRules(Tok); Index: test/ELF/linkerscript/Inputs/exclude-multiple1.s =================================================================== --- test/ELF/linkerscript/Inputs/exclude-multiple1.s +++ test/ELF/linkerscript/Inputs/exclude-multiple1.s @@ -0,0 +1,8 @@ +.section .foo.1,"a" + .quad 4 + +.section .foo.2,"a" + .quad 5 + +.section .foo.3,"a" + .quad 6 Index: test/ELF/linkerscript/Inputs/exclude-multiple2.s =================================================================== --- test/ELF/linkerscript/Inputs/exclude-multiple2.s +++ test/ELF/linkerscript/Inputs/exclude-multiple2.s @@ -0,0 +1,8 @@ +.section .foo.1,"a" + .quad 7 + +.section .foo.2,"a" + .quad 8 + +.section .foo.3,"a" + .quad 9 Index: test/ELF/linkerscript/exclude-multiple.s =================================================================== --- test/ELF/linkerscript/exclude-multiple.s +++ test/ELF/linkerscript/exclude-multiple.s @@ -0,0 +1,28 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %tfile1.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/exclude-multiple1.s -o %tfile2.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/exclude-multiple2.s -o %tfile3.o +# RUN: echo "SECTIONS { \ +# RUN: .foo : { *(.foo.1 EXCLUDE_FILE (*file1.o) .foo.2 EXCLUDE_FILE (*file2.o) .foo.3) } \ +# RUN: }" > %t1.script +# RUN: ld.lld -script %t1.script %tfile1.o %tfile2.o %tfile3.o -o %t1.o +# RUN: llvm-objdump -s %t1.o | FileCheck %s + +# CHECK: Contents of section .foo: +# CHECK-NEXT: 0120 01000000 00000000 04000000 00000000 +# CHECK-NEXT: 0130 07000000 00000000 05000000 00000000 +# CHECK-NEXT: 0140 08000000 00000000 03000000 00000000 +# CHECK-NEXT: 0150 09000000 00000000 +# CHECK-NEXT: Contents of section .foo.2: +# CHECK-NEXT: 0158 02000000 00000000 +# CHECK-NEXT: Contents of section .foo.3: +# CHECK-NEXT: 0160 06000000 00000000 + +.section .foo.1,"a" + .quad 1 + +.section .foo.2,"a" + .quad 2 + +.section .foo.3,"a" + .quad 3