|
11 | 11 |
|
12 | 12 | #include "bolt/Core/BinaryContext.h"
|
13 | 13 | #include "bolt/Core/BinaryFunction.h"
|
| 14 | +#include "bolt/Core/MCInstUtils.h" |
14 | 15 | #include "bolt/Passes/BinaryPasses.h"
|
15 | 16 | #include "llvm/Support/raw_ostream.h"
|
16 | 17 | #include <memory>
|
17 | 18 |
|
18 | 19 | namespace llvm {
|
19 | 20 | namespace bolt {
|
20 |
| - |
21 |
| -/// @brief MCInstReference represents a reference to an MCInst as stored either |
22 |
| -/// in a BinaryFunction (i.e. before a CFG is created), or in a BinaryBasicBlock |
23 |
| -/// (after a CFG is created). It aims to store the necessary information to be |
24 |
| -/// able to find the specific MCInst in either the BinaryFunction or |
25 |
| -/// BinaryBasicBlock data structures later, so that e.g. the InputAddress of |
26 |
| -/// the corresponding instruction can be computed. |
27 |
| - |
28 |
| -struct MCInstInBBReference { |
29 |
| - BinaryBasicBlock *BB; |
30 |
| - int64_t BBIndex; |
31 |
| - MCInstInBBReference(BinaryBasicBlock *BB, int64_t BBIndex) |
32 |
| - : BB(BB), BBIndex(BBIndex) {} |
33 |
| - MCInstInBBReference() : BB(nullptr), BBIndex(0) {} |
34 |
| - static MCInstInBBReference get(const MCInst *Inst, BinaryFunction &BF) { |
35 |
| - for (BinaryBasicBlock &BB : BF) |
36 |
| - for (size_t I = 0; I < BB.size(); ++I) |
37 |
| - if (Inst == &BB.getInstructionAtIndex(I)) |
38 |
| - return MCInstInBBReference(&BB, I); |
39 |
| - return {}; |
40 |
| - } |
41 |
| - bool operator==(const MCInstInBBReference &RHS) const { |
42 |
| - return BB == RHS.BB && BBIndex == RHS.BBIndex; |
43 |
| - } |
44 |
| - bool operator<(const MCInstInBBReference &RHS) const { |
45 |
| - return std::tie(BB, BBIndex) < std::tie(RHS.BB, RHS.BBIndex); |
46 |
| - } |
47 |
| - operator MCInst &() const { |
48 |
| - assert(BB != nullptr); |
49 |
| - return BB->getInstructionAtIndex(BBIndex); |
50 |
| - } |
51 |
| - uint64_t getAddress() const { |
52 |
| - // 4 bytes per instruction on AArch64. |
53 |
| - // FIXME: the assumption of 4 byte per instruction needs to be fixed before |
54 |
| - // this method gets used on any non-AArch64 binaries (but should be fine for |
55 |
| - // pac-ret analysis, as that is an AArch64-specific feature). |
56 |
| - return BB->getFunction()->getAddress() + BB->getOffset() + BBIndex * 4; |
57 |
| - } |
58 |
| -}; |
59 |
| - |
60 |
| -raw_ostream &operator<<(raw_ostream &OS, const MCInstInBBReference &); |
61 |
| - |
62 |
| -struct MCInstInBFReference { |
63 |
| - BinaryFunction *BF; |
64 |
| - uint64_t Offset; |
65 |
| - MCInstInBFReference(BinaryFunction *BF, uint64_t Offset) |
66 |
| - : BF(BF), Offset(Offset) {} |
67 |
| - |
68 |
| - static MCInstInBFReference get(const MCInst *Inst, BinaryFunction &BF) { |
69 |
| - for (auto &I : BF.instrs()) |
70 |
| - if (Inst == &I.second) |
71 |
| - return MCInstInBFReference(&BF, I.first); |
72 |
| - return {}; |
73 |
| - } |
74 |
| - |
75 |
| - MCInstInBFReference() : BF(nullptr), Offset(0) {} |
76 |
| - bool operator==(const MCInstInBFReference &RHS) const { |
77 |
| - return BF == RHS.BF && Offset == RHS.Offset; |
78 |
| - } |
79 |
| - bool operator<(const MCInstInBFReference &RHS) const { |
80 |
| - return std::tie(BF, Offset) < std::tie(RHS.BF, RHS.Offset); |
81 |
| - } |
82 |
| - operator MCInst &() const { |
83 |
| - assert(BF != nullptr); |
84 |
| - return *BF->getInstructionAtOffset(Offset); |
85 |
| - } |
86 |
| - |
87 |
| - uint64_t getOffset() const { return Offset; } |
88 |
| - |
89 |
| - uint64_t getAddress() const { return BF->getAddress() + getOffset(); } |
90 |
| -}; |
91 |
| - |
92 |
| -raw_ostream &operator<<(raw_ostream &OS, const MCInstInBFReference &); |
93 |
| - |
94 |
| -struct MCInstReference { |
95 |
| - enum Kind { FunctionParent, BasicBlockParent }; |
96 |
| - Kind ParentKind; |
97 |
| - union U { |
98 |
| - MCInstInBBReference BBRef; |
99 |
| - MCInstInBFReference BFRef; |
100 |
| - U(MCInstInBBReference BBRef) : BBRef(BBRef) {} |
101 |
| - U(MCInstInBFReference BFRef) : BFRef(BFRef) {} |
102 |
| - } U; |
103 |
| - MCInstReference(MCInstInBBReference BBRef) |
104 |
| - : ParentKind(BasicBlockParent), U(BBRef) {} |
105 |
| - MCInstReference(MCInstInBFReference BFRef) |
106 |
| - : ParentKind(FunctionParent), U(BFRef) {} |
107 |
| - MCInstReference(BinaryBasicBlock *BB, int64_t BBIndex) |
108 |
| - : MCInstReference(MCInstInBBReference(BB, BBIndex)) {} |
109 |
| - MCInstReference(BinaryFunction *BF, uint32_t Offset) |
110 |
| - : MCInstReference(MCInstInBFReference(BF, Offset)) {} |
111 |
| - |
112 |
| - static MCInstReference get(const MCInst *Inst, BinaryFunction &BF) { |
113 |
| - if (BF.hasCFG()) |
114 |
| - return MCInstInBBReference::get(Inst, BF); |
115 |
| - return MCInstInBFReference::get(Inst, BF); |
116 |
| - } |
117 |
| - |
118 |
| - bool operator<(const MCInstReference &RHS) const { |
119 |
| - if (ParentKind != RHS.ParentKind) |
120 |
| - return ParentKind < RHS.ParentKind; |
121 |
| - switch (ParentKind) { |
122 |
| - case BasicBlockParent: |
123 |
| - return U.BBRef < RHS.U.BBRef; |
124 |
| - case FunctionParent: |
125 |
| - return U.BFRef < RHS.U.BFRef; |
126 |
| - } |
127 |
| - llvm_unreachable(""); |
128 |
| - } |
129 |
| - |
130 |
| - bool operator==(const MCInstReference &RHS) const { |
131 |
| - if (ParentKind != RHS.ParentKind) |
132 |
| - return false; |
133 |
| - switch (ParentKind) { |
134 |
| - case BasicBlockParent: |
135 |
| - return U.BBRef == RHS.U.BBRef; |
136 |
| - case FunctionParent: |
137 |
| - return U.BFRef == RHS.U.BFRef; |
138 |
| - } |
139 |
| - llvm_unreachable(""); |
140 |
| - } |
141 |
| - |
142 |
| - operator MCInst &() const { |
143 |
| - switch (ParentKind) { |
144 |
| - case BasicBlockParent: |
145 |
| - return U.BBRef; |
146 |
| - case FunctionParent: |
147 |
| - return U.BFRef; |
148 |
| - } |
149 |
| - llvm_unreachable(""); |
150 |
| - } |
151 |
| - |
152 |
| - operator bool() const { |
153 |
| - switch (ParentKind) { |
154 |
| - case BasicBlockParent: |
155 |
| - return U.BBRef.BB != nullptr; |
156 |
| - case FunctionParent: |
157 |
| - return U.BFRef.BF != nullptr; |
158 |
| - } |
159 |
| - llvm_unreachable(""); |
160 |
| - } |
161 |
| - |
162 |
| - uint64_t getAddress() const { |
163 |
| - switch (ParentKind) { |
164 |
| - case BasicBlockParent: |
165 |
| - return U.BBRef.getAddress(); |
166 |
| - case FunctionParent: |
167 |
| - return U.BFRef.getAddress(); |
168 |
| - } |
169 |
| - llvm_unreachable(""); |
170 |
| - } |
171 |
| - |
172 |
| - BinaryFunction *getFunction() const { |
173 |
| - switch (ParentKind) { |
174 |
| - case FunctionParent: |
175 |
| - return U.BFRef.BF; |
176 |
| - case BasicBlockParent: |
177 |
| - return U.BBRef.BB->getFunction(); |
178 |
| - } |
179 |
| - llvm_unreachable(""); |
180 |
| - } |
181 |
| - |
182 |
| - BinaryBasicBlock *getBasicBlock() const { |
183 |
| - switch (ParentKind) { |
184 |
| - case FunctionParent: |
185 |
| - return nullptr; |
186 |
| - case BasicBlockParent: |
187 |
| - return U.BBRef.BB; |
188 |
| - } |
189 |
| - llvm_unreachable(""); |
190 |
| - } |
191 |
| -}; |
192 |
| - |
193 |
| -raw_ostream &operator<<(raw_ostream &OS, const MCInstReference &); |
194 |
| - |
195 | 21 | namespace PAuthGadgetScanner {
|
196 | 22 |
|
197 | 23 | // The report classes are designed to be used in an immutable manner.
|
|
0 commit comments