Skip to content

Commit 5ae8567

Browse files
authored
Fix R_AVR_7_PCREL and R_AVR_13_PCREL range checking (#92695)
Fix incorrect range check of R_AVR_7_PCREL. R_AVR_7_PCREL has 7 bits available, but it works in instruction words and the actual range is [-128, 126]. Disable range check of R_AVR_13_PCREL. This matches the behavior of avr-ld, and is needed for devices like the ATtiny85 which only have rjmp/rcall but have 8KiB flash memory.
1 parent b91b8fe commit 5ae8567

File tree

3 files changed

+15
-5
lines changed

3 files changed

+15
-5
lines changed

lld/ELF/Arch/AVR.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,14 +231,13 @@ 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 - 2, 7, rel);
234+
checkInt(loc, val - 2, 8, 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);
242241
checkAlignment(loc, val, 2, rel);
243242
const uint16_t target = (val - 2) >> 1;
244243
write16le(loc, (read16le(loc) & 0xf000) | (target & 0xfff));

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# RUN: rm -rf %t && split-file %s %t && cd %t
44

55
# 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 | \
6+
# RUN: not ld.lld avr-pcrel-7.o -o /dev/null -Ttext=0x1000 --defsym=callee0=0x1040 --defsym=callee1=0x1084 --defsym=callee2=0x100f 2>&1 | \
77
# RUN: FileCheck %s --check-prefix=PCREL7
88
# RUN: llvm-mc -filetype=obj -triple=avr -mcpu=atmega328 avr-pcrel-13.s -o avr-pcrel-13.o
99
# RUN: not ld.lld avr-pcrel-13.o -o /dev/null -Ttext=0x1000 --defsym=callee0=0x2000 --defsym=callee1=0x2004 --defsym=callee2=0x100f 2>&1 | \
@@ -20,7 +20,7 @@
2020
__start:
2121

2222
# PCREL7-NOT: callee0
23-
# PCREL7: error: {{.*}} relocation R_AVR_7_PCREL out of range: {{.*}} is not in [-64, 63]; references 'callee1'
23+
# PCREL7: error: {{.*}} relocation R_AVR_7_PCREL out of range: {{.*}} is not in [-128, 127]; references 'callee1'
2424
# PCREL7: error: {{.*}} improper alignment for relocation R_AVR_7_PCREL: {{.*}} is not aligned to 2 bytes
2525
brne callee0
2626
breq callee1
@@ -34,7 +34,6 @@ brlt callee2
3434
__start:
3535

3636
# PCREL13-NOT: callee0
37-
# PCREL13: error: {{.*}} relocation R_AVR_13_PCREL out of range: {{.*}} is not in [-4096, 4095]; references 'callee1'
3837
# PCREL13: error: {{.*}} improper alignment for relocation R_AVR_13_PCREL: {{.*}} is not aligned to 2 bytes
3938
rjmp callee0
4039
rcall callee1

lld/test/ELF/avr-reloc.s

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,25 @@ sbic b, 1 ; R_AVR_PORT5
8282
; CHECK-NEXT: rjmp .-36
8383
; CHECK-NEXT: breq .+26
8484
; CHECK-NEXT: breq .-40
85+
; CHECK-NEXT: rjmp .-4096
86+
; CHECK-NEXT: rjmp .+4094
87+
; CHECK-NEXT: rjmp .+4094
88+
; CHECK-NEXT: rjmp .-4096
89+
; CHECK-NEXT: breq .-128
90+
; CHECK-NEXT: breq .+126
8591
; HEX-LABEL: section .PCREL:
8692
; HEX-NEXT: 0fc0eecf 69f061f3
8793
foo:
8894
rjmp foo + 32 ; R_AVR_13_PCREL
8995
rjmp foo - 32 ; R_AVR_13_PCREL
9096
breq foo + 32 ; R_AVR_7_PCREL
9197
breq foo - 32 ; R_AVR_7_PCREL
98+
rjmp 1f - 4096 $ 1: ; R_AVR_13_PCREL
99+
rjmp 1f + 4094 $ 1: ; R_AVR_13_PCREL
100+
rjmp 1f - 4098 $ 1: ; R_AVR_13_PCREL (overflow)
101+
rjmp 1f + 4096 $ 1: ; R_AVR_13_PCREL (overflow)
102+
breq 1f - 128 $ 1: ; R_AVR_7_PCREL
103+
breq 1f + 126 $ 1: ; R_AVR_7_PCREL
92104

93105
.section .LDSSTS,"ax",@progbits
94106
; CHECK-LABEL: section .LDSSTS:

0 commit comments

Comments
 (0)