Skip to content

Commit 3f866ed

Browse files
committed
[CHERIoT] Make sure that CAPALIGN directives work properly with ". += ..." directives.
1 parent 0967d92 commit 3f866ed

File tree

4 files changed

+46
-4
lines changed

4 files changed

+46
-4
lines changed

lld/ELF/LinkerScript.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,12 +1102,21 @@ void LinkerScript::diagnoseMissingSGSectionAddress() const {
11021102
// This is roughly the same logic as the loop in assignOffsets() to loop
11031103
// through all commands and input sections in an output section to calculate
11041104
// the total size.
1105-
static uint64_t outputSectionCheriAlignment(Ctx &ctx, OutputSection *sec)
1106-
{
1105+
uint64_t LinkerScript::outputSectionCheriAlignment(OutputSection *sec) {
11071106
uint64_t total = 0;
11081107

11091108
for (SectionCommand *cmd : sec->commands) {
1110-
if (dyn_cast<SymbolAssignment>(cmd)) {
1109+
if (SymbolAssignment *assign = dyn_cast<SymbolAssignment>(cmd)) {
1110+
if (assign->name == ".") {
1111+
// Evaluating an expression like ". += 0x100" will attempt to read
1112+
// the current value of dot, which isn't accurate since we're doing
1113+
// things out of order here. We can fake it by temporarily setting
1114+
// the value of dot and restoring it later.
1115+
auto oldDot = dot;
1116+
dot = total;
1117+
total += assign->expression().getValue();
1118+
dot = oldDot;
1119+
}
11111120
continue;
11121121
}
11131122

@@ -1230,7 +1239,7 @@ bool LinkerScript::assignOffsets(OutputSection *sec) {
12301239
// ALIGN is respected. sec->alignment is the max of ALIGN and the maximum of
12311240
// input section alignments.
12321241
if (sec->isCapAligned) {
1233-
uint64_t capAlignment = outputSectionCheriAlignment(ctx, sec);
1242+
uint64_t capAlignment = outputSectionCheriAlignment(sec);
12341243
if (capAlignment > 1) {
12351244
sec->addralign = std::max<uint64_t>(capAlignment, sec->addralign);
12361245
}

lld/ELF/LinkerScript.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ class LinkerScript final {
340340
findMemoryRegion(OutputSection *sec, MemoryRegion *hint);
341341

342342
bool assignOffsets(OutputSection *sec);
343+
uint64_t outputSectionCheriAlignment(OutputSection *sec);
343344

344345
// This captures the local AddressState and makes it accessible
345346
// deliberately. This is needed as there are some cases where we cannot just
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
SECTIONS {
2+
. = 0x1245;
3+
. = ALIGN(8);
4+
.bar : CAPALIGN {
5+
.bar_start = .;
6+
. += 0x100000;
7+
.bar_end = .;
8+
}
9+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// REQUIRES: riscv
2+
// RUN: llvm-mc -triple riscv32-unknown-cheriotrtos -filetype=obj -o %t %s
3+
// RUN: ld.lld %t %S/Inputs/cheriot-capalign.lds -o %t2
4+
// RUN: llvm-readobj --sections %t2 | FileCheck %s
5+
6+
// Verify that CAPALIGN directives in the linker script actually
7+
// force higher alignment on an over-sized section.
8+
9+
// CHECK: Index: 2
10+
// CHECK-NEXT: Name: .bar (7)
11+
// CHECK-NEXT: Type: SHT_PROGBITS (0x1)
12+
// CHECK-NEXT: Flags [ (0x0)
13+
// CHECK-NEXT: ]
14+
// CHECK-NEXT: Address: 0x0
15+
// CHECK-NEXT: Offset: 0x20000
16+
// CHECK-NEXT: Size: 1179648
17+
// CHECK-NEXT: Link: 0
18+
// CHECK-NEXT: Info: 0
19+
// CHECK-NEXT: AddressAlignment: 131072
20+
// CHECK-NEXT: EntrySize: 0
21+
22+
.section .bar
23+
.byte 0

0 commit comments

Comments
 (0)