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