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/exceptions.hpp>
11 #include <triton/immediate.hpp>
12 #include <triton/instruction.hpp>
13 
14 
15 
16 namespace triton {
17   namespace arch {
18 
Instruction()19     Instruction::Instruction() {
20       this->address         = 0;
21       this->branch          = false;
22       this->codeCondition   = triton::arch::arm::ID_CONDITION_INVALID;
23       this->conditionTaken  = 0;
24       this->controlFlow     = false;
25       this->prefix          = triton::arch::x86::ID_PREFIX_INVALID;
26       this->size            = 0;
27       this->tainted         = false;
28       this->thumb           = false;
29       this->tid             = 0;
30       this->type            = 0;
31       this->updateFlag      = false;
32       this->writeBack       = false;
33 
34       std::memset(this->opcode, 0x00, sizeof(this->opcode));
35     }
36 
37 
Instruction(const triton::uint8 * opcode,triton::uint32 opSize)38     Instruction::Instruction(const triton::uint8* opcode, triton::uint32 opSize) : Instruction::Instruction() {
39       this->setOpcode(opcode, opSize);
40     }
41 
42 
Instruction(triton::uint64 addr,const triton::uint8 * opcode,triton::uint32 opSize)43     Instruction::Instruction(triton::uint64 addr, const triton::uint8* opcode, triton::uint32 opSize) : Instruction::Instruction(opcode, opSize) {
44       this->setAddress(addr);
45     }
46 
47 
Instruction(const Instruction & other)48     Instruction::Instruction(const Instruction& other) {
49       this->copy(other);
50     }
51 
52 
~Instruction()53     Instruction::~Instruction() {
54       /* See #828: Release ownership before calling container destructor */
55       this->loadAccess.clear();
56       this->readImmediates.clear();
57       this->readRegisters.clear();
58       this->storeAccess.clear();
59       this->symbolicExpressions.clear();
60       this->writtenRegisters.clear();
61     }
62 
63 
operator =(const Instruction & other)64     Instruction& Instruction::operator=(const Instruction& other) {
65       this->copy(other);
66       return *this;
67     }
68 
69 
copy(const Instruction & other)70     void Instruction::copy(const Instruction& other) {
71       this->address             = other.address;
72       this->branch              = other.branch;
73       this->codeCondition       = other.codeCondition;
74       this->conditionTaken      = other.conditionTaken;
75       this->controlFlow         = other.controlFlow;
76       this->loadAccess          = other.loadAccess;
77       this->operands            = other.operands;
78       this->prefix              = other.prefix;
79       this->readImmediates      = other.readImmediates;
80       this->readRegisters       = other.readRegisters;
81       this->size                = other.size;
82       this->storeAccess         = other.storeAccess;
83       this->symbolicExpressions = other.symbolicExpressions;
84       this->tainted             = other.tainted;
85       this->tid                 = other.tid;
86       this->type                = other.type;
87       this->undefinedRegisters  = other.undefinedRegisters;
88       this->updateFlag          = other.updateFlag;
89       this->writeBack           = other.writeBack;
90       this->writtenRegisters    = other.writtenRegisters;
91 
92       std::memcpy(this->opcode, other.opcode, sizeof(this->opcode));
93 
94       this->disassembly.clear();
95       this->disassembly.str(other.disassembly.str());
96     }
97 
98 
getThreadId(void) const99     triton::uint32 Instruction::getThreadId(void) const {
100       return this->tid;
101     }
102 
103 
setThreadId(triton::uint32 tid)104     void Instruction::setThreadId(triton::uint32 tid) {
105       this->tid = tid;
106     }
107 
108 
getAddress(void) const109     triton::uint64 Instruction::getAddress(void) const {
110       return this->address;
111     }
112 
113 
getNextAddress(void) const114     triton::uint64 Instruction::getNextAddress(void) const {
115       return this->address + this->size;
116     }
117 
118 
setAddress(triton::uint64 addr)119     void Instruction::setAddress(triton::uint64 addr) {
120       this->address = addr;
121     }
122 
123 
getDisassembly(void) const124     std::string Instruction::getDisassembly(void) const {
125       return this->disassembly.str();
126     }
127 
128 
getOpcode(void) const129     const triton::uint8* Instruction::getOpcode(void) const {
130       return this->opcode;
131     }
132 
133 
setOpcode(const triton::uint8 * opcode,triton::uint32 size)134     void Instruction::setOpcode(const triton::uint8* opcode, triton::uint32 size) {
135       if (size >= sizeof(this->opcode))
136        throw triton::exceptions::Instruction("Instruction::setOpcode(): Invalid size (too big).");
137       std::memcpy(this->opcode, opcode, size);
138       this->size = size;
139     }
140 
141 
getSize(void) const142     triton::uint32 Instruction::getSize(void) const {
143       return this->size;
144     }
145 
146 
getType(void) const147     triton::uint32 Instruction::getType(void) const {
148       return this->type;
149     }
150 
151 
getPrefix(void) const152     triton::arch::x86::prefix_e Instruction::getPrefix(void) const {
153       return this->prefix;
154     }
155 
156 
getCodeCondition(void) const157     triton::arch::arm::condition_e Instruction::getCodeCondition(void) const {
158       return this->codeCondition;
159     }
160 
161 
getLoadAccess(void)162     std::set<std::pair<triton::arch::MemoryAccess, triton::ast::SharedAbstractNode>>& Instruction::getLoadAccess(void) {
163       return this->loadAccess;
164     }
165 
166 
getStoreAccess(void)167     std::set<std::pair<triton::arch::MemoryAccess, triton::ast::SharedAbstractNode>>& Instruction::getStoreAccess(void) {
168       return this->storeAccess;
169     }
170 
171 
getReadRegisters(void)172     std::set<std::pair<triton::arch::Register, triton::ast::SharedAbstractNode>>& Instruction::getReadRegisters(void) {
173       return this->readRegisters;
174     }
175 
176 
getWrittenRegisters(void)177     std::set<std::pair<triton::arch::Register, triton::ast::SharedAbstractNode>>& Instruction::getWrittenRegisters(void) {
178       return this->writtenRegisters;
179     }
180 
181 
getReadImmediates(void)182     std::set<std::pair<triton::arch::Immediate, triton::ast::SharedAbstractNode>>& Instruction::getReadImmediates(void) {
183       return this->readImmediates;
184     }
185 
186 
getUndefinedRegisters(void)187     std::set<triton::arch::Register>& Instruction::getUndefinedRegisters(void) {
188       return this->undefinedRegisters;
189     }
190 
191 
setLoadAccess(const triton::arch::MemoryAccess & mem,const triton::ast::SharedAbstractNode & node)192     void Instruction::setLoadAccess(const triton::arch::MemoryAccess& mem, const triton::ast::SharedAbstractNode& node) {
193       this->loadAccess.insert(std::make_pair(mem, node));
194     }
195 
196 
removeLoadAccess(const triton::arch::MemoryAccess & mem)197     void Instruction::removeLoadAccess(const triton::arch::MemoryAccess& mem) {
198       auto it = this->loadAccess.begin();
199 
200       while (it != this->loadAccess.end()) {
201         if (it->first.getAddress() == mem.getAddress())
202           it = this->loadAccess.erase(it);
203         else
204           ++it;
205       }
206     }
207 
208 
setStoreAccess(const triton::arch::MemoryAccess & mem,const triton::ast::SharedAbstractNode & node)209     void Instruction::setStoreAccess(const triton::arch::MemoryAccess& mem, const triton::ast::SharedAbstractNode& node) {
210       this->storeAccess.insert(std::make_pair(mem, node));
211     }
212 
213 
removeStoreAccess(const triton::arch::MemoryAccess & mem)214     void Instruction::removeStoreAccess(const triton::arch::MemoryAccess& mem) {
215       auto it = this->storeAccess.begin();
216 
217       while (it != this->storeAccess.end()) {
218         if (it->first.getAddress() == mem.getAddress())
219           it = this->storeAccess.erase(it);
220         else
221           ++it;
222       }
223     }
224 
225 
setReadRegister(const triton::arch::Register & reg,const triton::ast::SharedAbstractNode & node)226     void Instruction::setReadRegister(const triton::arch::Register& reg, const triton::ast::SharedAbstractNode& node) {
227       this->readRegisters.insert(std::make_pair(reg, node));
228     }
229 
230 
removeReadRegister(const triton::arch::Register & reg)231     void Instruction::removeReadRegister(const triton::arch::Register& reg) {
232       auto it = this->readRegisters.begin();
233 
234       while (it != this->readRegisters.end()) {
235         if (it->first.getId() == reg.getId())
236           it = this->readRegisters.erase(it);
237         else
238           ++it;
239       }
240     }
241 
242 
setWrittenRegister(const triton::arch::Register & reg,const triton::ast::SharedAbstractNode & node)243     void Instruction::setWrittenRegister(const triton::arch::Register& reg, const triton::ast::SharedAbstractNode& node) {
244       this->writtenRegisters.insert(std::make_pair(reg, node));
245     }
246 
247 
removeWrittenRegister(const triton::arch::Register & reg)248     void Instruction::removeWrittenRegister(const triton::arch::Register& reg) {
249       auto it = this->writtenRegisters.begin();
250 
251       while (it != this->writtenRegisters.end()) {
252         if (it->first.getId() == reg.getId())
253           it = this->writtenRegisters.erase(it);
254         else
255           ++it;
256       }
257     }
258 
259 
setReadImmediate(const triton::arch::Immediate & imm,const triton::ast::SharedAbstractNode & node)260     void Instruction::setReadImmediate(const triton::arch::Immediate& imm, const triton::ast::SharedAbstractNode& node) {
261       this->readImmediates.insert(std::make_pair(imm, node));
262     }
263 
264 
removeReadImmediate(const triton::arch::Immediate & imm)265     void Instruction::removeReadImmediate(const triton::arch::Immediate& imm) {
266       auto it = this->readImmediates.begin();
267 
268       while (it != this->readImmediates.end()) {
269         if (it->first.getValue() == imm.getValue())
270           it = this->readImmediates.erase(it);
271         else
272           ++it;
273       }
274     }
275 
276 
setUndefinedRegister(const triton::arch::Register & reg)277     void Instruction::setUndefinedRegister(const triton::arch::Register& reg) {
278       this->undefinedRegisters.insert(reg);
279     }
280 
281 
removeUndefinedRegister(const triton::arch::Register & reg)282     void Instruction::removeUndefinedRegister(const triton::arch::Register& reg) {
283       this->undefinedRegisters.erase(reg);
284     }
285 
286 
setSize(triton::uint32 size)287     void Instruction::setSize(triton::uint32 size) {
288       this->size = size;
289     }
290 
291 
setType(triton::uint32 type)292     void Instruction::setType(triton::uint32 type) {
293       this->type = type;
294     }
295 
296 
setPrefix(triton::arch::x86::prefix_e prefix)297     void Instruction::setPrefix(triton::arch::x86::prefix_e prefix) {
298       this->prefix = prefix;
299     }
300 
301 
setWriteBack(bool state)302     void Instruction::setWriteBack(bool state) {
303       this->writeBack = state;
304     }
305 
306 
setUpdateFlag(bool state)307     void Instruction::setUpdateFlag(bool state) {
308       this->updateFlag = state;
309     }
310 
311 
setCodeCondition(triton::arch::arm::condition_e codeCondition)312     void Instruction::setCodeCondition(triton::arch::arm::condition_e codeCondition) {
313       this->codeCondition = codeCondition;
314     }
315 
316 
setThumb(bool state)317     void Instruction::setThumb(bool state) {
318       this->thumb = state;
319     }
320 
321 
setDisassembly(const std::string & str)322     void Instruction::setDisassembly(const std::string& str) {
323       this->disassembly.clear();
324       this->disassembly.str(str);
325     }
326 
327 
setTaint(bool state)328     void Instruction::setTaint(bool state) {
329       this->tainted = state;
330     }
331 
332 
setTaint(void)333     void Instruction::setTaint(void) {
334       for (auto it = this->symbolicExpressions.begin(); it != this->symbolicExpressions.end(); it++) {
335         if ((*it)->isTainted == true) {
336           this->tainted = true;
337           break;
338         }
339       }
340     }
341 
342 
addSymbolicExpression(const triton::engines::symbolic::SharedSymbolicExpression & expr)343     const triton::engines::symbolic::SharedSymbolicExpression& Instruction::addSymbolicExpression(const triton::engines::symbolic::SharedSymbolicExpression& expr) {
344       if (expr == nullptr)
345         throw triton::exceptions::Instruction("Instruction::addSymbolicExpression(): Cannot add a null expression.");
346       this->symbolicExpressions.push_back(expr);
347       return this->symbolicExpressions.back();
348     }
349 
350 
isBranch(void) const351     bool Instruction::isBranch(void) const {
352       return this->branch;
353     }
354 
355 
isControlFlow(void) const356     bool Instruction::isControlFlow(void) const {
357       return this->controlFlow;
358     }
359 
360 
isConditionTaken(void) const361     bool Instruction::isConditionTaken(void) const {
362       return this->conditionTaken;
363     }
364 
365 
isTainted(void) const366     bool Instruction::isTainted(void) const {
367       return this->tainted;
368     }
369 
370 
isSymbolized(void) const371     bool Instruction::isSymbolized(void) const {
372       for (auto it = this->symbolicExpressions.begin(); it != this->symbolicExpressions.end(); it++) {
373         if ((*it)->isSymbolized() == true)
374           return true;
375       }
376       return false;
377     }
378 
379 
isMemoryRead(void) const380     bool Instruction::isMemoryRead(void) const {
381       if (this->loadAccess.size() >= 1)
382         return true;
383       return false;
384     }
385 
386 
isMemoryWrite(void) const387     bool Instruction::isMemoryWrite(void) const {
388       if (this->storeAccess.size() >= 1)
389         return true;
390       return false;
391     }
392 
393 
isReadFrom(const triton::arch::OperandWrapper & target) const394     bool Instruction::isReadFrom(const triton::arch::OperandWrapper& target) const {
395       switch(target.getType()) {
396 
397         case triton::arch::OP_IMM:
398           for (auto&& pair : this->readImmediates) {
399             if (pair.first == target.getConstImmediate())
400               return true;
401           }
402           break;
403 
404         case triton::arch::OP_MEM:
405           for (auto&& pair : this->loadAccess) {
406             const triton::arch::MemoryAccess& m1 = pair.first;
407             const triton::arch::MemoryAccess& m2 = target.getConstMemory();
408 
409             if (m1.isOverlapWith(m2))
410               return true;
411           }
412           break;
413 
414         case triton::arch::OP_REG:
415           for (auto&& pair : this->readRegisters) {
416             const triton::arch::Register& r1 = pair.first;
417             const triton::arch::Register& r2 = target.getConstRegister();
418 
419             if (r1.isOverlapWith(r2))
420               return true;
421           }
422           break;
423 
424         default:
425           throw triton::exceptions::Instruction("Instruction::isReadFrom(): Invalid type operand.");
426       }
427 
428       return false;
429     }
430 
431 
isWriteTo(const triton::arch::OperandWrapper & target) const432     bool Instruction::isWriteTo(const triton::arch::OperandWrapper& target) const {
433       switch(target.getType()) {
434 
435         case triton::arch::OP_IMM:
436           break;
437 
438         case triton::arch::OP_MEM:
439           for (auto&& pair : this->storeAccess) {
440             const triton::arch::MemoryAccess& m1 = pair.first;
441             const triton::arch::MemoryAccess& m2 = target.getConstMemory();
442 
443             if (m1.isOverlapWith(m2))
444               return true;
445           }
446           break;
447 
448         case triton::arch::OP_REG:
449           for (auto&& pair : this->writtenRegisters) {
450             const triton::arch::Register& r1 = pair.first;
451             const triton::arch::Register& r2 = target.getConstRegister();
452 
453             if (r1.isOverlapWith(r2))
454               return true;
455           }
456           break;
457 
458         default:
459           throw triton::exceptions::Instruction("Instruction::isWriteTo(): Invalid type operand.");
460       }
461 
462       return false;
463     }
464 
465 
isPrefixed(void) const466     bool Instruction::isPrefixed(void) const {
467       if (this->prefix == triton::arch::x86::ID_PREFIX_INVALID)
468         return false;
469       return true;
470     }
471 
472 
isWriteBack(void) const473     bool Instruction::isWriteBack(void) const {
474       return this->writeBack;
475     }
476 
477 
isUpdateFlag(void) const478     bool Instruction::isUpdateFlag(void) const {
479       return this->updateFlag;
480     }
481 
482 
isThumb(void) const483     bool Instruction::isThumb(void) const {
484       return this->thumb;
485     }
486 
487 
setBranch(bool flag)488     void Instruction::setBranch(bool flag) {
489       this->branch = flag;
490     }
491 
492 
setControlFlow(bool flag)493     void Instruction::setControlFlow(bool flag) {
494       this->controlFlow = flag;
495     }
496 
497 
setConditionTaken(bool flag)498     void Instruction::setConditionTaken(bool flag) {
499       this->conditionTaken = flag;
500     }
501 
502 
clear(void)503     void Instruction::clear(void) {
504       this->address         = 0;
505       this->branch          = false;
506       this->codeCondition   = triton::arch::arm::ID_CONDITION_INVALID;
507       this->conditionTaken  = 0;
508       this->controlFlow     = false;
509       this->prefix          = triton::arch::x86::ID_PREFIX_INVALID;
510       this->size            = 0;
511       this->tainted         = false;
512       this->tid             = 0;
513       this->type            = 0;
514       this->updateFlag      = false;
515       this->writeBack       = false;
516 
517       this->disassembly.clear();
518       this->loadAccess.clear();
519       this->operands.clear();
520       this->readImmediates.clear();
521       this->readRegisters.clear();
522       this->storeAccess.clear();
523       this->symbolicExpressions.clear();
524       this->writtenRegisters.clear();
525 
526       std::memset(this->opcode, 0x00, sizeof(this->opcode));
527     }
528 
529 
operator <<(std::ostream & stream,const Instruction & inst)530     std::ostream& operator<<(std::ostream& stream, const Instruction& inst) {
531       stream << "0x" << std::hex << inst.getAddress() << ": " << inst.getDisassembly() << std::dec;
532       return stream;
533     }
534 
535 
operator <<(std::ostream & stream,const Instruction * inst)536     std::ostream& operator<<(std::ostream& stream, const Instruction* inst) {
537       stream << *inst;
538       return stream;
539     }
540 
541   };
542 };
543