Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -436,6 +436,8 @@ Sec->SectionIndex = I++; if (Sec->Noload) Sec->Type = SHT_NOBITS; + if (Sec->NonAlloc) + Sec->Flags &= ~(uint64_t)SHF_ALLOC; } } Ctx = nullptr; Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -100,6 +100,7 @@ std::string Location; std::string MemoryRegionName; std::string LMARegionName; + bool NonAlloc = false; bool Noload = false; template void finalize(); Index: ELF/ScriptParser.cpp =================================================================== --- ELF/ScriptParser.cpp +++ ELF/ScriptParser.cpp @@ -617,12 +617,14 @@ return V; } -// Reads an expression and/or the special directive "(NOLOAD)" for an -// output section definition. +// Reads an expression and/or the special directive for an output +// section definition. Directive is one of following: "(NOLOAD)", +// "(COPY)", "(INFO)" or "(OVERLAY)". // // An output section name can be followed by an address expression -// and/or by "(NOLOAD)". This grammar is not LL(1) because "(" can be -// interpreted as either the beginning of some expression or "(NOLOAD)". +// and/or directive. This grammar is not LL(1) because "(" can be +// interpreted as either the beginning of some expression or begining +// of directive. // // https://sourceware.org/binutils/docs/ld/Output-Section-Address.html // https://sourceware.org/binutils/docs/ld/Output-Section-Type.html @@ -633,6 +635,11 @@ Cmd->Noload = true; return; } + if (consume("COPY") || consume("INFO") || consume("OVERLAY")) { + expect(")"); + Cmd->NonAlloc = true; + return; + } Cmd->AddrExpr = readExpr(); expect(")"); } else { Index: test/ELF/linkerscript/info-section-type.s =================================================================== --- test/ELF/linkerscript/info-section-type.s +++ test/ELF/linkerscript/info-section-type.s @@ -0,0 +1,33 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o + +## In this test we check that output section types such as +## COPY, INFO and OVERLAY marks output section as non-allocatable. + +# RUN: echo "SECTIONS { .bar : { *(.foo) } };" > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o +# RUN: llvm-readobj -sections %t | FileCheck %s --check-prefix=DEFAULT +# DEFAULT: Name: .bar +# DEFAULT: Type: SHT_PROGBITS +# DEFAULT-NEXT: Flags [ +# DEFAULT-NEXT: SHF_ALLOC +# DEFAULT-NEXT: ] + +# RUN: echo "SECTIONS { .bar (COPY) : { *(.foo) } };" > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o +# RUN: llvm-readobj -sections %t | FileCheck %s --check-prefix=NONALLOC +# NONALLOC: Name: .bar +# NONALLOC: Type: SHT_PROGBITS +# NONALLOC-NEXT: Flags [ +# NONALLOC-NEXT: ] + +# RUN: echo "SECTIONS { .bar (INFO) : { *(.foo) } };" > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o +# RUN: llvm-readobj -sections %t | FileCheck %s --check-prefix=NONALLOC + +# RUN: echo "SECTIONS { .bar (OVERLAY) : { *(.foo) } };" > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o +# RUN: llvm-readobj -sections %t | FileCheck %s --check-prefix=NONALLOC + +.section .foo,"a",@progbits +.zero 1