libTriton version 1.0 build 1592
Loading...
Searching...
No Matches
irBuilder.cpp
Go to the documentation of this file.
1
2/*
3** Copyright (C) - Triton
4**
5** This program is under the terms of the Apache License 2.0.
6*/
7
8#include <new>
9
12#include <triton/astContext.hpp>
13#include <triton/exceptions.hpp>
14#include <triton/irBuilder.hpp>
17#include <triton/register.hpp>
19#ifdef COMPILE_RISCV
21#endif
22
23
24namespace triton {
25 namespace arch {
26
28 const triton::modes::SharedModes& modes,
29 const triton::ast::SharedAstContext& astCtxt,
32 : modes(modes), astCtxt(astCtxt) {
33
34 if (architecture == nullptr)
35 throw triton::exceptions::IrBuilder("IrBuilder::IrBuilder(): The architecture API must be defined.");
36
37 if (symbolicEngine == nullptr)
38 throw triton::exceptions::IrBuilder("IrBuilder::IrBuilder(): The symbolic engine API must be defined.");
39
40 if (taintEngine == nullptr)
41 throw triton::exceptions::IrBuilder("IrBuilder::IrBuilder(): The taint engines API must be defined.");
42
43 this->architecture = architecture;
44 this->symbolicEngine = symbolicEngine;
45 this->taintEngine = taintEngine;
46 this->aarch64Isa = new(std::nothrow) triton::arch::arm::aarch64::AArch64Semantics(architecture, symbolicEngine, taintEngine, astCtxt);
47 this->arm32Isa = new(std::nothrow) triton::arch::arm::arm32::Arm32Semantics(architecture, symbolicEngine, taintEngine, astCtxt);
48 this->x86Isa = new(std::nothrow) triton::arch::x86::x86Semantics(architecture, symbolicEngine, taintEngine, modes, astCtxt);
49 #ifdef COMPILE_RISCV
50 this->riscvIsa = new(std::nothrow) triton::arch::riscv::riscvSemantics(architecture, symbolicEngine, taintEngine, modes, astCtxt);
51 #endif
52
53 if (this->x86Isa == nullptr || this->aarch64Isa == nullptr || this->arm32Isa == nullptr
54 #ifdef COMPILE_RISCV
55 || this->riscvIsa == nullptr
56 #endif
57 )
58 throw triton::exceptions::IrBuilder("IrBuilder::IrBuilder(): Not enough memory.");
59 }
60
61
63 delete this->aarch64Isa;
64 delete this->arm32Isa;
65 delete this->x86Isa;
66 #ifdef COMPILE_RISCV
67 delete this->riscvIsa;
68 #endif
69 }
70
71
73 triton::arch::architecture_e arch = this->architecture->getArchitecture();
75
77 throw triton::exceptions::IrBuilder("IrBuilder::buildSemantics(): You must define an architecture.");
78
79 /* Initialize the target address of memory operands */
80 for (auto& operand : inst.operands) {
81 if (operand.getType() == triton::arch::OP_MEM) {
82 this->symbolicEngine->initLeaAst(operand.getMemory());
83 }
84 }
85
86 /* Pre IR processing */
87 this->preIrInit(inst);
88
89 /* Processing */
90 switch (arch) {
92 ret = this->aarch64Isa->buildSemantics(inst);
93 break;
94
96 ret = this->arm32Isa->buildSemantics(inst);
97 break;
98
101 ret = this->x86Isa->buildSemantics(inst);
102 break;
103
104 #ifdef COMPILE_RISCV
105 case triton::arch::ARCH_RV64:
106 case triton::arch::ARCH_RV32:
107 ret = this->riscvIsa->buildSemantics(inst);
108 break;
109 #endif
110
111 default:
112 throw triton::exceptions::IrBuilder("IrBuilder::buildSemantics(): Architecture not supported.");
113 break;
114 }
115
116 /* Post IR processing */
117 this->postIrInit(inst);
118
119 return ret;
120 }
121
122
125 triton::usize count = block.getSize();
126
127 for (auto& inst : block.getInstructions()) {
128 ret = this->buildSemantics(inst);
129 if (ret != triton::arch::NO_FAULT) {
130 return ret;
131 }
132 count--;
133 if (inst.isControlFlow() && count) {
134 throw triton::exceptions::IrBuilder("IrBuilder::buildSemantics(): Do not add instructions in a block after a branch instruction.");
135 }
136 }
137
138 return ret;
139 }
140
141
143 /* Clear previous expressions if exist */
144 inst.symbolicExpressions.clear();
145
146 /* Clear implicit and explicit previous semantics */
147 inst.getLoadAccess().clear();
148 inst.getReadRegisters().clear();
149 inst.getReadImmediates().clear();
150 inst.getStoreAccess().clear();
151 inst.getWrittenRegisters().clear();
152
153 /* Update instruction address if undefined */
154 if (!inst.getAddress()) {
155 inst.setAddress(static_cast<triton::uint64>(this->architecture->getConcreteRegisterValue(this->architecture->getProgramCounter())));
156 }
157 }
158
159
161 std::vector<triton::engines::symbolic::SharedSymbolicExpression> newVector;
162
163 /* Set the taint */
164 inst.setTaint();
165
166 /*
167 * If the symbolic engine is defined to process symbolic
168 * execution only on symbolized expressions, we delete all
169 * concrete expressions and their AST nodes.
170 */
171 if (this->modes->isModeEnabled(triton::modes::ONLY_ON_SYMBOLIZED)) {
172 /* Clear memory operands */
173 this->collectUnsymbolizedNodes(inst.operands);
174
175 /* Clear implicit and explicit semantics - MEM */
176 this->collectUnsymbolizedNodes(inst.getLoadAccess());
177
178 /* Clear implicit and explicit semantics - REG */
179 this->collectUnsymbolizedNodes(inst.getReadRegisters());
180
181 /* Clear implicit and explicit semantics - IMM */
182 this->collectUnsymbolizedNodes(inst.getReadImmediates());
183
184 /* Clear implicit and explicit semantics - MEM */
185 this->collectUnsymbolizedNodes(inst.getStoreAccess());
186
187 /* Clear implicit and explicit semantics - REG */
188 this->collectUnsymbolizedNodes(inst.getWrittenRegisters());
189
190 /* Clear symbolic expressions */
191 for (const auto& se : inst.symbolicExpressions) {
192 if (se->isSymbolized() == false) {
193 this->symbolicEngine->removeSymbolicExpression(se);
194 }
195 else
196 newVector.push_back(se);
197 }
198 inst.symbolicExpressions = newVector;
199 }
200
201 /*
202 * If the symbolic engine is defined to process symbolic
203 * execution only on tainted instructions, we delete all
204 * expressions untainted and their AST nodes.
205 */
206 else if (this->modes->isModeEnabled(triton::modes::ONLY_ON_TAINTED) && !inst.isTainted()) {
207 /* Memory operands */
208 this->collectNodes(inst.operands);
209
210 /* Implicit and explicit semantics - MEM */
211 this->collectNodes(inst.getLoadAccess());
212
213 /* Implicit and explicit semantics - REG */
214 this->collectNodes(inst.getReadRegisters());
215
216 /* Implicit and explicit semantics - IMM */
217 this->collectNodes(inst.getReadImmediates());
218
219 /* Implicit and explicit semantics - MEM */
220 this->collectNodes(inst.getStoreAccess());
221
222 /* Implicit and explicit semantics - REG */
223 this->collectNodes(inst.getWrittenRegisters());
224
225 /* Symbolic Expressions */
226 this->removeSymbolicExpressions(inst);
227 }
228
229 this->astCtxt->garbage();
230 }
231
232
233 void IrBuilder::removeSymbolicExpressions(triton::arch::Instruction& inst) {
234 for (const auto& se : inst.symbolicExpressions) {
235 this->symbolicEngine->removeSymbolicExpression(se);
236 }
237 inst.symbolicExpressions.clear();
238 }
239
240
241 template <typename T>
242 void IrBuilder::collectNodes(T& items) const {
243 items.clear();
244 }
245
246
247 void IrBuilder::collectNodes(std::vector<triton::arch::OperandWrapper>& operands) const {
248 for (auto& operand : operands) {
249 if (operand.getType() == triton::arch::OP_MEM) {
250 operand.getMemory().setLeaAst(nullptr);
251 }
252 }
253 }
254
255
256 template <typename T>
257 void IrBuilder::collectUnsymbolizedNodes(T& items) const {
258 T newItems;
259
260 for (const auto& item : items) {
261 if (std::get<1>(item) && std::get<1>(item)->isSymbolized() == true)
262 newItems.insert(item);
263 }
264
265 items.clear();
266 items = newItems;
267 }
268
269
270 void IrBuilder::collectUnsymbolizedNodes(std::vector<triton::arch::OperandWrapper>& operands) const {
271 for (auto& operand : operands) {
272 if (operand.getType() == triton::arch::OP_MEM) {
273 if (operand.getMemory().getLeaAst() && operand.getMemory().getLeaAst()->isSymbolized() == false) {
274 operand.getMemory().setLeaAst(nullptr);
275 }
276 }
277 }
278 }
279
280 }; /* arch namespace */
281}; /* triton namespace */
The abstract architecture class.
TRITON_EXPORT triton::uint512 getConcreteRegisterValue(const triton::arch::Register &reg, bool execCallbacks=true) const
Returns the concrete value of a register.
TRITON_EXPORT triton::arch::architecture_e getArchitecture(void) const
Returns the kind of architecture as triton::arch::architecture_e.
This class is used to represent a basic block.
TRITON_EXPORT triton::usize getSize(void) const
Returns the number of instructions in the block.
TRITON_EXPORT std::vector< triton::arch::Instruction > & getInstructions(void)
Gets all instructions of the block.
This class is used to represent an instruction.
TRITON_EXPORT std::set< std::pair< triton::arch::Register, triton::ast::SharedAbstractNode > > & getReadRegisters(void)
Returns the list of all implicit and explicit register (flags includes) inputs (read)
TRITON_EXPORT std::set< std::pair< triton::arch::MemoryAccess, triton::ast::SharedAbstractNode > > & getStoreAccess(void)
Returns the list of all implicit and explicit store access.
TRITON_EXPORT void setAddress(triton::uint64 addr)
Sets the address of the instruction.
TRITON_EXPORT std::set< std::pair< triton::arch::MemoryAccess, triton::ast::SharedAbstractNode > > & getLoadAccess(void)
Returns the list of all implicit and explicit load access.
TRITON_EXPORT bool isTainted(void) const
Returns true if at least one of its expressions is tainted.
TRITON_EXPORT triton::uint64 getAddress(void) const
Returns the address of the instruction.
TRITON_EXPORT void setTaint(bool state)
Sets the taint of the instruction.
TRITON_EXPORT std::set< std::pair< triton::arch::Register, triton::ast::SharedAbstractNode > > & getWrittenRegisters(void)
Returns the list of all implicit and explicit register (flags includes) outputs (write)
std::vector< triton::arch::OperandWrapper > operands
A list of operands.
std::vector< triton::engines::symbolic::SharedSymbolicExpression > symbolicExpressions
The semantics set of the instruction.
TRITON_EXPORT std::set< std::pair< triton::arch::Immediate, triton::ast::SharedAbstractNode > > & getReadImmediates(void)
Returns the list of all implicit and explicit immediate inputs (read)
virtual TRITON_EXPORT ~IrBuilder()
Destructor.
Definition irBuilder.cpp:62
TRITON_EXPORT IrBuilder(triton::arch::Architecture *architecture, const triton::modes::SharedModes &modes, const triton::ast::SharedAstContext &astCtxt, triton::engines::symbolic::SymbolicEngine *symbolicEngine, triton::engines::taint::TaintEngine *taintEngine)
Constructor.
Definition irBuilder.cpp:27
triton::arch::SemanticsInterface * arm32Isa
ARM32 ISA builder.
Definition irBuilder.hpp:77
triton::arch::SemanticsInterface * aarch64Isa
AArch64 ISA builder.
Definition irBuilder.hpp:74
TRITON_EXPORT triton::arch::exception_e buildSemantics(triton::arch::Instruction &inst)
Builds the semantics of the instruction. Returns triton::arch::NO_FAULT if succeed.
Definition irBuilder.cpp:72
TRITON_EXPORT void preIrInit(triton::arch::Instruction &inst)
Everything which must be done before buiding the semantics.
TRITON_EXPORT void postIrInit(triton::arch::Instruction &inst)
Everything which must be done after building the semantics.
triton::arch::SemanticsInterface * x86Isa
x86 ISA builder.
Definition irBuilder.hpp:80
virtual TRITON_EXPORT triton::arch::exception_e buildSemantics(triton::arch::Instruction &inst)=0
Builds the semantics of the instruction. Returns triton::arch::NO_FAULT if succeed.
TRITON_EXPORT void initLeaAst(triton::arch::MemoryAccess &mem, bool force=true)
Initializes the effective address of a memory access.
TRITON_EXPORT void removeSymbolicExpression(const SharedSymbolicExpression &expr)
Removes the symbolic expression corresponding to the id.
The exception class used by the IR builder.
std::shared_ptr< triton::ast::AstContext > SharedAstContext
Shared AST context.
Definition ast.hpp:65
std::shared_ptr< triton::modes::Modes > SharedModes
Shared Modes.
Definition modes.hpp:66
@ ONLY_ON_TAINTED
[symbolic] Perform symbolic execution only on tainted instructions.
@ ONLY_ON_SYMBOLIZED
[symbolic] Perform symbolic execution only on symbolized expressions.
std::size_t usize
unsigned MAX_INT 32 or 64 bits according to the CPU.
std::uint64_t uint64
unisgned 64-bits
The Triton namespace.