[lld] [lld][ELF][AVR] Add range check for R_AVR_13_PCREL (PR #67636)

Ben Shi via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 3 06:27:45 PDT 2023


https://github.com/benshi001 updated https://github.com/llvm/llvm-project/pull/67636

>From a0dd42ae49eb5a3ec905aae4fda773f59e83172e Mon Sep 17 00:00:00 2001
From: Ben Shi <bennshi at tencent.com>
Date: Thu, 28 Sep 2023 14:49:26 +0800
Subject: [PATCH] [lld][ELF][AVR] Add range and alignment checks for AVR
 relocations

lld should report explicit range and alignment errors for some relocations
other than silently generate incorrect ELF outputs.
---
 lld/ELF/Arch/AVR.cpp           |  4 ++-
 lld/test/ELF/avr-reloc-error.s | 53 ++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+), 1 deletion(-)
 create mode 100644 lld/test/ELF/avr-reloc-error.s

diff --git a/lld/ELF/Arch/AVR.cpp b/lld/ELF/Arch/AVR.cpp
index 4905d61796fa98f..9211eabc9669a5e 100644
--- a/lld/ELF/Arch/AVR.cpp
+++ b/lld/ELF/Arch/AVR.cpp
@@ -231,13 +231,14 @@ void AVR::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
 
   // Since every jump destination is word aligned we gain an extra bit
   case R_AVR_7_PCREL: {
-    checkInt(loc, val, 7, rel);
+    checkInt(loc, val - 2, 7, rel);
     checkAlignment(loc, val, 2, rel);
     const uint16_t target = (val - 2) >> 1;
     write16le(loc, (read16le(loc) & 0xfc07) | ((target & 0x7f) << 3));
     break;
   }
   case R_AVR_13_PCREL: {
+    checkInt(loc, val - 2, 13, rel);
     checkAlignment(loc, val, 2, rel);
     const uint16_t target = (val - 2) >> 1;
     write16le(loc, (read16le(loc) & 0xf000) | (target & 0xfff));
@@ -255,6 +256,7 @@ void AVR::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     break;
 
   case R_AVR_CALL: {
+    checkAlignment(loc, val, 2, rel);
     uint16_t hi = val >> 17;
     uint16_t lo = val >> 1;
     write16le(loc, read16le(loc) | ((hi >> 1) << 4) | (hi & 1));
diff --git a/lld/test/ELF/avr-reloc-error.s b/lld/test/ELF/avr-reloc-error.s
new file mode 100644
index 000000000000000..c8d84f99569cad6
--- /dev/null
+++ b/lld/test/ELF/avr-reloc-error.s
@@ -0,0 +1,53 @@
+# REQUIRES: avr
+
+# RUN: rm -rf %t && split-file %s %t && cd %t
+
+# RUN: llvm-mc -filetype=obj -triple=avr -mcpu=atmega328 avr-pcrel-7.s -o avr-pcrel-7.o
+# RUN: not ld.lld avr-pcrel-7.o -o /dev/null -Ttext=0x1000 --defsym=callee0=0x1040 --defsym=callee1=0x1044 --defsym=callee2=0x100f 2>&1 | \
+# RUN:     FileCheck %s --check-prefix=PCREL7
+# RUN: llvm-mc -filetype=obj -triple=avr -mcpu=atmega328 avr-pcrel-13.s -o avr-pcrel-13.o
+# RUN: not ld.lld avr-pcrel-13.o -o /dev/null -Ttext=0x1000 --defsym=callee0=0x2000 --defsym=callee1=0x2004 --defsym=callee2=0x100f 2>&1 | \
+# RUN:     FileCheck %s --check-prefix=PCREL13
+# RUN: llvm-mc -filetype=obj -triple=avr -mcpu=atmega328 avr-abs.s -o avr-abs.o
+# RUN: not ld.lld avr-abs.o -o /dev/null -Ttext=0x1000 --defsym=callee0=0x1009 --defsym=callee1=0x1010 2>&1 | \
+# RUN:     FileCheck %s --check-prefix=ABS
+
+#--- avr-pcrel-7.s
+
+.section .LDI,"ax", at progbits
+
+.globl __start
+__start:
+
+# PCREL7-NOT: callee0
+# PCREL7:     error: {{.*}} relocation R_AVR_7_PCREL out of range: {{.*}} is not in [-64, 63]; references 'callee1'
+# PCREL7:     error: {{.*}} improper alignment for relocation R_AVR_7_PCREL: {{.*}} is not aligned to 2 bytes
+brne callee0
+breq callee1
+brlt callee2
+
+#--- avr-pcrel-13.s
+
+.section .LDI,"ax", at progbits
+
+.globl __start
+__start:
+
+# PCREL13-NOT: callee0
+# PCREL13:     error: {{.*}} relocation R_AVR_13_PCREL out of range: {{.*}} is not in [-4096, 4095]; references 'callee1'
+# PCREL13:     error: {{.*}} improper alignment for relocation R_AVR_13_PCREL: {{.*}} is not aligned to 2 bytes
+rjmp  callee0
+rcall callee1
+rjmp  callee2
+
+#--- avr-abs.s
+
+.section .LDI,"ax", at progbits
+
+.globl __start
+__start:
+
+# ABS:     improper alignment for relocation R_AVR_CALL: 0x1009 is not aligned to 2 bytes
+# ABS-NOT: 0x1010
+call callee0
+jmp  callee1



More information about the llvm-commits mailing list