@@ -25,20 +25,21 @@ class BinaryFunction;
2525// / MCInstReference represents a reference to a constant MCInst as stored either
2626// / in a BinaryFunction (i.e. before a CFG is created), or in a BinaryBasicBlock
2727// / (after a CFG is created).
28+ // /
29+ // / The reference may be invalidated when the function containing the referenced
30+ // / instruction is modified.
2831class  MCInstReference  {
2932public: 
3033  using  nocfg_const_iterator = std::map<uint32_t , MCInst>::const_iterator;
3134
3235  // / Constructs an empty reference.
33-   MCInstReference () : Reference(RefInBB(nullptr , nullptr )) {}
36+   MCInstReference () : Reference(RefInBB(nullptr , /* Index= */ 0 )) {}
3437  // / Constructs a reference to the instruction inside the basic block.
3538  MCInstReference (const  BinaryBasicBlock *BB, const  MCInst *Inst)
36-       : Reference(RefInBB(BB, Inst)) {
37-     assert (BB && Inst && " Neither BB nor Inst should be nullptr" 
38-   }
39+       : Reference(RefInBB(BB, getInstIndexInBB(BB, Inst))) {}
3940  // / Constructs a reference to the instruction inside the basic block.
4041  MCInstReference (const  BinaryBasicBlock *BB, unsigned  Index)
41-       : Reference(RefInBB(BB, &BB-> getInstructionAtIndex ( Index) )) {
42+       : Reference(RefInBB(BB, Index)) {
4243    assert (BB && " Basic block should not be nullptr" 
4344  }
4445  // / Constructs a reference to the instruction inside the function without
@@ -57,8 +58,11 @@ class MCInstReference {
5758
5859  const  MCInst &getMCInst () const  {
5960    assert (!empty () && " Empty reference" 
60-     if  (auto  *Ref = tryGetRefInBB ())
61-       return  *Ref->Inst ;
61+     if  (auto  *Ref = tryGetRefInBB ()) {
62+       [[maybe_unused]] unsigned  NumInstructions = Ref->BB ->size ();
63+       assert (Ref->Index  < NumInstructions && " Invalid reference" 
64+       return  Ref->BB ->getInstructionAtIndex (Ref->Index );
65+     }
6266    return  getRefInBF ().It ->second ;
6367  }
6468
@@ -92,28 +96,36 @@ class MCInstReference {
9296  raw_ostream &print (raw_ostream &OS) const ;
9397
9498private: 
99+   static  unsigned  getInstIndexInBB (const  BinaryBasicBlock *BB,
100+                                    const  MCInst *Inst) {
101+     assert (BB && Inst && " Neither BB nor Inst should be nullptr" 
102+     //  Usage of pointer arithmetic assumes the instructions are stored in a
103+     //  vector, see BasicBlockStorageIsVector in MCInstUtils.cpp.
104+     const  MCInst *FirstInstInBB = &*BB->begin ();
105+     return  Inst - FirstInstInBB;
106+   }
107+ 
95108  //  Two cases are possible:
96109  //  * functions with CFG reconstructed - a function stores a collection of
97110  //    basic blocks, each basic block stores a contiguous vector of MCInst
98111  //  * functions without CFG - there are no basic blocks created,
99112  //    the instructions are directly stored in std::map in BinaryFunction
100113  // 
101114  //  In both cases, the direct parent of MCInst is stored together with an
102-   //  iterator pointing to the instruction.
115+   //  index or  iterator pointing to the instruction.
103116
104-   //  Helper struct: CFG is available, the direct parent is a basic block,
105-   //  iterator's type is `MCInst *`.
117+   //  Helper struct: CFG is available, the direct parent is a basic block.
106118  struct  RefInBB  {
107-     RefInBB (const  BinaryBasicBlock *BB, const  MCInst *Inst )
108-         : BB(BB), Inst(Inst ) {}
119+     RefInBB (const  BinaryBasicBlock *BB, unsigned  Index )
120+         : BB(BB), Index(Index ) {}
109121    RefInBB (const  RefInBB &Other) = default ;
110122    RefInBB &operator =(const  RefInBB &Other) = default ;
111123
112124    const  BinaryBasicBlock *BB;
113-     const  MCInst *Inst ;
125+     unsigned  Index ;
114126
115127    bool  operator ==(const  RefInBB &Other) const  {
116-       return  BB == Other.BB  && Inst  == Other.Inst ;
128+       return  BB == Other.BB  && Index  == Other.Index ;
117129    }
118130  };
119131
0 commit comments