libTriton version 1.0 build 1592
Loading...
Searching...
No Matches
architecture.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
10#include <triton/aarch64Cpu.hpp>
13#include <triton/arm32Cpu.hpp>
15#include <triton/exceptions.hpp>
16#ifdef COMPILE_RISCV
17#include <triton/riscv32Cpu.hpp>
18#include <triton/riscv64Cpu.hpp>
20#endif
21#include <triton/x8664Cpu.hpp>
22#include <triton/x86Cpu.hpp>
24
25
26
27namespace triton {
28 namespace arch {
29
32 this->callbacks = callbacks;
33 }
34
35
39
40
42 if (!this->cpu)
43 throw triton::exceptions::Architecture("Architecture::getEndianness(): You must define an architecture.");
44 return this->cpu->getEndianness();
45 }
46
47
49 if (!this->cpu)
50 throw triton::exceptions::Architecture("Architecture::getCpuInstance(): CPU undefined.");
51 return this->cpu.get();
52 }
53
54
56 /* Allocate and init the good arch */
57 switch (arch) {
58 case triton::arch::ARCH_X86_64: this->cpu.reset(new(std::nothrow) triton::arch::x86::x8664Cpu(this->callbacks)); break;
59 case triton::arch::ARCH_X86: this->cpu.reset(new(std::nothrow) triton::arch::x86::x86Cpu(this->callbacks)); break;
60 case triton::arch::ARCH_AARCH64: this->cpu.reset(new(std::nothrow) triton::arch::arm::aarch64::AArch64Cpu(this->callbacks)); break;
61 case triton::arch::ARCH_ARM32: this->cpu.reset(new(std::nothrow) triton::arch::arm::arm32::Arm32Cpu(this->callbacks)); break;
62 #ifdef COMPILE_RISCV
63 case triton::arch::ARCH_RV64: this->cpu.reset(new(std::nothrow) triton::arch::riscv::riscv64Cpu(this->callbacks)); break;
64 case triton::arch::ARCH_RV32: this->cpu.reset(new(std::nothrow) triton::arch::riscv::riscv32Cpu(this->callbacks)); break;
65 #endif
66 default:
67 throw triton::exceptions::Architecture("Architecture::setArchitecture(): Architecture not supported.");
68 }
69
70 if (this->cpu == nullptr) {
71 throw triton::exceptions::Architecture("Architecture::setArchitecture(): Not enough memory.");
72 }
73
74 /* Setup global variables */
75 this->arch = arch;
76 }
77
78
80 if (!this->cpu)
81 throw triton::exceptions::Architecture("Architecture::clearArchitecture(): You must define an architecture.");
82 this->cpu->clear();
83 }
84
85
86 bool Architecture::isValid(void) const {
88 return false;
89 return true;
90 }
91
92
94 if (!this->cpu)
95 return false;
96 return this->cpu->isFlag(regId);
97 }
98
99
101 return this->isFlag(reg.getId());
102 }
103
104
106 if (!this->cpu)
107 return false;
108 return this->cpu->isRegister(regId);
109 }
110
111
113 return this->isRegister(reg.getId());
114 }
115
116
118 if (!this->cpu)
119 return false;
120 return this->cpu->isRegisterValid(regId);
121 }
122
123
125 return this->isRegisterValid(reg.getId());
126 }
127
128
129 bool Architecture::isThumb(void) const {
130 if (!this->cpu)
131 return false;
132 return this->cpu->isThumb();
133 }
134
135
136 void Architecture::setThumb(bool state) {
137 if (this->cpu) {
138 this->cpu->setThumb(state);
139 }
140 }
141
142
144 if (!this->cpu)
145 return false;
146 return this->cpu->isMemoryExclusive(mem);
147 }
148
149
151 if (this->cpu) {
152 this->cpu->setMemoryExclusiveTag(mem, tag);
153 }
154 }
155
156
158 if (!this->cpu)
159 return 0;
160 return this->cpu->numberOfRegisters();
161 }
162
163
165 if (!this->cpu)
166 return 0;
167 return this->cpu->gprSize();
168 }
169
170
172 if (!this->cpu)
173 return 0;
174 return this->cpu->gprBitSize();
175 }
176
177
178 const std::unordered_map<triton::arch::register_e, const triton::arch::Register>& Architecture::getAllRegisters(void) const {
179 if (!this->cpu)
180 throw triton::exceptions::Architecture("Architecture::getAllRegisters(): You must define an architecture.");
181 return this->cpu->getAllRegisters();
182 }
183
184 const std::unordered_map<triton::uint64, triton::uint8, IdentityHash<triton::uint64>>& Architecture::getConcreteMemory(void) const {
185 if (!this->cpu)
186 throw triton::exceptions::Architecture("Architecture::getConcreteMemory(): You must define an architecture.");
187 return this->cpu->getConcreteMemory();
188 }
189
190
191 std::set<const triton::arch::Register*> Architecture::getParentRegisters(void) const {
192 if (!this->cpu)
193 throw triton::exceptions::Architecture("Architecture::getParentRegisters(): You must define an architecture.");
194 return this->cpu->getParentRegisters();
195 }
196
197
199 if (!this->cpu)
200 throw triton::exceptions::Architecture("Architecture::getProgramCounter(): You must define an architecture.");
201 return this->cpu->getProgramCounter();
202 }
203
204
206 if (!this->cpu)
207 throw triton::exceptions::Architecture("Architecture::getStackPointer(): You must define an architecture.");
208 return this->cpu->getStackPointer();
209 }
210
211
213 if (!this->cpu)
214 throw triton::exceptions::Architecture("Architecture::getRegister(): You must define an architecture.");
215 return this->cpu->getRegister(id);
216 }
217
218
219 const triton::arch::Register& Architecture::getRegister(const std::string& name) const {
220 if (!this->cpu)
221 throw triton::exceptions::Architecture("Architecture::getRegister(): You must define an architecture.");
222 return this->cpu->getRegister(name);
223 }
224
225
227 if (!this->cpu)
228 throw triton::exceptions::Architecture("Architecture::getParentRegister(): You must define an architecture.");
229 return this->cpu->getParentRegister(reg);
230 }
231
232
234 if (!this->cpu)
235 throw triton::exceptions::Architecture("Architecture::getParentRegister(): You must define an architecture.");
236 return this->cpu->getParentRegister(id);
237 }
238
239
241 if (!this->cpu)
242 throw triton::exceptions::Architecture("Architecture::disassembly(): You must define an architecture.");
243 this->cpu->disassembly(inst);
244 }
245
246
248 if (!this->cpu)
249 throw triton::exceptions::Architecture("Architecture::disassembly(): You must define an architecture.");
250
251 for (auto& inst : block.getInstructions()) {
252 inst.setAddress(addr);
253 this->cpu->disassembly(inst);
254 addr += inst.getSize();
255 }
256 }
257
258
259 std::vector<triton::arch::Instruction> Architecture::disassembly(triton::uint64 addr, triton::usize count) const {
260 std::vector<triton::arch::Instruction> ret;
261 ret.reserve(count);
262
263 while (count--) {
264 if (!this->isConcreteMemoryValueDefined(addr)) {
265 break;
266 }
267 auto opcodes = this->getConcreteMemoryAreaValue(addr, 16);
268 auto inst = triton::arch::Instruction(addr, reinterpret_cast<triton::uint8*>(opcodes.data()), opcodes.size());
269 this->disassembly(inst);
270 ret.push_back(inst);
271 addr += inst.getSize();
272 }
273
274 return ret;
275 }
276
277
278 triton::arch::BasicBlock Architecture::disassembly(triton::uint64 addr, bool(*filterCallback)(std::vector<triton::arch::Instruction>&)) const {
279 std::vector<triton::arch::Instruction> ret;
280 if (!filterCallback)
281 throw triton::exceptions::Exception("Architecture::disassembly(): Incorrect filterCallback.");
282 do {
283 if (!this->isConcreteMemoryValueDefined(addr)) {
284 break;
285 }
286 auto opcodes = this->getConcreteMemoryAreaValue(addr, 16);
287 auto inst = triton::arch::Instruction(addr, reinterpret_cast<triton::uint8*>(opcodes.data()), opcodes.size());
288 this->disassembly(inst);
289 ret.push_back(inst);
290 addr += inst.getSize();
291 } while (!filterCallback(ret));
292
293 return triton::arch::BasicBlock(ret);
294 }
295
296
298 return this->disassembly(addr, ([](std::vector<triton::arch::Instruction>& ret) -> bool {return ret.back().isControlFlow(); }));
299 }
300
301
303 if (!this->cpu)
304 throw triton::exceptions::Architecture("Architecture::getConcreteMemoryValue(): You must define an architecture.");
305 return this->cpu->getConcreteMemoryValue(addr, execCallbacks);
306 }
307
308
310 if (!this->cpu)
311 throw triton::exceptions::Architecture("Architecture::getConcreteMemoryValue(): You must define an architecture.");
312 return this->cpu->getConcreteMemoryValue(mem, execCallbacks);
313 }
314
315
316 std::vector<triton::uint8> Architecture::getConcreteMemoryAreaValue(triton::uint64 baseAddr, triton::usize size, bool execCallbacks) const {
317 if (!this->cpu)
318 throw triton::exceptions::Architecture("Architecture::getConcreteMemoryAreaValue(): You must define an architecture.");
319 return this->cpu->getConcreteMemoryAreaValue(baseAddr, size, execCallbacks);
320 }
321
322
324 if (!this->cpu)
325 throw triton::exceptions::Architecture("Architecture::getConcreteRegisterValue(): You must define an architecture.");
326 return this->cpu->getConcreteRegisterValue(reg, execCallbacks);
327 }
328
329
331 if (!this->cpu)
332 throw triton::exceptions::Architecture("Architecture::setConcreteMemoryValue(): You must define an architecture.");
333 this->cpu->setConcreteMemoryValue(addr, value, execCallbacks);
334 }
335
336
337 void Architecture::setConcreteMemoryValue(const triton::arch::MemoryAccess& mem, const triton::uint512& value, bool execCallbacks) {
338 if (!this->cpu)
339 throw triton::exceptions::Architecture("Architecture::setConcreteMemoryValue(): You must define an architecture.");
340 this->cpu->setConcreteMemoryValue(mem, value, execCallbacks);
341 }
342
343
344 void Architecture::setConcreteMemoryAreaValue(triton::uint64 baseAddr, const std::vector<triton::uint8>& values, bool execCallbacks) {
345 if (!this->cpu)
346 throw triton::exceptions::Architecture("Architecture::setConcreteMemoryAreaValue(): You must define an architecture.");
347 this->cpu->setConcreteMemoryAreaValue(baseAddr, values, execCallbacks);
348 }
349
350
351 void Architecture::setConcreteMemoryAreaValue(triton::uint64 baseAddr, const void* area, triton::usize size, bool execCallbacks) {
352 if (!this->cpu)
353 throw triton::exceptions::Architecture("Architecture::setConcreteMemoryAreaValue(): You must define an architecture.");
354 this->cpu->setConcreteMemoryAreaValue(baseAddr, area, size, execCallbacks);
355 }
356
357
358 void Architecture::setConcreteRegisterValue(const triton::arch::Register& reg, const triton::uint512& value, bool execCallbacks) {
359 if (!this->cpu)
360 throw triton::exceptions::Architecture("Architecture::setConcreteRegisterValue(): You must define an architecture.");
361 this->cpu->setConcreteRegisterValue(reg, value, execCallbacks);
362 }
363
364
366 if (!this->cpu)
367 throw triton::exceptions::Architecture("Architecture::isConcreteMemoryValueDefined(): You must define an architecture.");
368 return this->cpu->isConcreteMemoryValueDefined(mem);
369 }
370
371
373 if (!this->cpu)
374 throw triton::exceptions::Architecture("Architecture::isConcreteMemoryValueDefined(): You must define an architecture.");
375 return this->cpu->isConcreteMemoryValueDefined(baseAddr, size);
376 }
377
378
380 if (!this->cpu)
381 throw triton::exceptions::Architecture("Architecture::clearConcreteMemoryValue(): You must define an architecture.");
382 this->cpu->clearConcreteMemoryValue(mem);
383 }
384
385
387 if (!this->cpu)
388 throw triton::exceptions::Architecture("Architecture::clearConcreteMemoryValue(): You must define an architecture.");
389 this->cpu->clearConcreteMemoryValue(baseAddr, size);
390 }
391
392
394 if (!this->cpu)
395 throw triton::exceptions::Architecture("Architecture::getNopInstruction(): You must define an architecture.");
396
397 switch (this->getArchitecture()) {
400
402 if (this->isThumb())
404 else
406 }
407
411
412 #ifdef COMPILE_RISCV
413 case triton::arch::ARCH_RV64:
414 case triton::arch::ARCH_RV32:
416 #endif
417
418 default:
419 throw triton::exceptions::Architecture("Architecture::getNopInstruction(): Invalid architecture.");
420 }
421 }
422
423 }; /* arch namespace */
424}; /* triton namespace */
TRITON_EXPORT const triton::arch::Register & getRegister(triton::arch::register_e id) const
Returns register from id.
TRITON_EXPORT void setConcreteMemoryAreaValue(triton::uint64 baseAddr, const std::vector< triton::uint8 > &values, bool execCallbacks=true)
[architecture api] - Sets the concrete value of a memory area.
TRITON_EXPORT std::set< const triton::arch::Register * > getParentRegisters(void) const
Returns all parent registers.
TRITON_EXPORT void setThumb(bool state)
Sets CPU state to Thumb mode. Only valid for Arm32.
TRITON_EXPORT const triton::arch::Register & getStackPointer(void) const
Returns the stack pointer register.
TRITON_EXPORT triton::uint32 numberOfRegisters(void) const
Returns the number of registers according to the CPU architecture.
TRITON_EXPORT triton::uint32 gprBitSize(void) const
Returns the bit in bit of the General Purpose Registers.
TRITON_EXPORT void setConcreteRegisterValue(const triton::arch::Register &reg, const triton::uint512 &value, bool execCallbacks=true)
[architecture api] - Sets the concrete value of a register.
TRITON_EXPORT void setConcreteMemoryValue(triton::uint64 addr, triton::uint8 value, bool execCallbacks=true)
[architecture api] - Sets the concrete value of a memory cell.
TRITON_EXPORT void setArchitecture(triton::arch::architecture_e arch)
Initializes an architecture.
TRITON_EXPORT const std::unordered_map< triton::uint64, triton::uint8, IdentityHash< triton::uint64 > > & getConcreteMemory(void) const
Return all memory.
TRITON_EXPORT void disassembly(triton::arch::Instruction &inst) const
Disassembles the instruction according to the architecture.
TRITON_EXPORT void clearArchitecture(void)
Clears the architecture states (registers and memory).
TRITON_EXPORT bool isMemoryExclusive(const triton::arch::MemoryAccess &mem) const
Returns true if the memory access is tagged as exclusive. Only valid for Arm32 and AArch64.
TRITON_EXPORT std::vector< triton::uint8 > getConcreteMemoryAreaValue(triton::uint64 baseAddr, triton::usize size, bool execCallbacks=true) const
Returns the concrete value of a memory area.
TRITON_EXPORT const triton::arch::Instruction getNopInstruction(void) const
Returns a NOP instruction according to the architecture.
TRITON_EXPORT bool isConcreteMemoryValueDefined(const triton::arch::MemoryAccess &mem) const
Returns true if memory cells have a defined concrete value.
TRITON_EXPORT const std::unordered_map< triton::arch::register_e, const triton::arch::Register > & getAllRegisters(void) const
Returns all registers.
TRITON_EXPORT Architecture(triton::callbacks::Callbacks *callbacks=nullptr)
Constructor.
TRITON_EXPORT bool isFlag(triton::arch::register_e regId) const
Returns true if the register ID is a flag.
TRITON_EXPORT const triton::arch::Register & getProgramCounter(void) const
Returns the program counter register.
std::unique_ptr< triton::arch::CpuInterface > cpu
Instance to the real CPU class.
TRITON_EXPORT void setMemoryExclusiveTag(const triton::arch::MemoryAccess &mem, bool tag)
Sets exclusive memory access tag. Only valid for Arm32 and AArch64.
TRITON_EXPORT triton::uint8 getConcreteMemoryValue(triton::uint64 addr, bool execCallbacks=true) const
Returns the concrete value of a memory cell.
triton::arch::architecture_e arch
The kind of architecture used.
TRITON_EXPORT triton::uint512 getConcreteRegisterValue(const triton::arch::Register &reg, bool execCallbacks=true) const
Returns the concrete value of a register.
TRITON_EXPORT void clearConcreteMemoryValue(const triton::arch::MemoryAccess &mem)
Clears concrete values assigned to the memory cells.
TRITON_EXPORT bool isRegisterValid(triton::arch::register_e regId) const
Returns true if the register ID is a register or a flag.
TRITON_EXPORT bool isRegister(triton::arch::register_e regId) const
Returns true if the register ID is a register.
TRITON_EXPORT bool isThumb(void) const
Returns true if the execution mode is Thumb. Only valid for Arm32.
TRITON_EXPORT triton::arch::architecture_e getArchitecture(void) const
Returns the kind of architecture as triton::arch::architecture_e.
TRITON_EXPORT bool isValid(void) const
Returns true if the architecture is valid.
TRITON_EXPORT triton::arch::endianness_e getEndianness(void) const
Returns the kind of endianness as triton::arch::endianness_e.
TRITON_EXPORT triton::uint32 gprSize(void) const
Returns the bit in byte of the General Purpose Registers.
TRITON_EXPORT const triton::arch::Register & getParentRegister(triton::arch::register_e id) const
Returns parent register from id.
TRITON_EXPORT triton::arch::CpuInterface * getCpuInstance(void)
Returns the instance of the current CPU used.
This class is used to represent a basic block.
TRITON_EXPORT std::vector< triton::arch::Instruction > & getInstructions(void)
Gets all instructions of the block.
This interface is used as abstract CPU interface. All CPU must use this interface.
This class is used to represent an instruction.
This class is used to represent a memory access.
This class is used when an instruction has a register operand.
Definition register.hpp:44
TRITON_EXPORT triton::arch::register_e getId(void) const
Returns the id of the register.
Definition register.cpp:53
This class is used to describe the ARM (64-bits) spec.
This class is used to describe the ARM (32-bits) spec.
Definition arm32Cpu.hpp:61
This class is used to describe the RV32 spec.
This class is used to describe the RV64 spec.
This class is used to describe the x86 (64-bits) spec.
Definition x8664Cpu.hpp:53
This class is used to describe the x86 (32-bits) spec.
Definition x86Cpu.hpp:53
The callbacks class.
Definition callbacks.hpp:79
The exception class used by architectures.
The root class of all exceptions.
const triton::arch::Instruction nop
AArch64 NOP instruction.
register_e
Types of register.
Definition archEnums.hpp:68
const triton::arch::Instruction nop
ARM32 NOP instruction.
const triton::arch::Instruction thumbnop
ARM32 Thumb NOP instruction.
const triton::arch::Instruction nop
RISCV NOP instruction – ADDI x0, x0, 0.
std::size_t usize
unsigned MAX_INT 32 or 64 bits according to the CPU.
std::uint64_t uint64
unisgned 64-bits
std::uint32_t uint32
unisgned 32-bits
std::uint8_t uint8
unisgned 8-bits
const triton::arch::Instruction nop
x86 NOP instruction
The Triton namespace.