libTriton version 1.0 build 1590
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
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
168
169
171 return triton::size::dword;
172 }
173
174
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 const std::unordered_map<triton::uint64, triton::uint8, IdentityHash<triton::uint64>>& Arm32Cpu::getConcreteMemory(void) const {
185 return this->memory;
186 }
187
188
189 std::set<const triton::arch::Register*> Arm32Cpu::getParentRegisters(void) const {
190 std::set<const triton::arch::Register*> ret;
191
192 for (const auto& kv: this->id2reg) {
193 auto regId = kv.first;
194 const auto& reg = kv.second;
195
196 /* Add GPR */
197 if (reg.getSize() == this->gprSize())
198 ret.insert(&reg);
199
200 /* Add Flags */
201 else if (this->isFlag(regId))
202 ret.insert(&reg);
203 }
204
205 return ret;
206 }
207
208
210 try {
211 return this->id2reg.at(id);
212 } catch (const std::out_of_range&) {
213 throw triton::exceptions::Cpu("Arm32Cpu::getRegister(): Invalid register for this architecture.");
214 }
215 }
216
217
218 const triton::arch::Register& Arm32Cpu::getRegister(const std::string& name) const {
219 std::string lower = name;
220 std::transform(lower.begin(), lower.end(), lower.begin(), [](unsigned char c){ return std::tolower(c); });
221 try {
222 return this->getRegister(this->name2id.at(lower));
223 } catch (const std::out_of_range&) {
224 throw triton::exceptions::Cpu("Arm32Cpu::getRegister(): Invalid register for this architecture.");
225 }
226 }
227
228
230 return this->getRegister(reg.getParent());
231 }
232
233
237
238
240 return this->getRegister(this->pcId);
241 }
242
243
245 return this->getRegister(this->spId);
246 }
247
248
250 triton::extlibs::capstone::csh handle;
251 triton::extlibs::capstone::cs_insn* insn;
252 triton::usize count = 0;
253
254 /* Check if the opcode and opcode' size are defined */
255 if (inst.getOpcode() == nullptr || inst.getSize() == 0)
256 throw triton::exceptions::Disassembly("Arm32Cpu::disassembly(): Opcode and opcodeSize must be definied.");
257
258 /* Select capstone handler (based on execution mode) */
259 handle = (this->thumb ? this->handleThumb : this->handleArm);
260
261 /* Clear instructicon's operands if alredy defined */
262 inst.operands.clear();
263
264 /* Update instruction address if undefined */
265 if (!inst.getAddress()) {
266 inst.setAddress(static_cast<triton::uint64>(this->getConcreteRegisterValue(this->getProgramCounter())));
267 }
268
269 /* Let's disass and build our operands */
270 count = triton::extlibs::capstone::cs_disasm(handle, inst.getOpcode(), inst.getSize(), inst.getAddress(), 0, &insn);
271 if (count > 0) {
272 triton::extlibs::capstone::cs_detail* detail = insn->detail;
273
274 /* Refine the opcode */
275 inst.setOpcode(insn[0].bytes, insn[0].size);
276
277 /* Refine the size */
278 inst.setSize(insn[0].size);
279
280 /* Init the instruction's type */
281 inst.setType(this->capstoneInstructionToTritonInstruction(insn[0].id));
282
283 /* Init the instruction's code codition */
284 inst.setCodeCondition(this->capstoneConditionToTritonCondition(detail->arm.cc));
285
286 /* Init the instruction's write back flag */
287 inst.setWriteBack(detail->arm.writeback);
288
289 /* Set True if the instruction udpate flags */
290 inst.setUpdateFlag(detail->arm.update_flags);
291
292 /* Set thumb mode */
293 inst.setThumb(thumb);
294
295 /* Set architecture */
297
298 /* Init the disassembly */
299 std::stringstream str;
300
301 /* Add mnemonic */
302 str << insn[0].mnemonic;
303
304 /* Add operands */
305 if (inst.getType() == ID_INS_IT || detail->arm.op_count)
306 str << " " << insn[0].op_str;
307
308 inst.setDisassembly(str.str());
309
310 /* Process IT instruction */
311 if (inst.getType() == ID_INS_IT) {
312 /* Nested IT instruction, throw an exception as this is not valid ARM code */
313 if (this->itInstrsCount > 0)
314 throw triton::exceptions::Disassembly("Arm32Cpu::disassembly(): Nested IT instructions are not allowed.");
315
316 /* Copy state from the mnemonic of the instruction */
317 strncpy(this->itStateArray, &insn[0].mnemonic[1], 5);
318 this->itStateArray[4] = 0;
319
320 this->itInstrsCount = strlen(this->itStateArray);
321 this->itInstrIndex = 0;
322
323 this->itCC = inst.getCodeCondition();
324 this->itCCInv = this->invertCodeCondition(this->itCC);
325 }
326
327 /* Process instruction within an IT block */
328 if (inst.getType() != ID_INS_IT && this->itInstrsCount > 0) {
329 /* NOTE Assuming that CS always returns mnemonics in lower case */
330 triton::arch::arm::condition_e cc = this->itStateArray[this->itInstrIndex] == 't' ? this->itCC : this->itCCInv;
331
332 inst.setCodeCondition(cc);
333
334 /* From the reference manual: "16-bit instructions in the IT
335 block, other than CMP, CMN and TST, do not set the condition
336 flags". */
337 if (inst.getSize() == 2 && inst.getType() != ID_INS_CMP && \
338 inst.getType() != ID_INS_CMN && inst.getType() != ID_INS_TST) {
339 inst.setUpdateFlag(false);
340 }
341
342 this->itInstrsCount--;
343 this->itInstrIndex++;
344 }
345
346 /* Init operands */
347 for (triton::uint32 n = 0; n < detail->arm.op_count; n++) {
348 triton::extlibs::capstone::cs_arm_op* op = &(detail->arm.operands[n]);
349 switch(op->type) {
350
351 case triton::extlibs::capstone::ARM_OP_IMM: {
353
354 if (op->subtracted)
355 imm.setSubtracted(true);
356
357 inst.operands.push_back(triton::arch::OperandWrapper(imm));
358 break;
359 }
360
361 case triton::extlibs::capstone::ARM_OP_MEM: {
363
364 /* Set the size of the memory access */
366 mem.setBits(size ? ((size * triton::bitsize::byte) - 1) : triton::bitsize::dword-1, 0);
367
368 /* LEA if exists */
369 const triton::arch::Register base(*this, this->capstoneRegisterToTritonRegister(op->mem.base));
370 triton::arch::Register index(*this, this->capstoneRegisterToTritonRegister(op->mem.index));
371
372 /* Set Shift type and value */
373 triton::arch::arm::shift_e shiftType = this->capstoneShiftToTritonShift(op->shift.type);
374
375 index.setShiftType(shiftType);
376
377 switch(shiftType) {
379 break;
384 index.setShiftValue(op->shift.value);
385 break;
387 /* NOTE: According to the manual RRX there is no
388 * immediate associated with this shift type. However,
389 * from the description of the instruction it can be
390 * deduced that a value of one is used.
391 */
392 index.setShiftValue(1);
393 break;
398 index.setShiftValue(this->capstoneRegisterToTritonRegister(op->shift.value));
399 break;
401 /* NOTE: Capstone considers this as a viable shift operand
402 * but according to the ARM manual this is not possible.
403 */
404 throw triton::exceptions::Disassembly("Arm32Cpu::disassembly(): Invalid shift type.");
405 break;
406 default:
407 throw triton::exceptions::Disassembly("Arm32Cpu::disassembly(): Invalid shift type.");
408 }
409
410 if (op->subtracted) {
411 index.setSubtracted(true);
412 }
413
414 triton::uint32 immsize = (
415 this->isRegisterValid(base.getId()) ? base.getSize() :
416 this->isRegisterValid(index.getId()) ? index.getSize() :
417 this->gprSize()
418 );
419
420 triton::arch::Immediate disp(op->mem.disp, immsize);
421
422 /* Specify that LEA contains a PC relative */
423 if (base.getId() == this->pcId) {
424 /* NOTE: PC always points to the address to the current
425 * instruction plus: a) 8 in case of ARM mode, or b) 4 in
426 * case of Thumb. It is also aligned to 4 bytes. For more
427 * information, refer to section "Use of labels in UAL
428 * instruction syntax" of the reference manual.
429 */
430 auto offset = this->thumb ? 4 : 8;
431 auto address = (inst.getAddress() + offset);
432 /* Align address except when it is a TBB or TBH instruction. */
433 if (!(inst.getType() == ID_INS_TBB || inst.getType() == ID_INS_TBH)) {
434 address = address & 0xfffffffc;
435 }
436 mem.setPcRelative(address);
437 }
438
439 /* Note that in ARM32 there is no segment register and scale value */
440 mem.setBaseRegister(base);
441 mem.setIndexRegister(index);
442 mem.setDisplacement(disp);
443
444 /* If there is an index register available, set scale to 1 to perform this following computation (base) + (index * scale) */
445 if (this->isRegisterValid(index.getId()))
447
448 inst.operands.push_back(triton::arch::OperandWrapper(mem));
449 break;
450 }
451
452 case triton::extlibs::capstone::ARM_OP_REG: {
454
455 /* Set Shift type and value */
456 triton::arch::arm::shift_e shiftType = this->capstoneShiftToTritonShift(op->shift.type);
457
458 reg.setShiftType(shiftType);
459
460 switch(shiftType) {
462 break;
467 reg.setShiftValue(op->shift.value);
468 break;
470 /* NOTE: According to the manual RRX there is no
471 * immediate associated with this shift type. However,
472 * from the description of the instruction it can be
473 * deduced that a value of one is used.
474 */
475 reg.setShiftValue(1);
476 break;
481 reg.setShiftValue(this->capstoneRegisterToTritonRegister(op->shift.value));
482 break;
484 /* NOTE: Capstone considers this as a viable shift operand
485 * but according to the ARM manual this is not possible.
486 */
487 throw triton::exceptions::Disassembly("Arm32Cpu::disassembly(): Invalid shift type.");
488 break;
489 default:
490 throw triton::exceptions::Disassembly("Arm32Cpu::disassembly(): Invalid shift type.");
491 }
492
493 if (op->subtracted)
494 reg.setSubtracted(true);
495
496 inst.operands.push_back(triton::arch::OperandWrapper(reg));
497 break;
498 }
499
500 default:
501 /* NOTE: FP, CIMM, and missing one are not supported yet. */
502 throw triton::exceptions::Disassembly("Arm32Cpu::disassembly(): Invalid operand.");
503 } // switch
504 } // for operand
505
506 /* Set branch */
507 if (detail->groups_count > 0) {
508 for (triton::uint32 n = 0; n < detail->groups_count; n++) {
509 if (detail->groups[n] == triton::extlibs::capstone::ARM_GRP_JUMP) {
510 inst.setBranch(true);
511 inst.setControlFlow(true);
512 }
513 }
514 }
515
516 /* Post process instruction */
517 this->postDisassembly(inst);
518
519 /* Free capstone stuffs */
520 triton::extlibs::capstone::cs_free(insn, count);
521 }
522 else
523 throw triton::exceptions::Disassembly("Arm32Cpu::disassembly(): Failed to disassemble the given code.");
524
525 return;
526 }
527
528
529 void Arm32Cpu::postDisassembly(triton::arch::Instruction& inst) const {
530 /* Fix update flag */
531 /* NOTE: Quick (and super ugly) hack. Capstone is reporting
532 * update_flags equals true for ADC, RSC and SBC instruction when
533 * it shouldn't (it should only report true when the S suffix is
534 * present). This will be removed once Capstone is fixed. For more
535 * information, see: https://github.com/aquynh/capstone/issues/1568.
536 */
537 switch (inst.getType()) {
538 case ID_INS_ADC:
539 case ID_INS_RSC:
540 case ID_INS_SBC:
541 if (inst.getDisassembly().at(3) != 's')
542 inst.setUpdateFlag(false);
543 break;
544 }
545
546 /* Make implicit destination operand explicit */
547 /* NOTE: For some instructions the destination operand is
548 * optional (in which case the first source operand is used as
549 * destination). Capstone returns always all three operands for
550 * ARM instruction (i.e. make the destination operand explicit).
551 * However, it does not do the same for Thumb instructions. Here
552 * we make the destination operand explicit (in order to simplify
553 * the implementation of the semantics).
554 */
555 if (inst.isThumb() && inst.operands.size() == 2) {
557
558 switch (inst.getType()) {
559 case ID_INS_ADC:
560 case ID_INS_ADD:
561 case ID_INS_AND:
562 case ID_INS_ASR:
563 case ID_INS_BIC:
564 case ID_INS_EOR:
565 case ID_INS_LSL:
566 case ID_INS_LSR:
567 case ID_INS_ORR:
568 case ID_INS_ROR:
569 case ID_INS_SBC:
570 case ID_INS_SUB:
571 inst.operands.insert(inst.operands.begin(), op);
572 break;
573 }
574 }
575
576 /* NOTE: If the instruction is POP and contains a PC register,
577 * we have to define the instruction as modifiying the control
578 * flow. See #945.
579 */
580 if (inst.getType() == ID_INS_POP) {
581 /* FIXME: Maybe the loop is useless if PC is always the last operand? */
582 for (auto& op : inst.operands) {
583 if (op.getType() == triton::arch::OP_REG && op.getConstRegister().getId() == this->pcId) {
584 inst.setControlFlow(true);
585 break;
586 }
587 }
588 }
589 }
590
591
593 if (execCallbacks && this->callbacks)
595
596 auto it = this->memory.find(addr);
597 if (it == this->memory.end())
598 return 0x00;
599
600 return it->second;
601 }
602
603
605 triton::uint512 ret = 0;
606 triton::uint64 addr = 0;
607 triton::uint32 size = 0;
608
609 if (execCallbacks && this->callbacks)
611
612 addr = mem.getAddress();
613 size = mem.getSize();
614
615 if (size == 0 || size > triton::size::dqqword)
616 throw triton::exceptions::Cpu("Arm32Cpu::getConcreteMemoryValue(): Invalid size memory.");
617
618 for (triton::sint32 i = size-1; i >= 0; i--)
619 ret = ((ret << triton::bitsize::byte) | this->getConcreteMemoryValue(addr+i, false));
620
621 return ret;
622 }
623
624
625 std::vector<triton::uint8> Arm32Cpu::getConcreteMemoryAreaValue(triton::uint64 baseAddr, triton::usize size, bool execCallbacks) const {
626 std::vector<triton::uint8> area;
627
628 for (triton::usize index = 0; index < size; index++)
629 area.push_back(this->getConcreteMemoryValue(baseAddr+index, execCallbacks));
630
631 return area;
632 }
633
634
636 triton::uint512 value = 0;
637
638 if (execCallbacks && this->callbacks)
640
641 switch (reg.getId()) {
642 case triton::arch::ID_REG_ARM32_R0: return (*((triton::uint32*)(this->r0)));
643 case triton::arch::ID_REG_ARM32_R1: return (*((triton::uint32*)(this->r1)));
644 case triton::arch::ID_REG_ARM32_R2: return (*((triton::uint32*)(this->r2)));
645 case triton::arch::ID_REG_ARM32_R3: return (*((triton::uint32*)(this->r3)));
646 case triton::arch::ID_REG_ARM32_R4: return (*((triton::uint32*)(this->r4)));
647 case triton::arch::ID_REG_ARM32_R5: return (*((triton::uint32*)(this->r5)));
648 case triton::arch::ID_REG_ARM32_R6: return (*((triton::uint32*)(this->r6)));
649 case triton::arch::ID_REG_ARM32_R7: return (*((triton::uint32*)(this->r7)));
650 case triton::arch::ID_REG_ARM32_R8: return (*((triton::uint32*)(this->r8)));
651 case triton::arch::ID_REG_ARM32_R9: return (*((triton::uint32*)(this->r9)));
652 case triton::arch::ID_REG_ARM32_R10: return (*((triton::uint32*)(this->r10)));
653 case triton::arch::ID_REG_ARM32_R11: return (*((triton::uint32*)(this->r11)));
654 case triton::arch::ID_REG_ARM32_R12: return (*((triton::uint32*)(this->r12)));
655 case triton::arch::ID_REG_ARM32_SP: return (*((triton::uint32*)(this->sp)));
656 case triton::arch::ID_REG_ARM32_R14: return (*((triton::uint32*)(this->r14)));
657 case triton::arch::ID_REG_ARM32_PC: return (*((triton::uint32*)(this->pc)));
658 case triton::arch::ID_REG_ARM32_APSR: return (*((triton::uint32*)(this->apsr)));
659 case triton::arch::ID_REG_ARM32_N: return (((*((triton::uint32*)(this->apsr))) >> 31) & 1);
660 case triton::arch::ID_REG_ARM32_Z: return (((*((triton::uint32*)(this->apsr))) >> 30) & 1);
661 case triton::arch::ID_REG_ARM32_C: return (((*((triton::uint32*)(this->apsr))) >> 29) & 1);
662 case triton::arch::ID_REG_ARM32_V: return (((*((triton::uint32*)(this->apsr))) >> 28) & 1);
663 default:
664 throw triton::exceptions::Cpu("Arm32Cpu::getConcreteRegisterValue(): Invalid register.");
665 }
666
667 return value;
668 }
669
670
671 void Arm32Cpu::setConcreteMemoryValue(triton::uint64 addr, triton::uint8 value, bool execCallbacks) {
672 if (execCallbacks && this->callbacks)
674 this->memory[addr] = value;
675 }
676
677
678 void Arm32Cpu::setConcreteMemoryValue(const triton::arch::MemoryAccess& mem, const triton::uint512& value, bool execCallbacks) {
679 triton::uint64 addr = mem.getAddress();
680 triton::uint32 size = mem.getSize();
681 triton::uint512 cv = value;
682
683 if (cv > mem.getMaxValue())
684 throw triton::exceptions::Register("Arm32Cpu::setConcreteMemoryValue(): You cannot set this concrete value (too big) to this memory access.");
685
686 if (size == 0 || size > triton::size::dqqword)
687 throw triton::exceptions::Cpu("Arm32Cpu::setConcreteMemoryValue(): Invalid size memory.");
688
689 if (execCallbacks && this->callbacks)
691
692 for (triton::uint32 i = 0; i < size; i++) {
693 this->memory[addr+i] = static_cast<triton::uint8>((cv & 0xff));
694 cv >>= 8;
695 }
696 }
697
698
699 void Arm32Cpu::setConcreteMemoryAreaValue(triton::uint64 baseAddr, const std::vector<triton::uint8>& values, bool execCallbacks) {
700 this->memory.reserve(values.size() + this->memory.size());
701 for (triton::usize index = 0; index < values.size(); index++) {
702 this->setConcreteMemoryValue(baseAddr+index, values[index], execCallbacks);
703 }
704 }
705
706
707 void Arm32Cpu::setConcreteMemoryAreaValue(triton::uint64 baseAddr, const void* area, triton::usize size, bool execCallbacks) {
708 this->memory.reserve(size + this->memory.size());
709 for (triton::usize index = 0; index < size; index++) {
710 this->setConcreteMemoryValue(baseAddr+index, reinterpret_cast<const triton::uint8*>(area)[index], execCallbacks);
711 }
712 }
713
714
715 void Arm32Cpu::setConcreteRegisterValue(const triton::arch::Register& reg, const triton::uint512& value, bool execCallbacks) {
716 if (value > reg.getMaxValue())
717 throw triton::exceptions::Register("Arm32Cpu::setConcreteRegisterValue(): You cannot set this concrete value (too big) to this register.");
718
719 if (execCallbacks && this->callbacks)
721
722 switch (reg.getId()) {
723 case triton::arch::ID_REG_ARM32_R0: (*((triton::uint32*)(this->r0))) = static_cast<triton::uint32>(value); break;
724 case triton::arch::ID_REG_ARM32_R1: (*((triton::uint32*)(this->r1))) = static_cast<triton::uint32>(value); break;
725 case triton::arch::ID_REG_ARM32_R2: (*((triton::uint32*)(this->r2))) = static_cast<triton::uint32>(value); break;
726 case triton::arch::ID_REG_ARM32_R3: (*((triton::uint32*)(this->r3))) = static_cast<triton::uint32>(value); break;
727 case triton::arch::ID_REG_ARM32_R4: (*((triton::uint32*)(this->r4))) = static_cast<triton::uint32>(value); break;
728 case triton::arch::ID_REG_ARM32_R5: (*((triton::uint32*)(this->r5))) = static_cast<triton::uint32>(value); break;
729 case triton::arch::ID_REG_ARM32_R6: (*((triton::uint32*)(this->r6))) = static_cast<triton::uint32>(value); break;
730 case triton::arch::ID_REG_ARM32_R7: (*((triton::uint32*)(this->r7))) = static_cast<triton::uint32>(value); break;
731 case triton::arch::ID_REG_ARM32_R8: (*((triton::uint32*)(this->r8))) = static_cast<triton::uint32>(value); break;
732 case triton::arch::ID_REG_ARM32_R9: (*((triton::uint32*)(this->r9))) = static_cast<triton::uint32>(value); break;
733 case triton::arch::ID_REG_ARM32_R10: (*((triton::uint32*)(this->r10))) = static_cast<triton::uint32>(value); break;
734 case triton::arch::ID_REG_ARM32_R11: (*((triton::uint32*)(this->r11))) = static_cast<triton::uint32>(value); break;
735 case triton::arch::ID_REG_ARM32_R12: (*((triton::uint32*)(this->r12))) = static_cast<triton::uint32>(value); break;
736 case triton::arch::ID_REG_ARM32_SP: (*((triton::uint32*)(this->sp))) = static_cast<triton::uint32>(value); break;
737 case triton::arch::ID_REG_ARM32_R14: (*((triton::uint32*)(this->r14))) = static_cast<triton::uint32>(value); break;
738 case triton::arch::ID_REG_ARM32_PC: {
739 /* NOTE: Once in Thumb mode only switch to ARM through a Branch
740 * and Exchange instruction. The reason for this is that after
741 * switching to Thumb the ISB (instruction set selection bit) is
742 * cleared. Therefore, if we allow to switch back to ARM through
743 * these mechanism we would have a problem processing Thumb
744 * instructions.
745 */
746 auto pc = static_cast<triton::uint32>(value);
747 if (this->isThumb() == false && (pc & 0x1) == 0x1) {
748 this->setThumb(true);
749 }
750 (*((triton::uint32*)(this->pc))) = pc & ~0x1;
751 break;
752 }
753 case triton::arch::ID_REG_ARM32_APSR: (*((triton::uint32*)(this->apsr))) = static_cast<triton::uint32>(value); break;
754 case triton::arch::ID_REG_ARM32_N: {
755 triton::uint32 b = (*((triton::uint32*)(this->apsr)));
756 (*((triton::uint32*)(this->apsr))) = !value.is_zero() ? b | (1 << 31) : b & ~(1 << 31);
757 break;
758 }
759 case triton::arch::ID_REG_ARM32_Z: {
760 triton::uint32 b = (*((triton::uint32*)(this->apsr)));
761 (*((triton::uint32*)(this->apsr))) = !value.is_zero() ? b | (1 << 30) : b & ~(1 << 30);
762 break;
763 }
764 case triton::arch::ID_REG_ARM32_C: {
765 triton::uint32 b = (*((triton::uint32*)(this->apsr)));
766 (*((triton::uint32*)(this->apsr))) = !value.is_zero() ? b | (1 << 29) : b & ~(1 << 29);
767 break;
768 }
769 case triton::arch::ID_REG_ARM32_V: {
770 triton::uint32 b = (*((triton::uint32*)(this->apsr)));
771 (*((triton::uint32*)(this->apsr))) = !value.is_zero() ? b | (1 << 28) : b & ~(1 << 28);
772 break;
773 }
774 default:
775 throw triton::exceptions::Cpu("Arm32Cpu:setConcreteRegisterValue(): Invalid register.");
776 }
777 }
778
779
780 bool Arm32Cpu::isThumb(void) const {
781 return this->thumb;
782 }
783
784
785 void Arm32Cpu::setThumb(bool state) {
786 this->thumb = state;
787 }
788
789
791 triton::uint64 base = mem.getAddress();
792
793 for (triton::usize index = 0; index < mem.getSize(); index++) {
794 if (this->exclusiveMemoryTags.find(base + index) != this->exclusiveMemoryTags.end()) {
795 return true;
796 }
797 }
798
799 return false;
800 }
801
802
804 triton::uint64 base = mem.getAddress();
805
806 for (triton::usize index = 0; index < mem.getSize(); index++) {
807 if (tag == true) {
808 this->exclusiveMemoryTags.insert(base + index);
809 }
810 else {
811 this->exclusiveMemoryTags.erase(base + index);
812 }
813 }
814 }
815
816
820
821
823 for (triton::usize index = 0; index < size; index++) {
824 if (this->memory.find(baseAddr + index) == this->memory.end())
825 return false;
826 }
827 return true;
828 }
829
830
834
835
837 for (triton::usize index = 0; index < size; index++) {
838 if (this->memory.find(baseAddr + index) != this->memory.end()) {
839 this->memory.erase(baseAddr + index);
840 }
841 }
842 }
843
844
845 triton::arch::arm::condition_e Arm32Cpu::invertCodeCondition(triton::arch::arm::condition_e cc) const {
847
848 switch (cc) {
851
854
857
860
863
866
869
872
875
878
881
884
887
890
893
896
897 default:
899 }
900
901 return inv;
902 }
903
904 }; /* arm32 namespace */
905 }; /* arm namespace */
906 }; /* arch namespace */
907}; /* triton namespace */
TRITON_EXPORT triton::uint512 getMaxValue(void) const
Returns the max possible value of the bitvector.
TRITON_EXPORT void setBits(triton::uint32 high, triton::uint32 low)
Sets the bits (high, low) position.
This class is used to represent an immediate.
Definition immediate.hpp:37
This class is used to represent an instruction.
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:803
TRITON_EXPORT std::set< const triton::arch::Register * > getParentRegisters(void) const
Returns all parent registers.
Definition arm32Cpu.cpp:189
triton::uint8 r2[triton::size::dword]
Concrete value of r2.
Definition arm32Cpu.hpp:121
TRITON_EXPORT const std::unordered_map< triton::uint64, triton::uint8, IdentityHash< triton::uint64 > > & getConcreteMemory(void) const
Return all memory.
Definition arm32Cpu.cpp:184
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:244
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:831
TRITON_EXPORT triton::uint512 getConcreteRegisterValue(const triton::arch::Register &reg, bool execCallbacks=true) const
Returns the concrete value of a register.
Definition arm32Cpu.cpp:635
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:817
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:678
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:780
TRITON_EXPORT const triton::arch::Register & getRegister(triton::arch::register_e id) const
Returns register from id.
Definition arm32Cpu.cpp:209
TRITON_EXPORT const triton::arch::Register & getProgramCounter(void) const
Returns the program counter register.
Definition arm32Cpu.cpp:239
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
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:249
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:625
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:604
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:715
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:229
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:790
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:785
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:699
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.
The exception class used by all CPUs.
The exception class used by the disassembler.
The exception class used by register operands.
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.
condition_e
Types of condition.
@ ID_SHIFT_LSR
Logical Shift Right (immediate)
@ ID_SHIFT_LSR_REG
Logical Shift Right (register)
@ ID_SHIFT_ASR
Arithmetic Shift Right (immediate)
@ ID_SHIFT_ROR_REG
Rotate Right (register)
@ ID_SHIFT_ROR
Rotate Right (immediate)
@ ID_SHIFT_ASR_REG
Arithmetic Shift Right (register)
@ ID_SHIFT_RRX
Rotate Right with Extend (immediate)
@ ID_SHIFT_RRX_REG
Rotate Right with Extend (register)
@ ID_SHIFT_LSL_REG
Logical Shift Left (register)
@ ID_SHIFT_INVALID
invalid
@ ID_SHIFT_LSL
Logical Shift Left (immediate)
@ ID_CONDITION_HS
Higher or same (unsigned >=). C set.
@ ID_CONDITION_PL
Positive or zero. N clear.
@ ID_CONDITION_VC
No overflow. V clear.
@ ID_CONDITION_LE
Signed <=. Z set, N and V differ.
@ ID_CONDITION_VS
Overflow. V set.
@ ID_CONDITION_MI
Negative. N set.
@ ID_CONDITION_GE
Signed >=. N and V the same.
@ ID_CONDITION_GT
Signed >. Z clear, N and V the same.
@ ID_CONDITION_HI
Higher (unsigned >). C set and Z clear.
@ ID_CONDITION_NE
Not equal. Z clear.
@ ID_CONDITION_AL
Always. Any flags. This suffix is normally omitted.
@ ID_CONDITION_LO
Lower (unsigned <). C clear.
@ ID_CONDITION_LT
Signed <. N and V differ.
@ ID_CONDITION_LS
Lower or same (unsigned <=). C clear or Z set.
@ ID_CONDITION_INVALID
invalid
@ ID_CONDITION_EQ
Equal. Z set.
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
std::size_t usize
unsigned MAX_INT 32 or 64 bits according to the CPU.
std::uint64_t uint64
unisgned 64-bits
math::wide_integer::uint512_t uint512
unsigned 512-bits
std::uint32_t uint32
unisgned 32-bits
std::uint8_t uint8
unisgned 8-bits
The Triton namespace.