@@ -397,9 +397,8 @@ static bool instructionsMatch(const T (&Insns)[N], const uint8_t *Buf,
397397 llvm::endianness E) {
398398 for (size_t I = 0 ; I < N; ++I) {
399399 T Val = support::endian::read<T>(Buf + I * sizeof (T), E);
400- if (Val != Insns[I]) {
400+ if (Val != Insns[I])
401401 return false ;
402- }
403402 }
404403 return true ;
405404}
@@ -446,123 +445,7 @@ class ARMMCInstrAnalysis : public MCInstrAnalysis {
446445
447446 std::vector<std::pair<uint64_t , uint64_t >>
448447 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 ;
566449};
567450
568451} // namespace
@@ -753,6 +636,127 @@ std::optional<uint64_t> ARMMCInstrAnalysis::evaluateMemoryOperandAddress(
753636 }
754637}
755638
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+
756760static MCInstrAnalysis *createARMMCInstrAnalysis (const MCInstrInfo *Info) {
757761 return new ARMMCInstrAnalysis (Info);
758762}
0 commit comments