libTriton  version 0.9 build 1502
architecture.cpp
Go to the documentation of this file.
1 /*
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>
11 #include <triton/architecture.hpp>
12 #include <triton/arm32Cpu.hpp>
13 #include <triton/exceptions.hpp>
14 #include <triton/x8664Cpu.hpp>
15 #include <triton/x86Cpu.hpp>
16 
17 
18 
19 namespace triton {
20  namespace arch {
21 
24  this->callbacks = callbacks;
25  }
26 
27 
29  return this->arch;
30  }
31 
32 
34  if (!this->cpu)
35  throw triton::exceptions::Architecture("Architecture::getEndianness(): You must define an architecture.");
36  return this->cpu->getEndianness();
37  }
38 
39 
41  if (!this->cpu)
42  throw triton::exceptions::Architecture("Architecture::getCpuInstance(): CPU undefined.");
43  return this->cpu.get();
44  }
45 
46 
48  /* Allocate and init the good arch */
49  switch (arch) {
51  /* init the new instance */
52  this->cpu.reset(new(std::nothrow) triton::arch::x86::x8664Cpu(this->callbacks));
53  if (this->cpu == nullptr)
54  throw triton::exceptions::Architecture("Architecture::setArchitecture(): Not enough memory.");
55  break;
56 
58  /* init the new instance */
59  this->cpu.reset(new(std::nothrow) triton::arch::x86::x86Cpu(this->callbacks));
60  if (this->cpu == nullptr)
61  throw triton::exceptions::Architecture("Architecture::setArchitecture(): Not enough memory.");
62  break;
63 
65  /* init the new instance */
66  this->cpu.reset(new(std::nothrow) triton::arch::arm::aarch64::AArch64Cpu(this->callbacks));
67  if (this->cpu == nullptr)
68  throw triton::exceptions::Architecture("Architecture::setArchitecture(): Not enough memory.");
69  break;
70 
72  /* init the new instance */
73  this->cpu.reset(new(std::nothrow) triton::arch::arm::arm32::Arm32Cpu(this->callbacks));
74  if (this->cpu == nullptr)
75  throw triton::exceptions::Architecture("Architecture::setArchitecture(): Not enough memory.");
76  break;
77 
78  default:
79  throw triton::exceptions::Architecture("Architecture::setArchitecture(): Architecture not supported.");
80  break;
81  }
82 
83  /* Setup global variables */
84  this->arch = arch;
85  }
86 
87 
89  if (!this->cpu)
90  throw triton::exceptions::Architecture("Architecture::clearArchitecture(): You must define an architecture.");
91  this->cpu->clear();
92  }
93 
94 
95  bool Architecture::isValid(void) const {
96  if (this->arch == triton::arch::ARCH_INVALID)
97  return false;
98  return true;
99  }
100 
101 
103  if (!this->cpu)
104  return false;
105  return this->cpu->isFlag(regId);
106  }
107 
108 
110  return this->isFlag(reg.getId());
111  }
112 
113 
115  if (!this->cpu)
116  return false;
117  return this->cpu->isRegister(regId);
118  }
119 
120 
122  return this->isRegister(reg.getId());
123  }
124 
125 
127  if (!this->cpu)
128  return false;
129  return this->cpu->isRegisterValid(regId);
130  }
131 
132 
134  return this->isRegisterValid(reg.getId());
135  }
136 
137 
138  bool Architecture::isThumb(void) const {
139  if (!this->cpu)
140  return false;
141  return this->cpu->isThumb();
142  }
143 
144 
145  void Architecture::setThumb(bool state) {
146  if (this->cpu) {
147  this->cpu->setThumb(state);
148  }
149  }
150 
151 
153  if (!this->cpu)
154  return 0;
155  return this->cpu->numberOfRegisters();
156  }
157 
158 
160  if (!this->cpu)
161  return 0;
162  return this->cpu->gprSize();
163  }
164 
165 
167  if (!this->cpu)
168  return 0;
169  return this->cpu->gprBitSize();
170  }
171 
172 
173  const std::unordered_map<triton::arch::register_e, const triton::arch::Register>& Architecture::getAllRegisters(void) const {
174  if (!this->cpu)
175  throw triton::exceptions::Architecture("Architecture::getAllRegisters(): You must define an architecture.");
176  return this->cpu->getAllRegisters();
177  }
178 
179 
180  std::set<const triton::arch::Register*> Architecture::getParentRegisters(void) const {
181  if (!this->cpu)
182  throw triton::exceptions::Architecture("Architecture::getParentRegisters(): You must define an architecture.");
183  return this->cpu->getParentRegisters();
184  }
185 
186 
188  if (!this->cpu)
189  throw triton::exceptions::Architecture("Architecture::getProgramCounter(): You must define an architecture.");
190  return this->cpu->getProgramCounter();
191  }
192 
193 
195  if (!this->cpu)
196  throw triton::exceptions::Architecture("Architecture::getStackPointer(): You must define an architecture.");
197  return this->cpu->getStackPointer();
198  }
199 
200 
202  if (!this->cpu)
203  throw triton::exceptions::Architecture("Architecture::getRegister(): You must define an architecture.");
204  return this->cpu->getRegister(id);
205  }
206 
207 
208  const triton::arch::Register& Architecture::getRegister(const std::string& name) const {
209  if (!this->cpu)
210  throw triton::exceptions::Architecture("Architecture::getRegister(): You must define an architecture.");
211  return this->cpu->getRegister(name);
212  }
213 
214 
216  if (!this->cpu)
217  throw triton::exceptions::Architecture("Architecture::getParentRegister(): You must define an architecture.");
218  return this->cpu->getParentRegister(reg);
219  }
220 
221 
223  if (!this->cpu)
224  throw triton::exceptions::Architecture("Architecture::getParentRegister(): You must define an architecture.");
225  return this->cpu->getParentRegister(id);
226  }
227 
228 
230  if (!this->cpu)
231  throw triton::exceptions::Architecture("Architecture::disassembly(): You must define an architecture.");
232  this->cpu->disassembly(inst);
233  }
234 
235 
236  std::vector<triton::arch::Instruction> Architecture::disassembly(triton::uint64 addr, triton::usize count) const {
237  std::vector<triton::arch::Instruction> ret;
238  ret.reserve(count);
239 
240  while (count--) {
241  if (!this->isConcreteMemoryValueDefined(addr)) {
242  break;
243  }
244  auto opcodes = this->getConcreteMemoryAreaValue(addr, 16);
245  auto inst = triton::arch::Instruction(addr, reinterpret_cast<triton::uint8*>(opcodes.data()), opcodes.size());
246  this->disassembly(inst);
247  ret.push_back(inst);
248  addr += inst.getSize();
249  }
250 
251  return ret;
252  }
253 
254 
255  std::vector<triton::arch::Instruction> Architecture::disassembly(triton::uint64 addr) const {
256  std::vector<triton::arch::Instruction> ret;
257 
258  do {
259  if (!this->isConcreteMemoryValueDefined(addr)) {
260  break;
261  }
262  auto opcodes = this->getConcreteMemoryAreaValue(addr, 16);
263  auto inst = triton::arch::Instruction(addr, reinterpret_cast<triton::uint8*>(opcodes.data()), opcodes.size());
264  this->disassembly(inst);
265  ret.push_back(inst);
266  addr += inst.getSize();
267  } while (!ret.back().isControlFlow());
268 
269  return ret;
270  }
271 
272 
274  if (!this->cpu)
275  throw triton::exceptions::Architecture("Architecture::getConcreteMemoryValue(): You must define an architecture.");
276  return this->cpu->getConcreteMemoryValue(addr, execCallbacks);
277  }
278 
279 
281  if (!this->cpu)
282  throw triton::exceptions::Architecture("Architecture::getConcreteMemoryValue(): You must define an architecture.");
283  return this->cpu->getConcreteMemoryValue(mem, execCallbacks);
284  }
285 
286 
287  std::vector<triton::uint8> Architecture::getConcreteMemoryAreaValue(triton::uint64 baseAddr, triton::usize size, bool execCallbacks) const {
288  if (!this->cpu)
289  throw triton::exceptions::Architecture("Architecture::getConcreteMemoryAreaValue(): You must define an architecture.");
290  return this->cpu->getConcreteMemoryAreaValue(baseAddr, size, execCallbacks);
291  }
292 
293 
295  if (!this->cpu)
296  throw triton::exceptions::Architecture("Architecture::getConcreteRegisterValue(): You must define an architecture.");
297  return this->cpu->getConcreteRegisterValue(reg, execCallbacks);
298  }
299 
300 
302  if (!this->cpu)
303  throw triton::exceptions::Architecture("Architecture::setConcreteMemoryValue(): You must define an architecture.");
304  this->cpu->setConcreteMemoryValue(addr, value);
305  }
306 
307 
309  if (!this->cpu)
310  throw triton::exceptions::Architecture("Architecture::setConcreteMemoryValue(): You must define an architecture.");
311  this->cpu->setConcreteMemoryValue(mem, value);
312  }
313 
314 
315  void Architecture::setConcreteMemoryAreaValue(triton::uint64 baseAddr, const std::vector<triton::uint8>& values) {
316  if (!this->cpu)
317  throw triton::exceptions::Architecture("Architecture::setConcreteMemoryAreaValue(): You must define an architecture.");
318  this->cpu->setConcreteMemoryAreaValue(baseAddr, values);
319  }
320 
321 
323  if (!this->cpu)
324  throw triton::exceptions::Architecture("Architecture::setConcreteMemoryAreaValue(): You must define an architecture.");
325  this->cpu->setConcreteMemoryAreaValue(baseAddr, area, size);
326  }
327 
328 
330  if (!this->cpu)
331  throw triton::exceptions::Architecture("Architecture::setConcreteRegisterValue(): You must define an architecture.");
332  this->cpu->setConcreteRegisterValue(reg, value);
333  }
334 
335 
337  if (!this->cpu)
338  throw triton::exceptions::Architecture("Architecture::isConcreteMemoryValueDefined(): You must define an architecture.");
339  return this->cpu->isConcreteMemoryValueDefined(mem);
340  }
341 
342 
344  if (!this->cpu)
345  throw triton::exceptions::Architecture("Architecture::isConcreteMemoryValueDefined(): You must define an architecture.");
346  return this->cpu->isConcreteMemoryValueDefined(baseAddr, size);
347  }
348 
349 
351  if (!this->cpu)
352  throw triton::exceptions::Architecture("Architecture::clearConcreteMemoryValue(): You must define an architecture.");
353  this->cpu->clearConcreteMemoryValue(mem);
354  }
355 
356 
358  if (!this->cpu)
359  throw triton::exceptions::Architecture("Architecture::clearConcreteMemoryValue(): You must define an architecture.");
360  this->cpu->clearConcreteMemoryValue(baseAddr, size);
361  }
362 
363  }; /* arch namespace */
364 }; /* triton namespace */
TRITON_EXPORT const triton::arch::Register & getRegister(triton::arch::register_e id) const
Returns register from id.
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 void setConcreteMemoryAreaValue(triton::uint64 baseAddr, const std::vector< triton::uint8 > &values)
[architecture api] - Sets the concrete value of a memory area.
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 setArchitecture(triton::arch::architecture_e arch)
Initializes an architecture.
TRITON_EXPORT void setConcreteRegisterValue(const triton::arch::Register &reg, const triton::uint512 &value)
[architecture api] - Sets the concrete value of a register.
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 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 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 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 setConcreteMemoryValue(triton::uint64 addr, triton::uint8 value)
[architecture api] - Sets the concrete value of a memory cell.
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 interface is used as abstract CPU interface. All CPU must use this interface.
This class is used when to represent an instruction.
Definition: instruction.hpp:48
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.
Definition: aarch64Cpu.hpp:60
This class is used to describe the ARM (32-bits) spec.
Definition: arm32Cpu.hpp:60
This class is used to describe the x86 (64-bits) spec.
Definition: x8664Cpu.hpp:52
This class is used to describe the x86 (32-bits) spec.
Definition: x86Cpu.hpp:52
The callbacks class.
Definition: callbacks.hpp:79
The exception class used by architectures.
Definition: exceptions.hpp:197
register_e
Types of register.
Definition: archEnums.hpp:55
boost::multiprecision::uint512_t uint512
unsigned 512-bits
Definition: tritonTypes.hpp:43
std::size_t usize
unsigned MAX_INT 32 or 64 bits according to the CPU.
Definition: tritonTypes.hpp:67
std::uint64_t uint64
unisgned 64-bits
Definition: tritonTypes.hpp:34
std::uint32_t uint32
unisgned 32-bits
Definition: tritonTypes.hpp:31
std::uint8_t uint8
unisgned 8-bits
Definition: tritonTypes.hpp:25
The Triton namespace.
Definition: api.cpp:227