@@ -72,6 +72,17 @@ class AArch32Errors : public testing::Test {
72
72
return G->createMutableContentBlock (
73
73
*S, CharContent, orc::ExecutorAddr (Addr), Alignment, AlignmentOffset);
74
74
}
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
+ }
75
86
};
76
87
77
88
TEST_F (AArch32Errors, readAddendDataGeneric) {
@@ -209,3 +220,83 @@ TEST(AArch32_ELF, applyFixupThumbErrors) {
209
220
testing::EndsWith (aarch32::getEdgeKindName (K)))));
210
221
}
211
222
}
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