Index: lld/ELF/ScriptParser.cpp =================================================================== --- lld/ELF/ScriptParser.cpp +++ lld/ELF/ScriptParser.cpp @@ -695,22 +695,34 @@ ScriptParser::readInputSectionDescription(StringRef tok) { // Input section wildcard can be surrounded by KEEP. // https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep - uint64_t withFlags = 0; - uint64_t withoutFlags = 0; if (tok == "KEEP") { expect("("); - if (consume("INPUT_SECTION_FLAGS")) - std::tie(withFlags, withoutFlags) = readInputSectionFlags(); InputSectionDescription *cmd = - readInputSectionRules(next(), withFlags, withoutFlags); + peek() == "INPUT_SECTION_FLAGS" + ? readInputSectionDescription(next()) + : readInputSectionRules(next(), /*withFlags=*/0, + /*withoutFlags*/ 0); expect(")"); script->keptSections.push_back(cmd); return cmd; } + + uint64_t withFlags = 0; + uint64_t withoutFlags = 0; if (tok == "INPUT_SECTION_FLAGS") { std::tie(withFlags, withoutFlags) = readInputSectionFlags(); tok = next(); } + + if (peek() != "(") { + // We have a file name and no input sections description. It is not a + // commonly used syntax, but still acceptable. In that case, all sections + // from the file will be included. + auto *isd = make(tok, withFlags, withoutFlags); + isd->sectionPatterns.push_back({{}, StringMatcher("*")}); + return isd; + } + return readInputSectionRules(tok, withFlags, withoutFlags); } @@ -849,18 +861,8 @@ readSort(); } else if (tok == "INCLUDE") { readInclude(); - } else if (peek() == "(") { - cmd->sectionCommands.push_back(readInputSectionDescription(tok)); } else { - // We have a file name and no input sections description. It is not a - // commonly used syntax, but still acceptable. In that case, all sections - // from the file will be included. - // FIXME: GNU ld permits INPUT_SECTION_FLAGS to be used here. We do not - // handle this case here as it will already have been matched by the - // case above. - auto *isd = make(tok); - isd->sectionPatterns.push_back({{}, StringMatcher("*")}); - cmd->sectionCommands.push_back(isd); + cmd->sectionCommands.push_back(readInputSectionDescription(tok)); } } Index: lld/test/ELF/input-section-flags.s =================================================================== --- lld/test/ELF/input-section-flags.s +++ lld/test/ELF/input-section-flags.s @@ -59,6 +59,20 @@ # RUN: ld.lld -o %t3 --script %t3.script %t.o # RUN: llvm-readobj --symbols %t3 | FileCheck %s +## Same test but using just a filespec. +# RUN: echo "SECTIONS { \ +# RUN: .outsec1 : { INPUT_SECTION_FLAGS(SHF_ALLOC & !SHF_EXECINSTR & \ +# RUN: !SHF_WRITE & !SHF_MERGE) *.o }\ +# RUN: .outsec2 : { INPUT_SECTION_FLAGS(SHF_ALLOC & SHF_EXECINSTR & !SHF_WRITE\ +# RUN: & !SHF_MERGE) *.o } \ +# RUN: .outsec3 : { INPUT_SECTION_FLAGS(SHF_WRITE) *.o } \ +# RUN: .outsec4 : { INPUT_SECTION_FLAGS(SHF_MERGE & !SHF_STRINGS) * } \ +# RUN: .outsec5 : { INPUT_SECTION_FLAGS(SHF_STRINGS) * } \ +# RUN: } " > %t4.script + +# RUN: ld.lld -o %t4 --script %t4.script %t.o +# RUN: llvm-readobj --symbols %t4 | FileCheck %s + ## Check that we can handle multiple InputSectionDescriptions in a single ## OutputSection # RUN: echo "SECTIONS { \ @@ -66,10 +80,10 @@ # RUN: !SHF_WRITE & !SHF_MERGE) *(.sec.*) ; \ # RUN: INPUT_SECTION_FLAGS(SHF_ALLOC & SHF_EXECINSTR & !SHF_WRITE\ # RUN: & !SHF_MERGE) *(.sec.* *.text) }\ -# RUN: } " > %t4.script +# RUN: } " > %t5.script -# RUN: ld.lld -o %t4 --script %t4.script %t.o -# RUN: llvm-readobj --symbols %t4 | FileCheck --check-prefix MULTIPLE %s +# RUN: ld.lld -o %t5 --script %t5.script %t.o +# RUN: llvm-readobj --symbols %t5 | FileCheck --check-prefix MULTIPLE %s # MULTIPLE: Name: _start # MULTIPLE: Section: .outsec1