1 //! \file
2 /*
3 **  Copyright (C) - Triton
4 **
5 **  This program is under the terms of the Apache License 2.0.
6 */
7 
8 #include <cstring>
9 
10 #include <triton/aarch64Cpu.hpp>
11 #include <triton/architecture.hpp>
12 #include <triton/coreUtils.hpp>
13 #include <triton/cpuSize.hpp>
14 #include <triton/exceptions.hpp>
15 #include <triton/immediate.hpp>
16 
17 
18 
19 namespace triton {
20   namespace arch {
21     namespace arm {
22       namespace aarch64 {
23 
AArch64Cpu(triton::callbacks::Callbacks * callbacks)24         AArch64Cpu::AArch64Cpu(triton::callbacks::Callbacks* callbacks) : AArch64Specifications(ARCH_AARCH64) {
25           this->callbacks = callbacks;
26           this->handle    = 0;
27 
28           this->clear();
29           this->disassInit();
30         }
31 
32 
AArch64Cpu(const AArch64Cpu & other)33         AArch64Cpu::AArch64Cpu(const AArch64Cpu& other) : AArch64Specifications(ARCH_AARCH64) {
34           this->copy(other);
35         }
36 
37 
~AArch64Cpu()38         AArch64Cpu::~AArch64Cpu() {
39           this->memory.clear();
40           if (this->handle) {
41             triton::extlibs::capstone::cs_close(&this->handle);
42           }
43         }
44 
45 
disassInit(void)46         void AArch64Cpu::disassInit(void) {
47           if (this->handle) {
48             triton::extlibs::capstone::cs_close(&this->handle);
49           }
50 
51           if (triton::extlibs::capstone::cs_open(triton::extlibs::capstone::CS_ARCH_ARM64, triton::extlibs::capstone::CS_MODE_ARM, &this->handle) != triton::extlibs::capstone::CS_ERR_OK)
52             throw triton::exceptions::Disassembly("AArch64Cpu::disassInit(): Cannot open capstone.");
53 
54           triton::extlibs::capstone::cs_option(this->handle, triton::extlibs::capstone::CS_OPT_DETAIL, triton::extlibs::capstone::CS_OPT_ON);
55         }
56 
57 
copy(const AArch64Cpu & other)58         void AArch64Cpu::copy(const AArch64Cpu& other) {
59           this->callbacks = other.callbacks;
60           this->memory    = other.memory;
61 
62           this->disassInit();
63 
64           std::memcpy(this->x0,   other.x0,   sizeof(this->x0));
65           std::memcpy(this->x1,   other.x1,   sizeof(this->x1));
66           std::memcpy(this->x2,   other.x2,   sizeof(this->x2));
67           std::memcpy(this->x3,   other.x3,   sizeof(this->x3));
68           std::memcpy(this->x4,   other.x4,   sizeof(this->x4));
69           std::memcpy(this->x5,   other.x5,   sizeof(this->x5));
70           std::memcpy(this->x6,   other.x6,   sizeof(this->x6));
71           std::memcpy(this->x7,   other.x7,   sizeof(this->x7));
72           std::memcpy(this->x8,   other.x8,   sizeof(this->x8));
73           std::memcpy(this->x9,   other.x9,   sizeof(this->x9));
74           std::memcpy(this->x10,  other.x10,  sizeof(this->x10));
75           std::memcpy(this->x11,  other.x11,  sizeof(this->x11));
76           std::memcpy(this->x12,  other.x12,  sizeof(this->x12));
77           std::memcpy(this->x13,  other.x13,  sizeof(this->x13));
78           std::memcpy(this->x14,  other.x14,  sizeof(this->x14));
79           std::memcpy(this->x15,  other.x15,  sizeof(this->x15));
80           std::memcpy(this->x16,  other.x16,  sizeof(this->x16));
81           std::memcpy(this->x17,  other.x17,  sizeof(this->x17));
82           std::memcpy(this->x18,  other.x18,  sizeof(this->x18));
83           std::memcpy(this->x19,  other.x19,  sizeof(this->x19));
84           std::memcpy(this->x20,  other.x20,  sizeof(this->x20));
85           std::memcpy(this->x21,  other.x21,  sizeof(this->x21));
86           std::memcpy(this->x22,  other.x22,  sizeof(this->x22));
87           std::memcpy(this->x23,  other.x23,  sizeof(this->x23));
88           std::memcpy(this->x24,  other.x24,  sizeof(this->x24));
89           std::memcpy(this->x25,  other.x25,  sizeof(this->x25));
90           std::memcpy(this->x26,  other.x26,  sizeof(this->x26));
91           std::memcpy(this->x27,  other.x27,  sizeof(this->x27));
92           std::memcpy(this->x28,  other.x28,  sizeof(this->x28));
93           std::memcpy(this->x29,  other.x29,  sizeof(this->x29));
94           std::memcpy(this->x30,  other.x30,  sizeof(this->x30));
95           std::memcpy(this->sp,   other.sp,   sizeof(this->sp));
96           std::memcpy(this->pc,   other.pc,   sizeof(this->pc));
97           std::memcpy(this->spsr, other.spsr, sizeof(this->spsr));
98         }
99 
100 
clear(void)101         void AArch64Cpu::clear(void) {
102           /* Clear memory */
103           this->memory.clear();
104 
105           /* Clear registers */
106           std::memset(this->x0,   0x00, sizeof(this->x0));
107           std::memset(this->x1,   0x00, sizeof(this->x1));
108           std::memset(this->x2,   0x00, sizeof(this->x2));
109           std::memset(this->x3,   0x00, sizeof(this->x3));
110           std::memset(this->x4,   0x00, sizeof(this->x4));
111           std::memset(this->x5,   0x00, sizeof(this->x5));
112           std::memset(this->x6,   0x00, sizeof(this->x6));
113           std::memset(this->x7,   0x00, sizeof(this->x7));
114           std::memset(this->x8,   0x00, sizeof(this->x8));
115           std::memset(this->x9,   0x00, sizeof(this->x9));
116           std::memset(this->x10,  0x00, sizeof(this->x10));
117           std::memset(this->x11,  0x00, sizeof(this->x11));
118           std::memset(this->x12,  0x00, sizeof(this->x12));
119           std::memset(this->x13,  0x00, sizeof(this->x13));
120           std::memset(this->x14,  0x00, sizeof(this->x14));
121           std::memset(this->x15,  0x00, sizeof(this->x15));
122           std::memset(this->x16,  0x00, sizeof(this->x16));
123           std::memset(this->x17,  0x00, sizeof(this->x17));
124           std::memset(this->x18,  0x00, sizeof(this->x18));
125           std::memset(this->x19,  0x00, sizeof(this->x19));
126           std::memset(this->x20,  0x00, sizeof(this->x20));
127           std::memset(this->x21,  0x00, sizeof(this->x21));
128           std::memset(this->x22,  0x00, sizeof(this->x22));
129           std::memset(this->x23,  0x00, sizeof(this->x23));
130           std::memset(this->x24,  0x00, sizeof(this->x24));
131           std::memset(this->x25,  0x00, sizeof(this->x25));
132           std::memset(this->x26,  0x00, sizeof(this->x26));
133           std::memset(this->x27,  0x00, sizeof(this->x27));
134           std::memset(this->x28,  0x00, sizeof(this->x28));
135           std::memset(this->x29,  0x00, sizeof(this->x29));
136           std::memset(this->x30,  0x00, sizeof(this->x30));
137           std::memset(this->sp,   0x00, sizeof(this->sp));
138           std::memset(this->pc,   0x00, sizeof(this->pc));
139           std::memset(this->spsr, 0x00, sizeof(this->spsr));
140         }
141 
142 
operator =(const AArch64Cpu & other)143         AArch64Cpu& AArch64Cpu::operator=(const AArch64Cpu& other) {
144           this->copy(other);
145           return *this;
146         }
147 
148 
getEndianness(void) const149         triton::arch::endianness_e AArch64Cpu::getEndianness(void) const {
150           return triton::arch::LE_ENDIANNESS;
151         }
152 
153 
isFlag(triton::arch::register_e regId) const154         bool AArch64Cpu::isFlag(triton::arch::register_e regId) const {
155           return ((regId >= triton::arch::ID_REG_AARCH64_C && regId <= triton::arch::ID_REG_AARCH64_Z) ? true : false);
156         }
157 
158 
isRegister(triton::arch::register_e regId) const159         bool AArch64Cpu::isRegister(triton::arch::register_e regId) const {
160           return this->isGPR(regId);
161         }
162 
163 
isRegisterValid(triton::arch::register_e regId) const164         bool AArch64Cpu::isRegisterValid(triton::arch::register_e regId) const {
165           return (this->isFlag(regId) || this->isRegister(regId));
166         }
167 
168 
isGPR(triton::arch::register_e regId) const169         bool AArch64Cpu::isGPR(triton::arch::register_e regId) const {
170           return ((regId >= triton::arch::ID_REG_AARCH64_X0 && regId <= triton::arch::ID_REG_AARCH64_WZR) ? true : false);
171         }
172 
173 
numberOfRegisters(void) const174         triton::uint32 AArch64Cpu::numberOfRegisters(void) const {
175           return triton::arch::ID_REG_LAST_ITEM;
176         }
177 
178 
gprSize(void) const179         triton::uint32 AArch64Cpu::gprSize(void) const {
180           return triton::size::qword;
181         }
182 
183 
gprBitSize(void) const184         triton::uint32 AArch64Cpu::gprBitSize(void) const {
185           return triton::bitsize::qword;
186         }
187 
188 
getAllRegisters(void) const189         const std::unordered_map<triton::arch::register_e, const triton::arch::Register>& AArch64Cpu::getAllRegisters(void) const {
190           return this->registers_;
191         }
192 
193 
getParentRegisters(void) const194         std::set<const triton::arch::Register*> AArch64Cpu::getParentRegisters(void) const {
195           std::set<const triton::arch::Register*> ret;
196 
197           for (const auto& kv: this->registers_) {
198             auto regId = kv.first;
199             const auto& reg = kv.second;
200 
201             /* Add GPR */
202             if (reg.getSize() == this->gprSize())
203               ret.insert(&reg);
204 
205             /* Add Flags */
206             else if (this->isFlag(regId))
207               ret.insert(&reg);
208           }
209 
210           return ret;
211         }
212 
213 
getRegister(triton::arch::register_e id) const214         const triton::arch::Register& AArch64Cpu::getRegister(triton::arch::register_e id) const {
215           try {
216             return this->registers_.at(id);
217           } catch (const std::out_of_range&) {
218             throw triton::exceptions::Cpu("AArch64Cpu::getRegister(): Invalid register for this architecture.");
219           }
220         }
221 
222 
getParentRegister(const triton::arch::Register & reg) const223         const triton::arch::Register& AArch64Cpu::getParentRegister(const triton::arch::Register& reg) const {
224           return this->getRegister(reg.getParent());
225         }
226 
227 
getParentRegister(triton::arch::register_e id) const228         const triton::arch::Register& AArch64Cpu::getParentRegister(triton::arch::register_e id) const {
229           return this->getParentRegister(this->getRegister(id));
230         }
231 
232 
getProgramCounter(void) const233         const triton::arch::Register& AArch64Cpu::getProgramCounter(void) const {
234           return this->getRegister(this->pcId);
235         }
236 
237 
getStackPointer(void) const238         const triton::arch::Register& AArch64Cpu::getStackPointer(void) const {
239           return this->getRegister(this->spId);
240         }
241 
242 
disassembly(triton::arch::Instruction & inst) const243         void AArch64Cpu::disassembly(triton::arch::Instruction& inst) const {
244           triton::extlibs::capstone::cs_insn* insn;
245           triton::usize count = 0;
246           triton::uint32 size = 0;
247 
248           /* Check if the opcode and opcode' size are defined */
249           if (inst.getOpcode() == nullptr || inst.getSize() == 0)
250             throw triton::exceptions::Disassembly("AArch64Cpu::disassembly(): Opcode and opcodeSize must be definied.");
251 
252           /* Clear instructicon's operands if alredy defined */
253           inst.operands.clear();
254 
255           /* Let's disass and build our operands */
256           count = triton::extlibs::capstone::cs_disasm(this->handle, inst.getOpcode(), inst.getSize(), inst.getAddress(), 0, &insn);
257           if (count > 0) {
258             /* Detail information */
259             triton::extlibs::capstone::cs_detail* detail = insn->detail;
260 
261             /* Init the disassembly */
262             std::stringstream str;
263 
264             str << insn[0].mnemonic;
265             if (detail->arm64.op_count)
266               str << " " <<  insn[0].op_str;
267 
268             inst.setDisassembly(str.str());
269 
270             /* Refine the size */
271             inst.setSize(insn[0].size);
272 
273             /* Init the instruction's type */
274             inst.setType(this->capstoneInstructionToTritonInstruction(insn[0].id));
275 
276             /* Init the instruction's code codition */
277             inst.setCodeCondition(this->capstoneConditionToTritonCondition(detail->arm64.cc));
278 
279             /* Init the instruction's write back flag */
280             inst.setWriteBack(detail->arm64.writeback);
281 
282             /* Set True if the instruction udpate flags */
283             inst.setUpdateFlag(detail->arm64.update_flags);
284 
285             /* Init operands */
286             for (triton::uint32 n = 0; n < detail->arm64.op_count; n++) {
287               triton::extlibs::capstone::cs_arm64_op* op = &(detail->arm64.operands[n]);
288               switch(op->type) {
289 
290                 case triton::extlibs::capstone::ARM64_OP_IMM: {
291                   triton::arch::Immediate imm(op->imm, size ? size : triton::size::qword);
292 
293                   /*
294                    * Instruction such that CBZ, CBNZ or TBZ may imply a wrong size.
295                    * So, if Triton truncates the value by setting a size less than
296                    * the original one, we redefine the size automatically.
297                    */
298                   if (static_cast<triton::uint64>(op->imm) > imm.getValue()) {
299                     imm = Immediate();
300                     imm.setValue(op->imm, 0); /* By setting 0 as size, we automatically identify the size of the value */
301                   }
302 
303                   /* Set Shift type and value */
304                   imm.setShiftType(this->capstoneShiftToTritonShift(op->shift.type));
305                   imm.setShiftValue(op->shift.value);
306 
307                   inst.operands.push_back(triton::arch::OperandWrapper(imm));
308                   break;
309                 }
310 
311                 case triton::extlibs::capstone::ARM64_OP_MEM: {
312                   triton::arch::MemoryAccess mem;
313 
314                   /* Set the size of the memory access */
315                   mem.setPair(std::make_pair(size ? ((size * triton::bitsize::byte) - 1) : triton::bitsize::qword - 1, 0));
316 
317                   /* LEA if exists */
318                   triton::arch::Register base(*this, this->capstoneRegisterToTritonRegister(op->mem.base));
319                   triton::arch::Register index(*this, this->capstoneRegisterToTritonRegister(op->mem.index));
320 
321                   triton::uint32 immsize = (
322                                             this->isRegisterValid(base.getId()) ? base.getSize() :
323                                             this->isRegisterValid(index.getId()) ? index.getSize() :
324                                             this->gprSize()
325                                           );
326 
327                   triton::arch::Immediate disp(op->mem.disp, immsize);
328 
329                   /* Specify that LEA contains a PC relative */
330                   /* FIXME: Valid in ARM64 ? */
331                   if (base.getId() == this->pcId) {
332                     mem.setPcRelative(inst.getNextAddress());
333                   }
334 
335                   /* Set extend type and size */
336                   index.setExtendType(this->capstoneExtendToTritonExtend(op->ext));
337                   if (op->ext != triton::extlibs::capstone::ARM64_EXT_INVALID) {
338                     index.setExtendedSize(base.getBitSize());
339                   }
340 
341                   /* Note that in ARM64 there is no segment register and scale value */
342                   mem.setBaseRegister(base);
343                   mem.setIndexRegister(index);
344                   mem.setDisplacement(disp);
345 
346                   /* If there is an index register available, set scale to 1 to perform this following computation (base) + (index * scale) */
347                   if (this->isRegisterValid(index.getId())) {
348                     mem.setScale(triton::arch::Immediate(1, immsize));
349                   }
350 
351                   inst.operands.push_back(triton::arch::OperandWrapper(mem));
352                   break;
353                 }
354 
355                 case triton::extlibs::capstone::ARM64_OP_REG: {
356                   triton::arch::Register reg(*this, this->capstoneRegisterToTritonRegister(op->reg));
357 
358                   /* Set Shift type and value */
359                   reg.setShiftType(this->capstoneShiftToTritonShift(op->shift.type));
360                   reg.setShiftValue(op->shift.value);
361 
362                   /* Set extend type and size */
363                   reg.setExtendType(this->capstoneExtendToTritonExtend(op->ext));
364                   if (op->ext != triton::extlibs::capstone::ARM64_EXT_INVALID) {
365                     reg.setExtendedSize(size * triton::bitsize::byte);
366                   }
367 
368                   /* Define a base address for next operand */
369                   if (!size) {
370                     size = reg.getSize();
371                   }
372 
373                   inst.operands.push_back(triton::arch::OperandWrapper(reg));
374                   break;
375                 }
376 
377                 default:
378                   /* NOTE: FP, CIMM, and missing one are not supported yet. */
379                   throw triton::exceptions::Disassembly("AArch64Cpu::disassembly(): Invalid operand.");
380               } // switch
381             } // for operand
382 
383             /* Set control flow */
384             if (insn[0].id == triton::extlibs::capstone::ARM64_INS_RET)
385               inst.setControlFlow(true);
386 
387             /* Set branch */
388             if (detail->groups_count > 0) {
389               for (triton::uint32 n = 0; n < detail->groups_count; n++) {
390                 if (detail->groups[n] == triton::extlibs::capstone::ARM64_GRP_JUMP) {
391                   inst.setBranch(true);
392                   inst.setControlFlow(true);
393                 }
394               }
395             }
396 
397             /* Free capstone stuffs */
398             triton::extlibs::capstone::cs_free(insn, count);
399           }
400           else
401             throw triton::exceptions::Disassembly("AArch64Cpu::disassembly(): Failed to disassemble the given code.");
402         }
403 
404 
getConcreteMemoryValue(triton::uint64 addr,bool execCallbacks) const405         triton::uint8 AArch64Cpu::getConcreteMemoryValue(triton::uint64 addr, bool execCallbacks) const {
406           if (execCallbacks && this->callbacks)
407             this->callbacks->processCallbacks(triton::callbacks::GET_CONCRETE_MEMORY_VALUE, MemoryAccess(addr, triton::size::byte));
408 
409           auto it = this->memory.find(addr);
410           if (it == this->memory.end())
411             return 0x00;
412 
413           return it->second;
414         }
415 
416 
getConcreteMemoryValue(const triton::arch::MemoryAccess & mem,bool execCallbacks) const417         triton::uint512 AArch64Cpu::getConcreteMemoryValue(const triton::arch::MemoryAccess& mem, bool execCallbacks) const {
418           triton::uint512 ret = 0;
419           triton::uint64 addr = 0;
420           triton::uint32 size = 0;
421 
422           if (execCallbacks && this->callbacks)
423             this->callbacks->processCallbacks(triton::callbacks::GET_CONCRETE_MEMORY_VALUE, mem);
424 
425           addr = mem.getAddress();
426           size = mem.getSize();
427 
428           if (size == 0 || size > triton::size::dqqword)
429             throw triton::exceptions::Cpu("AArch64Cpu::getConcreteMemoryValue(): Invalid size memory.");
430 
431           for (triton::sint32 i = size-1; i >= 0; i--)
432             ret = ((ret << triton::bitsize::byte) | this->getConcreteMemoryValue(addr+i, false));
433 
434           return ret;
435         }
436 
437 
getConcreteMemoryAreaValue(triton::uint64 baseAddr,triton::usize size,bool execCallbacks) const438         std::vector<triton::uint8> AArch64Cpu::getConcreteMemoryAreaValue(triton::uint64 baseAddr, triton::usize size, bool execCallbacks) const {
439           std::vector<triton::uint8> area;
440 
441           for (triton::usize index = 0; index < size; index++)
442             area.push_back(this->getConcreteMemoryValue(baseAddr+index));
443 
444           return area;
445         }
446 
447 
getConcreteRegisterValue(const triton::arch::Register & reg,bool execCallbacks) const448         triton::uint512 AArch64Cpu::getConcreteRegisterValue(const triton::arch::Register& reg, bool execCallbacks) const {
449           triton::uint512 value = 0;
450 
451           if (execCallbacks && this->callbacks)
452             this->callbacks->processCallbacks(triton::callbacks::GET_CONCRETE_REGISTER_VALUE, reg);
453 
454           switch (reg.getId()) {
455             case triton::arch::ID_REG_AARCH64_X0:   return (*((triton::uint64*)(this->x0)));
456             case triton::arch::ID_REG_AARCH64_W0:   return (*((triton::uint32*)(this->x0)));
457             case triton::arch::ID_REG_AARCH64_X1:   return (*((triton::uint64*)(this->x1)));
458             case triton::arch::ID_REG_AARCH64_W1:   return (*((triton::uint32*)(this->x1)));
459             case triton::arch::ID_REG_AARCH64_X2:   return (*((triton::uint64*)(this->x2)));
460             case triton::arch::ID_REG_AARCH64_W2:   return (*((triton::uint32*)(this->x2)));
461             case triton::arch::ID_REG_AARCH64_X3:   return (*((triton::uint64*)(this->x3)));
462             case triton::arch::ID_REG_AARCH64_W3:   return (*((triton::uint32*)(this->x3)));
463             case triton::arch::ID_REG_AARCH64_X4:   return (*((triton::uint64*)(this->x4)));
464             case triton::arch::ID_REG_AARCH64_W4:   return (*((triton::uint32*)(this->x4)));
465             case triton::arch::ID_REG_AARCH64_X5:   return (*((triton::uint64*)(this->x5)));
466             case triton::arch::ID_REG_AARCH64_W5:   return (*((triton::uint32*)(this->x5)));
467             case triton::arch::ID_REG_AARCH64_X6:   return (*((triton::uint64*)(this->x6)));
468             case triton::arch::ID_REG_AARCH64_W6:   return (*((triton::uint32*)(this->x6)));
469             case triton::arch::ID_REG_AARCH64_X7:   return (*((triton::uint64*)(this->x7)));
470             case triton::arch::ID_REG_AARCH64_W7:   return (*((triton::uint32*)(this->x7)));
471             case triton::arch::ID_REG_AARCH64_X8:   return (*((triton::uint64*)(this->x8)));
472             case triton::arch::ID_REG_AARCH64_W8:   return (*((triton::uint32*)(this->x8)));
473             case triton::arch::ID_REG_AARCH64_X9:   return (*((triton::uint64*)(this->x9)));
474             case triton::arch::ID_REG_AARCH64_W9:   return (*((triton::uint32*)(this->x9)));
475             case triton::arch::ID_REG_AARCH64_X10:  return (*((triton::uint64*)(this->x10)));
476             case triton::arch::ID_REG_AARCH64_W10:  return (*((triton::uint32*)(this->x10)));
477             case triton::arch::ID_REG_AARCH64_X11:  return (*((triton::uint64*)(this->x11)));
478             case triton::arch::ID_REG_AARCH64_W11:  return (*((triton::uint32*)(this->x11)));
479             case triton::arch::ID_REG_AARCH64_X12:  return (*((triton::uint64*)(this->x12)));
480             case triton::arch::ID_REG_AARCH64_W12:  return (*((triton::uint32*)(this->x12)));
481             case triton::arch::ID_REG_AARCH64_X13:  return (*((triton::uint64*)(this->x13)));
482             case triton::arch::ID_REG_AARCH64_W13:  return (*((triton::uint32*)(this->x13)));
483             case triton::arch::ID_REG_AARCH64_X14:  return (*((triton::uint64*)(this->x14)));
484             case triton::arch::ID_REG_AARCH64_W14:  return (*((triton::uint32*)(this->x14)));
485             case triton::arch::ID_REG_AARCH64_X15:  return (*((triton::uint64*)(this->x15)));
486             case triton::arch::ID_REG_AARCH64_W15:  return (*((triton::uint32*)(this->x15)));
487             case triton::arch::ID_REG_AARCH64_X16:  return (*((triton::uint64*)(this->x16)));
488             case triton::arch::ID_REG_AARCH64_W16:  return (*((triton::uint32*)(this->x16)));
489             case triton::arch::ID_REG_AARCH64_X17:  return (*((triton::uint64*)(this->x17)));
490             case triton::arch::ID_REG_AARCH64_W17:  return (*((triton::uint32*)(this->x17)));
491             case triton::arch::ID_REG_AARCH64_X18:  return (*((triton::uint64*)(this->x18)));
492             case triton::arch::ID_REG_AARCH64_W18:  return (*((triton::uint32*)(this->x18)));
493             case triton::arch::ID_REG_AARCH64_X19:  return (*((triton::uint64*)(this->x19)));
494             case triton::arch::ID_REG_AARCH64_W19:  return (*((triton::uint32*)(this->x19)));
495             case triton::arch::ID_REG_AARCH64_X20:  return (*((triton::uint64*)(this->x20)));
496             case triton::arch::ID_REG_AARCH64_W20:  return (*((triton::uint32*)(this->x20)));
497             case triton::arch::ID_REG_AARCH64_X21:  return (*((triton::uint64*)(this->x21)));
498             case triton::arch::ID_REG_AARCH64_W21:  return (*((triton::uint32*)(this->x21)));
499             case triton::arch::ID_REG_AARCH64_X22:  return (*((triton::uint64*)(this->x22)));
500             case triton::arch::ID_REG_AARCH64_W22:  return (*((triton::uint32*)(this->x22)));
501             case triton::arch::ID_REG_AARCH64_X23:  return (*((triton::uint64*)(this->x23)));
502             case triton::arch::ID_REG_AARCH64_W23:  return (*((triton::uint32*)(this->x23)));
503             case triton::arch::ID_REG_AARCH64_X24:  return (*((triton::uint64*)(this->x24)));
504             case triton::arch::ID_REG_AARCH64_W24:  return (*((triton::uint32*)(this->x24)));
505             case triton::arch::ID_REG_AARCH64_X25:  return (*((triton::uint64*)(this->x25)));
506             case triton::arch::ID_REG_AARCH64_W25:  return (*((triton::uint32*)(this->x25)));
507             case triton::arch::ID_REG_AARCH64_X26:  return (*((triton::uint64*)(this->x26)));
508             case triton::arch::ID_REG_AARCH64_W26:  return (*((triton::uint32*)(this->x26)));
509             case triton::arch::ID_REG_AARCH64_X27:  return (*((triton::uint64*)(this->x27)));
510             case triton::arch::ID_REG_AARCH64_W27:  return (*((triton::uint32*)(this->x27)));
511             case triton::arch::ID_REG_AARCH64_X28:  return (*((triton::uint64*)(this->x28)));
512             case triton::arch::ID_REG_AARCH64_W28:  return (*((triton::uint32*)(this->x28)));
513             case triton::arch::ID_REG_AARCH64_X29:  return (*((triton::uint64*)(this->x29)));
514             case triton::arch::ID_REG_AARCH64_W29:  return (*((triton::uint32*)(this->x29)));
515             case triton::arch::ID_REG_AARCH64_X30:  return (*((triton::uint64*)(this->x30)));
516             case triton::arch::ID_REG_AARCH64_W30:  return (*((triton::uint32*)(this->x30)));
517             case triton::arch::ID_REG_AARCH64_SP:   return (*((triton::uint64*)(this->sp)));
518             case triton::arch::ID_REG_AARCH64_WSP:  return (*((triton::uint32*)(this->sp)));
519             case triton::arch::ID_REG_AARCH64_PC:   return (*((triton::uint64*)(this->pc)));
520             case triton::arch::ID_REG_AARCH64_XZR:  return 0;
521             case triton::arch::ID_REG_AARCH64_WZR:  return 0;
522             case triton::arch::ID_REG_AARCH64_SPSR: return (*((triton::uint32*)(this->spsr)));
523             case triton::arch::ID_REG_AARCH64_N:    return (((*((triton::uint32*)(this->spsr))) >> 31) & 1);
524             case triton::arch::ID_REG_AARCH64_Z:    return (((*((triton::uint32*)(this->spsr))) >> 30) & 1);
525             case triton::arch::ID_REG_AARCH64_C:    return (((*((triton::uint32*)(this->spsr))) >> 29) & 1);
526             case triton::arch::ID_REG_AARCH64_V:    return (((*((triton::uint32*)(this->spsr))) >> 28) & 1);
527             default:
528               throw triton::exceptions::Cpu("AArch64Cpu::getConcreteRegisterValue(): Invalid register.");
529           }
530 
531           return value;
532         }
533 
534 
setConcreteMemoryValue(triton::uint64 addr,triton::uint8 value)535         void AArch64Cpu::setConcreteMemoryValue(triton::uint64 addr, triton::uint8 value) {
536           if (this->callbacks)
537             this->callbacks->processCallbacks(triton::callbacks::SET_CONCRETE_MEMORY_VALUE, MemoryAccess(addr, triton::size::byte), value);
538           this->memory[addr] = value;
539         }
540 
541 
setConcreteMemoryValue(const triton::arch::MemoryAccess & mem,const triton::uint512 & value)542         void AArch64Cpu::setConcreteMemoryValue(const triton::arch::MemoryAccess& mem, const triton::uint512& value) {
543           triton::uint64 addr = mem.getAddress();
544           triton::uint32 size = mem.getSize();
545           triton::uint512 cv  = value;
546 
547           if (cv > mem.getMaxValue())
548             throw triton::exceptions::Register("AArch64Cpu::setConcreteMemoryValue(): You cannot set this concrete value (too big) to this memory access.");
549 
550           if (size == 0 || size > triton::size::dqqword)
551             throw triton::exceptions::Cpu("AArch64Cpu::setConcreteMemoryValue(): Invalid size memory.");
552 
553           if (this->callbacks)
554             this->callbacks->processCallbacks(triton::callbacks::SET_CONCRETE_MEMORY_VALUE, mem, value);
555 
556           for (triton::uint32 i = 0; i < size; i++) {
557             this->memory[addr+i] = (cv & 0xff).convert_to<triton::uint8>();
558             cv >>= 8;
559           }
560         }
561 
562 
setConcreteMemoryAreaValue(triton::uint64 baseAddr,const std::vector<triton::uint8> & values)563         void AArch64Cpu::setConcreteMemoryAreaValue(triton::uint64 baseAddr, const std::vector<triton::uint8>& values) {
564           for (triton::usize index = 0; index < values.size(); index++) {
565             this->setConcreteMemoryValue(baseAddr+index, values[index]);
566           }
567         }
568 
569 
setConcreteMemoryAreaValue(triton::uint64 baseAddr,const triton::uint8 * area,triton::usize size)570         void AArch64Cpu::setConcreteMemoryAreaValue(triton::uint64 baseAddr, const triton::uint8* area, triton::usize size) {
571           for (triton::usize index = 0; index < size; index++) {
572             this->setConcreteMemoryValue(baseAddr+index, area[index]);
573           }
574         }
575 
576 
setConcreteRegisterValue(const triton::arch::Register & reg,const triton::uint512 & value)577         void AArch64Cpu::setConcreteRegisterValue(const triton::arch::Register& reg, const triton::uint512& value) {
578           if (value > reg.getMaxValue())
579             throw triton::exceptions::Register("AArch64Cpu::setConcreteRegisterValue(): You cannot set this concrete value (too big) to this register.");
580 
581           if (this->callbacks)
582             this->callbacks->processCallbacks(triton::callbacks::SET_CONCRETE_REGISTER_VALUE, reg, value);
583 
584           switch (reg.getId()) {
585             case triton::arch::ID_REG_AARCH64_X0:   (*((triton::uint64*)(this->x0)))   = value.convert_to<triton::uint64>(); break;
586             case triton::arch::ID_REG_AARCH64_W0:   (*((triton::uint32*)(this->x0)))   = value.convert_to<triton::uint32>(); break;
587             case triton::arch::ID_REG_AARCH64_X1:   (*((triton::uint64*)(this->x1)))   = value.convert_to<triton::uint64>(); break;
588             case triton::arch::ID_REG_AARCH64_W1:   (*((triton::uint32*)(this->x1)))   = value.convert_to<triton::uint32>(); break;
589             case triton::arch::ID_REG_AARCH64_X2:   (*((triton::uint64*)(this->x2)))   = value.convert_to<triton::uint64>(); break;
590             case triton::arch::ID_REG_AARCH64_W2:   (*((triton::uint32*)(this->x2)))   = value.convert_to<triton::uint32>(); break;
591             case triton::arch::ID_REG_AARCH64_X3:   (*((triton::uint64*)(this->x3)))   = value.convert_to<triton::uint64>(); break;
592             case triton::arch::ID_REG_AARCH64_W3:   (*((triton::uint32*)(this->x3)))   = value.convert_to<triton::uint32>(); break;
593             case triton::arch::ID_REG_AARCH64_X4:   (*((triton::uint64*)(this->x4)))   = value.convert_to<triton::uint64>(); break;
594             case triton::arch::ID_REG_AARCH64_W4:   (*((triton::uint32*)(this->x4)))   = value.convert_to<triton::uint32>(); break;
595             case triton::arch::ID_REG_AARCH64_X5:   (*((triton::uint64*)(this->x5)))   = value.convert_to<triton::uint64>(); break;
596             case triton::arch::ID_REG_AARCH64_W5:   (*((triton::uint32*)(this->x5)))   = value.convert_to<triton::uint32>(); break;
597             case triton::arch::ID_REG_AARCH64_X6:   (*((triton::uint64*)(this->x6)))   = value.convert_to<triton::uint64>(); break;
598             case triton::arch::ID_REG_AARCH64_W6:   (*((triton::uint32*)(this->x6)))   = value.convert_to<triton::uint32>(); break;
599             case triton::arch::ID_REG_AARCH64_X7:   (*((triton::uint64*)(this->x7)))   = value.convert_to<triton::uint64>(); break;
600             case triton::arch::ID_REG_AARCH64_W7:   (*((triton::uint32*)(this->x7)))   = value.convert_to<triton::uint32>(); break;
601             case triton::arch::ID_REG_AARCH64_X8:   (*((triton::uint64*)(this->x8)))   = value.convert_to<triton::uint64>(); break;
602             case triton::arch::ID_REG_AARCH64_W8:   (*((triton::uint32*)(this->x8)))   = value.convert_to<triton::uint32>(); break;
603             case triton::arch::ID_REG_AARCH64_X9:   (*((triton::uint64*)(this->x9)))   = value.convert_to<triton::uint64>(); break;
604             case triton::arch::ID_REG_AARCH64_W9:   (*((triton::uint32*)(this->x9)))   = value.convert_to<triton::uint32>(); break;
605             case triton::arch::ID_REG_AARCH64_X10:  (*((triton::uint64*)(this->x10)))  = value.convert_to<triton::uint64>(); break;
606             case triton::arch::ID_REG_AARCH64_W10:  (*((triton::uint32*)(this->x10)))  = value.convert_to<triton::uint32>(); break;
607             case triton::arch::ID_REG_AARCH64_X11:  (*((triton::uint64*)(this->x11)))  = value.convert_to<triton::uint64>(); break;
608             case triton::arch::ID_REG_AARCH64_W11:  (*((triton::uint32*)(this->x11)))  = value.convert_to<triton::uint32>(); break;
609             case triton::arch::ID_REG_AARCH64_X12:  (*((triton::uint64*)(this->x12)))  = value.convert_to<triton::uint64>(); break;
610             case triton::arch::ID_REG_AARCH64_W12:  (*((triton::uint32*)(this->x12)))  = value.convert_to<triton::uint32>(); break;
611             case triton::arch::ID_REG_AARCH64_X13:  (*((triton::uint64*)(this->x13)))  = value.convert_to<triton::uint64>(); break;
612             case triton::arch::ID_REG_AARCH64_W13:  (*((triton::uint32*)(this->x13)))  = value.convert_to<triton::uint32>(); break;
613             case triton::arch::ID_REG_AARCH64_X14:  (*((triton::uint64*)(this->x14)))  = value.convert_to<triton::uint64>(); break;
614             case triton::arch::ID_REG_AARCH64_W14:  (*((triton::uint32*)(this->x14)))  = value.convert_to<triton::uint32>(); break;
615             case triton::arch::ID_REG_AARCH64_X15:  (*((triton::uint64*)(this->x15)))  = value.convert_to<triton::uint64>(); break;
616             case triton::arch::ID_REG_AARCH64_W15:  (*((triton::uint32*)(this->x15)))  = value.convert_to<triton::uint32>(); break;
617             case triton::arch::ID_REG_AARCH64_X16:  (*((triton::uint64*)(this->x16)))  = value.convert_to<triton::uint64>(); break;
618             case triton::arch::ID_REG_AARCH64_W16:  (*((triton::uint32*)(this->x16)))  = value.convert_to<triton::uint32>(); break;
619             case triton::arch::ID_REG_AARCH64_X17:  (*((triton::uint64*)(this->x17)))  = value.convert_to<triton::uint64>(); break;
620             case triton::arch::ID_REG_AARCH64_W17:  (*((triton::uint32*)(this->x17)))  = value.convert_to<triton::uint32>(); break;
621             case triton::arch::ID_REG_AARCH64_X18:  (*((triton::uint64*)(this->x18)))  = value.convert_to<triton::uint64>(); break;
622             case triton::arch::ID_REG_AARCH64_W18:  (*((triton::uint32*)(this->x18)))  = value.convert_to<triton::uint32>(); break;
623             case triton::arch::ID_REG_AARCH64_X19:  (*((triton::uint64*)(this->x19)))  = value.convert_to<triton::uint64>(); break;
624             case triton::arch::ID_REG_AARCH64_W19:  (*((triton::uint32*)(this->x19)))  = value.convert_to<triton::uint32>(); break;
625             case triton::arch::ID_REG_AARCH64_X20:  (*((triton::uint64*)(this->x20)))  = value.convert_to<triton::uint64>(); break;
626             case triton::arch::ID_REG_AARCH64_W20:  (*((triton::uint32*)(this->x20)))  = value.convert_to<triton::uint32>(); break;
627             case triton::arch::ID_REG_AARCH64_X21:  (*((triton::uint64*)(this->x21)))  = value.convert_to<triton::uint64>(); break;
628             case triton::arch::ID_REG_AARCH64_W21:  (*((triton::uint32*)(this->x21)))  = value.convert_to<triton::uint32>(); break;
629             case triton::arch::ID_REG_AARCH64_X22:  (*((triton::uint64*)(this->x22)))  = value.convert_to<triton::uint64>(); break;
630             case triton::arch::ID_REG_AARCH64_W22:  (*((triton::uint32*)(this->x22)))  = value.convert_to<triton::uint32>(); break;
631             case triton::arch::ID_REG_AARCH64_X23:  (*((triton::uint64*)(this->x23)))  = value.convert_to<triton::uint64>(); break;
632             case triton::arch::ID_REG_AARCH64_W23:  (*((triton::uint32*)(this->x23)))  = value.convert_to<triton::uint32>(); break;
633             case triton::arch::ID_REG_AARCH64_X24:  (*((triton::uint64*)(this->x24)))  = value.convert_to<triton::uint64>(); break;
634             case triton::arch::ID_REG_AARCH64_W24:  (*((triton::uint32*)(this->x24)))  = value.convert_to<triton::uint32>(); break;
635             case triton::arch::ID_REG_AARCH64_X25:  (*((triton::uint64*)(this->x25)))  = value.convert_to<triton::uint64>(); break;
636             case triton::arch::ID_REG_AARCH64_W25:  (*((triton::uint32*)(this->x25)))  = value.convert_to<triton::uint32>(); break;
637             case triton::arch::ID_REG_AARCH64_X26:  (*((triton::uint64*)(this->x26)))  = value.convert_to<triton::uint64>(); break;
638             case triton::arch::ID_REG_AARCH64_W26:  (*((triton::uint32*)(this->x26)))  = value.convert_to<triton::uint32>(); break;
639             case triton::arch::ID_REG_AARCH64_X27:  (*((triton::uint64*)(this->x27)))  = value.convert_to<triton::uint64>(); break;
640             case triton::arch::ID_REG_AARCH64_W27:  (*((triton::uint32*)(this->x27)))  = value.convert_to<triton::uint32>(); break;
641             case triton::arch::ID_REG_AARCH64_X28:  (*((triton::uint64*)(this->x28)))  = value.convert_to<triton::uint64>(); break;
642             case triton::arch::ID_REG_AARCH64_W28:  (*((triton::uint32*)(this->x28)))  = value.convert_to<triton::uint32>(); break;
643             case triton::arch::ID_REG_AARCH64_X29:  (*((triton::uint64*)(this->x29)))  = value.convert_to<triton::uint64>(); break;
644             case triton::arch::ID_REG_AARCH64_W29:  (*((triton::uint32*)(this->x29)))  = value.convert_to<triton::uint32>(); break;
645             case triton::arch::ID_REG_AARCH64_X30:  (*((triton::uint64*)(this->x30)))  = value.convert_to<triton::uint64>(); break;
646             case triton::arch::ID_REG_AARCH64_W30:  (*((triton::uint32*)(this->x30)))  = value.convert_to<triton::uint32>(); break;
647             case triton::arch::ID_REG_AARCH64_SP:   (*((triton::uint64*)(this->sp)))   = value.convert_to<triton::uint64>(); break;
648             case triton::arch::ID_REG_AARCH64_WSP:  (*((triton::uint32*)(this->sp)))   = value.convert_to<triton::uint32>(); break;
649             case triton::arch::ID_REG_AARCH64_PC:   (*((triton::uint64*)(this->pc)))   = value.convert_to<triton::uint64>(); break;
650             case triton::arch::ID_REG_AARCH64_SPSR: (*((triton::uint32*)(this->spsr))) = value.convert_to<triton::uint32>(); break;
651             case triton::arch::ID_REG_AARCH64_XZR:  break;  // Just do nothing
652             case triton::arch::ID_REG_AARCH64_WZR:  break;  // Just do nothing
653             case triton::arch::ID_REG_AARCH64_N: {
654               triton::uint32 b = (*((triton::uint32*)(this->spsr)));
655               (*((triton::uint32*)(this->spsr))) = !value.is_zero() ? b | (1 << 31) : b & ~(1 << 31);
656               break;
657             }
658             case triton::arch::ID_REG_AARCH64_Z: {
659               triton::uint32 b = (*((triton::uint32*)(this->spsr)));
660               (*((triton::uint32*)(this->spsr))) = !value.is_zero() ? b | (1 << 30) : b & ~(1 << 30);
661               break;
662             }
663             case triton::arch::ID_REG_AARCH64_C: {
664               triton::uint32 b = (*((triton::uint32*)(this->spsr)));
665               (*((triton::uint32*)(this->spsr))) = !value.is_zero() ? b | (1 << 29) : b & ~(1 << 29);
666               break;
667             }
668             case triton::arch::ID_REG_AARCH64_V: {
669               triton::uint32 b = (*((triton::uint32*)(this->spsr)));
670               (*((triton::uint32*)(this->spsr))) = !value.is_zero() ? b | (1 << 28) : b & ~(1 << 28);
671               break;
672             }
673             default:
674               throw triton::exceptions::Cpu("AArch64Cpu:setConcreteRegisterValue(): Invalid register.");
675           }
676         }
677 
678 
isThumb(void) const679         bool AArch64Cpu::isThumb(void) const {
680           /* There is no thumb mode in aarch64 */
681           return false;
682         }
683 
684 
setThumb(bool state)685         void AArch64Cpu::setThumb(bool state) {
686           /* There is no thumb mode in aarch64 */
687         }
688 
689 
isConcreteMemoryValueDefined(const triton::arch::MemoryAccess & mem) const690         bool AArch64Cpu::isConcreteMemoryValueDefined(const triton::arch::MemoryAccess& mem) const {
691           return this->isConcreteMemoryValueDefined(mem.getAddress(), mem.getSize());
692         }
693 
694 
isConcreteMemoryValueDefined(triton::uint64 baseAddr,triton::usize size) const695         bool AArch64Cpu::isConcreteMemoryValueDefined(triton::uint64 baseAddr, triton::usize size) const {
696           for (triton::usize index = 0; index < size; index++) {
697             if (this->memory.find(baseAddr + index) == this->memory.end())
698               return false;
699           }
700           return true;
701         }
702 
703 
clearConcreteMemoryValue(const triton::arch::MemoryAccess & mem)704         void AArch64Cpu::clearConcreteMemoryValue(const triton::arch::MemoryAccess& mem) {
705           this->clearConcreteMemoryValue(mem.getAddress(), mem.getSize());
706         }
707 
708 
clearConcreteMemoryValue(triton::uint64 baseAddr,triton::usize size)709         void AArch64Cpu::clearConcreteMemoryValue(triton::uint64 baseAddr, triton::usize size) {
710           for (triton::usize index = 0; index < size; index++) {
711             if (this->memory.find(baseAddr + index) != this->memory.end()) {
712               this->memory.erase(baseAddr + index);
713             }
714           }
715         }
716 
717       }; /* aarch64 namespace */
718     }; /* arm namespace */
719   }; /* arch namespace */
720 }; /* triton namespace */
721