[llvm] f6d525f - [JITLink][AArch32] Unittest for error paths of readAddend and applyFixup functionality (#69636)

via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 9 01:22:40 PST 2023


Author: Eymen Ünay
Date: 2023-11-09T12:22:36+03:00
New Revision: f6d525f8d8c8db8c509d4cc4441a567324c9e2fd

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

LOG: [JITLink][AArch32] Unittest for error paths of readAddend and applyFixup functionality (#69636)

This test checks for error paths in relocation dependent functions of readAddend and applyFixup. It is useful to check these to avoid unexpected assert errors. Currently opcode errors are triggered in most of the cases in AArch32 but there might be further checks to look for in the future. Different backends can also implement a similar test.

Added: 
    llvm/unittests/ExecutionEngine/JITLink/AArch32ErrorTests.cpp

Modified: 
    llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
    llvm/unittests/ExecutionEngine/JITLink/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
index 97999a61dfe7334..70a97ff83820cec 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
@@ -200,8 +200,8 @@ template <> struct FixupInfo<Arm_MovwAbsNC> : public FixupInfo<Arm_MovtAbs> {
 };
 
 template <> struct FixupInfo<Thumb_Jump24> {
-  static constexpr HalfWords Opcode{0xf000, 0x8000};
-  static constexpr HalfWords OpcodeMask{0xf800, 0x8000};
+  static constexpr HalfWords Opcode{0xf000, 0x9000};
+  static constexpr HalfWords OpcodeMask{0xf800, 0x9000};
   static constexpr HalfWords ImmMask{0x07ff, 0x2fff};
 };
 

diff  --git a/llvm/unittests/ExecutionEngine/JITLink/AArch32ErrorTests.cpp b/llvm/unittests/ExecutionEngine/JITLink/AArch32ErrorTests.cpp
new file mode 100644
index 000000000000000..9a9468b46d5e5cb
--- /dev/null
+++ b/llvm/unittests/ExecutionEngine/JITLink/AArch32ErrorTests.cpp
@@ -0,0 +1,185 @@
+//===------- AArch32ErrorTests.cpp - Test AArch32 error handling ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <llvm/ExecutionEngine/JITLink/aarch32.h>
+
+#include "llvm/Testing/Support/Error.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::jitlink;
+using namespace llvm::jitlink::aarch32;
+using namespace llvm::support;
+using namespace llvm::support::endian;
+
+constexpr unsigned PointerSize = 4;
+auto G = std::make_unique<LinkGraph>("foo", Triple("armv7-linux-gnueabi"),
+                                     PointerSize, llvm::endianness::little,
+                                     getGenericEdgeKindName);
+auto &Sec =
+    G->createSection("__data", orc::MemProt::Read | orc::MemProt::Write);
+
+auto ArmCfg = getArmConfigForCPUArch(ARMBuildAttrs::v7);
+
+constexpr uint64_t ArmAlignment = 4;
+constexpr uint64_t ThumbAlignment = 2;
+constexpr uint64_t AlignmentOffset = 0;
+
+constexpr orc::ExecutorAddrDiff SymbolOffset = 0;
+constexpr orc::ExecutorAddrDiff SymbolSize = 4;
+
+TEST(AArch32_ELF, readAddendArmErrors) {
+
+  constexpr orc::ExecutorAddr B1DummyAddr(0x1000);
+
+  // Permanently undefined instruction in ARM
+  //    udf #0
+  uint8_t ArmWord[] = {0xf0, 0x00, 0xf0, 0xe7};
+  ArrayRef<char> ArmContent(reinterpret_cast<const char *>(&ArmWord),
+                            sizeof(ArmWord));
+  auto &BArm = G->createContentBlock(Sec, ArmContent, B1DummyAddr, ArmAlignment,
+                                     AlignmentOffset);
+  Symbol &TargetSymbol =
+      G->addAnonymousSymbol(BArm, SymbolOffset, SymbolSize, false, false);
+  Edge InvalidEdge(Edge::GenericEdgeKind::Invalid, 0 /*Offset*/, TargetSymbol,
+                   0 /*Addend*/);
+
+  // Edge kind is tested, block itself is not significant here. So it is tested
+  // once in Arm
+  EXPECT_THAT_EXPECTED(readAddendData(*G, BArm, InvalidEdge),
+                       FailedWithMessage(testing::HasSubstr(
+                           "can not read implicit addend for aarch32 edge kind "
+                           "INVALID RELOCATION")));
+
+  EXPECT_THAT_EXPECTED(readAddendArm(*G, BArm, InvalidEdge),
+                       FailedWithMessage(testing::HasSubstr(
+                           "can not read implicit addend for aarch32 edge kind "
+                           "INVALID RELOCATION")));
+
+  EXPECT_THAT_EXPECTED(readAddendThumb(*G, BArm, InvalidEdge, ArmCfg),
+                       FailedWithMessage(testing::HasSubstr(
+                           "can not read implicit addend for aarch32 edge kind "
+                           "INVALID RELOCATION")));
+
+  for (Edge::Kind K = FirstArmRelocation; K < LastArmRelocation; K += 1) {
+    Edge E(K, 0, TargetSymbol, 0);
+    EXPECT_THAT_EXPECTED(
+        readAddendArm(*G, BArm, E),
+        FailedWithMessage(testing::StartsWith("Invalid opcode")));
+  }
+}
+
+TEST(AArch32_ELF, readAddendThumbErrors) {
+
+  constexpr orc::ExecutorAddr B2DummyAddr(0x2000);
+
+  // Permanently undefined instruction in Thumb
+  //    udf #0
+  //
+  //    11110:op:imm4:1:op1:imm12
+  //    op  = 1111111 Permanent undefined
+  //    op1 = 010
+  //
+  constexpr HalfWords ThumbHalfWords{0xf7f0, 0xa000};
+  ArrayRef<char> ThumbContent(reinterpret_cast<const char *>(&ThumbHalfWords),
+                              sizeof(ThumbHalfWords));
+  auto &BThumb = G->createContentBlock(Sec, ThumbContent, B2DummyAddr,
+                                       ThumbAlignment, AlignmentOffset);
+  Symbol &TargetSymbol =
+      G->addAnonymousSymbol(BThumb, SymbolOffset, SymbolSize, false, false);
+  Edge InvalidEdge(Edge::GenericEdgeKind::Invalid, 0 /*Offset*/, TargetSymbol,
+                   0 /*Addend*/);
+
+  for (Edge::Kind K = FirstThumbRelocation; K < LastThumbRelocation; K += 1) {
+    Edge E(K, 0, TargetSymbol, 0);
+    EXPECT_THAT_EXPECTED(
+        readAddendThumb(*G, BThumb, E, ArmCfg),
+        FailedWithMessage(testing::StartsWith("Invalid opcode")));
+  }
+}
+
+TEST(AArch32_ELF, applyFixupArmErrors) {
+
+  constexpr orc::ExecutorAddr B3DummyAddr(0x5000);
+
+  uint8_t ArmWord[] = {0xf0, 0x00, 0xf0, 0xe7};
+  MutableArrayRef<char> MutableArmContent(reinterpret_cast<char *>(ArmWord),
+                                          sizeof(ArmWord));
+
+  auto &BArm = G->createMutableContentBlock(Sec, MutableArmContent, B3DummyAddr,
+                                            ArmAlignment, AlignmentOffset);
+
+  Symbol &TargetSymbol =
+      G->addAnonymousSymbol(BArm, SymbolOffset, SymbolSize, false, false);
+  Edge InvalidEdge(Edge::GenericEdgeKind::Invalid, 0 /*Offset*/, TargetSymbol,
+                   0 /*Addend*/);
+
+  // Edge kind is tested, block itself is not significant here. So it is tested
+  // once in Arm
+  EXPECT_THAT_ERROR(
+      applyFixupData(*G, BArm, InvalidEdge),
+      FailedWithMessage(testing::HasSubstr(
+          "encountered unfixable aarch32 edge kind INVALID RELOCATION")));
+  EXPECT_THAT_ERROR(
+      applyFixupArm(*G, BArm, InvalidEdge),
+      FailedWithMessage(testing::HasSubstr(
+          "encountered unfixable aarch32 edge kind INVALID RELOCATION")));
+  EXPECT_THAT_ERROR(
+      applyFixupThumb(*G, BArm, InvalidEdge, ArmCfg),
+      FailedWithMessage(testing::HasSubstr(
+          "encountered unfixable aarch32 edge kind INVALID RELOCATION")));
+
+  for (Edge::Kind K = FirstArmRelocation; K < LastArmRelocation; K += 1) {
+    Edge E(K, 0, TargetSymbol, 0);
+    EXPECT_THAT_ERROR(applyFixupArm(*G, BArm, E),
+                      FailedWithMessage(testing::AllOf(
+                          testing::StartsWith("Invalid opcode"),
+                          testing::EndsWith(G->getEdgeKindName(K)))));
+  }
+}
+
+TEST(AArch32_ELF, applyFixupThumbErrors) {
+
+  struct MutableHalfWords {
+    constexpr MutableHalfWords(HalfWords Preset)
+        : Hi(Preset.Hi), Lo(Preset.Lo) {}
+
+    uint16_t Hi; // First halfword
+    uint16_t Lo; // Second halfword
+  };
+
+  constexpr orc::ExecutorAddr B4DummyAddr(0x6000);
+
+  // Permanently undefined instruction in Thumb
+  //    udf #0
+  //
+  //    11110:op:imm4:1:op1:imm12
+  //    op  = 1111111 Permanent undefined
+  //    op1 = 010
+  //
+  constexpr HalfWords ThumbHalfWords{0xf7f0, 0xa000};
+  MutableHalfWords MutableThumbHalfWords{ThumbHalfWords};
+  MutableArrayRef<char> MutableThumbContent(
+      reinterpret_cast<char *>(&MutableThumbHalfWords),
+      sizeof(MutableThumbHalfWords));
+
+  auto &BThumb = G->createMutableContentBlock(
+      Sec, MutableThumbContent, B4DummyAddr, ThumbAlignment, AlignmentOffset);
+  Symbol &TargetSymbol =
+      G->addAnonymousSymbol(BThumb, SymbolOffset, SymbolSize, false, false);
+  Edge InvalidEdge(Edge::GenericEdgeKind::Invalid, 0 /*Offset*/, TargetSymbol,
+                   0 /*Addend*/);
+
+  for (Edge::Kind K = FirstThumbRelocation; K < LastThumbRelocation; K += 1) {
+    Edge E(K, 0, TargetSymbol, 0);
+    EXPECT_THAT_ERROR(applyFixupThumb(*G, BThumb, E, ArmCfg),
+                      FailedWithMessage(testing::AllOf(
+                          testing::StartsWith("Invalid opcode"),
+                          testing::EndsWith(G->getEdgeKindName(K)))));
+  }
+}

diff  --git a/llvm/unittests/ExecutionEngine/JITLink/CMakeLists.txt b/llvm/unittests/ExecutionEngine/JITLink/CMakeLists.txt
index e535bcf47fc801e..d4886754f0a9ca4 100644
--- a/llvm/unittests/ExecutionEngine/JITLink/CMakeLists.txt
+++ b/llvm/unittests/ExecutionEngine/JITLink/CMakeLists.txt
@@ -9,6 +9,7 @@ set(LLVM_LINK_COMPONENTS
 
 add_llvm_unittest(JITLinkTests
     AArch32Tests.cpp
+    AArch32ErrorTests.cpp
     EHFrameSupportTests.cpp
     JITLinkMocks.cpp
     LinkGraphTests.cpp


        


More information about the llvm-commits mailing list