Index: lld/trunk/ELF/LinkerScript.h =================================================================== --- lld/trunk/ELF/LinkerScript.h +++ lld/trunk/ELF/LinkerScript.h @@ -187,7 +187,7 @@ std::vector KeptSections; // A map from memory region name to a memory region descriptor. - llvm::DenseMap MemoryRegions; + llvm::DenseMap MemoryRegions; // A list of symbols referenced by the script. std::vector ReferencedSymbols; Index: lld/trunk/ELF/LinkerScript.cpp =================================================================== --- lld/trunk/ELF/LinkerScript.cpp +++ lld/trunk/ELF/LinkerScript.cpp @@ -584,7 +584,7 @@ if (!Sec->MemoryRegionName.empty()) { auto It = Opt.MemoryRegions.find(Sec->MemoryRegionName); if (It != Opt.MemoryRegions.end()) - return &It->second; + return It->second; error("memory region '" + Sec->MemoryRegionName + "' not declared"); return nullptr; } @@ -597,9 +597,9 @@ // See if a region can be found by matching section flags. for (auto &Pair : Opt.MemoryRegions) { - MemoryRegion &M = Pair.second; - if ((M.Flags & Sec->Flags) && (M.NegFlags & Sec->Flags) == 0) - return &M; + MemoryRegion *M = Pair.second; + if ((M->Flags & Sec->Flags) && (M->NegFlags & Sec->Flags) == 0) + return M; } // Otherwise, no suitable region was found. @@ -778,7 +778,7 @@ LinkerScript::AddressState::AddressState(const ScriptConfiguration &Opt) { for (auto &MRI : Opt.MemoryRegions) { - const MemoryRegion *MR = &MRI.second; + const MemoryRegion *MR = MRI.second; MemRegionOffset[MR] = MR->Origin; } } Index: lld/trunk/ELF/ScriptParser.cpp =================================================================== --- lld/trunk/ELF/ScriptParser.cpp +++ lld/trunk/ELF/ScriptParser.cpp @@ -68,6 +68,7 @@ void readOutputArch(); void readOutputFormat(); void readPhdrs(); + void readRegionAlias(); void readSearchDir(); void readSections(); void readVersion(); @@ -241,6 +242,8 @@ readOutputFormat(); } else if (Tok == "PHDRS") { readPhdrs(); + } else if (Tok == "REGION_ALIAS") { + readRegionAlias(); } else if (Tok == "SEARCH_DIR") { readSearchDir(); } else if (Tok == "SECTIONS") { @@ -396,6 +399,20 @@ } } +void ScriptParser::readRegionAlias() { + expect("("); + StringRef Alias = unquote(next()); + expect(","); + StringRef Name = next(); + expect(")"); + + if (Script->Opt.MemoryRegions.count(Alias)) + setError("redefinition of memory region '" + Alias + "'"); + if (!Script->Opt.MemoryRegions.count(Name)) + setError("memory region '" + Name + "' is not defined"); + Script->Opt.MemoryRegions[Alias] = Script->Opt.MemoryRegions[Name]; +} + void ScriptParser::readSearchDir() { expect("("); StringRef Tok = next(); @@ -984,7 +1001,7 @@ StringRef Name = readParenLiteral(); if (Script->Opt.MemoryRegions.count(Name) == 0) setError("memory region not defined: " + Name); - return [=] { return Script->Opt.MemoryRegions[Name].Length; }; + return [=] { return Script->Opt.MemoryRegions[Name]->Length; }; } if (Tok == "LOADADDR") { StringRef Name = readParenLiteral(); @@ -995,7 +1012,7 @@ StringRef Name = readParenLiteral(); if (Script->Opt.MemoryRegions.count(Name) == 0) setError("memory region not defined: " + Name); - return [=] { return Script->Opt.MemoryRegions[Name].Origin; }; + return [=] { return Script->Opt.MemoryRegions[Name]->Origin; }; } if (Tok == "SEGMENT_START") { expect("("); @@ -1226,12 +1243,12 @@ expect(","); uint64_t Length = readMemoryAssignment("LENGTH", "len", "l"); - // Add the memory region to the region map (if it doesn't already exist). - auto It = Script->Opt.MemoryRegions.find(Name); - if (It != Script->Opt.MemoryRegions.end()) + // Add the memory region to the region map. + if (Script->Opt.MemoryRegions.count(Name)) setError("region '" + Name + "' already defined"); - else - Script->Opt.MemoryRegions[Name] = {Name, Origin, Length, Flags, NegFlags}; + MemoryRegion *MR = make(); + *MR = {Name, Origin, Length, Flags, NegFlags}; + Script->Opt.MemoryRegions[Name] = MR; } } Index: lld/trunk/test/ELF/linkerscript/region-alias.s =================================================================== --- lld/trunk/test/ELF/linkerscript/region-alias.s +++ lld/trunk/test/ELF/linkerscript/region-alias.s @@ -0,0 +1,54 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "MEMORY { \ +# RUN: ROM (rwx): ORIGIN = 0x1000, LENGTH = 0x100 \ +# RUN: RAM (rwx): ORIGIN = 0x2000, LENGTH = 0x100 \ +# RUN: } \ +# RUN: INCLUDE \"%t.script.inc\" \ +# RUN: SECTIONS { \ +# RUN: .text : { *(.text*) } > ALIAS_TEXT \ +# RUN: .data : { *(.data*) } > ALIAS_DATA \ +# RUN: }" > %t.script + +## .text to ROM, .data to RAM. +# RUN: echo "REGION_ALIAS (\"ALIAS_TEXT\", ROM);" > %t.script.inc +# RUN: echo "REGION_ALIAS (\"ALIAS_DATA\", RAM);" >> %t.script.inc +# RUN: ld.lld %t --script %t.script -o %t2 +# RUN: llvm-objdump -section-headers %t2 | FileCheck %s +# CHECK: .text 00000001 0000000000001000 TEXT DATA +# CHECK: .data 00000008 0000000000002000 DATA + +## All to ROM. +# RUN: echo "REGION_ALIAS (\"ALIAS_TEXT\", ROM);" > %t.script.inc +# RUN: echo "REGION_ALIAS (\"ALIAS_DATA\", ROM);" >> %t.script.inc +# RUN: ld.lld %t --script %t.script -o %t2 +# RUN: llvm-objdump -section-headers %t2 | FileCheck %s --check-prefix=RAM +# RAM: .text 00000001 0000000000001000 TEXT DATA +# RAM: .data 00000008 0000000000001001 DATA + +## Redefinition of region. +# RUN: echo "REGION_ALIAS (\"ROM\", ROM);" > %t.script.inc +# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \ +# RUN: FileCheck %s --check-prefix=ERR1 +# ERR1: {{.*}}script.inc:1: redefinition of memory region 'ROM' + +## Redefinition of alias. +# RUN: echo "REGION_ALIAS (\"ALIAS_TEXT\", ROM);" > %t.script.inc +# RUN: echo "REGION_ALIAS (\"ALIAS_TEXT\", ROM);" >> %t.script.inc +# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \ +# RUN: FileCheck %s --check-prefix=ERR2 +# ERR2: {{.*}}script.inc:2: redefinition of memory region 'ALIAS_TEXT' + +## Attemp to create an alias for undefined region. +# RUN: echo "REGION_ALIAS (\"ALIAS_TEXT\", FOO);" > %t.script.inc +# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \ +# RUN: FileCheck %s --check-prefix=ERR3 +# ERR3: {{.*}}script.inc:1: memory region 'FOO' is not defined + +.text +.global _start +_start: + nop + +.section .data,"aw" +.quad 0