return CmdRef;
}
+// Expands the memory region by the specified size.
+static void expandMemoryRegion(MemoryRegion *MemRegion, uint64_t Size,
+ StringRef RegionName, StringRef SecName) {
+ MemRegion->CurPos += Size;
+ uint64_t NewSize = MemRegion->CurPos - MemRegion->Origin;
+ if (NewSize > MemRegion->Length)
+ error("section '" + SecName + "' will not fit in region '" + RegionName +
+ "': overflowed by " + Twine(NewSize - MemRegion->Length) + " bytes");
+}
+
+void LinkerScript::expandOutputSection(uint64_t Size) {
+ Ctx->OutSec->Size += Size;
+ if (Ctx->MemRegion)
+ expandMemoryRegion(Ctx->MemRegion, Size, Ctx->MemRegion->Name,
+ Ctx->OutSec->Name);
+ // FIXME: check LMA region overflow too.
+ if (Ctx->LMARegion)
+ Ctx->LMARegion->CurPos += Size;
+}
+
void LinkerScript::setDot(Expr E, const Twine &Loc, bool InSec) {
uint64_t Val = E().getValue();
if (Val < Dot && InSec)
error(Loc + ": unable to move location counter backward for: " +
Ctx->OutSec->Name);
- Dot = Val;
// Update to location counter means update to section size.
if (InSec)
- Ctx->OutSec->Size = Dot - Ctx->OutSec->Addr;
+ expandOutputSection(Val - Dot);
+ Dot = Val;
}
// Used for handling linker symbol assignments, for both finalizing
return End;
}
-// Expands the memory region by the specified size.
-static void expandMemoryRegion(MemoryRegion *MemRegion, uint64_t Size,
- StringRef RegionName, StringRef SecName) {
- MemRegion->CurPos += Size;
- uint64_t NewSize = MemRegion->CurPos - MemRegion->Origin;
- if (NewSize > MemRegion->Length)
- error("section '" + SecName + "' will not fit in region '" + RegionName +
- "': overflowed by " + Twine(NewSize - MemRegion->Length) + " bytes");
-}
-
void LinkerScript::output(InputSection *S) {
uint64_t Before = advance(0, 1);
uint64_t Pos = advance(S->getSize(), S->Alignment);
// Update output section size after adding each section. This is so that
// SIZEOF works correctly in the case below:
// .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) }
- Ctx->OutSec->Size = Pos - Ctx->OutSec->Addr;
-
- // If there is a memory region associated with this input section, then
- // place the section in that region and update the region index.
- if (Ctx->LMARegion)
- Ctx->LMARegion->CurPos += Pos - Before;
- // FIXME: should we also produce overflow errors for LMARegion?
-
- if (Ctx->MemRegion)
- expandMemoryRegion(Ctx->MemRegion, Pos - Before, Ctx->MemRegion->Name,
- Ctx->OutSec->Name);
+ expandOutputSection(Pos - Before);
}
void LinkerScript::switchTo(OutputSection *Sec) {
if (auto *Cmd = dyn_cast<ByteCommand>(Base)) {
Cmd->Offset = Dot - Ctx->OutSec->Addr;
Dot += Cmd->Size;
- if (Ctx->MemRegion)
- expandMemoryRegion(Ctx->MemRegion, Cmd->Size, Ctx->MemRegion->Name,
- Ctx->OutSec->Name);
- if (Ctx->LMARegion)
- Ctx->LMARegion->CurPos += Cmd->Size;
- Ctx->OutSec->Size = Dot - Ctx->OutSec->Addr;
+ expandOutputSection(Cmd->Size);
continue;
}
--- /dev/null
+# REQUIRES: x86
+
+# RUN: echo ".section .foo,\"a\"" > %t.s
+# RUN: echo ".quad 1" >> %t.s
+# RUN: echo ".section .bar,\"a\"" >> %t.s
+# RUN: echo ".quad 1" >> %t.s
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t.s -o %t.o
+
+# RUN: ld.lld -o %t %t.o --script %s
+# RUN: llvm-readelf -sections -program-headers %t | FileCheck %s
+
+## Check that we can produce output without errors,
+## and .foo section has proper size.
+# CHECK: Section Headers:
+# CHECK-NEXT: [Nr] Name Type Address Off Size
+# CHECK-NEXT: [ 0] NULL 0000000000000000 000000 000000
+# CHECK-NEXT: [ 1] .foo PROGBITS 0000000000001000 001000 000108
+# CHECK-NEXT: [ 2] .bar PROGBITS 0000000000001108 001108 000008
+
+## Check that load address is correct.
+# CHECK: Program Headers:
+# CHECK-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz
+# CHECK-NEXT: LOAD 0x001000 0x0000000000001000 0x0000000000002000 0x000110 0x000110
+
+MEMORY {
+ ram (rwx) : org = 0x1000, len = 0x200
+ flash (rwx) : org = 0x2000, len = 0x200
+}
+SECTIONS {
+ .foo : {
+ *(.foo)
+ . += 0x100;
+ } > ram AT>flash
+ .bar : {
+ *(.bar)
+ } > ram AT>flash
+}