libTriton version 1.0 build 1588
Loading...
Searching...
No Matches
arm32Cpu.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 <algorithm>
9#include <cctype>
10#include <cstring>
11
13#include <triton/arm32Cpu.hpp>
14#include <triton/coreUtils.hpp>
15#include <triton/cpuSize.hpp>
16#include <triton/exceptions.hpp>
18#include <triton/immediate.hpp>
19
20
21
22namespace triton {
23 namespace arch {
24 namespace arm {
25 namespace arm32 {
26
28 this->callbacks = callbacks;
29 this->handleArm = 0;
30 this->handleThumb = 0;
31 this->thumb = false;
32 this->itInstrsCount = 0;
33 this->itInstrIndex = 0;
36
37 this->clear();
38 this->disassInit();
39 }
40
41
43 this->copy(other);
44 }
45
46
48 this->memory.clear();
49
50 if (this->handleArm) {
51 triton::extlibs::capstone::cs_close(&this->handleArm);
52 }
53
54 if (this->handleThumb) {
55 triton::extlibs::capstone::cs_close(&this->handleThumb);
56 }
57 }
58
59
60 void Arm32Cpu::disassInit(void) {
61 /* Open capstone in ARM mode. */
62 if (this->handleArm) {
63 triton::extlibs::capstone::cs_close(&this->handleArm);
64 }
65
66 /* Open capstone in Thumb mode. */
67 if (this->handleThumb) {
68 triton::extlibs::capstone::cs_close(&this->handleThumb);
69 }
70
71 if (triton::extlibs::capstone::cs_open(triton::extlibs::capstone::CS_ARCH_ARM, triton::extlibs::capstone::CS_MODE_ARM, &this->handleArm) != triton::extlibs::capstone::CS_ERR_OK) {
72 throw triton::exceptions::Disassembly("Arm32Cpu::disassInit(): Cannot open capstone in ARM mode.");
73 }
74
75 if (triton::extlibs::capstone::cs_open(triton::extlibs::capstone::CS_ARCH_ARM, triton::extlibs::capstone::CS_MODE_THUMB, &this->handleThumb) != triton::extlibs::capstone::CS_ERR_OK) {
76 throw triton::exceptions::Disassembly("Arm32Cpu::disassInit(): Cannot open capstone in Thumb mode.");
77 }
78
79 triton::extlibs::capstone::cs_option(this->handleThumb, triton::extlibs::capstone::CS_OPT_DETAIL, triton::extlibs::capstone::CS_OPT_ON);
80 triton::extlibs::capstone::cs_option(this->handleArm, triton::extlibs::capstone::CS_OPT_DETAIL, triton::extlibs::capstone::CS_OPT_ON);
81 }
82
83
84 void Arm32Cpu::copy(const Arm32Cpu& other) {
85 this->callbacks = other.callbacks;
86 this->exclusiveMemoryTags = other.exclusiveMemoryTags;
87 this->memory = other.memory;
88
89 std::memcpy(this->r0, other.r0, sizeof(this->r0));
90 std::memcpy(this->r1, other.r1, sizeof(this->r1));
91 std::memcpy(this->r2, other.r2, sizeof(this->r2));
92 std::memcpy(this->r3, other.r3, sizeof(this->r3));
93 std::memcpy(this->r4, other.r4, sizeof(this->r4));
94 std::memcpy(this->r5, other.r5, sizeof(this->r5));
95 std::memcpy(this->r6, other.r6, sizeof(this->r6));
96 std::memcpy(this->r7, other.r7, sizeof(this->r7));
97 std::memcpy(this->r8, other.r8, sizeof(this->r8));
98 std::memcpy(this->r9, other.r9, sizeof(this->r9));
99 std::memcpy(this->r10, other.r10, sizeof(this->r10));
100 std::memcpy(this->r11, other.r11, sizeof(this->r11));
101 std::memcpy(this->r12, other.r12, sizeof(this->r12));
102 std::memcpy(this->sp, other.sp, sizeof(this->sp));
103 std::memcpy(this->r14, other.r14, sizeof(this->r14));
104 std::memcpy(this->pc, other.pc, sizeof(this->pc));
105 std::memcpy(this->apsr, other.apsr, sizeof(this->apsr));
106 }
107
108
109 void Arm32Cpu::clear(void) {
110 /* Clear memory */
111 this->memory.clear();
112
113 /* Clear registers */
114 std::memset(this->r0, 0x00, sizeof(this->r0));
115 std::memset(this->r1, 0x00, sizeof(this->r1));
116 std::memset(this->r2, 0x00, sizeof(this->r2));
117 std::memset(this->r3, 0x00, sizeof(this->r3));
118 std::memset(this->r4, 0x00, sizeof(this->r4));
119 std::memset(this->r5, 0x00, sizeof(this->r5));
120 std::memset(this->r6, 0x00, sizeof(this->r6));
121 std::memset(this->r7, 0x00, sizeof(this->r7));
122 std::memset(this->r8, 0x00, sizeof(this->r8));
123 std::memset(this->r9, 0x00, sizeof(this->r9));
124 std::memset(this->r10, 0x00, sizeof(this->r10));
125 std::memset(this->r11, 0x00, sizeof(this->r11));
126 std::memset(this->r12, 0x00, sizeof(this->r12));
127 std::memset(this->sp, 0x00, sizeof(this->sp));
128 std::memset(this->r14, 0x00, sizeof(this->r14));
129 std::memset(this->pc, 0x00, sizeof(this->pc));
130 std::memset(this->apsr, 0x00, sizeof(this->apsr));
131 }
132
133
135 this->copy(other);
136 return *this;
137 }
138
139
142 }
143
144
146 return ((regId >= triton::arch::ID_REG_ARM32_C && regId <= triton::arch::ID_REG_ARM32_Z) ? true : false);
147 }
148
149
151 return this->isGPR(regId);
152 }
153
154
156 return (this->isFlag(regId) || this->isRegister(regId));
157 }
158
159
161 return ((regId >= triton::arch::ID_REG_ARM32_R0 && regId <= triton::arch::ID_REG_ARM32_APSR) ? true : false);
162 }
163
164
167 }
168
169
171 return triton::size::dword;
172 }
173
174
177 }
178
179
180 const std::unordered_map<triton::arch::register_e, const triton::arch::Register>& Arm32Cpu::getAllRegisters(void) const {
181 return this->id2reg;
182 }
183
184
185 std::set<const triton::arch::Register*> Arm32Cpu::getParentRegisters(void) const {
186 std::set<const triton::arch::Register*> ret;
187
188 for (const auto& kv: this->id2reg) {
189 auto regId = kv.first;
190 const auto& reg = kv.second;
191
192 /* Add GPR */
193 if (reg.getSize() == this->gprSize())
194 ret.insert(&reg);
195
196 /* Add Flags */
197 else if (this->isFlag(regId))
198 ret.insert(&reg);
199 }
200
201 return ret;
202 }
203
204
206 try {
207 return this->id2reg.at(id);
208 } catch (const std::out_of_range&) {
209 throw triton::exceptions::Cpu("Arm32Cpu::getRegister(): Invalid register for this architecture.");
210 }
211 }
212
213
214 const triton::arch::Register& Arm32Cpu::getRegister(const std::string& name) const {
215 std::string lower = name;
216 std::transform(lower.begin(), lower.end(), lower.begin(), [](unsigned char c){ return std::tolower(c); });
217 try {
218 return this->getRegister(this->name2id.at(lower));
219 } catch (const std::out_of_range&) {
220 throw triton::exceptions::Cpu("Arm32Cpu::getRegister(): Invalid register for this architecture.");
221 }
222 }
223
224
226 return this->getRegister(reg.getParent());
227 }
228
229
231 return this->getParentRegister(this->getRegister(id));
232 }
233
234
236 return this->getRegister(this->pcId);
237 }
238
239
241 return this->getRegister(this->spId);
242 }
243
244
246 triton::extlibs::capstone::csh handle;
247 triton::extlibs::capstone::cs_insn* insn;
248 triton::usize count = 0;
249
250 /* Check if the opcode and opcode' size are defined */
251 if (inst.getOpcode() == nullptr || inst.getSize() == 0)
252 throw triton::exceptions::Disassembly("Arm32Cpu::disassembly(): Opcode and opcodeSize must be definied.");
253
254 /* Select capstone handler (based on execution mode) */
255 handle = (this->thumb ? this->handleThumb : this->handleArm);
256
257 /* Clear instructicon's operands if alredy defined */
258 inst.operands.clear();
259
260 /* Update instruction address if undefined */
261 if (!inst.getAddress()) {
262 inst.setAddress(static_cast<triton::uint64>(this->getConcreteRegisterValue(this->getProgramCounter())));
263 }
264
265 /* Let's disass and build our operands */
266 count = triton::extlibs::capstone::cs_disasm(handle, inst.getOpcode(), inst.getSize(), inst.getAddress(), 0, &insn);
267 if (count > 0) {
268 triton::extlibs::capstone::cs_detail* detail = insn->detail;
269
270 /* Refine the opcode */
271 inst.setOpcode(insn[0].bytes, insn[0].size);
272
273 /* Refine the size */
274 inst.setSize(insn[0].size);
275
276 /* Init the instruction's type */
277 inst.setType(this->capstoneInstructionToTritonInstruction(insn[0].id));
278
279 /* Init the instruction's code codition */
280 inst.setCodeCondition(this->capstoneConditionToTritonCondition(detail->arm.cc));
281
282 /* Init the instruction's write back flag */
283 inst.setWriteBack(detail->arm.writeback);
284
285 /* Set True if the instruction udpate flags */
286 inst.setUpdateFlag(detail->arm.update_flags);
287
288 /* Set thumb mode */
289 inst.setThumb(thumb);
290
291 /* Set architecture */
293
294 /* Init the disassembly */
295 std::stringstream str;
296
297 /* Add mnemonic */
298 str << insn[0].mnemonic;
299
300 /* Add operands */
301 if (inst.getType() == ID_INS_IT || detail->arm.op_count)
302 str << " " << insn[0].op_str;
303
304 inst.setDisassembly(str.str());
305
306 /* Process IT instruction */
307 if (inst.getType() == ID_INS_IT) {
308 /* Nested IT instruction, throw an exception as this is not valid ARM code */
309 if (this->itInstrsCount > 0)
310 throw triton::exceptions::Disassembly("Arm32Cpu::disassembly(): Nested IT instructions are not allowed.");
311
312 /* Copy state from the mnemonic of the instruction */
313 strncpy(this->itStateArray, &insn[0].mnemonic[1], 5);
314 this->itStateArray[4] = 0;
315
316 this->itInstrsCount = strlen(this->itStateArray);
317 this->itInstrIndex = 0;
318
319 this->itCC = inst.getCodeCondition();
320 this->itCCInv = this->invertCodeCondition(this->itCC);
321 }
322
323 /* Process instruction within an IT block */
324 if (inst.getType() != ID_INS_IT && this->itInstrsCount > 0) {
325 /* NOTE Assuming that CS always returns mnemonics in lower case */
326 triton::arch::arm::condition_e cc = this->itStateArray[this->itInstrIndex] == 't' ? this->itCC : this->itCCInv;
327
328 inst.setCodeCondition(cc);
329
330 this->itInstrsCount--;
331 this->itInstrIndex++;
332 }
333
334 /* Init operands */
335 for (triton::uint32 n = 0; n < detail->arm.op_count; n++) {
336 triton::extlibs::capstone::cs_arm_op* op = &(detail->arm.operands[n]);
337 switch(op->type) {
338
339 case triton::extlibs::capstone::ARM_OP_IMM: {
341
342 if (op->subtracted)
343 imm.setSubtracted(true);
344
345 inst.operands.push_back(triton::arch::OperandWrapper(imm));
346 break;
347 }
348
349 case triton::extlibs::capstone::ARM_OP_MEM: {
351
352 /* Set the size of the memory access */
354 mem.setBits(size ? ((size * triton::bitsize::byte) - 1) : triton::bitsize::dword-1, 0);
355
356 /* LEA if exists */
357 const triton::arch::Register base(*this, this->capstoneRegisterToTritonRegister(op->mem.base));
358 triton::arch::Register index(*this, this->capstoneRegisterToTritonRegister(op->mem.index));
359
360 /* Set Shift type and value */
361 triton::arch::arm::shift_e shiftType = this->capstoneShiftToTritonShift(op->shift.type);
362
363 index.setShiftType(shiftType);
364
365 switch(shiftType) {
367 break;
372 index.setShiftValue(op->shift.value);
373 break;
375 /* NOTE: According to the manual RRX there is no
376 * immediate associated with this shift type. However,
377 * from the description of the instruction it can be
378 * deduced that a value of one is used.
379 */
380 index.setShiftValue(1);
381 break;
386 index.setShiftValue(this->capstoneRegisterToTritonRegister(op->shift.value));
387 break;
389 /* NOTE: Capstone considers this as a viable shift operand
390 * but according to the ARM manual this is not possible.
391 */
392 throw triton::exceptions::Disassembly("Arm32Cpu::disassembly(): Invalid shift type.");
393 break;
394 default:
395 throw triton::exceptions::Disassembly("Arm32Cpu::disassembly(): Invalid shift type.");
396 }
397
398 if (op->subtracted) {
399 index.setSubtracted(true);
400 }
401
402 triton::uint32 immsize = (
403 this->isRegisterValid(base.getId()) ? base.getSize() :
404 this->isRegisterValid(index.getId()) ? index.getSize() :
405 this->gprSize()
406 );
407
408 triton::arch::Immediate disp(op->mem.disp, immsize);
409
410 /* Specify that LEA contains a PC relative */
411 if (base.getId() == this->pcId) {
412 /* NOTE: PC always points to the address to the current
413 * instruction plus: a) 8 in case of ARM mode, or b) 4 in
414 * case of Thumb. It is also aligned to 4 bytes. For more
415 * information, refer to section "Use of labels in UAL
416 * instruction syntax" of the reference manual.
417 */
418 auto offset = this->thumb ? 4 : 8;
419 auto address = (inst.getAddress() + offset);
420 /* Align address except when it is a TBB or TBH instruction. */
421 if (!(inst.getType() == ID_INS_TBB || inst.getType() == ID_INS_TBH)) {
422 address = address & 0xfffffffc;
423 }
424 mem.setPcRelative(address);
425 }
426
427 /* Note that in ARM32 there is no segment register and scale value */
428 mem.setBaseRegister(base);
429 mem.setIndexRegister(index);
430 mem.setDisplacement(disp);
431
432 /* If there is an index register available, set scale to 1 to perform this following computation (base) + (index * scale) */
433 if (this->isRegisterValid(index.getId()))
435
436 inst.operands.push_back(triton::arch::OperandWrapper(mem));
437 break;
438 }
439
440 case triton::extlibs::capstone::ARM_OP_REG: {
442
443 /* Set Shift type and value */
444 triton::arch::arm::shift_e shiftType = this->capstoneShiftToTritonShift(op->shift.type);
445
446 reg.setShiftType(shiftType);
447
448 switch(shiftType) {
450 break;
455 reg.setShiftValue(op->shift.value);
456 break;
458 /* NOTE: According to the manual RRX there is no
459 * immediate associated with this shift type. However,
460 * from the description of the instruction it can be
461 * deduced that a value of one is used.
462 */
463 reg.setShiftValue(1);
464 break;
469 reg.setShiftValue(this->capstoneRegisterToTritonRegister(op->shift.value));
470 break;
472 /* NOTE: Capstone considers this as a viable shift operand
473 * but according to the ARM manual this is not possible.
474 */
475 throw triton::exceptions::Disassembly("Arm32Cpu::disassembly(): Invalid shift type.");
476 break;
477 default:
478 throw triton::exceptions::Disassembly("Arm32Cpu::disassembly(): Invalid shift type.");
479 }
480
481 if (op->subtracted)
482 reg.setSubtracted(true);
483
484 inst.operands.push_back(triton::arch::OperandWrapper(reg));
485 break;
486 }
487
488 default:
489 /* NOTE: FP, CIMM, and missing one are not supported yet. */
490 throw triton::exceptions::Disassembly("Arm32Cpu::disassembly(): Invalid operand.");
491 } // switch
492 } // for operand
493
494 /* Set branch */
495 if (detail->groups_count > 0) {
496 for (triton::uint32 n = 0; n < detail->groups_count; n++) {
497 if (detail->groups[n] == triton::extlibs::capstone::ARM_GRP_JUMP) {
498 inst.setBranch(true);
499 inst.setControlFlow(true);
500 }
501 }
502 }
503
504 /* Post process instruction */
505 this->postDisassembly(inst);
506
507 /* Free capstone stuffs */
508 triton::extlibs::capstone::cs_free(insn, count);
509 }
510 else
511 throw triton::exceptions::Disassembly("Arm32Cpu::disassembly(): Failed to disassemble the given code.");
512
513 return;
514 }
515
516
517 void Arm32Cpu::postDisassembly(triton::arch::Instruction& inst) const {
518 /* Fix update flag */
519 /* NOTE: Quick (and super ugly) hack. Capstone is reporting
520 * update_flags equals true for ADC, RSC and SBC instruction when
521 * it shouldn't (it should only report true when the S suffix is
522 * present). This will be removed once Capstone is fixed. For more
523 * information, see: https://github.com/aquynh/capstone/issues/1568.
524 */
525 switch (inst.getType()) {
526 case ID_INS_ADC:
527 case ID_INS_RSC:
528 case ID_INS_SBC:
529 if (inst.getDisassembly().at(3) != 's')
530 inst.setUpdateFlag(false);
531 break;
532 }
533
534 /* Make implicit destination operand explicit */
535 /* NOTE: For some instructions the destination operand is
536 * optional (in which case the first source operand is used as
537 * destination). Capstone returns always all three operands for
538 * ARM instruction (i.e. make the destination operand explicit).
539 * However, it does not do the same for Thumb instructions. Here
540 * we make the destination operand explicit (in order to simplify
541 * the implementation of the semantics).
542 */
543 if (inst.isThumb() && inst.operands.size() == 2) {
545
546 switch (inst.getType()) {
547 case ID_INS_ADC:
548 case ID_INS_ADD:
549 case ID_INS_AND:
550 case ID_INS_ASR:
551 case ID_INS_BIC:
552 case ID_INS_EOR:
553 case ID_INS_LSL:
554 case ID_INS_LSR:
555 case ID_INS_ORR:
556 case ID_INS_ROR:
557 case ID_INS_SBC:
558 case ID_INS_SUB:
559 inst.operands.insert(inst.operands.begin(), op);
560 break;
561 }
562 }
563
564 /* NOTE: If the instruction is POP and contains a PC register,
565 * we have to define the instruction as modifiying the control
566 * flow. See #945.
567 */
568 if (inst.getType() == ID_INS_POP) {
569 /* FIXME: Maybe the loop is useless if PC is always the last operand? */
570 for (auto& op : inst.operands) {
571 if (op.getType() == triton::arch::OP_REG && op.getConstRegister().getId() == this->pcId) {
572 inst.setControlFlow(true);
573 break;
574 }
575 }
576 }
577 }
578
579
581 if (execCallbacks && this->callbacks)
583
584 auto it = this->memory.find(addr);
585 if (it == this->memory.end())
586 return 0x00;
587
588 return it->second;
589 }
590
591
593 triton::uint512 ret = 0;
594 triton::uint64 addr = 0;
595 triton::uint32 size = 0;
596
597 if (execCallbacks && this->callbacks)
599
600 addr = mem.getAddress();
601 size = mem.getSize();
602
603 if (size == 0 || size > triton::size::dqqword)
604 throw triton::exceptions::Cpu("Arm32Cpu::getConcreteMemoryValue(): Invalid size memory.");
605
606 for (triton::sint32 i = size-1; i >= 0; i--)
607 ret = ((ret << triton::bitsize::byte) | this->getConcreteMemoryValue(addr+i, false));
608
609 return ret;
610 }
611
612
613 std::vector<triton::uint8> Arm32Cpu::getConcreteMemoryAreaValue(triton::uint64 baseAddr, triton::usize size, bool execCallbacks) const {
614 std::vector<triton::uint8> area;
615
616 for (triton::usize index = 0; index < size; index++)
617 area.push_back(this->getConcreteMemoryValue(baseAddr+index, execCallbacks));
618
619 return area;
620 }
621
622
624 triton::uint512 value = 0;
625
626 if (execCallbacks && this->callbacks)
628
629 switch (reg.getId()) {
630 case triton::arch::ID_REG_ARM32_R0: return (*((triton::uint32*)(this->r0)));
631 case triton::arch::ID_REG_ARM32_R1: return (*((triton::uint32*)(this->r1)));
632 case triton::arch::ID_REG_ARM32_R2: return (*((triton::uint32*)(this->r2)));
633 case triton::arch::ID_REG_ARM32_R3: return (*((triton::uint32*)(this->r3)));
634 case triton::arch::ID_REG_ARM32_R4: return (*((triton::uint32*)(this->r4)));
635 case triton::arch::ID_REG_ARM32_R5: return (*((triton::uint32*)(this->r5)));
636 case triton::arch::ID_REG_ARM32_R6: return (*((triton::uint32*)(this->r6)));
637 case triton::arch::ID_REG_ARM32_R7: return (*((triton::uint32*)(this->r7)));
638 case triton::arch::ID_REG_ARM32_R8: return (*((triton::uint32*)(this->r8)));
639 case triton::arch::ID_REG_ARM32_R9: return (*((triton::uint32*)(this->r9)));
640 case triton::arch::ID_REG_ARM32_R10: return (*((triton::uint32*)(this->r10)));
641 case triton::arch::ID_REG_ARM32_R11: return (*((triton::uint32*)(this->r11)));
642 case triton::arch::ID_REG_ARM32_R12: return (*((triton::uint32*)(this->r12)));
643 case triton::arch::ID_REG_ARM32_SP: return (*((triton::uint32*)(this->sp)));
644 case triton::arch::ID_REG_ARM32_R14: return (*((triton::uint32*)(this->r14)));
645 case triton::arch::ID_REG_ARM32_PC: return (*((triton::uint32*)(this->pc)));
646 case triton::arch::ID_REG_ARM32_APSR: return (*((triton::uint32*)(this->apsr)));
647 case triton::arch::ID_REG_ARM32_N: return (((*((triton::uint32*)(this->apsr))) >> 31) & 1);
648 case triton::arch::ID_REG_ARM32_Z: return (((*((triton::uint32*)(this->apsr))) >> 30) & 1);
649 case triton::arch::ID_REG_ARM32_C: return (((*((triton::uint32*)(this->apsr))) >> 29) & 1);
650 case triton::arch::ID_REG_ARM32_V: return (((*((triton::uint32*)(this->apsr))) >> 28) & 1);
651 default:
652 throw triton::exceptions::Cpu("Arm32Cpu::getConcreteRegisterValue(): Invalid register.");
653 }
654
655 return value;
656 }
657
658
659 void Arm32Cpu::setConcreteMemoryValue(triton::uint64 addr, triton::uint8 value, bool execCallbacks) {
660 if (execCallbacks && this->callbacks)
662 this->memory[addr] = value;
663 }
664
665
666 void Arm32Cpu::setConcreteMemoryValue(const triton::arch::MemoryAccess& mem, const triton::uint512& value, bool execCallbacks) {
667 triton::uint64 addr = mem.getAddress();
668 triton::uint32 size = mem.getSize();
669 triton::uint512 cv = value;
670
671 if (cv > mem.getMaxValue())
672 throw triton::exceptions::Register("Arm32Cpu::setConcreteMemoryValue(): You cannot set this concrete value (too big) to this memory access.");
673
674 if (size == 0 || size > triton::size::dqqword)
675 throw triton::exceptions::Cpu("Arm32Cpu::setConcreteMemoryValue(): Invalid size memory.");
676
677 if (execCallbacks && this->callbacks)
679
680 for (triton::uint32 i = 0; i < size; i++) {
681 this->memory[addr+i] = static_cast<triton::uint8>((cv & 0xff));
682 cv >>= 8;
683 }
684 }
685
686
687 void Arm32Cpu::setConcreteMemoryAreaValue(triton::uint64 baseAddr, const std::vector<triton::uint8>& values, bool execCallbacks) {
688 this->memory.reserve(values.size() + this->memory.size());
689 for (triton::usize index = 0; index < values.size(); index++) {
690 this->setConcreteMemoryValue(baseAddr+index, values[index], execCallbacks);
691 }
692 }
693
694
695 void Arm32Cpu::setConcreteMemoryAreaValue(triton::uint64 baseAddr, const void* area, triton::usize size, bool execCallbacks) {
696 this->memory.reserve(size + this->memory.size());
697 for (triton::usize index = 0; index < size; index++) {
698 this->setConcreteMemoryValue(baseAddr+index, reinterpret_cast<const triton::uint8*>(area)[index], execCallbacks);
699 }
700 }
701
702
703 void Arm32Cpu::setConcreteRegisterValue(const triton::arch::Register& reg, const triton::uint512& value, bool execCallbacks) {
704 if (value > reg.getMaxValue())
705 throw triton::exceptions::Register("Arm32Cpu::setConcreteRegisterValue(): You cannot set this concrete value (too big) to this register.");
706
707 if (execCallbacks && this->callbacks)
709
710 switch (reg.getId()) {
711 case triton::arch::ID_REG_ARM32_R0: (*((triton::uint32*)(this->r0))) = static_cast<triton::uint32>(value); break;
712 case triton::arch::ID_REG_ARM32_R1: (*((triton::uint32*)(this->r1))) = static_cast<triton::uint32>(value); break;
713 case triton::arch::ID_REG_ARM32_R2: (*((triton::uint32*)(this->r2))) = static_cast<triton::uint32>(value); break;
714 case triton::arch::ID_REG_ARM32_R3: (*((triton::uint32*)(this->r3))) = static_cast<triton::uint32>(value); break;
715 case triton::arch::ID_REG_ARM32_R4: (*((triton::uint32*)(this->r4))) = static_cast<triton::uint32>(value); break;
716 case triton::arch::ID_REG_ARM32_R5: (*((triton::uint32*)(this->r5))) = static_cast<triton::uint32>(value); break;
717 case triton::arch::ID_REG_ARM32_R6: (*((triton::uint32*)(this->r6))) = static_cast<triton::uint32>(value); break;
718 case triton::arch::ID_REG_ARM32_R7: (*((triton::uint32*)(this->r7))) = static_cast<triton::uint32>(value); break;
719 case triton::arch::ID_REG_ARM32_R8: (*((triton::uint32*)(this->r8))) = static_cast<triton::uint32>(value); break;
720 case triton::arch::ID_REG_ARM32_R9: (*((triton::uint32*)(this->r9))) = static_cast<triton::uint32>(value); break;
721 case triton::arch::ID_REG_ARM32_R10: (*((triton::uint32*)(this->r10))) = static_cast<triton::uint32>(value); break;
722 case triton::arch::ID_REG_ARM32_R11: (*((triton::uint32*)(this->r11))) = static_cast<triton::uint32>(value); break;
723 case triton::arch::ID_REG_ARM32_R12: (*((triton::uint32*)(this->r12))) = static_cast<triton::uint32>(value); break;
724 case triton::arch::ID_REG_ARM32_SP: (*((triton::uint32*)(this->sp))) = static_cast<triton::uint32>(value); break;
725 case triton::arch::ID_REG_ARM32_R14: (*((triton::uint32*)(this->r14))) = static_cast<triton::uint32>(value); break;
726 case triton::arch::ID_REG_ARM32_PC: {
727 /* NOTE: Once in Thumb mode only switch to ARM through a Branch
728 * and Exchange instruction. The reason for this is that after
729 * switching to Thumb the ISB (instruction set selection bit) is
730 * cleared. Therefore, if we allow to switch back to ARM through
731 * these mechanism we would have a problem processing Thumb
732 * instructions.
733 */
734 auto pc = static_cast<triton::uint32>(value);
735 if (this->isThumb() == false && (pc & 0x1) == 0x1) {
736 this->setThumb(true);
737 }
738 (*((triton::uint32*)(this->pc))) = pc & ~0x1;
739 break;
740 }
741 case triton::arch::ID_REG_ARM32_APSR: (*((triton::uint32*)(this->apsr))) = static_cast<triton::uint32>(value); break;
742 case triton::arch::ID_REG_ARM32_N: {
743 triton::uint32 b = (*((triton::uint32*)(this->apsr)));
744 (*((triton::uint32*)(this->apsr))) = !value.is_zero() ? b | (1 << 31) : b & ~(1 << 31);
745 break;
746 }
747 case triton::arch::ID_REG_ARM32_Z: {
748 triton::uint32 b = (*((triton::uint32*)(this->apsr)));
749 (*((triton::uint32*)(this->apsr))) = !value.is_zero() ? b | (1 << 30) : b & ~(1 << 30);
750 break;
751 }
752 case triton::arch::ID_REG_ARM32_C: {
753 triton::uint32 b = (*((triton::uint32*)(this->apsr)));
754 (*((triton::uint32*)(this->apsr))) = !value.is_zero() ? b | (1 << 29) : b & ~(1 << 29);
755 break;
756 }
757 case triton::arch::ID_REG_ARM32_V: {
758 triton::uint32 b = (*((triton::uint32*)(this->apsr)));
759 (*((triton::uint32*)(this->apsr))) = !value.is_zero() ? b | (1 << 28) : b & ~(1 << 28);
760 break;
761 }
762 default:
763 throw triton::exceptions::Cpu("Arm32Cpu:setConcreteRegisterValue(): Invalid register.");
764 }
765 }
766
767
768 bool Arm32Cpu::isThumb(void) const {
769 return this->thumb;
770 }
771
772
773 void Arm32Cpu::setThumb(bool state) {
774 this->thumb = state;
775 }
776
777
779 triton::uint64 base = mem.getAddress();
780
781 for (triton::usize index = 0; index < mem.getSize(); index++) {
782 if (this->exclusiveMemoryTags.find(base + index) != this->exclusiveMemoryTags.end()) {
783 return true;
784 }
785 }
786
787 return false;
788 }
789
790
792 triton::uint64 base = mem.getAddress();
793
794 for (triton::usize index = 0; index < mem.getSize(); index++) {
795 if (tag == true) {
796 this->exclusiveMemoryTags.insert(base + index);
797 }
798 else {
799 this->exclusiveMemoryTags.erase(base + index);
800 }
801 }
802 }
803
804
806 return this->isConcreteMemoryValueDefined(mem.getAddress(), mem.getSize());
807 }
808
809
811 for (triton::usize index = 0; index < size; index++) {
812 if (this->memory.find(baseAddr + index) == this->memory.end())
813 return false;
814 }
815 return true;
816 }
817
818
820 this->clearConcreteMemoryValue(mem.getAddress(), mem.getSize());
821 }
822
823
825 for (triton::usize index = 0; index < size; index++) {
826 if (this->memory.find(baseAddr + index) != this->memory.end()) {
827 this->memory.erase(baseAddr + index);
828 }
829 }
830 }
831
832
833 triton::arch::arm::condition_e Arm32Cpu::invertCodeCondition(triton::arch::arm::condition_e cc) const {
835
836 switch (cc) {
839
842
845
848
851
854
857
860
863
866
869
872
875
878
881
884
885 default:
887 }
888
889 return inv;
890 }
891
892 }; /* arm32 namespace */
893 }; /* arm namespace */
894 }; /* arch namespace */
895}; /* triton namespace */
TRITON_EXPORT triton::uint512 getMaxValue(void) const
Returns the max possible value of the bitvector.
Definition: bitsVector.cpp:49
TRITON_EXPORT void setBits(triton::uint32 high, triton::uint32 low)
Sets the bits (high, low) position.
Definition: bitsVector.cpp:72
This class is used to represent an immediate.
Definition: immediate.hpp:37
This class is used to represent an instruction.
Definition: instruction.hpp:48
TRITON_EXPORT void setOpcode(const void *opcode, triton::uint32 size)
Sets the opcode of the instruction.
TRITON_EXPORT void setUpdateFlag(bool state)
Sets the updateFlag of the instruction.
TRITON_EXPORT triton::uint32 getSize(void) const
Returns the size of the instruction.
TRITON_EXPORT void setDisassembly(const std::string &str)
Sets the disassembly of the instruction.
TRITON_EXPORT void setThumb(bool state)
Sets the Thumb mode of the instruction.
TRITON_EXPORT const triton::uint8 * getOpcode(void) const
Returns the opcode of the instruction.
TRITON_EXPORT bool isThumb(void) const
Returns true if it is a Thumb instruction.
TRITON_EXPORT void setType(triton::uint32 type)
Sets the type of the instruction.
TRITON_EXPORT void setAddress(triton::uint64 addr)
Sets the address of the instruction.
TRITON_EXPORT triton::uint32 getType(void) const
Returns the type of the instruction.
TRITON_EXPORT void setArchitecture(triton::arch::architecture_e arch)
Sets the instruction's architecture.
TRITON_EXPORT void setWriteBack(bool state)
Sets the writeBack flag of the instruction.
TRITON_EXPORT triton::uint64 getAddress(void) const
Returns the address of the instruction.
TRITON_EXPORT void setBranch(bool flag)
Sets flag to define this instruction as branch or not.
TRITON_EXPORT void setSize(triton::uint32 size)
Sets the size of the instruction.
TRITON_EXPORT void setCodeCondition(triton::arch::arm::condition_e codeCondition)
Sets the code condition of the instruction (mainly for AArch64).
std::vector< triton::arch::OperandWrapper > operands
A list of operands.
TRITON_EXPORT void setControlFlow(bool flag)
Sets flag to define this instruction changes the control flow or not.
TRITON_EXPORT triton::arch::arm::condition_e getCodeCondition(void) const
Returns the code codition of the instruction (mainly for AArch64).
TRITON_EXPORT std::string getDisassembly(void) const
Returns the disassembly of the instruction.
This class is used to represent a memory access.
TRITON_EXPORT void setDisplacement(const triton::arch::Immediate &displacement)
LEA - Sets the displacement operand.
TRITON_EXPORT void setScale(const triton::arch::Immediate &scale)
LEA - Sets the scale operand.
TRITON_EXPORT triton::uint64 getAddress(void) const
Returns the address of the memory.
TRITON_EXPORT void setPcRelative(triton::uint64 addr)
LEA - Sets pc relative.
TRITON_EXPORT triton::uint32 getSize(void) const
Returns the size (in bytes) of the memory vector.
TRITON_EXPORT void setIndexRegister(const triton::arch::Register &index)
LEA - Sets the index register operand.
TRITON_EXPORT void setBaseRegister(const triton::arch::Register &base)
LEA - Sets the base register operand.
This class is used as operand wrapper.
This class is used when an instruction has a register operand.
Definition: register.hpp:44
TRITON_EXPORT triton::arch::register_e getParent(void) const
Returns the parent id of the register.
Definition: register.cpp:58
TRITON_EXPORT triton::arch::register_e getId(void) const
Returns the id of the register.
Definition: register.cpp:53
TRITON_EXPORT triton::uint32 getSize(void) const
Returns the size (in bytes) of the register.
Definition: register.cpp:68
TRITON_EXPORT void setShiftType(triton::arch::arm::shift_e type)
Sets the type of the shift.
TRITON_EXPORT void setSubtracted(bool value)
Sets subtracted flag.
TRITON_EXPORT void setShiftValue(triton::uint32 imm)
Sets the value of the shift immediate.
This class is used to describe the ARM (32-bits) spec.
Definition: arm32Cpu.hpp:61
TRITON_EXPORT void setMemoryExclusiveTag(const triton::arch::MemoryAccess &mem, bool tag)
Sets exclusive memory access tag. Only valid for Arm32 and AArch64.
Definition: arm32Cpu.cpp:791
TRITON_EXPORT std::set< const triton::arch::Register * > getParentRegisters(void) const
Returns all parent registers.
Definition: arm32Cpu.cpp:185
triton::uint8 r2[triton::size::dword]
Concrete value of r2.
Definition: arm32Cpu.hpp:121
TRITON_EXPORT triton::uint32 gprSize(void) const
Returns the bit in byte of the General Purpose Registers.
Definition: arm32Cpu.cpp:170
triton::uint8 pc[triton::size::dword]
Concrete value of pc.
Definition: arm32Cpu.hpp:147
triton::uint8 r7[triton::size::dword]
Concrete value of r7.
Definition: arm32Cpu.hpp:131
triton::uint8 sp[triton::size::dword]
Concrete value of sp.
Definition: arm32Cpu.hpp:143
triton::uint8 r1[triton::size::dword]
Concrete value of r1.
Definition: arm32Cpu.hpp:119
TRITON_EXPORT const triton::arch::Register & getStackPointer(void) const
Returns the stack pointer register.
Definition: arm32Cpu.cpp:240
TRITON_EXPORT bool isGPR(triton::arch::register_e regId) const
Returns true if regId is a GRP.
Definition: arm32Cpu.cpp:160
TRITON_EXPORT triton::arch::endianness_e getEndianness(void) const
Returns the kind of endianness as triton::arch::endianness_e.
Definition: arm32Cpu.cpp:140
triton::uint8 r14[triton::size::dword]
Concrete value of r14.
Definition: arm32Cpu.hpp:145
TRITON_EXPORT void clearConcreteMemoryValue(const triton::arch::MemoryAccess &mem)
Clears concrete values assigned to the memory cells.
Definition: arm32Cpu.cpp:819
TRITON_EXPORT triton::uint512 getConcreteRegisterValue(const triton::arch::Register &reg, bool execCallbacks=true) const
Returns the concrete value of a register.
Definition: arm32Cpu.cpp:623
triton::uint8 r6[triton::size::dword]
Concrete value of r6.
Definition: arm32Cpu.hpp:129
TRITON_EXPORT bool isFlag(triton::arch::register_e regId) const
Returns true if the register ID is a flag.
Definition: arm32Cpu.cpp:145
TRITON_EXPORT bool isConcreteMemoryValueDefined(const triton::arch::MemoryAccess &mem) const
Returns true if memory cells have a defined concrete value.
Definition: arm32Cpu.cpp:805
TRITON_EXPORT void setConcreteMemoryValue(const triton::arch::MemoryAccess &mem, const triton::uint512 &value, bool execCallbacks=true)
[architecture api] - Sets the concrete value of memory cells.
Definition: arm32Cpu.cpp:666
TRITON_EXPORT bool isRegisterValid(triton::arch::register_e regId) const
Returns true if the register ID is valid.
Definition: arm32Cpu.cpp:155
TRITON_EXPORT bool isThumb(void) const
Returns true if the execution mode is Thumb. Only useful for Arm32.
Definition: arm32Cpu.cpp:768
TRITON_EXPORT const triton::arch::Register & getRegister(triton::arch::register_e id) const
Returns register from id.
Definition: arm32Cpu.cpp:205
TRITON_EXPORT const triton::arch::Register & getProgramCounter(void) const
Returns the program counter register.
Definition: arm32Cpu.cpp:235
virtual TRITON_EXPORT ~Arm32Cpu()
Destructor.
Definition: arm32Cpu.cpp:47
TRITON_EXPORT void clear(void)
Clears the architecture states (registers and memory).
Definition: arm32Cpu.cpp:109
bool thumb
Thumb mode flag.
Definition: arm32Cpu.hpp:152
std::unordered_map< triton::uint64, triton::uint8, IdentityHash< triton::uint64 > > memory
map of address -> concrete value
Definition: arm32Cpu.hpp:114
TRITON_EXPORT void disassembly(triton::arch::Instruction &inst)
Disassembles the instruction according to the architecture.
Definition: arm32Cpu.cpp:245
TRITON_EXPORT triton::uint32 gprBitSize(void) const
Returns the bit in bit of the General Purpose Registers.
Definition: arm32Cpu.cpp:175
TRITON_EXPORT Arm32Cpu(triton::callbacks::Callbacks *callbacks=nullptr)
Constructor.
Definition: arm32Cpu.cpp:27
triton::uint8 r5[triton::size::dword]
Concrete value of r5.
Definition: arm32Cpu.hpp:127
triton::uint8 r11[triton::size::dword]
Concrete value of r11.
Definition: arm32Cpu.hpp:139
triton::uint8 r8[triton::size::dword]
Concrete value of r8.
Definition: arm32Cpu.hpp:133
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.
Definition: arm32Cpu.cpp:613
triton::uint8 r10[triton::size::dword]
Concrete value of r10.
Definition: arm32Cpu.hpp:137
TRITON_EXPORT triton::uint512 getConcreteMemoryValue(const triton::arch::MemoryAccess &mem, bool execCallbacks=true) const
Returns the concrete value of memory cells.
Definition: arm32Cpu.cpp:592
triton::uint8 r12[triton::size::dword]
Concrete value of r12.
Definition: arm32Cpu.hpp:141
TRITON_EXPORT bool isRegister(triton::arch::register_e regId) const
Returns true if the register ID is a register.
Definition: arm32Cpu.cpp:150
TRITON_EXPORT triton::uint32 numberOfRegisters(void) const
Returns the number of registers according to the CPU architecture.
Definition: arm32Cpu.cpp:165
TRITON_EXPORT Arm32Cpu & operator=(const Arm32Cpu &other)
Copies a Arm32Cpu class.
Definition: arm32Cpu.cpp:134
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.
Definition: arm32Cpu.cpp:703
TRITON_EXPORT const std::unordered_map< triton::arch::register_e, const triton::arch::Register > & getAllRegisters(void) const
Returns all registers.
Definition: arm32Cpu.cpp:180
TRITON_EXPORT const triton::arch::Register & getParentRegister(const triton::arch::Register &reg) const
Returns parent register from a given one.
Definition: arm32Cpu.cpp:225
triton::uint8 r3[triton::size::dword]
Concrete value of r3.
Definition: arm32Cpu.hpp:123
TRITON_EXPORT bool isMemoryExclusive(const triton::arch::MemoryAccess &mem) const
Returns true if the given memory access is tagged as exclusive. Only valid for Arm32 and AArch64.
Definition: arm32Cpu.cpp:778
triton::uint8 r0[triton::size::dword]
Concrete value of r0.
Definition: arm32Cpu.hpp:117
TRITON_EXPORT void setThumb(bool state)
Sets CPU state to Thumb mode.
Definition: arm32Cpu.cpp:773
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.
Definition: arm32Cpu.cpp:687
triton::uint8 r4[triton::size::dword]
Concrete value of r4.
Definition: arm32Cpu.hpp:125
triton::uint8 r9[triton::size::dword]
Concrete value of r9.
Definition: arm32Cpu.hpp:135
The Arm32Specifications class defines specifications about the Arm32 CPU.
std::unordered_map< triton::arch::register_e, const triton::arch::Register > id2reg
List of registers specification available for this architecture.
TRITON_EXPORT triton::arch::register_e capstoneRegisterToTritonRegister(triton::uint32 id) const
Converts a capstone's register id to a triton's register id.
TRITON_EXPORT triton::uint32 capstoneInstructionToTritonInstruction(triton::uint32 id) const
Converts a capstone's instruction id to a triton's instruction id.
TRITON_EXPORT triton::arch::arm::shift_e capstoneShiftToTritonShift(triton::uint32 id) const
Converts a capstone's shift id to a triton's shift id.
TRITON_EXPORT triton::arch::arm::condition_e capstoneConditionToTritonCondition(triton::uint32 id) const
Converts a capstone's condition id to a triton's condition id.
TRITON_EXPORT triton::uint32 getMemoryOperandSpecialSize(triton::uint32 id) const
Returns memory access size if it is specified by instruction.
The callbacks class.
Definition: callbacks.hpp:79
TRITON_EXPORT triton::ast::SharedAbstractNode processCallbacks(triton::callbacks::callback_e kind, triton::ast::SharedAbstractNode node)
Processes callbacks according to the kind and the C++ polymorphism.
Definition: callbacks.cpp:193
The exception class used by all CPUs.
Definition: exceptions.hpp:317
The exception class used by the disassembler.
Definition: exceptions.hpp:365
The exception class used by register operands.
Definition: exceptions.hpp:257
register_e
Types of register.
Definition: archEnums.hpp:64
@ ID_REG_LAST_ITEM
must be the last item
Definition: archEnums.hpp:84
shift_e
Types of shift.
Definition: archEnums.hpp:124
condition_e
Types of condition.
Definition: archEnums.hpp:154
@ ID_SHIFT_LSR
Logical Shift Right (immediate)
Definition: archEnums.hpp:128
@ ID_SHIFT_LSR_REG
Logical Shift Right (register)
Definition: archEnums.hpp:133
@ ID_SHIFT_ASR
Arithmetic Shift Right (immediate)
Definition: archEnums.hpp:126
@ ID_SHIFT_ROR_REG
Rotate Right (register)
Definition: archEnums.hpp:134
@ ID_SHIFT_ROR
Rotate Right (immediate)
Definition: archEnums.hpp:129
@ ID_SHIFT_ASR_REG
Arithmetic Shift Right (register)
Definition: archEnums.hpp:131
@ ID_SHIFT_RRX
Rotate Right with Extend (immediate)
Definition: archEnums.hpp:130
@ ID_SHIFT_RRX_REG
Rotate Right with Extend (register)
Definition: archEnums.hpp:135
@ ID_SHIFT_LSL_REG
Logical Shift Left (register)
Definition: archEnums.hpp:132
@ ID_SHIFT_INVALID
invalid
Definition: archEnums.hpp:125
@ ID_SHIFT_LSL
Logical Shift Left (immediate)
Definition: archEnums.hpp:127
@ ID_CONDITION_HS
Higher or same (unsigned >=). C set.
Definition: archEnums.hpp:161
@ ID_CONDITION_PL
Positive or zero. N clear.
Definition: archEnums.hpp:168
@ ID_CONDITION_VC
No overflow. V clear.
Definition: archEnums.hpp:169
@ ID_CONDITION_LE
Signed <=. Z set, N and V differ.
Definition: archEnums.hpp:162
@ ID_CONDITION_VS
Overflow. V set.
Definition: archEnums.hpp:170
@ ID_CONDITION_MI
Negative. N set.
Definition: archEnums.hpp:166
@ ID_CONDITION_GE
Signed >=. N and V the same.
Definition: archEnums.hpp:158
@ ID_CONDITION_GT
Signed >. Z clear, N and V the same.
Definition: archEnums.hpp:159
@ ID_CONDITION_HI
Higher (unsigned >). C set and Z clear.
Definition: archEnums.hpp:160
@ ID_CONDITION_NE
Not equal. Z clear.
Definition: archEnums.hpp:167
@ ID_CONDITION_AL
Always. Any flags. This suffix is normally omitted.
Definition: archEnums.hpp:156
@ ID_CONDITION_LO
Lower (unsigned <). C clear.
Definition: archEnums.hpp:163
@ ID_CONDITION_LT
Signed <. N and V differ.
Definition: archEnums.hpp:165
@ ID_CONDITION_LS
Lower or same (unsigned <=). C clear or Z set.
Definition: archEnums.hpp:164
@ ID_CONDITION_INVALID
invalid
Definition: archEnums.hpp:155
@ ID_CONDITION_EQ
Equal. Z set.
Definition: archEnums.hpp:157
constexpr triton::uint32 byte
byte size in bit
Definition: cpuSize.hpp:60
constexpr triton::uint32 dword
dword size in bit
Definition: cpuSize.hpp:64
constexpr triton::uint32 dword
dword size in byte
Definition: cpuSize.hpp:34
constexpr triton::uint32 dqqword
dqqword size in byte
Definition: cpuSize.hpp:44
constexpr triton::uint32 byte
byte size in byte
Definition: cpuSize.hpp:30
std::int32_t sint32
signed 32-bits
Definition: tritonTypes.hpp:79
std::size_t usize
unsigned MAX_INT 32 or 64 bits according to the CPU.
std::uint64_t uint64
unisgned 64-bits
Definition: tritonTypes.hpp:42
std::uint32_t uint32
unisgned 32-bits
Definition: tritonTypes.hpp:39
std::uint8_t uint8
unisgned 8-bits
Definition: tritonTypes.hpp:33
The Triton namespace.