Skip to content

Commit 488a62f

Browse files
authored
[lld][ELF][AVR] Add range check for R_AVR_13_PCREL (#67636)
Some large AVR programs (for devices without long jump) may exceed 128KiB, and lld should give explicit errors other than generate wrong executables silently.
1 parent b935882 commit 488a62f

File tree

2 files changed

+56
-1
lines changed

2 files changed

+56
-1
lines changed

lld/ELF/Arch/AVR.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,13 +231,14 @@ void AVR::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
231231

232232
// Since every jump destination is word aligned we gain an extra bit
233233
case R_AVR_7_PCREL: {
234-
checkInt(loc, val, 7, rel);
234+
checkInt(loc, val - 2, 7, rel);
235235
checkAlignment(loc, val, 2, rel);
236236
const uint16_t target = (val - 2) >> 1;
237237
write16le(loc, (read16le(loc) & 0xfc07) | ((target & 0x7f) << 3));
238238
break;
239239
}
240240
case R_AVR_13_PCREL: {
241+
checkInt(loc, val - 2, 13, rel);
241242
checkAlignment(loc, val, 2, rel);
242243
const uint16_t target = (val - 2) >> 1;
243244
write16le(loc, (read16le(loc) & 0xf000) | (target & 0xfff));
@@ -255,6 +256,7 @@ void AVR::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
255256
break;
256257

257258
case R_AVR_CALL: {
259+
checkAlignment(loc, val, 2, rel);
258260
uint16_t hi = val >> 17;
259261
uint16_t lo = val >> 1;
260262
write16le(loc, read16le(loc) | ((hi >> 1) << 4) | (hi & 1));

lld/test/ELF/avr-reloc-error.s

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# REQUIRES: avr
2+
3+
# RUN: rm -rf %t && split-file %s %t && cd %t
4+
5+
# RUN: llvm-mc -filetype=obj -triple=avr -mcpu=atmega328 avr-pcrel-7.s -o avr-pcrel-7.o
6+
# RUN: not ld.lld avr-pcrel-7.o -o /dev/null -Ttext=0x1000 --defsym=callee0=0x1040 --defsym=callee1=0x1044 --defsym=callee2=0x100f 2>&1 | \
7+
# RUN: FileCheck %s --check-prefix=PCREL7
8+
# RUN: llvm-mc -filetype=obj -triple=avr -mcpu=atmega328 avr-pcrel-13.s -o avr-pcrel-13.o
9+
# RUN: not ld.lld avr-pcrel-13.o -o /dev/null -Ttext=0x1000 --defsym=callee0=0x2000 --defsym=callee1=0x2004 --defsym=callee2=0x100f 2>&1 | \
10+
# RUN: FileCheck %s --check-prefix=PCREL13
11+
# RUN: llvm-mc -filetype=obj -triple=avr -mcpu=atmega328 avr-abs.s -o avr-abs.o
12+
# RUN: not ld.lld avr-abs.o -o /dev/null -Ttext=0x1000 --defsym=callee0=0x1009 --defsym=callee1=0x1010 2>&1 | \
13+
# RUN: FileCheck %s --check-prefix=ABS
14+
15+
#--- avr-pcrel-7.s
16+
17+
.section .LDI,"ax",@progbits
18+
19+
.globl __start
20+
__start:
21+
22+
# PCREL7-NOT: callee0
23+
# PCREL7: error: {{.*}} relocation R_AVR_7_PCREL out of range: {{.*}} is not in [-64, 63]; references 'callee1'
24+
# PCREL7: error: {{.*}} improper alignment for relocation R_AVR_7_PCREL: {{.*}} is not aligned to 2 bytes
25+
brne callee0
26+
breq callee1
27+
brlt callee2
28+
29+
#--- avr-pcrel-13.s
30+
31+
.section .LDI,"ax",@progbits
32+
33+
.globl __start
34+
__start:
35+
36+
# PCREL13-NOT: callee0
37+
# PCREL13: error: {{.*}} relocation R_AVR_13_PCREL out of range: {{.*}} is not in [-4096, 4095]; references 'callee1'
38+
# PCREL13: error: {{.*}} improper alignment for relocation R_AVR_13_PCREL: {{.*}} is not aligned to 2 bytes
39+
rjmp callee0
40+
rcall callee1
41+
rjmp callee2
42+
43+
#--- avr-abs.s
44+
45+
.section .LDI,"ax",@progbits
46+
47+
.globl __start
48+
__start:
49+
50+
# ABS: error: {{.*}} improper alignment for relocation R_AVR_CALL: 0x1009 is not aligned to 2 bytes
51+
# ABS-NOT: 0x1010
52+
call callee0
53+
jmp callee1

0 commit comments

Comments
 (0)