Skip to content

Commit f32509b

Browse files
[JITLink][AArch32] Test out-of-range and interworking errors for Thumb (#73397)
1 parent 9415fca commit f32509b

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

llvm/unittests/ExecutionEngine/JITLink/AArch32ErrorTests.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,17 @@ class AArch32Errors : public testing::Test {
7272
return G->createMutableContentBlock(
7373
*S, CharContent, orc::ExecutorAddr(Addr), Alignment, AlignmentOffset);
7474
}
75+
76+
Symbol &createSymbolWithDistance(Block &Origin, uint64_t Dist) {
77+
uint64_t TargetAddr = Origin.getAddress().getValue() + Dist;
78+
return G->addAnonymousSymbol(createBlock(Zeros, TargetAddr), 0 /*Offset*/,
79+
PointerSize, false, false);
80+
};
81+
82+
template <endianness Endian> void write(uint8_t *Mem, HalfWords Data) {
83+
write16<Endian>(Mem, Data.Hi);
84+
write16<Endian>(Mem + 2, Data.Lo);
85+
}
7586
};
7687

7788
TEST_F(AArch32Errors, readAddendDataGeneric) {
@@ -209,3 +220,83 @@ TEST(AArch32_ELF, applyFixupThumbErrors) {
209220
testing::EndsWith(aarch32::getEdgeKindName(K)))));
210221
}
211222
}
223+
224+
TEST_F(AArch32Errors, applyFixupThumbCall) {
225+
// Check range of R_ARM_THM_CALL relocation
226+
constexpr uint64_t Call1Offset = 0; //< first out-of-range
227+
constexpr uint64_t Call2Offset = 4; //< last in-range
228+
229+
uint8_t TwoCallsMem[8];
230+
Block &Site = createMutableBlock(TwoCallsMem, 0);
231+
constexpr HalfWords CallOpcode = FixupInfo<Thumb_Call>::Opcode;
232+
write<endianness::little>(TwoCallsMem + Call1Offset, CallOpcode);
233+
write<endianness::little>(TwoCallsMem + Call2Offset, CallOpcode);
234+
235+
// Thumb call with J1J2-encoding has range of 25 bit
236+
ArmConfig ArmCfg;
237+
ArmCfg.J1J2BranchEncoding = true;
238+
Symbol &J1J2Target = createSymbolWithDistance(Site, 0x01ull << 24);
239+
{
240+
Edge LastInRange(Thumb_Call, Call2Offset, J1J2Target, 0);
241+
EXPECT_THAT_ERROR(applyFixup(*G, Site, LastInRange, ArmCfg), Succeeded());
242+
Edge FirstOutOfRange(Thumb_Call, Call1Offset, J1J2Target, 0);
243+
EXPECT_THAT_ERROR(applyFixup(*G, Site, FirstOutOfRange, ArmCfg),
244+
FailedWithMessage(testing::HasSubstr("out of range")));
245+
}
246+
247+
// Thumb call without J1J2-encoding has range of 22 bit
248+
ArmCfg.J1J2BranchEncoding = false;
249+
Symbol &NonJ1J2Target = createSymbolWithDistance(Site, 0x01ull << 21);
250+
{
251+
Edge LastInRange(Thumb_Call, Call2Offset, NonJ1J2Target, 0);
252+
EXPECT_THAT_ERROR(applyFixup(*G, Site, LastInRange, ArmCfg), Succeeded());
253+
Edge FirstOutOfRange(Thumb_Call, Call1Offset, NonJ1J2Target, 0);
254+
EXPECT_THAT_ERROR(applyFixup(*G, Site, FirstOutOfRange, ArmCfg),
255+
FailedWithMessage(testing::HasSubstr("out of range")));
256+
}
257+
}
258+
259+
TEST_F(AArch32Errors, applyFixupThumbJump24) {
260+
// Check range of R_ARM_THM_JUMP24 relocation
261+
constexpr uint64_t Jump1Offset = 0; //< first out-of-range
262+
constexpr uint64_t Jump2Offset = 4; //< last in-range
263+
264+
uint8_t TwoJumpsMem[8];
265+
constexpr HalfWords JumpOpcode = FixupInfo<Thumb_Jump24>::Opcode;
266+
write<endianness::little>(TwoJumpsMem + Jump1Offset, JumpOpcode);
267+
write<endianness::little>(TwoJumpsMem + Jump2Offset, JumpOpcode);
268+
Block &Site = createMutableBlock(TwoJumpsMem, 0);
269+
270+
// Thumb Jump24 with J1J2-encoding has range of 25 bit
271+
ArmCfg.J1J2BranchEncoding = true;
272+
Symbol &J1J2Target = createSymbolWithDistance(Site, 0x01ull << 24);
273+
J1J2Target.setTargetFlags(TargetFlags_aarch32::ThumbSymbol);
274+
{
275+
Edge LastInRange(Thumb_Jump24, Jump2Offset, J1J2Target, 0);
276+
EXPECT_THAT_ERROR(applyFixup(*G, Site, LastInRange, ArmCfg), Succeeded());
277+
Edge FirstOutOfRange(Thumb_Jump24, Jump1Offset, J1J2Target, 0);
278+
EXPECT_THAT_ERROR(applyFixup(*G, Site, FirstOutOfRange, ArmCfg),
279+
FailedWithMessage(testing::HasSubstr("out of range")));
280+
}
281+
282+
// Thumb Jump24 without J1J2-encoding has range of 22 bit
283+
ArmCfg.J1J2BranchEncoding = false;
284+
Symbol &NonJ1J2Target = createSymbolWithDistance(Site, 0x01ull << 21);
285+
NonJ1J2Target.setTargetFlags(TargetFlags_aarch32::ThumbSymbol);
286+
{
287+
Edge LastInRange(Thumb_Jump24, Jump2Offset, NonJ1J2Target, 0);
288+
EXPECT_THAT_ERROR(applyFixup(*G, Site, LastInRange, ArmCfg), Succeeded());
289+
Edge FirstOutOfRange(Thumb_Jump24, Jump1Offset, NonJ1J2Target, 0);
290+
EXPECT_THAT_ERROR(applyFixup(*G, Site, FirstOutOfRange, ArmCfg),
291+
FailedWithMessage(testing::HasSubstr("out of range")));
292+
}
293+
294+
// Check that branching to an ARM target with Jump24 fails
295+
Symbol &ArmTarget = createSymbolWithDistance(Site, 0x1000);
296+
assert((ArmTarget.getTargetFlags() & TargetFlags_aarch32::ThumbSymbol) == 0);
297+
Edge Interworking(Thumb_Jump24, Jump2Offset, ArmTarget, 0);
298+
EXPECT_THAT_ERROR(applyFixup(*G, Site, Interworking, ArmCfg),
299+
FailedWithMessage(testing::HasSubstr(
300+
"Branch relocation needs interworking "
301+
"stub when bridging to ARM")));
302+
}

0 commit comments

Comments
 (0)