Loading [MathJax]/extensions/tex2jax.js
libTriton version 1.0 build 1599
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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#include <triton/riscv32Cpu.hpp>
17#include <triton/riscv64Cpu.hpp>
19#include <triton/x8664Cpu.hpp>
20#include <triton/x86Cpu.hpp>
22
23
24
25namespace triton {
26 namespace arch {
27
30 this->callbacks = callbacks;
31 }
32
33
37
38
40 if (!this->cpu)
41 throw triton::exceptions::Architecture("Architecture::getEndianness(): You must define an architecture.");
42 return this->cpu->getEndianness();
43 }
44
45
47 if (!this->cpu)
48 throw triton::exceptions::Architecture("Architecture::getCpuInstance(): CPU undefined.");
49 return this->cpu.get();
50 }
51
52
54 /* Allocate and init the good arch */
55 switch (arch) {
56 case triton::arch::ARCH_AARCH64: this->cpu.reset(new(std::nothrow) triton::arch::arm::aarch64::AArch64Cpu(this->callbacks)); break;
57 case triton::arch::ARCH_ARM32: this->cpu.reset(new(std::nothrow) triton::arch::arm::arm32::Arm32Cpu(this->callbacks)); break;
58 case triton::arch::ARCH_RV32: this->cpu.reset(new(std::nothrow) triton::arch::riscv::riscv32Cpu(this->callbacks)); break;
59 case triton::arch::ARCH_RV64: this->cpu.reset(new(std::nothrow) triton::arch::riscv::riscv64Cpu(this->callbacks)); break;
60 case triton::arch::ARCH_X86: this->cpu.reset(new(std::nothrow) triton::arch::x86::x86Cpu(this->callbacks)); break;
61 case triton::arch::ARCH_X86_64: this->cpu.reset(new(std::nothrow) triton::arch::x86::x8664Cpu(this->callbacks)); break;
62 default:
63 throw triton::exceptions::Architecture("Architecture::setArchitecture(): Architecture not supported.");
64 }
65
66 if (this->cpu == nullptr) {
67 throw triton::exceptions::Architecture("Architecture::setArchitecture(): Not enough memory.");
68 }
69
70 /* Setup global variables */
71 this->arch = arch;
72 }
73
74
76 if (!this->cpu)
77 throw triton::exceptions::Architecture("Architecture::clearArchitecture(): You must define an architecture.");
78 this->cpu->clear();
79 }
80
81
82 bool Architecture::isValid(void) const {
84 return false;
85 return true;
86 }
87
88
90 if (!this->cpu)
91 return false;
92 return this->cpu->isFlag(regId);
93 }
94
95
97 return this->isFlag(reg.getId());
98 }
99
100
102 if (!this->cpu)
103 return false;
104 return this->cpu->isRegister(regId);
105 }
106
107
109 return this->isRegister(reg.getId());
110 }
111
112
114 if (!this->cpu)
115 return false;
116 return this->cpu->isRegisterValid(regId);
117 }
118
119
121 return this->isRegisterValid(reg.getId());
122 }
123
124
125 bool Architecture::isThumb(void) const {
126 if (!this->cpu)
127 return false;
128 return this->cpu->isThumb();
129 }
130
131
132 void Architecture::setThumb(bool state) {
133 if (this->cpu) {
134 this->cpu->setThumb(state);
135 }
136 }
137
138
140 if (!this->cpu)
141 return false;
142 return this->cpu->isMemoryExclusive(mem);
143 }
144
145
147 if (this->cpu) {
148 this->cpu->setMemoryExclusiveTag(mem, tag);
149 }
150 }
151
152
154 if (!this->cpu)
155 return 0;
156 return this->cpu->numberOfRegisters();
157 }
158
159
161 if (!this->cpu)
162 return 0;
163 return this->cpu->gprSize();
164 }
165
166
168 if (!this->cpu)
169 return 0;
170 return this->cpu->gprBitSize();
171 }
172
173
174 const std::unordered_map<triton::arch::register_e, const triton::arch::Register>& Architecture::getAllRegisters(void) const {
175 if (!this->cpu)
176 throw triton::exceptions::Architecture("Architecture::getAllRegisters(): You must define an architecture.");
177 return this->cpu->getAllRegisters();
178 }
179
180 const std::unordered_map<triton::uint64, triton::uint8, IdentityHash<triton::uint64>>& Architecture::getConcreteMemory(void) const {
181 if (!this->cpu)
182 throw triton::exceptions::Architecture("Architecture::getConcreteMemory(): You must define an architecture.");
183 return this->cpu->getConcreteMemory();
184 }
185
186
187 std::set<const triton::arch::Register*> Architecture::getParentRegisters(void) const {
188 if (!this->cpu)
189 throw triton::exceptions::Architecture("Architecture::getParentRegisters(): You must define an architecture.");
190 return this->cpu->getParentRegisters();
191 }
192
193
195 if (!this->cpu)
196 throw triton::exceptions::Architecture("Architecture::getProgramCounter(): You must define an architecture.");
197 return this->cpu->getProgramCounter();
198 }
199
200
202 if (!this->cpu)
203 throw triton::exceptions::Architecture("Architecture::getStackPointer(): You must define an architecture.");
204 return this->cpu->getStackPointer();
205 }
206
207
209 if (!this->cpu)
210 throw triton::exceptions::Architecture("Architecture::getRegister(): You must define an architecture.");
211 return this->cpu->getRegister(id);
212 }
213
214
215 const triton::arch::Register& Architecture::getRegister(const std::string& name) const {
216 if (!this->cpu)
217 throw triton::exceptions::Architecture("Architecture::getRegister(): You must define an architecture.");
218 return this->cpu->getRegister(name);
219 }
220
221
223 if (!this->cpu)
224 throw triton::exceptions::Architecture("Architecture::getParentRegister(): You must define an architecture.");
225 return this->cpu->getParentRegister(reg);
226 }
227
228
230 if (!this->cpu)
231 throw triton::exceptions::Architecture("Architecture::getParentRegister(): You must define an architecture.");
232 return this->cpu->getParentRegister(id);
233 }
234
235
237 if (!this->cpu)
238 throw triton::exceptions::Architecture("Architecture::disassembly(): You must define an architecture.");
239 this->cpu->disassembly(inst);
240 }
241
242
244 if (!this->cpu)
245 throw triton::exceptions::Architecture("Architecture::disassembly(): You must define an architecture.");
246
247 for (auto& inst : block.getInstructions()) {
248 inst.setAddress(addr);
249 this->cpu->disassembly(inst);
250 addr += inst.getSize();
251 }
252 }
253
254
255 std::vector<triton::arch::Instruction> Architecture::disassembly(triton::uint64 addr, triton::usize count) const {
256 std::vector<triton::arch::Instruction> ret;
257 ret.reserve(count);
258
259 while (count--) {
260 if (!this->isConcreteMemoryValueDefined(addr)) {
261 break;
262 }
263 auto opcodes = this->getConcreteMemoryAreaValue(addr, 16);
264 auto inst = triton::arch::Instruction(addr, reinterpret_cast<triton::uint8*>(opcodes.data()), opcodes.size());
265 this->disassembly(inst);
266 ret.push_back(inst);
267 addr += inst.getSize();
268 }
269
270 return ret;
271 }
272
273
274 triton::arch::BasicBlock Architecture::disassembly(triton::uint64 addr, bool(*filterCallback)(std::vector<triton::arch::Instruction>&)) const {
275 std::vector<triton::arch::Instruction> ret;
276 if (!filterCallback)
277 throw triton::exceptions::Exception("Architecture::disassembly(): Incorrect filterCallback.");
278 do {
279 if (!this->isConcreteMemoryValueDefined(addr)) {
280 break;
281 }
282 auto opcodes = this->getConcreteMemoryAreaValue(addr, 16);
283 auto inst = triton::arch::Instruction(addr, reinterpret_cast<triton::uint8*>(opcodes.data()), opcodes.size());
284 this->disassembly(inst);
285 ret.push_back(inst);
286 addr += inst.getSize();
287 } while (!filterCallback(ret));
288
289 return triton::arch::BasicBlock(ret);
290 }
291
292
294 return this->disassembly(addr, ([](std::vector<triton::arch::Instruction>& ret) -> bool {return ret.back().isControlFlow(); }));
295 }
296
297
299 if (!this->cpu)
300 throw triton::exceptions::Architecture("Architecture::getConcreteMemoryValue(): You must define an architecture.");
301 return this->cpu->getConcreteMemoryValue(addr, execCallbacks);
302 }
303
304
306 if (!this->cpu)
307 throw triton::exceptions::Architecture("Architecture::getConcreteMemoryValue(): You must define an architecture.");
308 return this->cpu->getConcreteMemoryValue(mem, execCallbacks);
309 }
310
311
312 std::vector<triton::uint8> Architecture::getConcreteMemoryAreaValue(triton::uint64 baseAddr, triton::usize size, bool execCallbacks) const {
313 if (!this->cpu)
314 throw triton::exceptions::Architecture("Architecture::getConcreteMemoryAreaValue(): You must define an architecture.");
315 return this->cpu->getConcreteMemoryAreaValue(baseAddr, size, execCallbacks);
316 }
317
318
320 if (!this->cpu)
321 throw triton::exceptions::Architecture("Architecture::getConcreteRegisterValue(): You must define an architecture.");
322 return this->cpu->getConcreteRegisterValue(reg, execCallbacks);
323 }
324
325
327 if (!this->cpu)
328 throw triton::exceptions::Architecture("Architecture::setConcreteMemoryValue(): You must define an architecture.");
329 this->cpu->setConcreteMemoryValue(addr, value, execCallbacks);
330 }
331
332
333 void Architecture::setConcreteMemoryValue(const triton::arch::MemoryAccess& mem, const triton::uint512& value, bool execCallbacks) {
334 if (!this->cpu)
335 throw triton::exceptions::Architecture("Architecture::setConcreteMemoryValue(): You must define an architecture.");
336 this->cpu->setConcreteMemoryValue(mem, value, execCallbacks);
337 }
338
339
340 void Architecture::setConcreteMemoryAreaValue(triton::uint64 baseAddr, const std::vector<triton::uint8>& values, bool execCallbacks) {
341 if (!this->cpu)
342 throw triton::exceptions::Architecture("Architecture::setConcreteMemoryAreaValue(): You must define an architecture.");
343 this->cpu->setConcreteMemoryAreaValue(baseAddr, values, execCallbacks);
344 }
345
346
347 void Architecture::setConcreteMemoryAreaValue(triton::uint64 baseAddr, const void* area, triton::usize size, bool execCallbacks) {
348 if (!this->cpu)
349 throw triton::exceptions::Architecture("Architecture::setConcreteMemoryAreaValue(): You must define an architecture.");
350 this->cpu->setConcreteMemoryAreaValue(baseAddr, area, size, execCallbacks);
351 }
352
353
354 void Architecture::setConcreteRegisterValue(const triton::arch::Register& reg, const triton::uint512& value, bool execCallbacks) {
355 if (!this->cpu)
356 throw triton::exceptions::Architecture("Architecture::setConcreteRegisterValue(): You must define an architecture.");
357 this->cpu->setConcreteRegisterValue(reg, value, execCallbacks);
358 }
359
360
362 if (!this->cpu)
363 throw triton::exceptions::Architecture("Architecture::isConcreteMemoryValueDefined(): You must define an architecture.");
364 return this->cpu->isConcreteMemoryValueDefined(mem);
365 }
366
367
369 if (!this->cpu)
370 throw triton::exceptions::Architecture("Architecture::isConcreteMemoryValueDefined(): You must define an architecture.");
371 return this->cpu->isConcreteMemoryValueDefined(baseAddr, size);
372 }
373
374
376 if (!this->cpu)
377 throw triton::exceptions::Architecture("Architecture::clearConcreteMemoryValue(): You must define an architecture.");
378 this->cpu->clearConcreteMemoryValue(mem);
379 }
380
381
383 if (!this->cpu)
384 throw triton::exceptions::Architecture("Architecture::clearConcreteMemoryValue(): You must define an architecture.");
385 this->cpu->clearConcreteMemoryValue(baseAddr, size);
386 }
387
388
390 if (!this->cpu)
391 throw triton::exceptions::Architecture("Architecture::getNopInstruction(): You must define an architecture.");
392
393 switch (this->getArchitecture()) {
396
398 if (this->isThumb())
400 else
402 }
403
407
411
412 default:
413 throw triton::exceptions::Architecture("Architecture::getNopInstruction(): Invalid architecture.");
414 }
415 }
416
417 }; /* arch namespace */
418}; /* 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:66
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.