[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
Mon Oct 2 18:50:07 PDT 2023


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

>From c2b7340214305f8e1ee1102307a42582ba9fcce3 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

Some large AVR programs (for devices without long jump) may
exceed 128KiB, and lld should report explicit errors other than
generate wrong executables silently.
---
 lld/ELF/Arch/AVR.cpp           |  2 ++
 lld/test/ELF/avr-reloc-error.s | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+)
 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..de51d155a7c9f1c 100644
--- a/lld/ELF/Arch/AVR.cpp
+++ b/lld/ELF/Arch/AVR.cpp
@@ -238,6 +238,7 @@ void AVR::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     break;
   }
   case R_AVR_13_PCREL: {
+    checkInt(loc, val, 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..293d2ce10b9cea1
--- /dev/null
+++ b/lld/test/ELF/avr-reloc-error.s
@@ -0,0 +1,33 @@
+; REQUIRES: avr
+; RUN: llvm-mc -filetype=obj -triple=avr -mcpu=atmega328 %s -o %t.o
+; RUN: not ld.lld %t.o -o /dev/null -Ttext=0x1000 --defsym=callee=0xf00 2>&1 | \
+; RUN:     FileCheck %s --check-prefix=CHECKA --implicit-check-not=R_AVR_13_PCREL
+; RUN: not ld.lld %t.o -o /dev/null -Ttext=0x1000 --defsym=callee=0x2048 2>&1 | \
+; RUN:     FileCheck %s --check-prefix=CHECKB --implicit-check-not=R_AVR_CALL
+; RUN: not ld.lld %t.o -o /dev/null -Ttext=0x1000 --defsym=callee=0x100f 2>&1 | \
+; RUN:     FileCheck %s --check-prefix=CHECKC
+
+.section .LDI,"ax", at progbits
+
+.globl __init
+__init:
+
+; CHECKA: error: {{.*}} relocation R_AVR_7_PCREL out of range: {{.*}} is not in [-64, 63]; references 'callee'
+; CHECKB: error: {{.*}} relocation R_AVR_7_PCREL out of range: {{.*}} is not in [-64, 63]; references 'callee'
+; CHECKB: error: {{.*}} relocation R_AVR_13_PCREL out of range: {{.*}} is not in [-4096, 4095]; references 'callee'
+; CHECKC: error: {{.*}} improper alignment for relocation R_AVR_7_PCREL: {{.*}} is not aligned to 2 bytes
+; CHECKC: error: {{.*}} improper alignment for relocation R_AVR_13_PCREL: {{.*}} is not aligned to 2 bytes
+; CHECKC: error: {{.*}} improper alignment for relocation R_AVR_CALL: {{.*}} is not aligned to 2 bytes
+brne  callee
+rjmp  callee
+jmp   callee
+
+; CHECKA: error: {{.*}} relocation R_AVR_7_PCREL out of range: {{.*}} is not in [-64, 63]; references 'callee'
+; CHECKB: error: {{.*}} relocation R_AVR_7_PCREL out of range: {{.*}} is not in [-64, 63]; references 'callee'
+; CHECKB: error: {{.*}} relocation R_AVR_13_PCREL out of range: {{.*}} is not in [-4096, 4095]; references 'callee'
+; CHECKC: error: {{.*}} improper alignment for relocation R_AVR_7_PCREL: {{.*}} is not aligned to 2 bytes
+; CHECKC: error: {{.*}} improper alignment for relocation R_AVR_13_PCREL: {{.*}} is not aligned to 2 bytes
+; CHECKC: error: {{.*}} improper alignment for relocation R_AVR_CALL: {{.*}} is not aligned to 2 bytes
+breq  callee
+rcall callee
+call  callee



More information about the llvm-commits mailing list