@@ -397,9 +397,8 @@ static bool instructionsMatch(const T (&Insns)[N], const uint8_t *Buf,
397
397
llvm::endianness E) {
398
398
for (size_t I = 0 ; I < N; ++I) {
399
399
T Val = support::endian::read <T>(Buf + I * sizeof (T), E);
400
- if (Val != Insns[I]) {
400
+ if (Val != Insns[I])
401
401
return false ;
402
- }
403
402
}
404
403
return true ;
405
404
}
@@ -446,123 +445,7 @@ class ARMMCInstrAnalysis : public MCInstrAnalysis {
446
445
447
446
std::vector<std::pair<uint64_t , uint64_t >>
448
447
findPltEntries (uint64_t PltSectionVA, ArrayRef<uint8_t > PltContents,
449
- const MCSubtargetInfo &STI) const override {
450
- llvm::endianness DataEndianness = STI.getTargetTriple ().isLittleEndian ()
451
- ? endianness::little
452
- : endianness::big;
453
- llvm::endianness InstrEndianness =
454
- STI.checkFeatures (" +big-endian-instructions" ) ? endianness::big
455
- : endianness::little;
456
-
457
- // Do a lightweight parsing of PLT entries.
458
- std::vector<std::pair<uint64_t , uint64_t >> Result;
459
- if (STI.checkFeatures (" +thumb-mode" )) {
460
- for (uint64_t Byte = 0 , End = PltContents.size (); Byte + 12 < End;
461
- Byte += 16 ) {
462
- // Expected instruction sequence:
463
- //
464
- // movw ip, #lower16
465
- // movt ip, #upper16
466
- // add ip, pc
467
- // ldr.w pc, [ip]
468
- // b . -4
469
-
470
- uint32_t MovwPart1 =
471
- support::endian::read16 (PltContents.data () + Byte , InstrEndianness);
472
- if ((MovwPart1 & 0xffb0 ) != 0xf200 )
473
- continue ;
474
-
475
- uint32_t MovwPart2 = support::endian::read16 (
476
- PltContents.data () + Byte + 2 , InstrEndianness);
477
- if ((MovwPart2 & 0x8f00 ) != 0xc00 )
478
- continue ;
479
-
480
- uint64_t OffsetLower =
481
- (MovwPart2 & 0xff ) + ((MovwPart2 & 0x7000 ) >> 4 ) +
482
- ((MovwPart1 & 0x400 ) << 1 ) + ((MovwPart1 & 0xf ) << 12 );
483
-
484
- uint32_t MovtPart1 = support::endian::read16 (
485
- PltContents.data () + Byte + 4 , InstrEndianness);
486
- if ((MovtPart1 & 0xfbf0 ) != 0xf2c0 )
487
- continue ;
488
-
489
- uint32_t MovtPart2 = support::endian::read16 (
490
- PltContents.data () + Byte + 6 , InstrEndianness);
491
- if ((MovtPart2 & 0x8f00 ) != 0xc00 )
492
- continue ;
493
-
494
- uint64_t OffsetHigher =
495
- ((MovtPart2 & 0xff ) << 16 ) + ((MovtPart2 & 0x7000 ) << 12 ) +
496
- ((MovtPart1 & 0x400 ) << 17 ) + ((MovtPart1 & 0xf ) << 28 );
497
-
498
- const uint16_t Insns[] = {
499
- 0x44fc , // add ip, pc
500
- 0xf8dc , 0xf000 , // ldr.w pc, [ip]
501
- 0xe7fc , // b . -4
502
- };
503
-
504
- if (instructionsMatch (Insns, PltContents.data () + Byte + 8 ,
505
- InstrEndianness)) {
506
- // add ip, pc at Byte + 8 + thumb-pc-bias = 12
507
- uint64_t Offset =
508
- (PltSectionVA + Byte + 12 ) + OffsetLower + OffsetHigher;
509
- Result.emplace_back (PltSectionVA + Byte , Offset);
510
- }
511
- }
512
- } else {
513
- const uint32_t LongEntryInsns[] = {
514
- 0xe59fc004 , // ldr ip, L2
515
- 0xe08cc00f , // L1: add ip, ip, pc
516
- 0xe59cf000 , // ldr pc, [ip]
517
- };
518
-
519
- for (uint64_t Byte = 0 , End = PltContents.size (); Byte + 12 < End;
520
- Byte += 4 ) {
521
- // Is it a long entry?
522
- if (instructionsMatch (LongEntryInsns, PltContents.data () + Byte ,
523
- InstrEndianness)) {
524
- // Expected instruction sequence:
525
- //
526
- // ldr ip, L2
527
- // L1: add ip, ip, pc
528
- // ldr pc, [ip]
529
- // L2: .word Offset(&(.got.plt) - L1 - 8
530
-
531
- uint64_t Offset = (PltSectionVA + Byte + 12 ) +
532
- support::endian::read32 (
533
- PltContents.data () + Byte + 12 , DataEndianness);
534
- Result.emplace_back (PltSectionVA + Byte , Offset);
535
- Byte += 12 ;
536
- } else {
537
- // Expected instruction sequence:
538
- //
539
- // L1: add ip, pc, #0x0NN00000 Offset(&(.got.plt) - L1 - 8
540
- // add ip, ip, #0x000NN000 Offset(&(.got.plt) - L1 - 8
541
- // ldr pc, [ip, #0x00000NNN] Offset(&(.got.plt) - L1 - 8
542
-
543
- uint32_t Add1 = support::endian::read32 (PltContents.data () + Byte ,
544
- InstrEndianness);
545
- if ((Add1 & 0xe28fc600 ) != 0xe28fc600 )
546
- continue ;
547
- uint32_t Add2 = support::endian::read32 (PltContents.data () + Byte + 4 ,
548
- InstrEndianness);
549
- if ((Add2 & 0xe28cca00 ) != 0xe28cca00 )
550
- continue ;
551
- uint32_t Ldr = support::endian::read32 (PltContents.data () + Byte + 8 ,
552
- InstrEndianness);
553
- if ((Ldr & 0xe5bcf000 ) != 0xe5bcf000 )
554
- continue ;
555
-
556
- // add ip, pc, #offset at Byte + 0 + arm-pc-bias = 8
557
- uint64_t Offset = (PltSectionVA + Byte + 8 ) + ((Add1 & 0xff ) << 20 ) +
558
- ((Add2 & 0xff ) << 12 ) + (Ldr & 0xfff );
559
- Result.emplace_back (PltSectionVA + Byte , Offset);
560
- Byte += 8 ;
561
- }
562
- }
563
- }
564
- return Result;
565
- }
448
+ const MCSubtargetInfo &STI) const override ;
566
449
};
567
450
568
451
} // namespace
@@ -753,6 +636,127 @@ std::optional<uint64_t> ARMMCInstrAnalysis::evaluateMemoryOperandAddress(
753
636
}
754
637
}
755
638
639
+ std::vector<std::pair<uint64_t , uint64_t >>
640
+ ARMMCInstrAnalysis::findPltEntries (uint64_t PltSectionVA,
641
+ ArrayRef<uint8_t > PltContents,
642
+ const MCSubtargetInfo &STI) const {
643
+ llvm::endianness DataEndianness = STI.getTargetTriple ().isLittleEndian ()
644
+ ? endianness::little
645
+ : endianness::big;
646
+ llvm::endianness InstrEndianness =
647
+ STI.checkFeatures (" +big-endian-instructions" ) ? endianness::big
648
+ : endianness::little;
649
+
650
+ // Do a lightweight parsing of PLT entries.
651
+ std::vector<std::pair<uint64_t , uint64_t >> Result;
652
+ if (STI.checkFeatures (" +thumb-mode" )) {
653
+ for (uint64_t Byte = 0 , End = PltContents.size (); Byte + 12 < End;
654
+ Byte += 16 ) {
655
+ // Expected instruction sequence:
656
+ //
657
+ // movw ip, #lower16
658
+ // movt ip, #upper16
659
+ // add ip, pc
660
+ // ldr.w pc, [ip]
661
+ // b . -4
662
+
663
+ uint32_t MovwPart1 =
664
+ support::endian::read16 (PltContents.data () + Byte , InstrEndianness);
665
+ if ((MovwPart1 & 0xffb0 ) != 0xf200 )
666
+ continue ;
667
+
668
+ uint32_t MovwPart2 = support::endian::read16 (
669
+ PltContents.data () + Byte + 2 , InstrEndianness);
670
+ if ((MovwPart2 & 0x8f00 ) != 0xc00 )
671
+ continue ;
672
+
673
+ uint64_t OffsetLower = (MovwPart2 & 0xff ) + ((MovwPart2 & 0x7000 ) >> 4 ) +
674
+ ((MovwPart1 & 0x400 ) << 1 ) +
675
+ ((MovwPart1 & 0xf ) << 12 );
676
+
677
+ uint32_t MovtPart1 = support::endian::read16 (
678
+ PltContents.data () + Byte + 4 , InstrEndianness);
679
+ if ((MovtPart1 & 0xfbf0 ) != 0xf2c0 )
680
+ continue ;
681
+
682
+ uint32_t MovtPart2 = support::endian::read16 (
683
+ PltContents.data () + Byte + 6 , InstrEndianness);
684
+ if ((MovtPart2 & 0x8f00 ) != 0xc00 )
685
+ continue ;
686
+
687
+ uint64_t OffsetHigher =
688
+ ((MovtPart2 & 0xff ) << 16 ) + ((MovtPart2 & 0x7000 ) << 12 ) +
689
+ ((MovtPart1 & 0x400 ) << 17 ) + ((MovtPart1 & 0xf ) << 28 );
690
+
691
+ const uint16_t Insns[] = {
692
+ 0x44fc , // add ip, pc
693
+ 0xf8dc , 0xf000 , // ldr.w pc, [ip]
694
+ 0xe7fc , // b . -4
695
+ };
696
+
697
+ if (instructionsMatch (Insns, PltContents.data () + Byte + 8 ,
698
+ InstrEndianness)) {
699
+ // add ip, pc at Byte + 8 + thumb-pc-bias = 12
700
+ uint64_t Offset =
701
+ (PltSectionVA + Byte + 12 ) + OffsetLower + OffsetHigher;
702
+ Result.emplace_back (PltSectionVA + Byte , Offset);
703
+ }
704
+ }
705
+ } else {
706
+ const uint32_t LongEntryInsns[] = {
707
+ 0xe59fc004 , // ldr ip, L2
708
+ 0xe08cc00f , // L1: add ip, ip, pc
709
+ 0xe59cf000 , // ldr pc, [ip]
710
+ };
711
+
712
+ for (uint64_t Byte = 0 , End = PltContents.size (); Byte + 12 < End;
713
+ Byte += 4 ) {
714
+ // Is it a long entry?
715
+ if (instructionsMatch (LongEntryInsns, PltContents.data () + Byte ,
716
+ InstrEndianness)) {
717
+ // Expected instruction sequence:
718
+ //
719
+ // ldr ip, L2
720
+ // L1: add ip, ip, pc
721
+ // ldr pc, [ip]
722
+ // L2: .word Offset(&(.got.plt) - L1 - 8
723
+
724
+ uint64_t Offset = (PltSectionVA + Byte + 12 ) +
725
+ support::endian::read32 (
726
+ PltContents.data () + Byte + 12 , DataEndianness);
727
+ Result.emplace_back (PltSectionVA + Byte , Offset);
728
+ Byte += 12 ;
729
+ } else {
730
+ // Expected instruction sequence:
731
+ //
732
+ // L1: add ip, pc, #0x0NN00000 Offset(&(.got.plt) - L1 - 8
733
+ // add ip, ip, #0x000NN000 Offset(&(.got.plt) - L1 - 8
734
+ // ldr pc, [ip, #0x00000NNN] Offset(&(.got.plt) - L1 - 8
735
+
736
+ uint32_t Add1 =
737
+ support::endian::read32 (PltContents.data () + Byte , InstrEndianness);
738
+ if ((Add1 & 0xe28fc600 ) != 0xe28fc600 )
739
+ continue ;
740
+ uint32_t Add2 = support::endian::read32 (PltContents.data () + Byte + 4 ,
741
+ InstrEndianness);
742
+ if ((Add2 & 0xe28cca00 ) != 0xe28cca00 )
743
+ continue ;
744
+ uint32_t Ldr = support::endian::read32 (PltContents.data () + Byte + 8 ,
745
+ InstrEndianness);
746
+ if ((Ldr & 0xe5bcf000 ) != 0xe5bcf000 )
747
+ continue ;
748
+
749
+ // add ip, pc, #offset at Byte + 0 + arm-pc-bias = 8
750
+ uint64_t Offset = (PltSectionVA + Byte + 8 ) + ((Add1 & 0xff ) << 20 ) +
751
+ ((Add2 & 0xff ) << 12 ) + (Ldr & 0xfff );
752
+ Result.emplace_back (PltSectionVA + Byte , Offset);
753
+ Byte += 8 ;
754
+ }
755
+ }
756
+ }
757
+ return Result;
758
+ }
759
+
756
760
static MCInstrAnalysis *createARMMCInstrAnalysis (const MCInstrInfo *Info) {
757
761
return new ARMMCInstrAnalysis (Info);
758
762
}
0 commit comments