Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linker scripts can align to offsets, and require valid alignments #1271

Merged
merged 1 commit into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions man/rgblink.5
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,25 @@ and
.Ic DS :
.Bl -bullet
.It
.Ic ORG
sets the address in which new sections will be placed.
.Ic ORG Ar addr
sets the address in which new sections will be placed to
.Ar addr .
It can not be lower than the current address.
.It
.Ic ALIGN
.Ic ALIGN Ar addr
or
.Ic ALIGN Ar addr , Ar offset
will increase the address until it is aligned to the specified boundary
.Po it tries to set to 0 the number of bits specified after the directive:
.Po it tries to set to
.Ar offset
the number of bits specified by
.Ar align :
for example,
.Ql ALIGN 8
will align to $100
will align to $100 ,
and
.Ql ALIGN 8 , 10
will align to $10A
.Pc .
.It
.Ic DS
Expand Down
41 changes: 32 additions & 9 deletions src/link/script.y
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@

%token YYEOF 0 "end of file"
%token newline
%token COMMA ","
%token ORG "ORG"
INCLUDE "INCLUDE"
ALIGN "ALIGN"
Expand Down Expand Up @@ -83,6 +84,7 @@ directive: section_type { setSectionType($1); }
| section_type number { setSectionType($1, $2); }
| ORG number { setAddr($2); }
| ALIGN number { alignTo($2, 0); }
| ALIGN number COMMA number { alignTo($2, $4); }
| DS number { pad($2); }
| string { placeSection($1); }
;
Expand Down Expand Up @@ -197,6 +199,8 @@ try_again: // Can't use a `do {} while(0)` loop, otherwise compilers (wrongly) t
} else {
return yy::parser::make_YYEOF();
}
} else if (c == ',') {
return yy::parser::make_COMMA();
} else if (isNewline(c)) {
// Handle CRLF.
if (c == '\r' && context.file.sgetc() == '\n') {
Expand Down Expand Up @@ -372,18 +376,37 @@ static void alignTo(uint32_t alignment, uint32_t alignOfs) {
auto const &typeInfo = sectionTypeInfo[activeType];
auto &pc = curAddr[activeType][activeBankIdx];

// TODO: maybe warn if truncating?
alignOfs %= 1 << alignment;
if (alignment > 16) {
scriptError(context, "Cannot align: The alignment (%" PRIu32 ") must be less than 16\n",
alignment);
return;
}

// Let it wrap around, this'll trip the final check if alignment == 16.
uint16_t length = alignOfs - pc;

if (alignment < 16) {
uint32_t alignSize = 1u << alignment;

if (alignOfs >= alignSize) {
scriptError(context, "Cannot align: The alignment offset (%" PRIu32
") must be less than alignment size (%" PRIu32 ")\n",
alignOfs, 1 << alignment);
return;
}

assert(pc >= typeInfo.startAddr);
length %= alignSize;
}

assert(pc >= typeInfo.startAddr);
uint16_t length = alignment < 16 ? (uint16_t)(alignOfs - pc) % (1u << alignment)
: alignOfs - pc; // Let it wrap around, this'll trip the check.
if (uint16_t offset = pc - typeInfo.startAddr; length > typeInfo.size - offset) {
scriptError(context, "Cannot align: the next suitable address after $%04" PRIx16 " is $%04" PRIx16 ", past $%04" PRIx16,
pc, (uint16_t)(pc + length), (uint16_t)(endaddr(activeType) + 1));
} else {
pc += length;
scriptError(context, "Cannot align: the next suitable address after $%04"
PRIx16 " is $%04" PRIx16 ", past $%04" PRIx16,
pc, (uint16_t)(pc + length), (uint16_t)(endaddr(activeType) + 1));
return;
}

pc += length;
}

static void pad(uint32_t length) {
Expand Down
2 changes: 1 addition & 1 deletion test/link/section-attributes-mismatch.out
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
error: ./section-attributes-mismatch.link(3): The linker script assigns section "sec" to address $0018, but that would be ALIGN[4, 8] instead of the requested ALIGN[4, 0]
error: ./section-attributes-mismatch.link(3): The linker script assigns section "sec" to address $0018, but that would be ALIGN[4, 8] instead of the requested ALIGN[4, 2]
Linking failed with 1 error
4 changes: 2 additions & 2 deletions test/link/section-attributes.asm
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
SECTION "sec",ROM0,ALIGN[4]
ds 8, $42
SECTION "sec",ROM0,ALIGN[4,2]
ds 6, $42
SECTION "secfix",ROM0[$20]
3 changes: 2 additions & 1 deletion test/link/section-attributes.link
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
ROM0
align 4
align 4, 2
"sec"
ds $18
org $20
align 5
"secfix"