|
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