[lld] 7a781fb - [LLD][ELF][AVR] Propagate ELF flags to the linked image

via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 16 01:40:24 PDT 2021


Author: LemonBoy
Date: 2021-04-16T10:40:18+02:00
New Revision: 7a781fb692975ded33ff86c06f838fe904e706f8

URL: https://github.com/llvm/llvm-project/commit/7a781fb692975ded33ff86c06f838fe904e706f8
DIFF: https://github.com/llvm/llvm-project/commit/7a781fb692975ded33ff86c06f838fe904e706f8.diff

LOG: [LLD][ELF][AVR] Propagate ELF flags to the linked image

The `e_flags` for a ELF file targeting the AVR ISA contains two fields at the time of writing:
- A 7-bit integer field specifying the ISA revision being targeted
- A 1-bit flag specifying whether the object files being linked are suited for applying the relaxations at link time

The linked ELF file is blessed with the arch revision shared among all the files.
The behaviour in case of mismatch is purposefully different than the one implemented in libbfd: LLD will raise a fatal error while libbfd silently picks a default value of `avr2`.
The relaxation-ready flag is handled as done by libbfd, in order for it to appear in the linked object every source object must be tagged with it.

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D99754

Added: 
    lld/test/ELF/avr-flags.s

Modified: 
    lld/ELF/Arch/AVR.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Arch/AVR.cpp b/lld/ELF/Arch/AVR.cpp
index 4513a970b32d7..0926ff2d0b4b6 100644
--- a/lld/ELF/Arch/AVR.cpp
+++ b/lld/ELF/Arch/AVR.cpp
@@ -43,6 +43,7 @@ namespace {
 class AVR final : public TargetInfo {
 public:
   AVR();
+  uint32_t calcEFlags() const override;
   RelExpr getRelExpr(RelType type, const Symbol &s,
                      const uint8_t *loc) const override;
   void relocate(uint8_t *loc, const Relocation &rel,
@@ -196,3 +197,28 @@ TargetInfo *elf::getAVRTargetInfo() {
   static AVR target;
   return ⌖
 }
+
+static uint32_t getEFlags(InputFile *file) {
+  return cast<ObjFile<ELF32LE>>(file)->getObj().getHeader().e_flags;
+}
+
+uint32_t AVR::calcEFlags() const {
+  assert(!objectFiles.empty());
+
+  uint32_t flags = getEFlags(objectFiles[0]);
+  bool hasLinkRelaxFlag = flags & EF_AVR_LINKRELAX_PREPARED;
+
+  for (InputFile *f : makeArrayRef(objectFiles).slice(1)) {
+    uint32_t objFlags = getEFlags(f);
+    if ((objFlags & EF_AVR_ARCH_MASK) != (flags & EF_AVR_ARCH_MASK))
+      error(toString(f) +
+            ": cannot link object files with incompatible target ISA");
+    if (!(objFlags & EF_AVR_LINKRELAX_PREPARED))
+      hasLinkRelaxFlag = false;
+  }
+
+  if (!hasLinkRelaxFlag)
+    flags &= ~EF_AVR_LINKRELAX_PREPARED;
+
+  return flags;
+}

diff  --git a/lld/test/ELF/avr-flags.s b/lld/test/ELF/avr-flags.s
new file mode 100644
index 0000000000000..61e86ba4cc9f7
--- /dev/null
+++ b/lld/test/ELF/avr-flags.s
@@ -0,0 +1,15 @@
+; RUN: llvm-mc -filetype=obj -triple=avr -mcpu=avr5 %s -o %t-v5
+; RUN: llvm-mc -filetype=obj -triple=avr -mcpu=avrxmega3 %s -o %t-xmega3
+; RUN: ld.lld %t-v5 -o %t-v5.out
+; RUN: ld.lld %t-xmega3 -o %t-xmega3.out
+; RUN: llvm-readobj -h %t-v5.out | FileCheck --check-prefix V5 %s
+; RUN: llvm-readobj -h %t-xmega3.out | FileCheck --check-prefix XMEGA3 %s
+
+;; Ensure LLD won't silently mix object files targeting 
diff erent ISAs.
+; RUN: not ld.lld %t-v5 %t-xmega3 -o /dev/null 2>&1 | FileCheck --check-prefix ERR %s
+; ERR: error: {{.*}}: cannot link object files with incompatible target ISA
+
+; V5:  Flags [ (0x5)
+; V5:  EF_AVR_ARCH_AVR5 (0x5)
+; XMEGA3: Flags [ (0x67)
+; XMEGA3: EF_AVR_ARCH_XMEGA3 (0x67)


        


More information about the llvm-commits mailing list