/* * SMPDataFlowAnalysis.cpp - <see below>. * * Copyright (c) 2000, 2001, 2010 - University of Virginia * * This file is part of the Memory Error Detection System (MEDS) infrastructure. * This file may be used and modified for non-commercial purposes as long as * all copyright, permission, and nonwarranty notices are preserved. * Redistribution is prohibited without prior written consent from the University * of Virginia. * * Please contact the authors for restrictions applying to commercial use. * * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Author: University of Virginia * e-mail: jwd@virginia.com * URL : http://www.cs.virginia.edu/ * * Additional copyrights 2010, 2011, 2012, 2013, 2014, 2015 by Zephyr Software LLC * e-mail: {clc,jwd}@zephyr-software.com * URL : http://www.zephyr-software.com/ * */ // // SMPDataFlowAnalysis.cpp // // This module contains common types an helper classes needed for the // SMP project (Software Memory Protection). // #include <list> #include <set> #include <vector> #include <algorithm> #include <string> #include <cstdlib> #include <cstring> #include <cassert> #include "interfaces/SMPDBInterface.h" #include "base/SMPDataFlowAnalysis.h" #include "base/SMPInstr.h" #include "base/SMPBasicBlock.h" #include "base/SMPFunction.h" using namespace std; // Set these to 1 for debugging output #define SMP_DEBUG_CONTROLFLOW 0 // tells what processing stage is entered #define SMP_DEBUG_CHUNKS 1 // tracking down tail chunks for functions #define SMP_DEBUG_FRAMEFIXUP 0 // Fixing up stack frame info the way we want the offsets #define SMP_DEBUG_OPERAND_TYPES 1 // leave on; warnings that should never happen #define STARS_DEBUG_DUMP_IDENTIFY_HIDDEN_OPERANDS 0 // print HIDDEN if operand.showed() is false #define MAX_IDA_REG STARS_x86_R_last // return true if Item is in IntList bool IsIntInList(const std::list<int> &IntList, int Item) { bool Found = false; for (list<int>::const_iterator ListIter = IntList.cbegin(); ListIter != IntList.cend(); ++ListIter) { if ((*ListIter) == Item) { Found = true; break; } } return Found; } // Bit masks for extracting bits from a STARSBitSet unsigned char. const uint8_t STARSBitMasks[8] = { 1, 2, 4, 8, 16, 32, 64, 128 }; const char *RegNames[MAX_IDA_REG + 1] = { "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH", "SPL", "BPL", "SIL", "DIL", "EIP", "ES", "CS", "SS", "DS", "FS", "GS", "CF", "ZF", "SF", "OF", "PF", "AF", "TF", "IF", "DF", "EFLAGS", "FPU_ST0", "FPU_ST1", "FPU_ST2", "FPU_ST3", "FPU_ST4", "FPU_ST5", "FPU_ST6", "FPU_ST7", "FPU_CTRL", "FPU_STAT", "FPU_TAGS", "MMX0", "MMX1", "MMX2", "MMX3", "MMX4", "MMX5", "MMX6", "MMX7", "XMM0", "XMM1", "XMM2", "XMM3", "XMM4", "XMM5", "XMM6", "XMM7", "XMM8", "XMM9", "XMM10", "XMM11", "XMM12", "XMM13", "XMM14", "XMM15", "MXCSR", "YMM0", "YMM1", "YMM2", "YMM3", "YMM4", "YMM5", "YMM6", "YMM7", "YMM8", "YMM9", "YMM10", "YMM11", "YMM12", "YMM13", "YMM14", "YMM15", "BND0", "BND1", "BND2", "BND3", "XMM16", "XMM17", "XMM18", "XMM19", "XMM20", "XMM21", "XMM22", "XMM23", "XMM24", "XMM25", "XMM26", "XMM27", "XMM28", "XMM29", "XMM30", "XMM31", "YMM16", "YMM17", "YMM18", "YMM19", "YMM20", "YMM21", "YMM22", "YMM23", "YMM24", "YMM25", "YMM26", "YMM27", "YMM28", "YMM29", "YMM30", "YMM31", "XMM0", "XMM1", "XMM2", "XMM3", "XMM4", "XMM5", "XMM6", "XMM7", "XMM8", "XMM9", "XMM10", "XMM11", "XMM12", "XMM13", "XMM14", "XMM15", "ZMM16", "ZMM17", "ZMM18", "ZMM19", "ZMM20", "ZMM21", "ZMM22", "ZMM23", "ZMM24", "ZMM25", "ZMM26", "ZMM27", "ZMM28", "ZMM29", "ZMM30", "ZMM31", "K0", "K1", "K2", "K3", "K4", "K5", "K6", "K7", "REG_ERROR" }; // NOTE: Review these sizes. Alter when annotation diffs can be isolated to the change. // !!!!****!!!! FP reg stack should be 10-byte registers, right? const unsigned char RegSizes[MAX_IDA_REG + 1] = { 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 10, 10, 10, 10, 10, 10, 10, 10, 4, 4, 4, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 4 }; unsigned char GetRegSize(STARS_regnum_t RegNum) { assert(RegNum != ((STARS_regnum_t) STARS_x86_R_none)); return RegSizes[RegNum]; } const char RegDtyps[MAX_IDA_REG + 1] = { STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_qword, STARS_dt_qword, STARS_dt_qword, STARS_dt_qword, STARS_dt_qword, STARS_dt_qword, STARS_dt_qword, STARS_dt_qword, STARS_dt_byte, STARS_dt_byte, STARS_dt_byte, STARS_dt_byte, STARS_dt_byte, STARS_dt_byte, STARS_dt_byte, STARS_dt_byte, STARS_dt_byte, STARS_dt_byte, STARS_dt_byte, STARS_dt_byte, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_tbyte, STARS_dt_tbyte, STARS_dt_tbyte, STARS_dt_tbyte, STARS_dt_tbyte, STARS_dt_tbyte, STARS_dt_tbyte, STARS_dt_tbyte, STARS_dt_word, STARS_dt_word, STARS_dt_word, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_word, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_word }; const char *ErrorStrings[1] = { "ERROR_REG" }; const char *WordRegStrings[8] = { "AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI" }; const char *QWordRegStrings[8] = { "RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI" }; const char *QDWordRegStrings[8] = { "R8D", "R9D", "R10D", "R11D", "R12D", "R13D", "R14D", "R15D" }; const char *QWWordRegStrings[8] = { "R8W", "R9W", "R10W", "R11W", "R12W", "R13W", "R14W", "R15W" }; const char *QByteRegStrings[8] = { "R8L", "R9L", "R10L", "R11L", "R12L", "R13L", "R14L", "R15L" }; const char *SignednessStrings[4] = { "UNKNOWNSIGN", "SIGNED", "UNSIGNED", "UNKNOWNSIGN" }; const char *LeaSignednessStrings[4] = { "NOFLAGUNKNOWNSIGN", "NOFLAGSIGNED", "NOFLAGUNSIGNED", "NOFLAGUNKNOWNSIGN" }; const char *SPARKFloatingPointStackRegNames[8] = { "FloatingPointStackDummy", "FloatingPointStackDummy1", "FloatingPointStackDummy1", "FloatingPointStackDummy1", "FloatingPointStackDummy1", "FloatingPointStackDummy1", "FloatingPointStackDummy1", "FloatingPointStackDummy1" }; const char *CFTTypeStrings[20] = { "FALL_THROUGH", "BRANCH_IF_THEN", "BRANCH_IF_THEN_ELSE", "JUMP_BEFORE_ELSE", "LOOP_BACK", "LOOP_EXIT", "LOOP_CONTINUE", "JUMP_INTO_LOOP_TEST", "JUMP_TO_DEFAULT_CASE", "CASE_BREAK_TO_FOLLOW_NODE", "JUMP_TO_SWITCH_INDIR_JUMP", "SHORT_CIRCUIT_BRANCH", "SHORT_CIRCUIT_LOOP_EXIT", "INVERTED_LOOP_EXIT", "INVERTED_LOOP_BACK", "SHORT_CIRCUIT_INVERTED_LOOP_EXIT", "", "", "", "" }; // Distinguishes subword regs from their parent regs const char *MDGetRegNumName(STARS_regnum_t RegNum, uint16_t ByteWidth) { if ((STARS_x86_R_none == RegNum) || (MAX_IDA_REG < RegNum)) return ErrorStrings[0]; else if ((ByteWidth == 2) && (RegNum >= STARS_x86_R_ax) && (RegNum <= STARS_x86_R_di)) { // 16-bit registers return WordRegStrings[RegNum]; } else if ((ByteWidth == 8) && (RegNum >= STARS_x86_R_ax) && (RegNum <= STARS_x86_R_di)) { // 64-bit registers return QWordRegStrings[RegNum]; } else if ((ByteWidth < 8) && (RegNum >= STARS_x86_R_r8) && (RegNum <= STARS_x86_R_r15)) { if (ByteWidth == 4) return QDWordRegStrings[RegNum - STARS_x86_R_r8]; else if (ByteWidth == 2) return QWWordRegStrings[RegNum - STARS_x86_R_r8]; else if (ByteWidth == 1) return QByteRegStrings[RegNum - STARS_x86_R_r8]; else return ErrorStrings[0]; } else { return RegNames[RegNum]; } } // end of MDGetRegNumName() // Distinguishes subword regs from their parent regs, uses SPARK dummy names for FP stack. const char *MDGetSPARKRegNumName(STARS_regnum_t RegNum, uint16_t ByteWidth) { if ((RegNum >= STARS_x86_R_st0) && (RegNum <= STARS_x86_R_st7)) return SPARKFloatingPointStackRegNames[RegNum - STARS_x86_R_st0]; else return MDGetRegNumName(RegNum, ByteWidth); } // Distinguishes subword regs from their parent regs const char *MDGetRegName(const STARSOpndTypePtr &RegOp) { if (!(RegOp->IsRegOp() || RegOp->IsFloatingPointRegOp())) return ErrorStrings[0]; STARS_regnum_t RegNum = RegOp->GetReg(); uint16_t ByteWidth = RegOp->GetByteWidth(); return MDGetRegNumName(RegNum, ByteWidth); } // Define instruction categories for data flow analysis. vector<SMPitype> DFACategory; // Define instruction categories for data type analysis. int SMPTypeCategory[STARS_NN_last+1]; // Define which instructions define and use the CPU flags. bool SMPDefsFlags[STARS_NN_last + 1]; bool SMPUsesFlags[STARS_NN_last + 1]; // print to log file using SMP_msg() void DumpDataFlowType(const SMPitype FlowType) { switch (FlowType) { case DEFAULT: SMP_msg("DEFAULT\n"); break; case LABEL: SMP_msg("LABEL\n"); break; case CASE: SMP_msg("CASE\n"); break; case JUMP: SMP_msg("JUMP\n"); break; case COND_BRANCH: SMP_msg("COND_BRANCH\n"); break; case INDIR_JUMP: SMP_msg("INDIR_JUMP\n"); break; case CALL: SMP_msg("CALL\n"); break; case INDIR_CALL: SMP_msg("INDIR_CALL\n"); break; case RETURN: SMP_msg("RETURN\n"); break; case HALT: SMP_msg("HALT\n"); break; default: SMP_msg("ERROR\n"); break; } return; } // end of DumpDataFlowType() // Hash a global name and SSA number into an int, for use in SMPFunction.GlobalDefAddrBySSA map int HashGlobalNameAndSSA(const STARSOpndTypePtr &DefOp, int SSANum) { int HashValue = 0; if (DefOp->IsRegOp()) { HashValue = ((SSANum << 16) | ((int)(DefOp->GetReg()))); } return HashValue; } // Hash a global name and SSA number into an int, for use in SMPFunction.GlobalDefAddrBySSA map int64_t HashGlobalStackNameAndSSA(const STARSOpndTypePtr &DefOp, int SSANum, bool UseFP) { int64_t HashValue = 0; assert(MDIsDirectStackAccessOpnd(DefOp, UseFP)); HashValue = ((((int64_t) SSANum) << 32) | (((uint64_t)(DefOp->GetAddr())) & 0xffffffff)); return HashValue; } // Get the size in bytes of the data type of an operand. size_t GetOpDataSize(const STARSOpndTypePtr &DataOp) { size_t DataSize; char OpDtyp = DataOp->GetOpDtyp(); if (DataOp->IsRegOp()) { DataSize = RegSizes[DataOp->GetReg()]; if (OpDtyp == STARS_dt_word) { DataSize = 2; #if 0 SMP_msg("Found 16-bit register using dtyp field.\n"); #endif } else if (OpDtyp == STARS_dt_qword) { DataSize = 8; #if 0 SMP_msg("Found 64-bit register using dtyp field.\n"); #endif } return DataSize; } switch (OpDtyp) { case STARS_dt_byte: DataSize = 1; break; case STARS_dt_word: DataSize = 2; break; case STARS_dt_dword: case STARS_dt_float: case STARS_dt_code: case STARS_dt_unicode: case STARS_dt_string: DataSize = 4; break; case STARS_dt_double: case STARS_dt_qword: DataSize = 8; break; case STARS_dt_tbyte: DataSize = 10; break; case STARS_dt_packreal: DataSize = 12; break; case STARS_dt_byte16: case STARS_dt_ldbl: DataSize = 16; break; case STARS_dt_fword: DataSize = 6; break; #if (IDA_SDK_VERSION < 700) case STARS_dt_3byte: DataSize = 3; break; #endif case STARS_dt_byte32: DataSize = 32; break; case STARS_dt_byte64: DataSize = 64; break; #if (IDA_SDK_VERSION >= 700) case STARS_dt_half: // 2-byte floating point DataSize = 16; break; #endif default: SMP_msg("ERROR: unexpected data type %d in GetOpDataSize() :", OpDtyp); PrintOperand(DataOp); SMP_msg("\n"); DataSize = global_STARS_program->GetSTARS_ISA_dtyp(); break; } return DataSize; } // end of GetOpDataSize() // Get the IDA Pro register size (dtyp) field char GetRegDtyp(STARS_regnum_t RegNum, bool Has64BitOpnds) { assert(RegNum != ((STARS_regnum_t) STARS_x86_R_none)); assert(RegNum < MAX_IDA_REG); char RegDtyp = RegDtyps[RegNum]; if ((global_STARS_program->GetSTARS_ISA_Bytewidth() == 8) && Has64BitOpnds && (RegDtyp == STARS_dt_dword) && (RegNum <= STARS_x86_R_ip)) { // 32-bit IDA general regs are 64-bit for x86-64 RegDtyp = STARS_dt_qword; } return RegDtyp; } // Return one of the bit width masks for the current operand. // Pass in DataSize in bytes if known, else pass in DataSize = 0. unsigned short ComputeOperandBitWidthMask(const STARSOpndTypePtr &CurrOp, size_t DataSize) { unsigned short BitWidthMask = 32; if (0 == DataSize) DataSize = CurrOp->GetByteWidth(); if (4 == DataSize) BitWidthMask = FG_MASK_BITWIDTH_32; else if (8 == DataSize) BitWidthMask = FG_MASK_BITWIDTH_64; else if (1 == DataSize) BitWidthMask = FG_MASK_BITWIDTH_8; else if (2 == DataSize) BitWidthMask = FG_MASK_BITWIDTH_16; else if (16 == DataSize) BitWidthMask = FG_MASK_BITWIDTH_128; else if (3 == DataSize) BitWidthMask = FG_MASK_BITWIDTH_24; else if (6 == DataSize) BitWidthMask = FG_MASK_BITWIDTH_48; else if (10 == DataSize) BitWidthMask = FG_MASK_BITWIDTH_80; else if (12 == DataSize) BitWidthMask = FG_MASK_BITWIDTH_96; else if (32 == DataSize) BitWidthMask = FG_MASK_BITWIDTH_256; else { SMP_msg("ERROR: Unknown DataSize: %zu bytes ", DataSize); PrintOperand(CurrOp); SMP_msg("\n"); } return BitWidthMask; } // end of ComputeOperandBitWidthMask() // Compute largest bit width from a SignMiscInfo bit mask. size_t LargestBitWidthFromMask(unsigned short WidthTypeInfo) { unsigned short BitWidthMask = WidthTypeInfo & FG_MASK_BITWIDTH_FIELDS; size_t LargestWidth = 0; // Go from highest bit width to lowest. if (BitWidthMask & FG_MASK_BITWIDTH_256) LargestWidth = 256; else if (BitWidthMask & FG_MASK_BITWIDTH_128) LargestWidth = 128; else if (BitWidthMask & FG_MASK_BITWIDTH_96) LargestWidth = 96; else if (BitWidthMask & FG_MASK_BITWIDTH_64) LargestWidth = 64; else if (BitWidthMask & FG_MASK_BITWIDTH_48) LargestWidth = 48; else if (BitWidthMask & FG_MASK_BITWIDTH_32) LargestWidth = 32; else if (BitWidthMask & FG_MASK_BITWIDTH_24) LargestWidth = 24; else if (BitWidthMask & FG_MASK_BITWIDTH_16) LargestWidth = 16; else if (BitWidthMask & FG_MASK_BITWIDTH_8) LargestWidth = 8; return LargestWidth; } // end of LargestBitWidthFromMask() // Is CurrOp a general purpose register? (not flags, instruction pointer, non-integer reg, etc.) bool MDIsGeneralPurposeReg(const STARSOpndTypePtr &CurrOp) { bool success = (nullptr != CurrOp); if (success) { // intel.hpp defines two ranges that are general purpose regs in enum RegNo. STARS_regnum_t CurrReg = CurrOp->GetReg(); success = (CurrOp->IsRegOp() && ((CurrReg >= STARS_x86_R_ax) && (CurrReg <= STARS_x86_R_dil))); } return success; } // Are operands equal? bool IsEqOp(const STARSOpndTypePtr &Opnd1, const STARSOpndTypePtr &Opnd2) { if ((nullptr == Opnd1) && (nullptr == Opnd2)) return true; if ((nullptr == Opnd1) || (nullptr == Opnd2)) return false; // this expression is logically equiv. to "equal" // // truth table: // // O1 O2 O1<O2 !(O1<O2) O2<O1 !(O2<O1) !(O1<O2)&&!(O2<O1) == // 0 0 0 1 0 1 1 1 // 0 1 1 0 0 0 0 0 // 1 0 0 1 1 0 0 0 // 1 1 0 1 0 0 1 1 return !(*Opnd1 < *Opnd2) && !(*Opnd2 < *Opnd1); } // end of function IsEqOp() // Are operands equal, ignoring bitwidth differences for register operands? bool IsEqOpIgnoreBitwidth(const STARSOpndTypePtr &Opnd1, const STARSOpndTypePtr &Opnd2) { if (Opnd1->GetOpType() != Opnd2->GetOpType()) return false; if (Opnd1->IsRegOp()) return (MDCanonicalizeSubReg(Opnd1->GetReg()) == MDCanonicalizeSubReg(Opnd2->GetReg())); // no concern for subword regs; AX == EAX == RAX else return IsEqOp(Opnd1, Opnd2); } // end of function IsEqOpIgnoreBitwidth() // Are operands equal, ignoring value differences for immediate operands? bool IsEqOpIgnoreImmedValues(const STARSOpndTypePtr &Opnd1, const STARSOpndTypePtr &Opnd2) { if (nullptr == Opnd1) return (nullptr == Opnd2); if (nullptr == Opnd2) return (nullptr == Opnd1); if (Opnd1->GetOpType() != Opnd2->GetOpType()) return false; if (Opnd1->IsImmedOp()) return true; else return IsEqOp(Opnd1, Opnd2); } // end of function IsEqOpIgnoreImmedValues() // We need to make subword registers equal to their containing registers when we // do comparisons, so that we will realize that register EAX is killed by a prior DEF // of register AL, for example, and vice versa. To keep sets ordered strictly, // we also have to make AL and AH be equal to each other as well as equal to EAX. bool MDLessReg(const STARS_regnum_t Reg1, const STARS_regnum_t Reg2) { STARS_regnum_t SReg1 = MDCanonicalizeSubReg(Reg1); STARS_regnum_t SReg2 = MDCanonicalizeSubReg(Reg2); return (SReg1 < SReg2); } // end of MDLessReg() bool MDEqReg(const STARS_regnum_t Reg1, const STARS_regnum_t Reg2) { STARS_regnum_t SReg1 = MDCanonicalizeSubReg(Reg1); STARS_regnum_t SReg2 = MDCanonicalizeSubReg(Reg2); return (SReg1 == SReg2); } // end of MDEqReg() bool MDLessRegOpnd(const STARSOpndTypePtr &RegOp1, const STARSOpndTypePtr &RegOp2) { STARS_regnum_t SReg1 = MDCanonicalizeSubReg(RegOp1->GetReg()); STARS_regnum_t SReg2 = MDCanonicalizeSubReg(RegOp2->GetReg()); return ((SReg1 < SReg2) || ((SReg1 == SReg2) && (RegOp1->GetByteWidth() < RegOp2->GetByteWidth()))); } // end of MDLessRegOpnd() STARS_regnum_t MDCanonicalizeSubReg(const STARS_regnum_t Reg1) { bool Subword = ((Reg1 >= FIRST_X86_SUBWORD_REG) && (Reg1 <= LAST_X86_SUBWORD_REG)); STARS_regnum_t SReg1 = Reg1; if (Subword) { // See enumeration RegNo in intel.hpp. switch (SReg1) { case STARS_x86_R_al: case STARS_x86_R_ah: SReg1 = STARS_x86_R_ax; break; case STARS_x86_R_cl: case STARS_x86_R_ch: SReg1 = STARS_x86_R_cx; break; case STARS_x86_R_dl: case STARS_x86_R_dh: SReg1 = STARS_x86_R_dx; break; case STARS_x86_R_bl: case STARS_x86_R_bh: SReg1 = STARS_x86_R_bx; break; case STARS_x86_R_spl: SReg1 = STARS_x86_R_sp; break; case STARS_x86_R_bpl: SReg1 = STARS_x86_R_bp; break; case STARS_x86_R_sil: SReg1 = STARS_x86_R_si; break; case STARS_x86_R_dil: SReg1 = STARS_x86_R_di; break; default: assert(false); } // end switch (SReg1) } return SReg1; } // end of MDCanonicalizeSubReg() #if 0 // If TempOp is a register, call MDCanonicalizeSubReg() on it. void CanonicalizeOpnd(STARSOpndTypePtr &TempOp) { if (TempOp->IsRegOp()) { STARS_regnum_t NewReg = MDCanonicalizeSubReg(TempOp->GetReg()); if (TempOp->GetReg() != NewReg) { TempOp->SetReg(NewReg); } } } #else // If TempOp is a register, call MDCanonicalizeSubReg() on it. void CanonicalizeOpnd(STARSOpndTypePtr &TempOp) { if ((nullptr != TempOp) && TempOp->IsRegOp()) { #if 0 if (4 > TempOp->GetByteWidth()) { TempOp->SetReg(MDCanonicalizeSubReg(TempOp->GetReg())); } #else STARS_regnum_t Reg1 = TempOp->GetReg(); bool Subword = ((Reg1 >= FIRST_X86_SUBWORD_REG) && (Reg1 <= LAST_X86_SUBWORD_REG)); if (Subword) { TempOp->SetReg(MDCanonicalizeSubReg(TempOp->GetReg())); } #endif // Convert 32-bit regs to 64-bit on 64-bit binaries. uint16_t CanonicalByteWidth = global_STARS_program->GetSTARS_ISA_Bytewidth(); if (TempOp->GetByteWidth() < CanonicalByteWidth) { TempOp->SetByteWidth(CanonicalByteWidth); } } } #endif bool MDIsStackOrFramePointerReg(const STARSOpndTypePtr &RegOp, bool UseFP) { bool PtrReg = false; if ((nullptr != RegOp) && RegOp->IsRegOp()) { PtrReg = RegOp->MatchesReg(MD_STACK_POINTER_REG) || (UseFP && RegOp->MatchesReg(MD_FRAME_POINTER_REG)); } return PtrReg; } // In SSA computations, we are storing the GlobalNames index into the op_t fields // n, offb, and offo. This function extracts an unsigned int from these three 8-bit // fields. unsigned int ExtractGlobalIndex(const STARSOpndTypePtr &GlobalOp) { return GlobalOp->GetOpGlobalIndex(); } void SetGlobalIndex(STARSOpndTypePtr TempOp, size_t index) { TempOp->SetOpGlobalIndex(index); return; } int MD_STARS_sib_base(const STARSOpndTypePtr &x) { // get extended sib base return x->MDGetSIBBaseReg(); } short MD_STARS_sib_index(const STARSOpndTypePtr &x) { // get extended sib index return x->MDGetSIBIndexReg(); } // Return true if CurrOp could be an indirect memory reference. bool MDIsIndirectMemoryOpnd(const STARSOpndTypePtr &CurrOp, bool UseFP) { bool indirect = false; if ((nullptr == CurrOp) || (! CurrOp->IsMemOp())) return false; if (CurrOp->HasSIBByte()) { STARS_RegNo BaseReg = (STARS_RegNo) MD_STARS_sib_base(CurrOp); STARS_RegNo IndexReg = (STARS_RegNo) MD_STARS_sib_index(CurrOp); if ((STARS_x86_R_none != IndexReg) && (MD_STACK_POINTER_REG != IndexReg)) { if ((MD_FRAME_POINTER_REG == IndexReg) && UseFP && (!CurrOp->IsStaticMemOp())) ; else indirect = true; } if (0 != CurrOp->GetSIBScaleFactor()) indirect = true; if (!indirect && (STARS_x86_R_none != BaseReg)) { if ((BaseReg == MD_FRAME_POINTER_REG) && CurrOp->IsStaticMemOp()) { ; // EBP ==> no base register for o_mem type } else if ((BaseReg == MD_FRAME_POINTER_REG) && UseFP) ; // EBP used as frame pointer for direct access else if (BaseReg == MD_STACK_POINTER_REG) ; // ESP used as stack pointer for direct access else indirect = true; // conservative; some register used for addressing // other than a stack or frame pointer } } // end if hasSIB else { // no SIB; can have base register only STARS_RegNo BaseReg = (STARS_RegNo) CurrOp->GetReg(); if (CurrOp->IsStaticMemOp()) { // no base register for o_mem #if 1 if (!((0 == BaseReg) || (MD_FRAME_POINTER_REG == BaseReg))) { SMP_msg("ERROR: o_mem base reg %d ignored \n", BaseReg); } #endif } else if ((BaseReg == MD_FRAME_POINTER_REG) && UseFP) ; // EBP used as frame pointer for direct access else if (BaseReg == MD_STACK_POINTER_REG) ; // ESP used as stack pointer for direct access else { indirect = true; } } return indirect; } // end MDIsIndirectMemoryOpnd() // Extract the base and index registers and scale factor and displacement from the // memory operand. void MDExtractAddressFields(const STARSOpndTypePtr &MemOp, int &BaseReg, int &IndexReg, uint16_t &Scale, STARS_ea_t &Offset) { assert(MemOp->IsMemOp()); Scale = 0; BaseReg = STARS_x86_R_none; IndexReg = STARS_x86_R_none; Offset = MemOp->GetAddr(); if (MemOp->HasSIBByte()) { BaseReg = MD_STARS_sib_base(MemOp); IndexReg = (int) MD_STARS_sib_index(MemOp); if (MD_STACK_POINTER_REG == IndexReg) // signifies no index register IndexReg = STARS_x86_R_none; if (STARS_x86_R_none != IndexReg) { Scale = (uint16_t) MemOp->GetSIBScaleFactor(); } if (STARS_x86_R_none != BaseReg) { if (MemOp->IsStaticMemOp()) { BaseReg = STARS_x86_R_none; // Only IndexReg is allowed for o_mem with SIB byte } } } else { // no SIB byte; can have base reg but no index reg or scale factor BaseReg = (int) MemOp->GetReg(); // cannot be STARS_x86_R_none for no SIB case if (MemOp->IsStaticMemOp()) { BaseReg = STARS_x86_R_none; // no Base register for o_mem operands } } return; } // end of MDExtractAddressFields() // MACHINE DEPENDENT: Does MemOp have both a base reg and an index reg, or a scaled index reg? bool MDIsIndexedMemoryAccess(const STARSOpndTypePtr &MemOp) { bool EIPRelativeAccess = (MemOp->HasSegReg() && (STARS_x86_R_cs == MemOp->GetSegReg())); if (!EIPRelativeAccess) { EIPRelativeAccess = (MemOp->GetReg() == STARS_x86_R_ip); } if (EIPRelativeAccess) return true; int BaseReg, IndexReg; uint16_t Scale; STARS_ea_t Offset; MDExtractAddressFields(MemOp, BaseReg, IndexReg, Scale, Offset); return ((Scale != 0) || ((BaseReg != STARS_x86_R_none) && (IndexReg != STARS_x86_R_none))); } // Is CurrOp a memory operand? bool IsMemOperand(const STARSOpndTypePtr &CurrOp) { return ((nullptr != CurrOp) && CurrOp->IsMemOp()); } // MACHINE DEPENDENT: Is CurrOp the flags register? bool MDIsFlagsReg(const STARSOpndTypePtr &CurrOp) { return ((nullptr != CurrOp) && CurrOp->MatchesReg(X86_FLAGS_REG)); } // MACHINE DEPENDENT: Is register a stack pointer or frame pointer? bool MDIsStackPtrReg(int RegNumber, bool UseFP) { return ((RegNumber == MD_STACK_POINTER_REG) || (UseFP && (RegNumber == MD_FRAME_POINTER_REG))); } // MACHINE DEPENDENT: Is operand a stack memory access? bool MDIsStackAccessOpnd(const STARSOpndTypePtr &CurrOp, bool UseFP) { int BaseReg; int IndexReg; uint16_t ScaleFactor; STARS_ea_t offset; if ((nullptr == CurrOp) || ((!CurrOp->IsMemDisplacementOp()) && (!CurrOp->IsMemNoDisplacementOp()))) { return false; } MDExtractAddressFields(CurrOp, BaseReg, IndexReg, ScaleFactor, offset); return MDIsStackPtrReg(BaseReg, UseFP); } // end of MDIsStackAccessOpnd() // MACHINE DEPENDENT: Is operand a direct stack memory access? bool MDIsDirectStackAccessOpnd(const STARSOpndTypePtr &CurrOp, bool UseFP) { int BaseReg; int IndexReg; uint16_t ScaleFactor; STARS_ea_t offset; if ((nullptr == CurrOp) || ((! CurrOp->IsMemDisplacementOp()) && (! CurrOp->IsMemNoDisplacementOp()))) { return false; } MDExtractAddressFields(CurrOp, BaseReg, IndexReg, ScaleFactor, offset); // When the IndexReg is R_none, access is direct. return (MDIsStackPtrReg(BaseReg, UseFP) && (IndexReg == STARS_x86_R_none)); } // end of MDIsDirectStackAccessOpnd() // MACHINE DEPENDENT: Is operand trackable in data flow analyses (i.e. a direct stack memory access or a register?) bool MDIsDataFlowOpnd(const STARSOpndTypePtr &CurrOp, bool UseFP) { return ((nullptr != CurrOp) && ((CurrOp->IsRegOp() && ((STARS_x86_R_ip > CurrOp->GetReg()) || (STARS_x86_R_gs < CurrOp->GetReg()))) || MDIsDirectStackAccessOpnd(CurrOp, UseFP))); } // MACHINE DEPENDENT: Is operand a caller-saved register? bool MDIsCallerSavedReg(const STARSOpndTypePtr &CurrOp) { if (! CurrOp->IsRegOp()) return false; STARS_regnum_t CurrReg = MDCanonicalizeSubReg(CurrOp->GetReg()); return ((STARS_x86_R_ax == CurrReg) || (STARS_x86_R_cx == CurrReg) || (STARS_x86_R_dx == CurrReg)); } // end of MDIsCallerSavedReg() // If CurrOp would change when reg is canonicalized, then return CurrOp->clone(), else return CurrOp; STARSOpndTypePtr CloneIfSubwordReg(const STARSOpndTypePtr &CurrOp) { if ((nullptr != CurrOp) && CurrOp->IsRegOp()) { if (global_STARS_program->GetSTARS_ISA_Bytewidth() > CurrOp->GetByteWidth()) { return CurrOp->clone(); } else { return CurrOp; } } else { return CurrOp; } } // end of CloneIfSubwordReg() // If CurrOp would change when Canonicalized or stack-normalized, then return CurrOp->clone(), else return CurrOp; STARSOpndTypePtr CloneIfNecessary(const STARSOpndTypePtr &CurrOp, bool UseFP) { if (MDIsStackAccessOpnd(CurrOp, UseFP)) { return CurrOp->clone(); } else { return CloneIfSubwordReg(CurrOp); } } // end of CloneIfNecessary() // DEBUG Print DEF and/or USE for an operand. void PrintDefUse(unsigned long feature, int OpNum) { // CF_ macros number the operands from 1 to 6, while OpNum // is a 0 to 5 index into the insn_t.Operands[] array. // OpNum == -1 is a signal that this is a DEF or USE or VarKillSet etc. // operand and not an instruction operand. if (-1 == OpNum) return; switch (OpNum) { case 0: if (feature & STARS_CF_CHG1) SMP_msg(" DEF"); if (feature & STARS_CF_USE1) SMP_msg(" USE"); break; case 1: if (feature & STARS_CF_CHG2) SMP_msg(" DEF"); if (feature & STARS_CF_USE2) SMP_msg(" USE"); break; case 2: if (feature & STARS_CF_CHG3) SMP_msg(" DEF"); if (feature & STARS_CF_USE3) SMP_msg(" USE"); break; case 3: if (feature & STARS_CF_CHG4) SMP_msg(" DEF"); if (feature & STARS_CF_USE4) SMP_msg(" USE"); break; case 4: if (feature & STARS_CF_CHG5) SMP_msg(" DEF"); if (feature & STARS_CF_USE5) SMP_msg(" USE"); break; case 5: if (feature & STARS_CF_CHG6) SMP_msg(" DEF"); if (feature & STARS_CF_USE6) SMP_msg(" USE"); break; } return; } // end PrintDefUse() // DEBUG print SIB info for an operand. void PrintSIB(const STARSOpndTypePtr &Opnd) { int BaseReg; int IndexReg; uint16_t ScaleFactor; STARS_ea_t offset; #define NAME_LEN 5 char BaseName[NAME_LEN] = {'N', 'o', 'n', 'e', '\0'}; char IndexName[NAME_LEN] = {'N', 'o', 'n', 'e', '\0'}; MDExtractAddressFields(Opnd, BaseReg, IndexReg, ScaleFactor, offset); if (BaseReg != STARS_x86_R_none) SMP_strncpy(BaseName, RegNames[BaseReg], NAME_LEN - 1); if (IndexReg != STARS_x86_R_none) { SMP_strncpy(IndexName, RegNames[IndexReg], NAME_LEN -1); } SMP_msg(" Base %s Index %s Scale %d Flag4 %d", BaseName, IndexName, ScaleFactor, Opnd->GetSpecFlag4()); } // end PrintSIB() // Annotations: concisely print SIB info for an operand. void AnnotPrintSIB(const STARSOpndTypePtr &Opnd, bool HasOffset, FILE *OutFile, char OutString[STARS_MAXSTR], bool Has64BitAddressing) { int BaseReg; int IndexReg; uint16_t ScaleFactor; uint16_t ByteWidth = Opnd->GetByteWidth(); STARS_ea_t offset; char ScaleString[4]; if (Has64BitAddressing) ByteWidth = 8; SMP_strncat(OutString, "[", STARS_MAXSTR - 1); MDExtractAddressFields(Opnd, BaseReg, IndexReg, ScaleFactor, offset); if (ScaleFactor > 0) { ScaleFactor = 1 << ScaleFactor; (void) SMP_snprintf(ScaleString, 4, "%d", ScaleFactor); } if (BaseReg != STARS_x86_R_none) { (void) SMP_strncat(OutString, MDGetRegNumName((STARS_regnum_t) BaseReg, ByteWidth), STARS_MAXSTR - 1); if (IndexReg != STARS_x86_R_none) { (void) SMP_strncat(OutString, "+", STARS_MAXSTR - 1); (void) SMP_strncat(OutString, MDGetRegNumName((STARS_regnum_t) IndexReg, ByteWidth), STARS_MAXSTR - 1); if (ScaleFactor > 0) { (void) SMP_strncat(OutString, "*", STARS_MAXSTR - 1); (void) SMP_strncat(OutString, ScaleString, STARS_MAXSTR - 1); } } } else if (IndexReg != STARS_x86_R_none) { (void) SMP_strncat(OutString, MDGetRegNumName((STARS_regnum_t) IndexReg, ByteWidth), STARS_MAXSTR - 1); if (ScaleFactor > 0) { (void) SMP_strncat(OutString, "*", STARS_MAXSTR - 1); (void) SMP_strncat(OutString, ScaleString, STARS_MAXSTR - 1); } } else { SMP_msg("ERROR: No BaseReg, no IndexReg in SIB\n"); } if (!HasOffset) // can close the brackets around regs (void) SMP_strncat(OutString, "]", STARS_MAXSTR - 1); SMP_fprintf(OutFile, " %s", OutString); } // end AnnotPrintSIB() // Annotations: concisely print SIB info for an operand to OutString. void StringPrintSIB(const STARSOpndTypePtr &Opnd, bool HasOffset, char *OutString, bool Has64BitAddressing) { int BaseReg; int IndexReg; uint16_t ScaleFactor; uint16_t ByteWidth = Opnd->GetByteWidth(); STARS_ea_t offset; char ScaleString[4]; if (Has64BitAddressing) ByteWidth = 8; SMP_strncat(OutString, "[", STARS_MAXSTR - 1); MDExtractAddressFields(Opnd, BaseReg, IndexReg, ScaleFactor, offset); if (ScaleFactor > 0) { ScaleFactor = 1 << ScaleFactor; (void) SMP_snprintf(ScaleString, 4, "%d", ScaleFactor); } if (BaseReg != STARS_x86_R_none) { (void) SMP_strncat(OutString, MDGetRegNumName((STARS_regnum_t) BaseReg, ByteWidth), STARS_MAXSTR - 1); if (IndexReg != STARS_x86_R_none) { (void) SMP_strncat(OutString, "+", STARS_MAXSTR - 1); (void) SMP_strncat(OutString, MDGetRegNumName((STARS_regnum_t) IndexReg, ByteWidth), STARS_MAXSTR - 1); if (ScaleFactor > 0) { (void) SMP_strncat(OutString, "*", STARS_MAXSTR - 1); (void) SMP_strncat(OutString, ScaleString, STARS_MAXSTR - 1); } } } else if (IndexReg != STARS_x86_R_none) { (void) SMP_strncat(OutString, MDGetRegNumName((STARS_regnum_t) IndexReg, ByteWidth), STARS_MAXSTR - 1); if (ScaleFactor > 0) { (void) SMP_strncat(OutString, "*", STARS_MAXSTR - 1); (void) SMP_strncat(OutString, ScaleString, STARS_MAXSTR - 1); } } else { SMP_msg("ERROR: No BaseReg, no IndexReg in SIB\n"); } if (!HasOffset) // can close the brackets around regs (void) SMP_strncat(OutString, "]", STARS_MAXSTR - 1); return; } // end StringPrintSIB() // Annotations: concisely print SIB info for an operand. void SPARKAnnotPrintSIB(const STARSOpndTypePtr &Opnd, bool HasOffset, FILE *OutFile, STARS_regnum_t SegReg, bool UseFP, bool Has64BitAddressing, bool UseSavedStackPtr) { #if 1 std::string OutString; SPARKAnnotSIBToString(Opnd, HasOffset, OutString, SegReg, UseFP, Has64BitAddressing, UseSavedStackPtr); SMP_fprintf(OutFile, " %s", OutString.c_str()); #else int BaseReg; int IndexReg; uint16_t ScaleFactor; uint16_t ByteWidth = Opnd->GetByteWidth(); STARS_ea_t offset; char OutString[STARS_MAXSTR] = {'(', '\0'}; char ScaleString[4]; if (Has64BitAddressing) ByteWidth = 8; MDExtractAddressFields(Opnd, BaseReg, IndexReg, ScaleFactor, offset); bool SegRegPrefix = STARS_x86_is_segreg((int) SegReg); if (SegRegPrefix) { // Emit segment register string unless it is just the stack segment plus a stack operand, // where the stack segment is implied anyway. if ((SegReg == STARS_x86_R_ss) && MDIsStackAccessOpnd(Opnd, UseFP)) { SegRegPrefix = false; } #if STARS_SPARK_EMIT_SEGMENT_REGS else { (void) SMP_strncat(OutString, "X86.", STARS_MAXSTR-1); (void) SMP_strncat(OutString, MDGetRegNumName(SegReg, RegSizes[SegReg]), STARS_MAXSTR-1); } #endif } if (ScaleFactor > 0) { ScaleFactor = 1 << (ScaleFactor - 1); (void) SMP_snprintf(ScaleString, 4, "%d", ScaleFactor); } if (BaseReg != STARS_x86_R_none) { #if STARS_SPARK_EMIT_SEGMENT_REGS if (SegRegPrefix) { (void) SMP_strncat(OutString, " + ", STARS_MAXSTR-1); } #endif if (!(UseSavedStackPtr && (BaseReg == MD_STACK_POINTER_REG))) { (void) SMP_strncat(OutString, "X86.", STARS_MAXSTR - 1); (void) SMP_strncat(OutString, MDGetRegNumName((STARS_regnum_t)BaseReg, ByteWidth), STARS_MAXSTR - 1); } else { (void) SMP_strncat(OutString, "SaveStackPtr", STARS_MAXSTR - 1); } if (global_STARS_program->GetSTARS_ISA_Bytewidth() > ByteWidth) { ++SubwordAddressRegCount; } if (IndexReg != STARS_x86_R_none) { (void) SMP_strncat(OutString, " + ", STARS_MAXSTR - 1); if (!(UseSavedStackPtr && (IndexReg == MD_STACK_POINTER_REG))) { (void) SMP_strncat(OutString, "X86.", STARS_MAXSTR - 1); (void) SMP_strncat(OutString, MDGetRegNumName((STARS_regnum_t) IndexReg, ByteWidth), STARS_MAXSTR - 1); } else { (void) SMP_strncat(OutString, "SaveStackPtr", STARS_MAXSTR - 1); } if (global_STARS_program->GetSTARS_ISA_Bytewidth() > ByteWidth) { ++SubwordAddressRegCount; } if (ScaleFactor > 0) { (void) SMP_strncat(OutString, "*", STARS_MAXSTR-1); (void) SMP_strncat(OutString, ScaleString, STARS_MAXSTR-1); } } } else if (IndexReg != STARS_x86_R_none) { #if STARS_SPARK_EMIT_SEGMENT_REGS if (SegRegPrefix) { (void) SMP_strncat(OutString, " + ", STARS_MAXSTR-1); } #endif if (!(UseSavedStackPtr && (IndexReg == MD_STACK_POINTER_REG))) { (void)SMP_strncat(OutString, "X86.", STARS_MAXSTR - 1); (void)SMP_strncat(OutString, MDGetRegNumName((STARS_regnum_t)IndexReg, ByteWidth), STARS_MAXSTR - 1); } else { (void)SMP_strncat(OutString, "SaveStackPtr", STARS_MAXSTR - 1); } if (global_STARS_program->GetSTARS_ISA_Bytewidth() > ByteWidth) { ++SubwordAddressRegCount; } if (ScaleFactor > 0) { (void) SMP_strncat(OutString, "*", STARS_MAXSTR-1); (void) SMP_strncat(OutString, ScaleString, STARS_MAXSTR-1); } } else if (!SegRegPrefix) { SMP_msg("ERROR: No BaseReg, no IndexReg in SIB\n"); } if (!HasOffset) // can close the parens around regs (void) SMP_strncat(OutString, ")", STARS_MAXSTR-1); SMP_fprintf(OutFile, " %s", OutString); #endif return; } // end SPARKAnnotPrintSIB() void SPARKAnnotSIBToString(const STARSOpndTypePtr &Opnd, bool HasOffset, std::string &OutString, STARS_regnum_t SegReg, bool UseFP, bool Has64BitAddressing, bool UseSavedStackPtr) { int BaseReg; int IndexReg; uint16_t ScaleFactor; uint16_t ByteWidth = Opnd->GetByteWidth(); STARS_ea_t offset; char OutString2[STARS_MAXSTR] = { '(', '\0' }; char ScaleString[4]; if (Has64BitAddressing) ByteWidth = 8; MDExtractAddressFields(Opnd, BaseReg, IndexReg, ScaleFactor, offset); bool SegRegPrefix = STARS_x86_is_segreg((int)SegReg); if (SegRegPrefix) { // Emit segment register string unless it is just the stack segment plus a stack operand, // where the stack segment is implied anyway. if ((SegReg == STARS_x86_R_ss) && MDIsStackAccessOpnd(Opnd, UseFP)) { SegRegPrefix = false; } #if STARS_SPARK_EMIT_SEGMENT_REGS else { (void)SMP_strncat(OutString2, "X86.", STARS_MAXSTR - 1); (void)SMP_strncat(OutString2, MDGetRegNumName(SegReg, RegSizes[SegReg]), STARS_MAXSTR - 1); } #endif } if (ScaleFactor > 0) { ScaleFactor = 1 << ScaleFactor; (void) SMP_snprintf(ScaleString, 4, "%d", ScaleFactor); } if (BaseReg != STARS_x86_R_none) { #if STARS_SPARK_EMIT_SEGMENT_REGS if (SegRegPrefix) { (void) SMP_strncat(OutString2, " + ", STARS_MAXSTR - 1); } #endif if (!(UseSavedStackPtr && (BaseReg == MD_STACK_POINTER_REG))) { (void) SMP_strncat(OutString2, "X86.", STARS_MAXSTR - 1); (void) SMP_strncat(OutString2, MDGetRegNumName((STARS_regnum_t)BaseReg, ByteWidth), STARS_MAXSTR - 1); } else { (void) SMP_strncat(OutString2, "SaveStackPtr", STARS_MAXSTR - 1); } if (global_STARS_program->GetSTARS_ISA_Bytewidth() > ByteWidth) { ++SubwordAddressRegCount; } if (IndexReg != STARS_x86_R_none) { if (!(UseSavedStackPtr && (IndexReg == MD_STACK_POINTER_REG))) { (void) SMP_strncat(OutString2, " + X86.", STARS_MAXSTR - 1); (void) SMP_strncat(OutString2, MDGetRegNumName((STARS_regnum_t)IndexReg, ByteWidth), STARS_MAXSTR - 1); } else { (void) SMP_strncat(OutString2, " + SaveStackPtr", STARS_MAXSTR - 1); } if (global_STARS_program->GetSTARS_ISA_Bytewidth() > ByteWidth) { ++SubwordAddressRegCount; } if (ScaleFactor > 0) { (void) SMP_strncat(OutString2, "*", STARS_MAXSTR - 1); (void) SMP_strncat(OutString2, ScaleString, STARS_MAXSTR - 1); } } } else if (IndexReg != STARS_x86_R_none) { #if STARS_SPARK_EMIT_SEGMENT_REGS if (SegRegPrefix) { (void) SMP_strncat(OutString2, " + ", STARS_MAXSTR - 1); } #endif if (!(UseSavedStackPtr && (IndexReg == MD_STACK_POINTER_REG))) { (void)SMP_strncat(OutString2, "X86.", STARS_MAXSTR - 1); (void)SMP_strncat(OutString2, MDGetRegNumName((STARS_regnum_t) IndexReg, ByteWidth), STARS_MAXSTR - 1); } else { (void)SMP_strncat(OutString2, "SaveStackPtr", STARS_MAXSTR - 1); } if (global_STARS_program->GetSTARS_ISA_Bytewidth() > ByteWidth) { ++SubwordAddressRegCount; } if (ScaleFactor > 0) { (void) SMP_strncat(OutString2, "*", STARS_MAXSTR - 1); (void) SMP_strncat(OutString2, ScaleString, STARS_MAXSTR - 1); } } else if (!SegRegPrefix) { SMP_msg("ERROR: No BaseReg, no IndexReg in SIB\n"); } if (!HasOffset) // can close the parens around regs (void) SMP_strncat(OutString2, ")", STARS_MAXSTR - 1); OutString.assign(OutString2); return; } // end of SPARKAnnotSIBToString() // Debug: print one operand from an instruction or DEF or USE list. void PrintOneOperand(const STARSOpndTypePtr &Opnd, uint32_t features, int OpNum) { if ((nullptr != Opnd) && (!Opnd->IsVoidOp())) { PrintOperand(Opnd); PrintDefUse(features, OpNum); } return; } // end of PrintOneOperand() // Debug: print one operand. void PrintOperand(const STARSOpndTypePtr &Opnd) { if ((nullptr == Opnd) || (Opnd->IsVoidOp())) return; else if (Opnd->IsStaticMemOp()) { SMP_msg(" Operand: memory : addr: %lx", (unsigned long) Opnd->GetAddr()); if (Opnd->HasSIBByte()) { PrintSIB(Opnd); } } else if (Opnd->IsMemNoDisplacementOp()) { SMP_msg(" Operand: memory phrase :"); if (Opnd->HasSIBByte()) { // has SIB info PrintSIB(Opnd); } else { // no SIB info STARS_regnum_t BaseReg = Opnd->GetReg(); SMP_msg(" reg %s", RegNames[BaseReg]); } if (Opnd->GetAddr() != 0) { SMP_msg(" \n ERROR: addr for o_phrase type: %lx\n", (unsigned long) Opnd->GetAddr()); } } else if (Opnd->IsMemDisplacementOp()) { SMP_msg(" Operand: memory displ :"); STARS_ea_t offset = Opnd->GetAddr(); int SignedOffset = (int) offset; if (Opnd->HasSIBByte()) { PrintSIB(Opnd); SMP_msg(" displ %d", SignedOffset); } else { STARS_regnum_t BaseReg = Opnd->GetReg(); SMP_msg(" reg %s displ %d", RegNames[BaseReg], SignedOffset); } } else if (Opnd->IsRegOp()) { SMP_msg(" Operand: register %s", MDGetRegName(Opnd)); } else if (Opnd->IsImmedOp()) { SMP_msg(" Operand: immed %ld", (long) Opnd->GetImmedValue()); } else if (Opnd->IsFarPointer()) { SMP_msg(" Operand: FarPtrImmed addr: %lx", (unsigned long) Opnd->GetAddr()); } else if (Opnd->IsNearPointer()) { SMP_msg(" Operand: NearPtrImmed addr: %lx", (unsigned long) Opnd->GetAddr()); } else if (Opnd->IsTestRegOp()) { SMP_msg(" Operand: TestReg reg: %d", Opnd->GetReg()); } else if (Opnd->IsDebugRegOp()) { SMP_msg(" Operand: DebugReg reg: %d", Opnd->GetReg()); } else if (Opnd->IsControlRegOp()) { SMP_msg(" Operand: ControlReg reg: %d", Opnd->GetReg()); } else if (Opnd->IsFloatingPointRegOp()) { SMP_msg(" Operand: FloatReg reg: %d", Opnd->GetReg()); } else if (Opnd->IsMMXRegOp()) { SMP_msg(" Operand: MMXReg reg: %d", Opnd->GetReg()); } else if (Opnd->IsXMMRegOp()) { SMP_msg(" Operand: XMMReg reg: %d", Opnd->GetReg()); } else if (Opnd->IsYMMRegOp()) { SMP_msg(" Operand: YMMReg reg: %d", Opnd->GetReg()); } else { SMP_msg(" Operand: unknown"); } #if STARS_DEBUG_DUMP_IDENTIFY_HIDDEN_OPERANDS if (!(Opnd->IsVisible())) SMP_msg(" HIDDEN "); #endif return; } // end of PrintOperand() // Print an operand that has no features flags or operand position number, such // as the op_t types found in lists and sets throughout the blocks, phi functions, etc. void PrintListOperand(const STARSOpndTypePtr &Opnd, int SSANum) { if ((nullptr != Opnd) && (!Opnd->IsVoidOp())) { PrintOperand(Opnd); if (!Opnd->IsImmedOp()) { SMP_msg(" SSANum: %d ", SSANum); } else { SMP_msg(" "); } } return; } // end of PrintListOperand() // Annotations: concisely print one operand to OutFile. void AnnotPrintOperand(const STARSOpndTypePtr &Opnd, FILE *OutFile, bool UseFP, bool Has64BitAddressing) { char OutString[STARS_MAXSTR] = { '\0', '\0' }; uint16_t ByteWidth = Opnd->GetByteWidth(); if (Has64BitAddressing) ByteWidth = 8; STARS_regnum_t SegReg = Opnd->GetSegReg(); bool SegRegPrefix = STARS_x86_is_segreg((int) SegReg); if (SegRegPrefix) { // Emit segment register string unless it is just the stack segment plus a stack operand, // where the stack segment is implied anyway. if ((SegReg == STARS_x86_R_ss) && MDIsStackAccessOpnd(Opnd, UseFP)) { SegRegPrefix = false; } else if (SegReg != STARS_x86_R_ds) { // not default data segment (void) SMP_strncat(OutString, MDGetRegNumName(SegReg, RegSizes[SegReg]), STARS_MAXSTR - 1); (void) SMP_strncat(OutString, ":", STARS_MAXSTR - 1); } } if (Opnd->IsStaticMemOp()) { SMP_snprintf(OutString, STARS_MAXSTR - 1, " %llx", (unsigned long long) Opnd->GetAddr()); if (Opnd->HasSIBByte()) { AnnotPrintSIB(Opnd, false, OutFile, OutString, Has64BitAddressing); } else { SMP_fprintf(OutFile, " %s", OutString); } } else if (Opnd->IsMemNoDisplacementOp()) { if (Opnd->HasSIBByte()) { // has SIB info AnnotPrintSIB(Opnd, false, OutFile, OutString, Has64BitAddressing); } else { // no SIB info STARS_regnum_t BaseReg = Opnd->GetReg(); SMP_fprintf(OutFile, " [%s]", MDGetRegNumName(BaseReg, ByteWidth)); } if (Opnd->GetAddr() != 0) { SMP_msg(" \n ERROR: addr for o_phrase type: %llx\n", (unsigned long long) Opnd->GetAddr()); } } else if (Opnd->IsMemDisplacementOp()) { STARS_ea_t offset = Opnd->GetAddr(); int SignedOffset = (int) offset; if (Opnd->HasSIBByte()) { AnnotPrintSIB(Opnd, (SignedOffset != 0), OutFile, OutString, Has64BitAddressing); if (SignedOffset > 0) // print plus sign SMP_fprintf(OutFile, "+%d]", SignedOffset); else if (SignedOffset < 0) // minus sign will print automatically SMP_fprintf(OutFile, "%d]", SignedOffset); } else { STARS_regnum_t BaseReg = Opnd->GetReg(); if (SignedOffset >= 0) // print plus sign SMP_fprintf(OutFile, " [%s+%d]", MDGetRegNumName(BaseReg, ByteWidth), SignedOffset); else // minus sign will print automatically SMP_fprintf(OutFile, " [%s%d]", MDGetRegNumName(BaseReg, ByteWidth), SignedOffset); } } else if (Opnd->IsRegOp()) { SMP_fprintf(OutFile, " %s", MDGetRegName(Opnd)); } else if (Opnd->IsImmedOp()) { SMP_fprintf(OutFile, " %ld", (long) Opnd->GetImmedValue()); } else if ((Opnd->IsFarPointer()) || (Opnd->IsNearPointer())) { SMP_fprintf(OutFile, " %llx", (unsigned long long) Opnd->GetAddr()); } else { SMP_fprintf(OutFile, " ERROROP"); } return; } // end of AnnotPrintOperand() // Annotations: concisely print one operand to a string. void StringPrintOperand(const STARSOpndTypePtr &Opnd, string &OutStream, bool UseFP, bool Has64BitAddressing) { char OutString[STARS_MAXSTR] = { '\0', '\0' }; char DummyBuf[STARS_MAXSTR] = { '\0', '\0' }; uint16_t ByteWidth = Opnd->GetByteWidth(); if (Has64BitAddressing) ByteWidth = 8; STARS_regnum_t SegReg = Opnd->GetSegReg(); bool SegRegPrefix = STARS_x86_is_segreg((int)SegReg); if (SegRegPrefix) { // Emit segment register string unless it is just the stack segment plus a stack operand, // where the stack segment is implied anyway. if ((SegReg == STARS_x86_R_ss) && MDIsStackAccessOpnd(Opnd, UseFP)) { SegRegPrefix = false; } else if (SegReg != STARS_x86_R_ds) { // not default data segment (void) SMP_strncat(OutString, MDGetRegNumName(SegReg, RegSizes[SegReg]), STARS_MAXSTR - 1); (void) SMP_strncat(OutString, ":", STARS_MAXSTR - 1); } } if (Opnd->IsStaticMemOp()) { SMP_snprintf(OutString, STARS_MAXSTR - 1, " %llx", (unsigned long long) Opnd->GetAddr()); if (Opnd->HasSIBByte()) { StringPrintSIB(Opnd, false, OutString, Has64BitAddressing); } } else if (Opnd->IsMemNoDisplacementOp()) { if (Opnd->HasSIBByte()) { // has SIB info StringPrintSIB(Opnd, false, OutString, Has64BitAddressing); } else { // no SIB info STARS_regnum_t BaseReg = Opnd->GetReg(); (void) SMP_strncat(OutString, " [", STARS_MAXSTR - 1); (void) SMP_strncat(OutString, MDGetRegNumName(BaseReg, ByteWidth), STARS_MAXSTR - 1); (void) SMP_strncat(OutString, "] ", STARS_MAXSTR - 1); } if (Opnd->GetAddr() != 0) { SMP_msg(" \n ERROR: addr for o_phrase type: %llx\n", (unsigned long long) Opnd->GetAddr()); } } else if (Opnd->IsMemDisplacementOp()) { STARS_ea_t offset = Opnd->GetAddr(); int SignedOffset = (int) offset; if (Opnd->HasSIBByte()) { StringPrintSIB(Opnd, (SignedOffset != 0), OutString, Has64BitAddressing); if (SignedOffset > 0) { // print plus sign (void) SMP_strncat(OutString, "+", STARS_MAXSTR - 1); } #if 0 (void) SMP_snprintf(DummyBuf, STARS_MAXSTR - 1, "%lld", (int64_t) Opnd->GetImmedValue()); #else (void)SMP_snprintf(DummyBuf, STARS_MAXSTR - 1, "%lld", (int64_t)SignedOffset); SMP_msg("INFO: StringPrintOperand case reached: MemDisplacement with SIB byte.\n"); #endif (void) SMP_strncat(OutString, DummyBuf, STARS_MAXSTR - 1); (void) SMP_strncat(OutString, "]", STARS_MAXSTR - 1); } else { STARS_regnum_t BaseReg = Opnd->GetReg(); (void) SMP_strncat(OutString, " [", STARS_MAXSTR - 1); (void) SMP_strncat(OutString, MDGetRegNumName(BaseReg, ByteWidth), STARS_MAXSTR - 1); if (SignedOffset >= 0) { // print plus sign (void) SMP_strncat(OutString, "+", STARS_MAXSTR - 1); } (void) SMP_snprintf(DummyBuf, STARS_MAXSTR - 1, "%lld", (int64_t)SignedOffset); (void) SMP_strncat(OutString, DummyBuf, STARS_MAXSTR - 1); (void) SMP_strncat(OutString, "] ", STARS_MAXSTR - 1); } } else if (Opnd->IsRegOp()) { SMP_strncat(OutString, MDGetRegName(Opnd), STARS_MAXSTR - 1); } else if (Opnd->IsImmedOp()) { SMP_snprintf(DummyBuf, STARS_MAXSTR - 1, "%lld", (int64_t) Opnd->GetImmedValue()); SMP_strncat(OutString, DummyBuf, STARS_MAXSTR - 1); } else if ((Opnd->IsFarPointer()) || (Opnd->IsNearPointer())) { SMP_snprintf(DummyBuf, STARS_MAXSTR - 1, " %llx", (uint64_t) Opnd->GetAddr()); SMP_strncat(OutString, DummyBuf, STARS_MAXSTR - 1); } else { SMP_strncat(OutString, " ERROROP", STARS_MAXSTR - 1); } OutStream += OutString; return; } // end of StringPrintOperand() // Print opcode string. void PrintOpcode(uint16_t opcode, FILE *OutFile) { switch (opcode) { case STARS_NN_null: // Unknown Operation case STARS_NN_aaa: // ASCII Adjust after Addition case STARS_NN_aad: // ASCII Adjust AX before Division case STARS_NN_aam: // ASCII Adjust AX after Multiply case STARS_NN_aas: // ASCII Adjust AL after Subtraction case STARS_NN_adc: // Add with Carry SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_add: // Add SMP_fprintf(OutFile, "add"); break; case STARS_NN_and: // Logical AND SMP_fprintf(OutFile, "and"); break; case STARS_NN_arpl: // Adjust RPL Field of Selector case STARS_NN_bound: // Check Array Index Against Bounds case STARS_NN_bsf: // Bit Scan Forward case STARS_NN_bsr: // Bit Scan Reverse case STARS_NN_bt: // Bit Test case STARS_NN_btc: // Bit Test and Complement case STARS_NN_btr: // Bit Test and Reset case STARS_NN_bts: // Bit Test and Set SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_call: // Call Procedure case STARS_NN_callfi: // Indirect Call Far Procedure case STARS_NN_callni: // Indirect Call Near Procedure SMP_fprintf(OutFile, ""); break; case STARS_NN_cbw: // AL -> AX (with sign) case STARS_NN_cwde: // AX -> EAX (with sign) case STARS_NN_cdqe: // EAX -> RAX (with sign) case STARS_NN_clc: // Clear Carry Flag case STARS_NN_cld: // Clear Direction Flag case STARS_NN_cli: // Clear Interrupt Flag case STARS_NN_clts: // Clear Task-Switched Flag in CR0 case STARS_NN_cmc: // Complement Carry Flag case STARS_NN_cmp: // Compare Two Operands case STARS_NN_cmps: // Compare Strings case STARS_NN_cwd: // AX -> DX:AX (with sign) case STARS_NN_cdq: // EAX -> EDX:EAX (with sign) case STARS_NN_cqo: // RAX -> RDX:RAX (with sign) case STARS_NN_daa: // Decimal Adjust AL after Addition case STARS_NN_das: // Decimal Adjust AL after Subtraction SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_dec: // Decrement by 1 SMP_fprintf(OutFile, "sub"); break; case STARS_NN_div: // Unsigned Divide SMP_fprintf(OutFile, "div"); break; case STARS_NN_enterw: // Make Stack Frame for Procedure Parameters case STARS_NN_enter: // Make Stack Frame for Procedure Parameters case STARS_NN_enterd: // Make Stack Frame for Procedure Parameters case STARS_NN_enterq: // Make Stack Frame for Procedure Parameters SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_hlt: // Halt SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_idiv: // Signed Divide SMP_fprintf(OutFile, "div"); break; case STARS_NN_imul: // Signed Multiply SMP_fprintf(OutFile, "mul"); break; case STARS_NN_in: // Input from Port SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_inc: // Increment by 1 SMP_fprintf(OutFile, "add"); break; case STARS_NN_ins: // Input Byte(s) from Port to String case STARS_NN_int: // Call to Interrupt Procedure case STARS_NN_into: // Call to Interrupt Procedure if Overflow Flag = 1 case STARS_NN_int3: // Trap to Debugger case STARS_NN_iretw: // Interrupt Return case STARS_NN_iret: // Interrupt Return case STARS_NN_iretd: // Interrupt Return (use32) case STARS_NN_iretq: // Interrupt Return (use64) SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_ja: // Jump if Above (CF=0 & ZF=0) case STARS_NN_jae: // Jump if Above or Equal (CF=0) case STARS_NN_jb: // Jump if Below (CF=1) case STARS_NN_jbe: // Jump if Below or Equal (CF=1 | ZF=1) case STARS_NN_jc: // Jump if Carry (CF=1) case STARS_NN_jcxz: // Jump if CX is 0 case STARS_NN_jecxz: // Jump if ECX is 0 case STARS_NN_jrcxz: // Jump if RCX is 0 case STARS_NN_je: // Jump if Equal (ZF=1) case STARS_NN_jg: // Jump if Greater (ZF=0 & SF=OF) case STARS_NN_jge: // Jump if Greater or Equal (SF=OF) case STARS_NN_jl: // Jump if Less (SF!=OF) case STARS_NN_jle: // Jump if Less or Equal (ZF=1 | SF!=OF) case STARS_NN_jna: // Jump if Not Above (CF=1 | ZF=1) case STARS_NN_jnae: // Jump if Not Above or Equal (CF=1) case STARS_NN_jnb: // Jump if Not Below (CF=0) case STARS_NN_jnbe: // Jump if Not Below or Equal (CF=0 & ZF=0) case STARS_NN_jnc: // Jump if Not Carry (CF=0) case STARS_NN_jne: // Jump if Not Equal (ZF=0) case STARS_NN_jng: // Jump if Not Greater (ZF=1 | SF!=OF) case STARS_NN_jnge: // Jump if Not Greater or Equal (ZF=1) case STARS_NN_jnl: // Jump if Not Less (SF=OF) case STARS_NN_jnle: // Jump if Not Less or Equal (ZF=0 & SF=OF) case STARS_NN_jno: // Jump if Not Overflow (OF=0) case STARS_NN_jnp: // Jump if Not Parity (PF=0) case STARS_NN_jns: // Jump if Not Sign (SF=0) case STARS_NN_jnz: // Jump if Not Zero (ZF=0) case STARS_NN_jo: // Jump if Overflow (OF=1) case STARS_NN_jp: // Jump if Parity (PF=1) case STARS_NN_jpe: // Jump if Parity Even (PF=1) case STARS_NN_jpo: // Jump if Parity Odd (PF=0) case STARS_NN_js: // Jump if Sign (SF=1) case STARS_NN_jz: // Jump if Zero (ZF=1) case STARS_NN_jmp: // Jump case STARS_NN_jmpfi: // Indirect Far Jump case STARS_NN_jmpni: // Indirect Near Jump case STARS_NN_jmpshort: // Jump Short (not used) SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_lahf: // Load Flags into AH Register case STARS_NN_lar: // Load Access Right Byte SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_lea: // Load Effective Address SMP_fprintf(OutFile, "lea"); break; case STARS_NN_leavew: // High Level Procedure Exit case STARS_NN_leave: // High Level Procedure Exit case STARS_NN_leaved: // High Level Procedure Exit case STARS_NN_leaveq: // High Level Procedure Exit SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_lgdt: // Load Global Descriptor Table Register case STARS_NN_lidt: // Load Interrupt Descriptor Table Register case STARS_NN_lgs: // Load Full Pointer to GS:xx case STARS_NN_lss: // Load Full Pointer to SS:xx case STARS_NN_lds: // Load Full Pointer to DS:xx case STARS_NN_les: // Load Full Pointer to ES:xx case STARS_NN_lfs: // Load Full Pointer to FS:xx case STARS_NN_lldt: // Load Local Descriptor Table Register case STARS_NN_lmsw: // Load Machine Status Word case STARS_NN_lock: // Assert LOCK# Signal Prefix SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_lods: // Load String SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_loopw: // Loop while ECX != 0 case STARS_NN_loop: // Loop while CX != 0 case STARS_NN_loopd: // Loop while ECX != 0 case STARS_NN_loopq: // Loop while RCX != 0 case STARS_NN_loopwe: // Loop while CX != 0 and ZF=1 case STARS_NN_loope: // Loop while rCX != 0 and ZF=1 case STARS_NN_loopde: // Loop while ECX != 0 and ZF=1 case STARS_NN_loopqe: // Loop while RCX != 0 and ZF=1 case STARS_NN_loopwne: // Loop while CX != 0 and ZF=0 case STARS_NN_loopne: // Loop while rCX != 0 and ZF=0 case STARS_NN_loopdne: // Loop while ECX != 0 and ZF=0 case STARS_NN_loopqne: // Loop while RCX != 0 and ZF=0 SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_lsl: // Load Segment Limit case STARS_NN_ltr: // Load Task Register SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_mov: // Move Data SMP_fprintf(OutFile, "mov"); break; case STARS_NN_movsp: // Move to/from Special Registers SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_movs: // Move Byte(s) from String to String SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_movsx: // Move with Sign-Extend SMP_fprintf(OutFile, "movsx"); break; case STARS_NN_movzx: // Move with Zero-Extend SMP_fprintf(OutFile, "movzx"); break; case STARS_NN_mul: // Unsigned Multiplication of AL or AX SMP_fprintf(OutFile, "mul"); break; case STARS_NN_neg: // Two's Complement Negation SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_nop: // No Operation SMP_fprintf(OutFile, ""); break; case STARS_NN_not: // One's Complement Negation SMP_fprintf(OutFile, "not"); break; case STARS_NN_or: // Logical Inclusive OR SMP_fprintf(OutFile, "or"); break; case STARS_NN_out: // Output to Port case STARS_NN_outs: // Output Byte(s) to Port SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_pop: // Pop a word from the Stack SMP_fprintf(OutFile, "pop"); break; case STARS_NN_popaw: // Pop all General Registers case STARS_NN_popa: // Pop all General Registers case STARS_NN_popad: // Pop all General Registers (use32) case STARS_NN_popaq: // Pop all General Registers (use64) case STARS_NN_popfw: // Pop Stack into Flags Register case STARS_NN_popf: // Pop Stack into Flags Register case STARS_NN_popfd: // Pop Stack into Eflags Register case STARS_NN_popfq: // Pop Stack into Rflags Register SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_push: // Push Operand onto the Stack SMP_fprintf(OutFile, "push"); break; case STARS_NN_pushaw: // Push all General Registers case STARS_NN_pusha: // Push all General Registers case STARS_NN_pushad: // Push all General Registers (use32) case STARS_NN_pushaq: // Push all General Registers (use64) case STARS_NN_pushfw: // Push Flags Register onto the Stack case STARS_NN_pushf: // Push Flags Register onto the Stack case STARS_NN_pushfd: // Push Flags Register onto the Stack (use32) case STARS_NN_pushfq: // Push Flags Register onto the Stack (use64) SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_rcl: // Rotate Through Carry Left case STARS_NN_rcr: // Rotate Through Carry Right case STARS_NN_rol: // Rotate Left case STARS_NN_ror: // Rotate Right SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_rep: // Repeat String Operation case STARS_NN_repe: // Repeat String Operation while ZF=1 case STARS_NN_repne: // Repeat String Operation while ZF=0 SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_retn: // Return Near from Procedure case STARS_NN_retf: // Return Far from Procedure SMP_fprintf(OutFile, "return"); break; case STARS_NN_sahf: // Store AH into Flags Register SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_sal: // Shift Arithmetic Left SMP_fprintf(OutFile, "sal"); break; case STARS_NN_sar: // Shift Arithmetic Right SMP_fprintf(OutFile, "sar"); break; case STARS_NN_shl: // Shift Logical Left SMP_fprintf(OutFile, "shl"); break; case STARS_NN_shr: // Shift Logical Right SMP_fprintf(OutFile, "shr"); break; case STARS_NN_sbb: // Integer Subtraction with Borrow SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_scas: // Compare String SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_seta: // Set Byte if Above (CF=0 & ZF=0) case STARS_NN_setae: // Set Byte if Above or Equal (CF=0) case STARS_NN_setb: // Set Byte if Below (CF=1) case STARS_NN_setbe: // Set Byte if Below or Equal (CF=1 | ZF=1) case STARS_NN_setc: // Set Byte if Carry (CF=1) case STARS_NN_sete: // Set Byte if Equal (ZF=1) case STARS_NN_setg: // Set Byte if Greater (ZF=0 & SF=OF) case STARS_NN_setge: // Set Byte if Greater or Equal (SF=OF) case STARS_NN_setl: // Set Byte if Less (SF!=OF) case STARS_NN_setle: // Set Byte if Less or Equal (ZF=1 | SF!=OF) case STARS_NN_setna: // Set Byte if Not Above (CF=1 | ZF=1) case STARS_NN_setnae: // Set Byte if Not Above or Equal (CF=1) case STARS_NN_setnb: // Set Byte if Not Below (CF=0) case STARS_NN_setnbe: // Set Byte if Not Below or Equal (CF=0 & ZF=0) case STARS_NN_setnc: // Set Byte if Not Carry (CF=0) case STARS_NN_setne: // Set Byte if Not Equal (ZF=0) case STARS_NN_setng: // Set Byte if Not Greater (ZF=1 | SF!=OF) case STARS_NN_setnge: // Set Byte if Not Greater or Equal (ZF=1) case STARS_NN_setnl: // Set Byte if Not Less (SF=OF) case STARS_NN_setnle: // Set Byte if Not Less or Equal (ZF=0 & SF=OF) case STARS_NN_setno: // Set Byte if Not Overflow (OF=0) case STARS_NN_setnp: // Set Byte if Not Parity (PF=0) case STARS_NN_setns: // Set Byte if Not Sign (SF=0) case STARS_NN_setnz: // Set Byte if Not Zero (ZF=0) case STARS_NN_seto: // Set Byte if Overflow (OF=1) case STARS_NN_setp: // Set Byte if Parity (PF=1) case STARS_NN_setpe: // Set Byte if Parity Even (PF=1) case STARS_NN_setpo: // Set Byte if Parity Odd (PF=0) case STARS_NN_sets: // Set Byte if Sign (SF=1) case STARS_NN_setz: // Set Byte if Zero (ZF=1) SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_sgdt: // Store Global Descriptor Table Register case STARS_NN_sidt: // Store Interrupt Descriptor Table Register SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_shld: // Double Precision Shift Left case STARS_NN_shrd: // Double Precision Shift Right SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_sldt: // Store Local Descriptor Table Register case STARS_NN_smsw: // Store Machine Status Word case STARS_NN_stc: // Set Carry Flag case STARS_NN_std: // Set Direction Flag case STARS_NN_sti: // Set Interrupt Flag SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_stos: // Store String case STARS_NN_str: // Store Task Register SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_sub: // Integer Subtraction SMP_fprintf(OutFile, "sub"); break; case STARS_NN_test: // Logical Compare SMP_fprintf(OutFile, "test"); break; case STARS_NN_verr: // Verify a Segment for Reading case STARS_NN_verw: // Verify a Segment for Writing case STARS_NN_wait: // Wait until BUSY# Pin is Inactive (HIGH) SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_xchg: // Exchange Register/Memory with Register case STARS_NN_xlat: // Table Lookup Translation SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_xor: // Logical Exclusive OR SMP_fprintf(OutFile, "xor"); break; // // 486 instructions // case STARS_NN_cmpxchg: // Compare and Exchange case STARS_NN_bswap: // Swap bits in EAX case STARS_NN_xadd: // t<-dest; dest<-src+dest; src<-t case STARS_NN_invd: // Invalidate Data Cache case STARS_NN_wbinvd: // Invalidate Data Cache (write changes) case STARS_NN_invlpg: // Invalidate TLB entry SMP_fprintf(OutFile, "ERROR"); break; // // Pentium instructions // case STARS_NN_rdmsr: // Read Machine Status Register case STARS_NN_wrmsr: // Write Machine Status Register case STARS_NN_cpuid: // Get CPU ID case STARS_NN_cmpxchg8b: // Compare and Exchange Eight Bytes case STARS_NN_rdtsc: // Read Time Stamp Counter case STARS_NN_rsm: // Resume from System Management Mode SMP_fprintf(OutFile, "ERROR"); break; // // Pentium Pro instructions // case STARS_NN_cmova: // Move if Above (CF=0 & ZF=0) case STARS_NN_cmovb: // Move if Below (CF=1) case STARS_NN_cmovbe: // Move if Below or Equal (CF=1 | ZF=1) case STARS_NN_cmovg: // Move if Greater (ZF=0 & SF=OF) case STARS_NN_cmovge: // Move if Greater or Equal (SF=OF) case STARS_NN_cmovl: // Move if Less (SF!=OF) case STARS_NN_cmovle: // Move if Less or Equal (ZF=1 | SF!=OF) case STARS_NN_cmovnb: // Move if Not Below (CF=0) case STARS_NN_cmovno: // Move if Not Overflow (OF=0) case STARS_NN_cmovnp: // Move if Not Parity (PF=0) case STARS_NN_cmovns: // Move if Not Sign (SF=0) case STARS_NN_cmovnz: // Move if Not Zero (ZF=0) case STARS_NN_cmovo: // Move if Overflow (OF=1) case STARS_NN_cmovp: // Move if Parity (PF=1) case STARS_NN_cmovs: // Move if Sign (SF=1) case STARS_NN_cmovz: // Move if Zero (ZF=1) case STARS_NN_fcmovb: // Floating Move if Below case STARS_NN_fcmove: // Floating Move if Equal case STARS_NN_fcmovbe: // Floating Move if Below or Equal case STARS_NN_fcmovu: // Floating Move if Unordered case STARS_NN_fcmovnb: // Floating Move if Not Below case STARS_NN_fcmovne: // Floating Move if Not Equal case STARS_NN_fcmovnbe: // Floating Move if Not Below or Equal case STARS_NN_fcmovnu: // Floating Move if Not Unordered case STARS_NN_fcomi: // FP Compare, result in EFLAGS case STARS_NN_fucomi: // FP Unordered Compare, result in EFLAGS case STARS_NN_fcomip: // FP Compare, result in EFLAGS, pop stack case STARS_NN_fucomip: // FP Unordered Compare, result in EFLAGS, pop stack case STARS_NN_rdpmc: // Read Performance Monitor Counter SMP_fprintf(OutFile, "ERROR"); break; // // FPP instructions // case STARS_NN_fld: // Load Real case STARS_NN_fst: // Store Real case STARS_NN_fstp: // Store Real and Pop case STARS_NN_fxch: // Exchange Registers case STARS_NN_fild: // Load Integer case STARS_NN_fist: // Store Integer case STARS_NN_fistp: // Store Integer and Pop case STARS_NN_fbld: // Load BCD case STARS_NN_fbstp: // Store BCD and Pop case STARS_NN_fadd: // Add Real case STARS_NN_faddp: // Add Real and Pop case STARS_NN_fiadd: // Add Integer case STARS_NN_fsub: // Subtract Real case STARS_NN_fsubp: // Subtract Real and Pop case STARS_NN_fisub: // Subtract Integer case STARS_NN_fsubr: // Subtract Real Reversed case STARS_NN_fsubrp: // Subtract Real Reversed and Pop case STARS_NN_fisubr: // Subtract Integer Reversed case STARS_NN_fmul: // Multiply Real case STARS_NN_fmulp: // Multiply Real and Pop case STARS_NN_fimul: // Multiply Integer case STARS_NN_fdiv: // Divide Real case STARS_NN_fdivp: // Divide Real and Pop case STARS_NN_fidiv: // Divide Integer case STARS_NN_fdivr: // Divide Real Reversed case STARS_NN_fdivrp: // Divide Real Reversed and Pop case STARS_NN_fidivr: // Divide Integer Reversed case STARS_NN_fsqrt: // Square Root case STARS_NN_fscale: // Scale: st(0) <- st(0) * 2^st(1) case STARS_NN_fprem: // Partial Remainder case STARS_NN_frndint: // Round to Integer case STARS_NN_fxtract: // Extract exponent and significand case STARS_NN_fabs: // Absolute value case STARS_NN_fchs: // Change Sign case STARS_NN_fcom: // Compare Real case STARS_NN_fcomp: // Compare Real and Pop case STARS_NN_fcompp: // Compare Real and Pop Twice case STARS_NN_ficom: // Compare Integer case STARS_NN_ficomp: // Compare Integer and Pop case STARS_NN_ftst: // Test case STARS_NN_fxam: // Examine case STARS_NN_fptan: // Partial tangent case STARS_NN_fpatan: // Partial arctangent case STARS_NN_f2xm1: // 2^x - 1 case STARS_NN_fyl2x: // Y * lg2(X) case STARS_NN_fyl2xp1: // Y * lg2(X+1) case STARS_NN_fldz: // Load +0.0 case STARS_NN_fld1: // Load +1.0 case STARS_NN_fldpi: // Load PI=3.14... case STARS_NN_fldl2t: // Load lg2(10) case STARS_NN_fldl2e: // Load lg2(e) case STARS_NN_fldlg2: // Load lg10(2) case STARS_NN_fldln2: // Load ln(2) case STARS_NN_finit: // Initialize Processor case STARS_NN_fninit: // Initialize Processor (no wait) case STARS_NN_fsetpm: // Set Protected Mode case STARS_NN_fldcw: // Load Control Word case STARS_NN_fstcw: // Store Control Word case STARS_NN_fnstcw: // Store Control Word (no wait) case STARS_NN_fstsw: // Store Status Word case STARS_NN_fnstsw: // Store Status Word (no wait) case STARS_NN_fclex: // Clear Exceptions case STARS_NN_fnclex: // Clear Exceptions (no wait) case STARS_NN_fstenv: // Store Environment case STARS_NN_fnstenv: // Store Environment (no wait) case STARS_NN_fldenv: // Load Environment case STARS_NN_fsave: // Save State case STARS_NN_fnsave: // Save State (no wait) case STARS_NN_frstor: // Restore State case STARS_NN_fincstp: // Increment Stack Pointer case STARS_NN_fdecstp: // Decrement Stack Pointer case STARS_NN_ffree: // Free Register case STARS_NN_fnop: // No Operation case STARS_NN_feni: // (8087 only) case STARS_NN_fneni: // (no wait) (8087 only) case STARS_NN_fdisi: // (8087 only) case STARS_NN_fndisi: // (no wait) (8087 only) SMP_fprintf(OutFile, "ERROR"); break; // // 80387 instructions // case STARS_NN_fprem1: // Partial Remainder ( < half ) case STARS_NN_fsincos: // t<-cos(st); st<-sin(st); push t case STARS_NN_fsin: // Sine case STARS_NN_fcos: // Cosine case STARS_NN_fucom: // Compare Unordered Real case STARS_NN_fucomp: // Compare Unordered Real and Pop case STARS_NN_fucompp: // Compare Unordered Real and Pop Twice SMP_fprintf(OutFile, "ERROR"); break; // // Instructions added 28.02.96 // case STARS_NN_setalc: // Set AL to Carry Flag case STARS_NN_svdc: // Save Register and Descriptor case STARS_NN_rsdc: // Restore Register and Descriptor case STARS_NN_svldt: // Save LDTR and Descriptor case STARS_NN_rsldt: // Restore LDTR and Descriptor case STARS_NN_svts: // Save TR and Descriptor case STARS_NN_rsts: // Restore TR and Descriptor case STARS_NN_icebp: // ICE Break Point case STARS_NN_loadall: // Load the entire CPU state from ES:EDI SMP_fprintf(OutFile, "ERROR"); break; // // MMX instructions // case STARS_NN_emms: // Empty MMX state case STARS_NN_movd: // Move 32 bits case STARS_NN_movq: // Move 64 bits case STARS_NN_packsswb: // Pack with Signed Saturation (Word->Byte) case STARS_NN_packssdw: // Pack with Signed Saturation (Dword->Word) case STARS_NN_packuswb: // Pack with Unsigned Saturation (Word->Byte) case STARS_NN_paddb: // Packed Add Byte case STARS_NN_paddw: // Packed Add Word case STARS_NN_paddd: // Packed Add Dword case STARS_NN_paddsb: // Packed Add with Saturation (Byte) case STARS_NN_paddsw: // Packed Add with Saturation (Word) case STARS_NN_paddusb: // Packed Add Unsigned with Saturation (Byte) case STARS_NN_paddusw: // Packed Add Unsigned with Saturation (Word) case STARS_NN_pand: // Bitwise Logical And case STARS_NN_pandn: // Bitwise Logical And Not case STARS_NN_pcmpeqb: // Packed Compare for Equal (Byte) case STARS_NN_pcmpeqw: // Packed Compare for Equal (Word) case STARS_NN_pcmpeqd: // Packed Compare for Equal (Dword) case STARS_NN_pcmpgtb: // Packed Compare for Greater Than (Byte) case STARS_NN_pcmpgtw: // Packed Compare for Greater Than (Word) case STARS_NN_pcmpgtd: // Packed Compare for Greater Than (Dword) case STARS_NN_pmaddwd: // Packed Multiply and Add case STARS_NN_pmulhw: // Packed Multiply High case STARS_NN_pmullw: // Packed Multiply Low case STARS_NN_por: // Bitwise Logical Or case STARS_NN_psllw: // Packed Shift Left Logical (Word) case STARS_NN_pslld: // Packed Shift Left Logical (Dword) case STARS_NN_psllq: // Packed Shift Left Logical (Qword) case STARS_NN_psraw: // Packed Shift Right Arithmetic (Word) case STARS_NN_psrad: // Packed Shift Right Arithmetic (Dword) case STARS_NN_psrlw: // Packed Shift Right Logical (Word) case STARS_NN_psrld: // Packed Shift Right Logical (Dword) case STARS_NN_psrlq: // Packed Shift Right Logical (Qword) case STARS_NN_psubb: // Packed Subtract Byte case STARS_NN_psubw: // Packed Subtract Word case STARS_NN_psubd: // Packed Subtract Dword case STARS_NN_psubsb: // Packed Subtract with Saturation (Byte) case STARS_NN_psubsw: // Packed Subtract with Saturation (Word) case STARS_NN_psubusb: // Packed Subtract Unsigned with Saturation (Byte) case STARS_NN_psubusw: // Packed Subtract Unsigned with Saturation (Word) case STARS_NN_punpckhbw: // Unpack High Packed Data (Byte->Word) case STARS_NN_punpckhwd: // Unpack High Packed Data (Word->Dword) case STARS_NN_punpckhdq: // Unpack High Packed Data (Dword->Qword) case STARS_NN_punpcklbw: // Unpack Low Packed Data (Byte->Word) case STARS_NN_punpcklwd: // Unpack Low Packed Data (Word->Dword) case STARS_NN_punpckldq: // Unpack Low Packed Data (Dword->Qword) case STARS_NN_pxor: // Bitwise Logical Exclusive Or SMP_fprintf(OutFile, "ERROR"); break; // // Undocumented Deschutes processor instructions // case STARS_NN_fxsave: // Fast save FP context case STARS_NN_fxrstor: // Fast restore FP context SMP_fprintf(OutFile, "ERROR"); break; // Pentium II instructions case STARS_NN_sysenter: // Fast Transition to System Call Entry Point case STARS_NN_sysexit: // Fast Transition from System Call Entry Point SMP_fprintf(OutFile, "ERROR"); break; // 3DNow! instructions case STARS_NN_pavgusb: // Packed 8-bit Unsigned Integer Averaging case STARS_NN_pfadd: // Packed Floating-Point Addition case STARS_NN_pfsub: // Packed Floating-Point Subtraction case STARS_NN_pfsubr: // Packed Floating-Point Reverse Subtraction case STARS_NN_pfacc: // Packed Floating-Point Accumulate case STARS_NN_pfcmpge: // Packed Floating-Point Comparison, Greater or Equal case STARS_NN_pfcmpgt: // Packed Floating-Point Comparison, Greater case STARS_NN_pfcmpeq: // Packed Floating-Point Comparison, Equal case STARS_NN_pfmin: // Packed Floating-Point Minimum case STARS_NN_pfmax: // Packed Floating-Point Maximum case STARS_NN_pi2fd: // Packed 32-bit Integer to Floating-Point case STARS_NN_pf2id: // Packed Floating-Point to 32-bit Integer case STARS_NN_pfrcp: // Packed Floating-Point Reciprocal Approximation case STARS_NN_pfrsqrt: // Packed Floating-Point Reciprocal Square Root Approximation case STARS_NN_pfmul: // Packed Floating-Point Multiplication case STARS_NN_pfrcpit1: // Packed Floating-Point Reciprocal First Iteration Step case STARS_NN_pfrsqit1: // Packed Floating-Point Reciprocal Square Root First Iteration Step case STARS_NN_pfrcpit2: // Packed Floating-Point Reciprocal Second Iteration Step case STARS_NN_pmulhrw: // Packed Floating-Point 16-bit Integer Multiply with rounding case STARS_NN_femms: // Faster entry/exit of the MMX or floating-point state case STARS_NN_prefetch: // Prefetch at least a 32-byte line into L1 data cache case STARS_NN_prefetchw: // Prefetch processor cache line into L1 data cache (mark as modified) SMP_fprintf(OutFile, "ERROR"); break; // Pentium III instructions case STARS_NN_addps: // Packed Single-FP Add case STARS_NN_addss: // Scalar Single-FP Add case STARS_NN_andnps: // Bitwise Logical And Not for Single-FP case STARS_NN_andps: // Bitwise Logical And for Single-FP case STARS_NN_cmpps: // Packed Single-FP Compare case STARS_NN_cmpss: // Scalar Single-FP Compare case STARS_NN_comiss: // Scalar Ordered Single-FP Compare and Set EFLAGS case STARS_NN_cvtpi2ps: // Packed signed INT32 to Packed Single-FP conversion case STARS_NN_cvtps2pi: // Packed Single-FP to Packed INT32 conversion case STARS_NN_cvtsi2ss: // Scalar signed INT32 to Single-FP conversion case STARS_NN_cvtss2si: // Scalar Single-FP to signed INT32 conversion case STARS_NN_cvttps2pi: // Packed Single-FP to Packed INT32 conversion (truncate) case STARS_NN_cvttss2si: // Scalar Single-FP to signed INT32 conversion (truncate) case STARS_NN_divps: // Packed Single-FP Divide case STARS_NN_divss: // Scalar Single-FP Divide case STARS_NN_ldmxcsr: // Load Streaming SIMD Extensions Technology Control/Status Register case STARS_NN_maxps: // Packed Single-FP Maximum case STARS_NN_maxss: // Scalar Single-FP Maximum case STARS_NN_minps: // Packed Single-FP Minimum case STARS_NN_minss: // Scalar Single-FP Minimum case STARS_NN_movaps: // Move Aligned Four Packed Single-FP case STARS_NN_movhlps: // Move High to Low Packed Single-FP case STARS_NN_movhps: // Move High Packed Single-FP case STARS_NN_movlhps: // Move Low to High Packed Single-FP case STARS_NN_movlps: // Move Low Packed Single-FP case STARS_NN_movmskps: // Move Mask to Register case STARS_NN_movss: // Move Scalar Single-FP case STARS_NN_movups: // Move Unaligned Four Packed Single-FP case STARS_NN_mulps: // Packed Single-FP Multiply case STARS_NN_mulss: // Scalar Single-FP Multiply case STARS_NN_orps: // Bitwise Logical OR for Single-FP Data case STARS_NN_rcpps: // Packed Single-FP Reciprocal case STARS_NN_rcpss: // Scalar Single-FP Reciprocal case STARS_NN_rsqrtps: // Packed Single-FP Square Root Reciprocal case STARS_NN_rsqrtss: // Scalar Single-FP Square Root Reciprocal case STARS_NN_shufps: // Shuffle Single-FP case STARS_NN_sqrtps: // Packed Single-FP Square Root case STARS_NN_sqrtss: // Scalar Single-FP Square Root case STARS_NN_stmxcsr: // Store Streaming SIMD Extensions Technology Control/Status Register case STARS_NN_subps: // Packed Single-FP Subtract case STARS_NN_subss: // Scalar Single-FP Subtract case STARS_NN_ucomiss: // Scalar Unordered Single-FP Compare and Set EFLAGS case STARS_NN_unpckhps: // Unpack High Packed Single-FP Data case STARS_NN_unpcklps: // Unpack Low Packed Single-FP Data case STARS_NN_xorps: // Bitwise Logical XOR for Single-FP Data case STARS_NN_pavgb: // Packed Average (Byte) case STARS_NN_pavgw: // Packed Average (Word) case STARS_NN_pextrw: // Extract Word case STARS_NN_pinsrw: // Insert Word case STARS_NN_pmaxsw: // Packed Signed Integer Word Maximum case STARS_NN_pmaxub: // Packed Unsigned Integer Byte Maximum case STARS_NN_pminsw: // Packed Signed Integer Word Minimum case STARS_NN_pminub: // Packed Unsigned Integer Byte Minimum case STARS_NN_pmovmskb: // Move Byte Mask to Integer case STARS_NN_pmulhuw: // Packed Multiply High Unsigned case STARS_NN_psadbw: // Packed Sum of Absolute Differences case STARS_NN_pshufw: // Packed Shuffle Word case STARS_NN_maskmovq: // Byte Mask write case STARS_NN_movntps: // Move Aligned Four Packed Single-FP Non Temporal case STARS_NN_movntq: // Move 64 Bits Non Temporal case STARS_NN_prefetcht0: // Prefetch to all cache levels case STARS_NN_prefetcht1: // Prefetch to all cache levels case STARS_NN_prefetcht2: // Prefetch to L2 cache case STARS_NN_prefetchnta: // Prefetch to L1 cache case STARS_NN_sfence: // Store Fence SMP_fprintf(OutFile, "ERROR"); break; // Pentium III Pseudo instructions case STARS_NN_cmpeqps: // Packed Single-FP Compare EQ case STARS_NN_cmpltps: // Packed Single-FP Compare LT case STARS_NN_cmpleps: // Packed Single-FP Compare LE case STARS_NN_cmpunordps: // Packed Single-FP Compare UNORD case STARS_NN_cmpneqps: // Packed Single-FP Compare NOT EQ case STARS_NN_cmpnltps: // Packed Single-FP Compare NOT LT case STARS_NN_cmpnleps: // Packed Single-FP Compare NOT LE case STARS_NN_cmpordps: // Packed Single-FP Compare ORDERED case STARS_NN_cmpeqss: // Scalar Single-FP Compare EQ case STARS_NN_cmpltss: // Scalar Single-FP Compare LT case STARS_NN_cmpless: // Scalar Single-FP Compare LE case STARS_NN_cmpunordss: // Scalar Single-FP Compare UNORD case STARS_NN_cmpneqss: // Scalar Single-FP Compare NOT EQ case STARS_NN_cmpnltss: // Scalar Single-FP Compare NOT LT case STARS_NN_cmpnless: // Scalar Single-FP Compare NOT LE case STARS_NN_cmpordss: // Scalar Single-FP Compare ORDERED SMP_fprintf(OutFile, "ERROR"); break; // AMD K7 instructions case STARS_NN_pf2iw: // Packed Floating-Point to Integer with Sign Extend case STARS_NN_pfnacc: // Packed Floating-Point Negative Accumulate case STARS_NN_pfpnacc: // Packed Floating-Point Mixed Positive-Negative Accumulate case STARS_NN_pi2fw: // Packed 16-bit Integer to Floating-Point case STARS_NN_pswapd: // Packed Swap Double Word SMP_fprintf(OutFile, "ERROR"); break; // Undocumented FP instructions (thanks to norbert.juffa@adm.com) case STARS_NN_fstp1: // Alias of Store Real and Pop case STARS_NN_fcom2: // Alias of Compare Real case STARS_NN_fcomp3: // Alias of Compare Real and Pop case STARS_NN_fxch4: // Alias of Exchange Registers case STARS_NN_fcomp5: // Alias of Compare Real and Pop case STARS_NN_ffreep: // Free Register and Pop case STARS_NN_fxch7: // Alias of Exchange Registers case STARS_NN_fstp8: // Alias of Store Real and Pop case STARS_NN_fstp9: // Alias of Store Real and Pop SMP_fprintf(OutFile, "ERROR"); break; // Pentium 4 instructions case STARS_NN_addpd: // Add Packed Double-Precision Floating-Point Values case STARS_NN_addsd: // Add Scalar Double-Precision Floating-Point Values case STARS_NN_andnpd: // Bitwise Logical AND NOT of Packed Double-Precision Floating-Point Values case STARS_NN_andpd: // Bitwise Logical AND of Packed Double-Precision Floating-Point Values case STARS_NN_clflush: // Flush Cache Line case STARS_NN_cmppd: // Compare Packed Double-Precision Floating-Point Values case STARS_NN_cmpsd: // Compare Scalar Double-Precision Floating-Point Values case STARS_NN_comisd: // Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS case STARS_NN_cvtdq2pd: // Convert Packed Doubleword Integers to Packed Single-Precision Floating-Point Values case STARS_NN_cvtdq2ps: // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values case STARS_NN_cvtpd2dq: // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers case STARS_NN_cvtpd2pi: // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers case STARS_NN_cvtpd2ps: // Convert Packed Double-Precision Floating-Point Values to Packed Single-Precision Floating-Point Values case STARS_NN_cvtpi2pd: // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values case STARS_NN_cvtps2dq: // Convert Packed Single-Precision Floating-Point Values to Packed Doubleword Integers case STARS_NN_cvtps2pd: // Convert Packed Single-Precision Floating-Point Values to Packed Double-Precision Floating-Point Values case STARS_NN_cvtsd2si: // Convert Scalar Double-Precision Floating-Point Value to Doubleword Integer case STARS_NN_cvtsd2ss: // Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value case STARS_NN_cvtsi2sd: // Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value case STARS_NN_cvtss2sd: // Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value case STARS_NN_cvttpd2dq: // Convert With Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers case STARS_NN_cvttpd2pi: // Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers case STARS_NN_cvttps2dq: // Convert With Truncation Packed Single-Precision Floating-Point Values to Packed Doubleword Integers case STARS_NN_cvttsd2si: // Convert with Truncation Scalar Double-Precision Floating-Point Value to Doubleword Integer case STARS_NN_divpd: // Divide Packed Double-Precision Floating-Point Values case STARS_NN_divsd: // Divide Scalar Double-Precision Floating-Point Values case STARS_NN_lfence: // Load Fence case STARS_NN_maskmovdqu: // Store Selected Bytes of Double Quadword case STARS_NN_maxpd: // Return Maximum Packed Double-Precision Floating-Point Values case STARS_NN_maxsd: // Return Maximum Scalar Double-Precision Floating-Point Value case STARS_NN_mfence: // Memory Fence case STARS_NN_minpd: // Return Minimum Packed Double-Precision Floating-Point Values case STARS_NN_minsd: // Return Minimum Scalar Double-Precision Floating-Point Value case STARS_NN_movapd: // Move Aligned Packed Double-Precision Floating-Point Values case STARS_NN_movdq2q: // Move Quadword from XMM to MMX Register case STARS_NN_movdqa: // Move Aligned Double Quadword case STARS_NN_movdqu: // Move Unaligned Double Quadword case STARS_NN_movhpd: // Move High Packed Double-Precision Floating-Point Values case STARS_NN_movlpd: // Move Low Packed Double-Precision Floating-Point Values case STARS_NN_movmskpd: // Extract Packed Double-Precision Floating-Point Sign Mask case STARS_NN_movntdq: // Store Double Quadword Using Non-Temporal Hint case STARS_NN_movnti: // Store Doubleword Using Non-Temporal Hint case STARS_NN_movntpd: // Store Packed Double-Precision Floating-Point Values Using Non-Temporal Hint case STARS_NN_movq2dq: // Move Quadword from MMX to XMM Register case STARS_NN_movsd: // Move Scalar Double-Precision Floating-Point Values case STARS_NN_movupd: // Move Unaligned Packed Double-Precision Floating-Point Values case STARS_NN_mulpd: // Multiply Packed Double-Precision Floating-Point Values case STARS_NN_mulsd: // Multiply Scalar Double-Precision Floating-Point Values case STARS_NN_orpd: // Bitwise Logical OR of Double-Precision Floating-Point Values case STARS_NN_paddq: // Add Packed Quadword Integers case STARS_NN_pause: // Spin Loop Hint case STARS_NN_pmuludq: // Multiply Packed Unsigned Doubleword Integers case STARS_NN_pshufd: // Shuffle Packed Doublewords case STARS_NN_pshufhw: // Shuffle Packed High Words case STARS_NN_pshuflw: // Shuffle Packed Low Words case STARS_NN_pslldq: // Shift Double Quadword Left Logical case STARS_NN_psrldq: // Shift Double Quadword Right Logical case STARS_NN_psubq: // Subtract Packed Quadword Integers case STARS_NN_punpckhqdq: // Unpack High Data case STARS_NN_punpcklqdq: // Unpack Low Data case STARS_NN_shufpd: // Shuffle Packed Double-Precision Floating-Point Values case STARS_NN_sqrtpd: // Compute Square Roots of Packed Double-Precision Floating-Point Values case STARS_NN_sqrtsd: // Compute Square Rootof Scalar Double-Precision Floating-Point Value case STARS_NN_subpd: // Subtract Packed Double-Precision Floating-Point Values case STARS_NN_subsd: // Subtract Scalar Double-Precision Floating-Point Values case STARS_NN_ucomisd: // Unordered Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS case STARS_NN_unpckhpd: // Unpack and Interleave High Packed Double-Precision Floating-Point Values case STARS_NN_unpcklpd: // Unpack and Interleave Low Packed Double-Precision Floating-Point Values case STARS_NN_xorpd: // Bitwise Logical OR of Double-Precision Floating-Point Values SMP_fprintf(OutFile, "ERROR"); break; // AMD syscall/sysret instructions case STARS_NN_syscall: // Low latency system call case STARS_NN_sysret: // Return from system call SMP_fprintf(OutFile, "ERROR"); break; // AMD64 instructions case STARS_NN_swapgs: // Exchange GS base with KernelGSBase MSR SMP_fprintf(OutFile, "ERROR"); break; // New Pentium instructions (SSE3) case STARS_NN_movddup: // Move One Double-FP and Duplicate case STARS_NN_movshdup: // Move Packed Single-FP High and Duplicate case STARS_NN_movsldup: // Move Packed Single-FP Low and Duplicate SMP_fprintf(OutFile, "ERROR"); break; // Missing AMD64 instructions case STARS_NN_movsxd: // Move with Sign-Extend Doubleword case STARS_NN_cmpxchg16b: // Compare and Exchange 16 Bytes SMP_fprintf(OutFile, "ERROR"); break; // SSE3 instructions case STARS_NN_addsubpd: // Add /Sub packed DP FP numbers case STARS_NN_addsubps: // Add /Sub packed SP FP numbers case STARS_NN_haddpd: // Add horizontally packed DP FP numbers case STARS_NN_haddps: // Add horizontally packed SP FP numbers case STARS_NN_hsubpd: // Sub horizontally packed DP FP numbers case STARS_NN_hsubps: // Sub horizontally packed SP FP numbers case STARS_NN_monitor: // Set up a linear address range to be monitored by hardware case STARS_NN_mwait: // Wait until write-back store performed within the range specified by the MONITOR instruction case STARS_NN_fisttp: // Store ST in intXX (chop) and pop case STARS_NN_lddqu: // Load unaligned integer 128-bit SMP_fprintf(OutFile, "ERROR"); break; // SSSE3 instructions case STARS_NN_psignb: // Packed SIGN Byte case STARS_NN_psignw: // Packed SIGN Word case STARS_NN_psignd: // Packed SIGN Doubleword case STARS_NN_pshufb: // Packed Shuffle Bytes case STARS_NN_pmulhrsw: // Packed Multiply High with Round and Scale case STARS_NN_pmaddubsw: // Multiply and Add Packed Signed and Unsigned Bytes case STARS_NN_phsubsw: // Packed Horizontal Subtract and Saturate case STARS_NN_phaddsw: // Packed Horizontal Add and Saturate case STARS_NN_phaddw: // Packed Horizontal Add Word case STARS_NN_phaddd: // Packed Horizontal Add Doubleword case STARS_NN_phsubw: // Packed Horizontal Subtract Word case STARS_NN_phsubd: // Packed Horizontal Subtract Doubleword case STARS_NN_palignr: // Packed Align Right case STARS_NN_pabsb: // Packed Absolute Value Byte case STARS_NN_pabsw: // Packed Absolute Value Word case STARS_NN_pabsd: // Packed Absolute Value Doubleword SMP_fprintf(OutFile, "ERROR"); break; // VMX instructions case STARS_NN_vmcall: // Call to VM Monitor case STARS_NN_vmclear: // Clear Virtual Machine Control Structure case STARS_NN_vmlaunch: // Launch Virtual Machine case STARS_NN_vmresume: // Resume Virtual Machine case STARS_NN_vmptrld: // Load Pointer to Virtual Machine Control Structure case STARS_NN_vmptrst: // Store Pointer to Virtual Machine Control Structure case STARS_NN_vmread: // Read Field from Virtual Machine Control Structure case STARS_NN_vmwrite: // Write Field from Virtual Machine Control Structure case STARS_NN_vmxoff: // Leave VMX Operation case STARS_NN_vmxon: // Enter VMX Operation SMP_fprintf(OutFile, "ERROR"); break; // Undefined Instruction case STARS_NN_ud2: // Undefined Instruction SMP_fprintf(OutFile, "ERROR"); break; // Added with x86-64 case STARS_NN_rdtscp: // Read Time-Stamp Counter and Processor ID SMP_fprintf(OutFile, "ERROR"); break; // Geode LX 3DNow! extensions case STARS_NN_pfrcpv: // Reciprocal Approximation for a Pair of 32-bit Floats case STARS_NN_pfrsqrtv: // Reciprocal Square Root Approximation for a Pair of 32-bit Floats SMP_fprintf(OutFile, "ERROR"); break; // SSE2 pseudoinstructions case STARS_NN_cmpeqpd: // Packed Double-FP Compare EQ case STARS_NN_cmpltpd: // Packed Double-FP Compare LT case STARS_NN_cmplepd: // Packed Double-FP Compare LE case STARS_NN_cmpunordpd: // Packed Double-FP Compare UNORD case STARS_NN_cmpneqpd: // Packed Double-FP Compare NOT EQ case STARS_NN_cmpnltpd: // Packed Double-FP Compare NOT LT case STARS_NN_cmpnlepd: // Packed Double-FP Compare NOT LE case STARS_NN_cmpordpd: // Packed Double-FP Compare ORDERED case STARS_NN_cmpeqsd: // Scalar Double-FP Compare EQ case STARS_NN_cmpltsd: // Scalar Double-FP Compare LT case STARS_NN_cmplesd: // Scalar Double-FP Compare LE case STARS_NN_cmpunordsd: // Scalar Double-FP Compare UNORD case STARS_NN_cmpneqsd: // Scalar Double-FP Compare NOT EQ case STARS_NN_cmpnltsd: // Scalar Double-FP Compare NOT LT case STARS_NN_cmpnlesd: // Scalar Double-FP Compare NOT LE case STARS_NN_cmpordsd: // Scalar Double-FP Compare ORDERED SMP_fprintf(OutFile, "ERROR"); break; // SSSE4.1 instructions case STARS_NN_blendpd: // Blend Packed Double Precision Floating-Point Values case STARS_NN_blendps: // Blend Packed Single Precision Floating-Point Values case STARS_NN_blendvpd: // Variable Blend Packed Double Precision Floating-Point Values case STARS_NN_blendvps: // Variable Blend Packed Single Precision Floating-Point Values case STARS_NN_dppd: // Dot Product of Packed Double Precision Floating-Point Values case STARS_NN_dpps: // Dot Product of Packed Single Precision Floating-Point Values case STARS_NN_extractps: // Extract Packed Single Precision Floating-Point Value case STARS_NN_insertps: // Insert Packed Single Precision Floating-Point Value case STARS_NN_movntdqa: // Load Double Quadword Non-Temporal Aligned Hint case STARS_NN_mpsadbw: // Compute Multiple Packed Sums of Absolute Difference case STARS_NN_packusdw: // Pack with Unsigned Saturation case STARS_NN_pblendvb: // Variable Blend Packed Bytes case STARS_NN_pblendw: // Blend Packed Words case STARS_NN_pcmpeqq: // Compare Packed Qword Data for Equal case STARS_NN_pextrb: // Extract Byte case STARS_NN_pextrd: // Extract Dword case STARS_NN_pextrq: // Extract Qword case STARS_NN_phminposuw: // Packed Horizontal Word Minimum case STARS_NN_pinsrb: // Insert Byte case STARS_NN_pinsrd: // Insert Dword case STARS_NN_pinsrq: // Insert Qword case STARS_NN_pmaxsb: // Maximum of Packed Signed Byte Integers case STARS_NN_pmaxsd: // Maximum of Packed Signed Dword Integers case STARS_NN_pmaxud: // Maximum of Packed Unsigned Dword Integers case STARS_NN_pmaxuw: // Maximum of Packed Word Integers case STARS_NN_pminsb: // Minimum of Packed Signed Byte Integers case STARS_NN_pminsd: // Minimum of Packed Signed Dword Integers case STARS_NN_pminud: // Minimum of Packed Unsigned Dword Integers case STARS_NN_pminuw: // Minimum of Packed Word Integers case STARS_NN_pmovsxbw: // Packed Move with Sign Extend case STARS_NN_pmovsxbd: // Packed Move with Sign Extend case STARS_NN_pmovsxbq: // Packed Move with Sign Extend case STARS_NN_pmovsxwd: // Packed Move with Sign Extend case STARS_NN_pmovsxwq: // Packed Move with Sign Extend case STARS_NN_pmovsxdq: // Packed Move with Sign Extend case STARS_NN_pmovzxbw: // Packed Move with Zero Extend case STARS_NN_pmovzxbd: // Packed Move with Zero Extend case STARS_NN_pmovzxbq: // Packed Move with Zero Extend case STARS_NN_pmovzxwd: // Packed Move with Zero Extend case STARS_NN_pmovzxwq: // Packed Move with Zero Extend case STARS_NN_pmovzxdq: // Packed Move with Zero Extend case STARS_NN_pmuldq: // Multiply Packed Signed Dword Integers case STARS_NN_pmulld: // Multiply Packed Signed Dword Integers and Store Low Result case STARS_NN_ptest: // Logical Compare case STARS_NN_roundpd: // Round Packed Double Precision Floating-Point Values case STARS_NN_roundps: // Round Packed Single Precision Floating-Point Values case STARS_NN_roundsd: // Round Scalar Double Precision Floating-Point Values case STARS_NN_roundss: // Round Scalar Single Precision Floating-Point Values SMP_fprintf(OutFile, "ERROR"); break; // SSSE4.2 instructions case STARS_NN_crc32: // Accumulate CRC32 Value case STARS_NN_pcmpestri: // Packed Compare Explicit Length Strings: Return Index case STARS_NN_pcmpestrm: // Packed Compare Explicit Length Strings: Return Mask case STARS_NN_pcmpistri: // Packed Compare Implicit Length Strings: Return Index case STARS_NN_pcmpistrm: // Packed Compare Implicit Length Strings: Return Mask case STARS_NN_pcmpgtq: // Compare Packed Data for Greater Than case STARS_NN_popcnt: // Return the Count of Number of Bits Set to 1 SMP_fprintf(OutFile, "ERROR"); break; // AMD SSE4a instructions case STARS_NN_extrq: // Extract Field From Register case STARS_NN_insertq: // Insert Field case STARS_NN_movntsd: // Move Non-Temporal Scalar Double-Precision Floating-Point case STARS_NN_movntss: // Move Non-Temporal Scalar Single-Precision Floating-Point case STARS_NN_lzcnt: // Leading Zero Count SMP_fprintf(OutFile, "ERROR"); break; // xsave/xrstor instructions case STARS_NN_xgetbv: // Get Value of Extended Control Register case STARS_NN_xrstor: // Restore Processor Extended States case STARS_NN_xsave: // Save Processor Extended States case STARS_NN_xsetbv: // Set Value of Extended Control Register SMP_fprintf(OutFile, "ERROR"); break; // Intel Safer Mode Extensions (SMX) case STARS_NN_getsec: // Safer Mode Extensions (SMX) Instruction SMP_fprintf(OutFile, "ERROR"); break; // AMD-V Virtualization ISA Extension case STARS_NN_clgi: // Clear Global Interrupt Flag case STARS_NN_invlpga: // Invalidate TLB Entry in a Specified ASID case STARS_NN_skinit: // Secure Init and Jump with Attestation case STARS_NN_stgi: // Set Global Interrupt Flag case STARS_NN_vmexit: // Stop Executing Guest: Begin Executing Host case STARS_NN_vmload: // Load State from VMCB case STARS_NN_vmmcall: // Call VMM case STARS_NN_vmrun: // Run Virtual Machine case STARS_NN_vmsave: // Save State to VMCB SMP_fprintf(OutFile, "ERROR"); break; // VMX+ instructions case STARS_NN_invept: // Invalidate Translations Derived from EPT case STARS_NN_invvpid: // Invalidate Translations Based on VPID SMP_fprintf(OutFile, "ERROR"); break; // Intel Atom instructions case STARS_NN_movbe: // Move Data After Swapping Bytes SMP_fprintf(OutFile, "ERROR"); break; // Intel AES instructions case STARS_NN_aesenc: // Perform One Round of an AES Encryption Flow case STARS_NN_aesenclast: // Perform the Last Round of an AES Encryption Flow case STARS_NN_aesdec: // Perform One Round of an AES Decryption Flow case STARS_NN_aesdeclast: // Perform the Last Round of an AES Decryption Flow case STARS_NN_aesimc: // Perform the AES InvMixColumn Transformation case STARS_NN_aeskeygenassist: // AES Round Key Generation Assist SMP_fprintf(OutFile, "ERROR"); break; // Carryless multiplication case STARS_NN_pclmulqdq: // Carry-Less Multiplication Quadword SMP_fprintf(OutFile, "ERROR"); break; // Returns modifies by operand size prefixes case STARS_NN_retnw: // Return Near from Procedure (use16) case STARS_NN_retnd: // Return Near from Procedure (use32) case STARS_NN_retnq: // Return Near from Procedure (use64) case STARS_NN_retfw: // Return Far from Procedure (use16) case STARS_NN_retfd: // Return Far from Procedure (use32) case STARS_NN_retfq: // Return Far from Procedure (use64) SMP_fprintf(OutFile, "return"); break; // RDRAND support case STARS_NN_rdrand: // Read Random Number SMP_fprintf(OutFile, "ERROR"); break; // new GPR instructions case STARS_NN_adcx: // Unsigned Integer Addition of Two Operands with Carry Flag case STARS_NN_adox: // Unsigned Integer Addition of Two Operands with Overflow Flag case STARS_NN_andn: // Logical AND NOT case STARS_NN_bextr: // Bit Field Extract case STARS_NN_blsi: // Extract Lowest Set Isolated Bit case STARS_NN_blsmsk: // Get Mask Up to Lowest Set Bit case STARS_NN_blsr: // Reset Lowest Set Bit case STARS_NN_bzhi: // Zero High Bits Starting with Specified Bit Position case STARS_NN_clac: // Clear AC Flag in EFLAGS Register case STARS_NN_mulx: // Unsigned Multiply Without Affecting Flags case STARS_NN_pdep: // Parallel Bits Deposit case STARS_NN_pext: // Parallel Bits Extract case STARS_NN_rorx: // Rotate Right Logical Without Affecting Flags case STARS_NN_sarx: // Shift Arithmetically Right Without Affecting Flags case STARS_NN_shlx: // Shift Logically Left Without Affecting Flags case STARS_NN_shrx: // Shift Logically Right Without Affecting Flags case STARS_NN_stac: // Set AC Flag in EFLAGS Register case STARS_NN_tzcnt: // Count the Number of Trailing Zero Bits case STARS_NN_xsaveopt: // Save Processor Extended States Optimized case STARS_NN_invpcid: // Invalidate Processor Context ID case STARS_NN_rdseed: // Read Random Seed case STARS_NN_rdfsbase: // Read FS Segment Base case STARS_NN_rdgsbase: // Read GS Segment Base case STARS_NN_wrfsbase: // Write FS Segment Base case STARS_NN_wrgsbase: // Write GS Segment Base SMP_fprintf(OutFile, "ERROR"); break; // new AVX instructions case STARS_NN_vaddpd: // Add Packed Double-Precision Floating-Point Values case STARS_NN_vaddps: // Packed Single-FP Add case STARS_NN_vaddsd: // Add Scalar Double-Precision Floating-Point Values case STARS_NN_vaddss: // Scalar Single-FP Add case STARS_NN_vaddsubpd: // Add /Sub packed DP FP numbers case STARS_NN_vaddsubps: // Add /Sub packed SP FP numbers case STARS_NN_vaesdec: // Perform One Round of an AES Decryption Flow case STARS_NN_vaesdeclast: // Perform the Last Round of an AES Decryption Flow case STARS_NN_vaesenc: // Perform One Round of an AES Encryption Flow case STARS_NN_vaesenclast: // Perform the Last Round of an AES Encryption Flow case STARS_NN_vaesimc: // Perform the AES InvMixColumn Transformation case STARS_NN_vaeskeygenassist: // AES Round Key Generation Assist case STARS_NN_vandnpd: // Bitwise Logical AND NOT of Packed Double-Precision Floating-Point Values case STARS_NN_vandnps: // Bitwise Logical And Not for Single-FP case STARS_NN_vandpd: // Bitwise Logical AND of Packed Double-Precision Floating-Point Values case STARS_NN_vandps: // Bitwise Logical And for Single-FP case STARS_NN_vblendpd: // Blend Packed Double Precision Floating-Point Values case STARS_NN_vblendps: // Blend Packed Single Precision Floating-Point Values case STARS_NN_vblendvpd: // Variable Blend Packed Double Precision Floating-Point Values case STARS_NN_vblendvps: // Variable Blend Packed Single Precision Floating-Point Values case STARS_NN_vbroadcastf128: // Broadcast 128 Bits of Floating-Point Data case STARS_NN_vbroadcasti128: // Broadcast 128 Bits of Integer Data case STARS_NN_vbroadcastsd: // Broadcast Double-Precision Floating-Point Element case STARS_NN_vbroadcastss: // Broadcast Single-Precision Floating-Point Element case STARS_NN_vcmppd: // Compare Packed Double-Precision Floating-Point Values case STARS_NN_vcmpps: // Packed Single-FP Compare case STARS_NN_vcmpsd: // Compare Scalar Double-Precision Floating-Point Values case STARS_NN_vcmpss: // Scalar Single-FP Compare case STARS_NN_vcomisd: // Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS case STARS_NN_vcomiss: // Scalar Ordered Single-FP Compare and Set EFLAGS case STARS_NN_vcvtdq2pd: // Convert Packed Doubleword Integers to Packed Single-Precision Floating-Point Values case STARS_NN_vcvtdq2ps: // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values case STARS_NN_vcvtpd2dq: // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers case STARS_NN_vcvtpd2ps: // Convert Packed Double-Precision Floating-Point Values to Packed Single-Precision Floating-Point Values case STARS_NN_vcvtph2ps: // Convert 16-bit FP Values to Single-Precision FP Values case STARS_NN_vcvtps2dq: // Convert Packed Single-Precision Floating-Point Values to Packed Doubleword Integers case STARS_NN_vcvtps2pd: // Convert Packed Single-Precision Floating-Point Values to Packed Double-Precision Floating-Point Values case STARS_NN_vcvtps2ph: // Convert Single-Precision FP value to 16-bit FP value case STARS_NN_vcvtsd2si: // Convert Scalar Double-Precision Floating-Point Value to Doubleword Integer case STARS_NN_vcvtsd2ss: // Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value case STARS_NN_vcvtsi2sd: // Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value case STARS_NN_vcvtsi2ss: // Scalar signed INT32 to Single-FP conversion case STARS_NN_vcvtss2sd: // Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value case STARS_NN_vcvtss2si: // Scalar Single-FP to signed INT32 conversion case STARS_NN_vcvttpd2dq: // Convert With Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers case STARS_NN_vcvttps2dq: // Convert With Truncation Packed Single-Precision Floating-Point Values to Packed Doubleword Integers case STARS_NN_vcvttsd2si: // Convert with Truncation Scalar Double-Precision Floating-Point Value to Doubleword Integer case STARS_NN_vcvttss2si: // Scalar Single-FP to signed INT32 conversion (truncate) case STARS_NN_vdivpd: // Divide Packed Double-Precision Floating-Point Values case STARS_NN_vdivps: // Packed Single-FP Divide case STARS_NN_vdivsd: // Divide Scalar Double-Precision Floating-Point Values case STARS_NN_vdivss: // Scalar Single-FP Divide case STARS_NN_vdppd: // Dot Product of Packed Double Precision Floating-Point Values case STARS_NN_vdpps: // Dot Product of Packed Single Precision Floating-Point Values case STARS_NN_vextractf128: // Extract Packed Floating-Point Values case STARS_NN_vextracti128: // Extract Packed Integer Values case STARS_NN_vextractps: // Extract Packed Floating-Point Values case STARS_NN_vfmadd132pd: // Fused Multiply-Add of Packed Double-Precision Floating-Point Values case STARS_NN_vfmadd132ps: // Fused Multiply-Add of Packed Single-Precision Floating-Point Values case STARS_NN_vfmadd132sd: // Fused Multiply-Add of Scalar Double-Precision Floating-Point Values case STARS_NN_vfmadd132ss: // Fused Multiply-Add of Scalar Single-Precision Floating-Point Values case STARS_NN_vfmadd213pd: // Fused Multiply-Add of Packed Double-Precision Floating-Point Values case STARS_NN_vfmadd213ps: // Fused Multiply-Add of Packed Single-Precision Floating-Point Values case STARS_NN_vfmadd213sd: // Fused Multiply-Add of Scalar Double-Precision Floating-Point Values case STARS_NN_vfmadd213ss: // Fused Multiply-Add of Scalar Single-Precision Floating-Point Values case STARS_NN_vfmadd231pd: // Fused Multiply-Add of Packed Double-Precision Floating-Point Values case STARS_NN_vfmadd231ps: // Fused Multiply-Add of Packed Single-Precision Floating-Point Values case STARS_NN_vfmadd231sd: // Fused Multiply-Add of Scalar Double-Precision Floating-Point Values case STARS_NN_vfmadd231ss: // Fused Multiply-Add of Scalar Single-Precision Floating-Point Values case STARS_NN_vfmaddsub132pd: // Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values case STARS_NN_vfmaddsub132ps: // Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values case STARS_NN_vfmaddsub213pd: // Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values case STARS_NN_vfmaddsub213ps: // Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values case STARS_NN_vfmaddsub231pd: // Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values case STARS_NN_vfmaddsub231ps: // Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values case STARS_NN_vfmsub132pd: // Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values case STARS_NN_vfmsub132ps: // Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values case STARS_NN_vfmsub132sd: // Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values case STARS_NN_vfmsub132ss: // Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values case STARS_NN_vfmsub213pd: // Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values case STARS_NN_vfmsub213ps: // Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values case STARS_NN_vfmsub213sd: // Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values case STARS_NN_vfmsub213ss: // Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values case STARS_NN_vfmsub231pd: // Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values case STARS_NN_vfmsub231ps: // Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values case STARS_NN_vfmsub231sd: // Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values case STARS_NN_vfmsub231ss: // Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values case STARS_NN_vfmsubadd132pd: // Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values case STARS_NN_vfmsubadd132ps: // Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values case STARS_NN_vfmsubadd213pd: // Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values case STARS_NN_vfmsubadd213ps: // Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values case STARS_NN_vfmsubadd231pd: // Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values case STARS_NN_vfmsubadd231ps: // Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values case STARS_NN_vfnmadd132pd: // Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values case STARS_NN_vfnmadd132ps: // Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values case STARS_NN_vfnmadd132sd: // Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values case STARS_NN_vfnmadd132ss: // Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values case STARS_NN_vfnmadd213pd: // Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values case STARS_NN_vfnmadd213ps: // Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values case STARS_NN_vfnmadd213sd: // Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values case STARS_NN_vfnmadd213ss: // Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values case STARS_NN_vfnmadd231pd: // Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values case STARS_NN_vfnmadd231ps: // Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values case STARS_NN_vfnmadd231sd: // Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values case STARS_NN_vfnmadd231ss: // Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values case STARS_NN_vfnmsub132pd: // Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values case STARS_NN_vfnmsub132ps: // Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values case STARS_NN_vfnmsub132sd: // Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values case STARS_NN_vfnmsub132ss: // Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values case STARS_NN_vfnmsub213pd: // Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values case STARS_NN_vfnmsub213ps: // Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values case STARS_NN_vfnmsub213sd: // Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values case STARS_NN_vfnmsub213ss: // Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values case STARS_NN_vfnmsub231pd: // Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values case STARS_NN_vfnmsub231ps: // Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values case STARS_NN_vfnmsub231sd: // Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values case STARS_NN_vfnmsub231ss: // Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values case STARS_NN_vgatherdps: // Gather Packed SP FP Values Using Signed Dword Indices case STARS_NN_vgatherdpd: // Gather Packed DP FP Values Using Signed Dword Indices case STARS_NN_vgatherqps: // Gather Packed SP FP Values Using Signed Qword Indices case STARS_NN_vgatherqpd: // Gather Packed DP FP Values Using Signed Qword Indices case STARS_NN_vhaddpd: // Add horizontally packed DP FP numbers case STARS_NN_vhaddps: // Add horizontally packed SP FP numbers case STARS_NN_vhsubpd: // Sub horizontally packed DP FP numbers case STARS_NN_vhsubps: // Sub horizontally packed SP FP numbers case STARS_NN_vinsertf128: // Insert Packed Floating-Point Values case STARS_NN_vinserti128: // Insert Packed Integer Values case STARS_NN_vinsertps: // Insert Packed Single Precision Floating-Point Value case STARS_NN_vlddqu: // Load Unaligned Packed Integer Values case STARS_NN_vldmxcsr: // Load Streaming SIMD Extensions Technology Control/Status Register case STARS_NN_vmaskmovdqu: // Store Selected Bytes of Double Quadword with NT Hint case STARS_NN_vmaskmovpd: // Conditionally Load Packed Double-Precision Floating-Point Values case STARS_NN_vmaskmovps: // Conditionally Load Packed Single-Precision Floating-Point Values case STARS_NN_vmaxpd: // Return Maximum Packed Double-Precision Floating-Point Values case STARS_NN_vmaxps: // Packed Single-FP Maximum case STARS_NN_vmaxsd: // Return Maximum Scalar Double-Precision Floating-Point Value case STARS_NN_vmaxss: // Scalar Single-FP Maximum case STARS_NN_vminpd: // Return Minimum Packed Double-Precision Floating-Point Values case STARS_NN_vminps: // Packed Single-FP Minimum case STARS_NN_vminsd: // Return Minimum Scalar Double-Precision Floating-Point Value case STARS_NN_vminss: // Scalar Single-FP Minimum case STARS_NN_vmovapd: // Move Aligned Packed Double-Precision Floating-Point Values case STARS_NN_vmovaps: // Move Aligned Four Packed Single-FP case STARS_NN_vmovd: // Move 32 bits case STARS_NN_vmovddup: // Move One Double-FP and Duplicate case STARS_NN_vmovdqa: // Move Aligned Double Quadword case STARS_NN_vmovdqu: // Move Unaligned Double Quadword case STARS_NN_vmovhlps: // Move High to Low Packed Single-FP case STARS_NN_vmovhpd: // Move High Packed Double-Precision Floating-Point Values case STARS_NN_vmovhps: // Move High Packed Single-FP case STARS_NN_vmovlhps: // Move Low to High Packed Single-FP case STARS_NN_vmovlpd: // Move Low Packed Double-Precision Floating-Point Values case STARS_NN_vmovlps: // Move Low Packed Single-FP case STARS_NN_vmovmskpd: // Extract Packed Double-Precision Floating-Point Sign Mask case STARS_NN_vmovmskps: // Move Mask to Register case STARS_NN_vmovntdq: // Store Double Quadword Using Non-Temporal Hint case STARS_NN_vmovntdqa: // Load Double Quadword Non-Temporal Aligned Hint case STARS_NN_vmovntpd: // Store Packed Double-Precision Floating-Point Values Using Non-Temporal Hint case STARS_NN_vmovntps: // Move Aligned Four Packed Single-FP Non Temporal #if (IDA_SDK_VERSION < 700) // Incredibly, these opcodes were removed in IDA Pro 7.0 case STARS_NN_vmovntsd: // Move Non-Temporal Scalar Double-Precision Floating-Point case STARS_NN_vmovntss: // Move Non-Temporal Scalar Single-Precision Floating-Point #endif case STARS_NN_vmovq: // Move 64 bits case STARS_NN_vmovsd: // Move Scalar Double-Precision Floating-Point Values case STARS_NN_vmovshdup: // Move Packed Single-FP High and Duplicate case STARS_NN_vmovsldup: // Move Packed Single-FP Low and Duplicate case STARS_NN_vmovss: // Move Scalar Single-FP case STARS_NN_vmovupd: // Move Unaligned Packed Double-Precision Floating-Point Values case STARS_NN_vmovups: // Move Unaligned Four Packed Single-FP case STARS_NN_vmpsadbw: // Compute Multiple Packed Sums of Absolute Difference case STARS_NN_vmulpd: // Multiply Packed Double-Precision Floating-Point Values case STARS_NN_vmulps: // Packed Single-FP Multiply case STARS_NN_vmulsd: // Multiply Scalar Double-Precision Floating-Point Values case STARS_NN_vmulss: // Scalar Single-FP Multiply case STARS_NN_vorpd: // Bitwise Logical OR of Double-Precision Floating-Point Values case STARS_NN_vorps: // Bitwise Logical OR for Single-FP Data case STARS_NN_vpabsb: // Packed Absolute Value Byte case STARS_NN_vpabsd: // Packed Absolute Value Doubleword case STARS_NN_vpabsw: // Packed Absolute Value Word case STARS_NN_vpackssdw: // Pack with Signed Saturation (Dword->Word) case STARS_NN_vpacksswb: // Pack with Signed Saturation (Word->Byte) case STARS_NN_vpackusdw: // Pack with Unsigned Saturation case STARS_NN_vpackuswb: // Pack with Unsigned Saturation (Word->Byte) case STARS_NN_vpaddb: // Packed Add Byte case STARS_NN_vpaddd: // Packed Add Dword case STARS_NN_vpaddq: // Add Packed Quadword Integers case STARS_NN_vpaddsb: // Packed Add with Saturation (Byte) case STARS_NN_vpaddsw: // Packed Add with Saturation (Word) case STARS_NN_vpaddusb: // Packed Add Unsigned with Saturation (Byte) case STARS_NN_vpaddusw: // Packed Add Unsigned with Saturation (Word) case STARS_NN_vpaddw: // Packed Add Word case STARS_NN_vpalignr: // Packed Align Right case STARS_NN_vpand: // Bitwise Logical And case STARS_NN_vpandn: // Bitwise Logical And Not case STARS_NN_vpavgb: // Packed Average (Byte) case STARS_NN_vpavgw: // Packed Average (Word) case STARS_NN_vpblendd: // Blend Packed Dwords case STARS_NN_vpblendvb: // Variable Blend Packed Bytes case STARS_NN_vpblendw: // Blend Packed Words case STARS_NN_vpbroadcastb: // Broadcast a Byte Integer case STARS_NN_vpbroadcastd: // Broadcast a Dword Integer case STARS_NN_vpbroadcastq: // Broadcast a Qword Integer case STARS_NN_vpbroadcastw: // Broadcast a Word Integer case STARS_NN_vpclmulqdq: // Carry-Less Multiplication Quadword case STARS_NN_vpcmpeqb: // Packed Compare for Equal (Byte) case STARS_NN_vpcmpeqd: // Packed Compare for Equal (Dword) case STARS_NN_vpcmpeqq: // Compare Packed Qword Data for Equal case STARS_NN_vpcmpeqw: // Packed Compare for Equal (Word) case STARS_NN_vpcmpestri: // Packed Compare Explicit Length Strings: Return Index case STARS_NN_vpcmpestrm: // Packed Compare Explicit Length Strings: Return Mask case STARS_NN_vpcmpgtb: // Packed Compare for Greater Than (Byte) case STARS_NN_vpcmpgtd: // Packed Compare for Greater Than (Dword) case STARS_NN_vpcmpgtq: // Compare Packed Data for Greater Than case STARS_NN_vpcmpgtw: // Packed Compare for Greater Than (Word) case STARS_NN_vpcmpistri: // Packed Compare Implicit Length Strings: Return Index case STARS_NN_vpcmpistrm: // Packed Compare Implicit Length Strings: Return Mask case STARS_NN_vperm2f128: // Permute Floating-Point Values case STARS_NN_vperm2i128: // Permute Integer Values case STARS_NN_vpermd: // Full Doublewords Element Permutation case STARS_NN_vpermilpd: // Permute Double-Precision Floating-Point Values case STARS_NN_vpermilps: // Permute Single-Precision Floating-Point Values case STARS_NN_vpermpd: // Permute Double-Precision Floating-Point Elements case STARS_NN_vpermps: // Permute Single-Precision Floating-Point Elements case STARS_NN_vpermq: // Qwords Element Permutation case STARS_NN_vpextrb: // Extract Byte case STARS_NN_vpextrd: // Extract Dword case STARS_NN_vpextrq: // Extract Qword case STARS_NN_vpextrw: // Extract Word case STARS_NN_vpgatherdd: // Gather Packed Dword Values Using Signed Dword Indices case STARS_NN_vpgatherdq: // Gather Packed Qword Values Using Signed Dword Indices case STARS_NN_vpgatherqd: // Gather Packed Dword Values Using Signed Qword Indices case STARS_NN_vpgatherqq: // Gather Packed Qword Values Using Signed Qword Indices case STARS_NN_vphaddd: // Packed Horizontal Add Doubleword case STARS_NN_vphaddsw: // Packed Horizontal Add and Saturate case STARS_NN_vphaddw: // Packed Horizontal Add Word case STARS_NN_vphminposuw: // Packed Horizontal Word Minimum case STARS_NN_vphsubd: // Packed Horizontal Subtract Doubleword case STARS_NN_vphsubsw: // Packed Horizontal Subtract and Saturate case STARS_NN_vphsubw: // Packed Horizontal Subtract Word case STARS_NN_vpinsrb: // Insert Byte case STARS_NN_vpinsrd: // Insert Dword case STARS_NN_vpinsrq: // Insert Qword case STARS_NN_vpinsrw: // Insert Word case STARS_NN_vpmaddubsw: // Multiply and Add Packed Signed and Unsigned Bytes case STARS_NN_vpmaddwd: // Packed Multiply and Add case STARS_NN_vpmaskmovd: // Conditionally Store Dword Values Using Mask case STARS_NN_vpmaskmovq: // Conditionally Store Qword Values Using Mask case STARS_NN_vpmaxsb: // Maximum of Packed Signed Byte Integers case STARS_NN_vpmaxsd: // Maximum of Packed Signed Dword Integers case STARS_NN_vpmaxsw: // Packed Signed Integer Word Maximum case STARS_NN_vpmaxub: // Packed Unsigned Integer Byte Maximum case STARS_NN_vpmaxud: // Maximum of Packed Unsigned Dword Integers case STARS_NN_vpmaxuw: // Maximum of Packed Word Integers case STARS_NN_vpminsb: // Minimum of Packed Signed Byte Integers case STARS_NN_vpminsd: // Minimum of Packed Signed Dword Integers case STARS_NN_vpminsw: // Packed Signed Integer Word Minimum case STARS_NN_vpminub: // Packed Unsigned Integer Byte Minimum case STARS_NN_vpminud: // Minimum of Packed Unsigned Dword Integers case STARS_NN_vpminuw: // Minimum of Packed Word Integers case STARS_NN_vpmovmskb: // Move Byte Mask to Integer case STARS_NN_vpmovsxbd: // Packed Move with Sign Extend case STARS_NN_vpmovsxbq: // Packed Move with Sign Extend case STARS_NN_vpmovsxbw: // Packed Move with Sign Extend case STARS_NN_vpmovsxdq: // Packed Move with Sign Extend case STARS_NN_vpmovsxwd: // Packed Move with Sign Extend case STARS_NN_vpmovsxwq: // Packed Move with Sign Extend case STARS_NN_vpmovzxbd: // Packed Move with Zero Extend case STARS_NN_vpmovzxbq: // Packed Move with Zero Extend case STARS_NN_vpmovzxbw: // Packed Move with Zero Extend case STARS_NN_vpmovzxdq: // Packed Move with Zero Extend case STARS_NN_vpmovzxwd: // Packed Move with Zero Extend case STARS_NN_vpmovzxwq: // Packed Move with Zero Extend case STARS_NN_vpmuldq: // Multiply Packed Signed Dword Integers case STARS_NN_vpmulhrsw: // Packed Multiply High with Round and Scale case STARS_NN_vpmulhuw: // Packed Multiply High Unsigned case STARS_NN_vpmulhw: // Packed Multiply High case STARS_NN_vpmulld: // Multiply Packed Signed Dword Integers and Store Low Result case STARS_NN_vpmullw: // Packed Multiply Low case STARS_NN_vpmuludq: // Multiply Packed Unsigned Doubleword Integers case STARS_NN_vpor: // Bitwise Logical Or case STARS_NN_vpsadbw: // Packed Sum of Absolute Differences case STARS_NN_vpshufb: // Packed Shuffle Bytes case STARS_NN_vpshufd: // Shuffle Packed Doublewords case STARS_NN_vpshufhw: // Shuffle Packed High Words case STARS_NN_vpshuflw: // Shuffle Packed Low Words case STARS_NN_vpsignb: // Packed SIGN Byte case STARS_NN_vpsignd: // Packed SIGN Doubleword case STARS_NN_vpsignw: // Packed SIGN Word case STARS_NN_vpslld: // Packed Shift Left Logical (Dword) case STARS_NN_vpslldq: // Shift Double Quadword Left Logical case STARS_NN_vpsllq: // Packed Shift Left Logical (Qword) case STARS_NN_vpsllvd: // Variable Bit Shift Left Logical (Dword) case STARS_NN_vpsllvq: // Variable Bit Shift Left Logical (Qword) case STARS_NN_vpsllw: // Packed Shift Left Logical (Word) case STARS_NN_vpsrad: // Packed Shift Right Arithmetic (Dword) case STARS_NN_vpsravd: // Variable Bit Shift Right Arithmetic case STARS_NN_vpsraw: // Packed Shift Right Arithmetic (Word) case STARS_NN_vpsrld: // Packed Shift Right Logical (Dword) case STARS_NN_vpsrldq: // Shift Double Quadword Right Logical (Qword) case STARS_NN_vpsrlq: // Packed Shift Right Logical (Qword) case STARS_NN_vpsrlvd: // Variable Bit Shift Right Logical (Dword) case STARS_NN_vpsrlvq: // Variable Bit Shift Right Logical (Qword) case STARS_NN_vpsrlw: // Packed Shift Right Logical (Word) case STARS_NN_vpsubb: // Packed Subtract Byte case STARS_NN_vpsubd: // Packed Subtract Dword case STARS_NN_vpsubq: // Subtract Packed Quadword Integers case STARS_NN_vpsubsb: // Packed Subtract with Saturation (Byte) case STARS_NN_vpsubsw: // Packed Subtract with Saturation (Word) case STARS_NN_vpsubusb: // Packed Subtract Unsigned with Saturation (Byte) case STARS_NN_vpsubusw: // Packed Subtract Unsigned with Saturation (Word) case STARS_NN_vpsubw: // Packed Subtract Word case STARS_NN_vptest: // Logical Compare case STARS_NN_vpunpckhbw: // Unpack High Packed Data (Byte->Word) case STARS_NN_vpunpckhdq: // Unpack High Packed Data (Dword->Qword) case STARS_NN_vpunpckhqdq: // Unpack High Packed Data (Qword->Xmmword) case STARS_NN_vpunpckhwd: // Unpack High Packed Data (Word->Dword) case STARS_NN_vpunpcklbw: // Unpack Low Packed Data (Byte->Word) case STARS_NN_vpunpckldq: // Unpack Low Packed Data (Dword->Qword) case STARS_NN_vpunpcklqdq: // Unpack Low Packed Data (Qword->Xmmword) case STARS_NN_vpunpcklwd: // Unpack Low Packed Data (Word->Dword) case STARS_NN_vpxor: // Bitwise Logical Exclusive Or case STARS_NN_vrcpps: // Packed Single-FP Reciprocal case STARS_NN_vrcpss: // Scalar Single-FP Reciprocal case STARS_NN_vroundpd: // Round Packed Double Precision Floating-Point Values case STARS_NN_vroundps: // Round Packed Single Precision Floating-Point Values case STARS_NN_vroundsd: // Round Scalar Double Precision Floating-Point Values case STARS_NN_vroundss: // Round Scalar Single Precision Floating-Point Values case STARS_NN_vrsqrtps: // Packed Single-FP Square Root Reciprocal case STARS_NN_vrsqrtss: // Scalar Single-FP Square Root Reciprocal case STARS_NN_vshufpd: // Shuffle Packed Double-Precision Floating-Point Values case STARS_NN_vshufps: // Shuffle Single-FP case STARS_NN_vsqrtpd: // Compute Square Roots of Packed Double-Precision Floating-Point Values case STARS_NN_vsqrtps: // Packed Single-FP Square Root case STARS_NN_vsqrtsd: // Compute Square Rootof Scalar Double-Precision Floating-Point Value case STARS_NN_vsqrtss: // Scalar Single-FP Square Root case STARS_NN_vstmxcsr: // Store Streaming SIMD Extensions Technology Control/Status Register case STARS_NN_vsubpd: // Subtract Packed Double-Precision Floating-Point Values case STARS_NN_vsubps: // Packed Single-FP Subtract case STARS_NN_vsubsd: // Subtract Scalar Double-Precision Floating-Point Values case STARS_NN_vsubss: // Scalar Single-FP Subtract case STARS_NN_vtestpd: // Packed Double-Precision Floating-Point Bit Test case STARS_NN_vtestps: // Packed Single-Precision Floating-Point Bit Test case STARS_NN_vucomisd: // Unordered Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS case STARS_NN_vucomiss: // Scalar Unordered Single-FP Compare and Set EFLAGS case STARS_NN_vunpckhpd: // Unpack and Interleave High Packed Double-Precision Floating-Point Values case STARS_NN_vunpckhps: // Unpack High Packed Single-FP Data case STARS_NN_vunpcklpd: // Unpack and Interleave Low Packed Double-Precision Floating-Point Values case STARS_NN_vunpcklps: // Unpack Low Packed Single-FP Data case STARS_NN_vxorpd: // Bitwise Logical OR of Double-Precision Floating-Point Values case STARS_NN_vxorps: // Bitwise Logical XOR for Single-FP Data case STARS_NN_vzeroall: // Zero All YMM Registers case STARS_NN_vzeroupper: // Zero Upper Bits of YMM Registers SMP_fprintf(OutFile, "ERROR"); break; // Transactional Synchronization Extensions case STARS_NN_xabort: // Transaction Abort case STARS_NN_xbegin: // Transaction Begin case STARS_NN_xend: // Transaction End case STARS_NN_xtest: // Test If In Transactional Execution SMP_fprintf(OutFile, "ERROR"); break; // Virtual PC synthetic instructions case STARS_NN_vmgetinfo: // Virtual PC - Get VM Information case STARS_NN_vmsetinfo: // Virtual PC - Set VM Information case STARS_NN_vmdxdsbl: // Virtual PC - Disable Direct Execution case STARS_NN_vmdxenbl: // Virtual PC - Enable Direct Execution case STARS_NN_vmcpuid: // Virtual PC - Virtualized CPU Information case STARS_NN_vmhlt: // Virtual PC - Halt case STARS_NN_vmsplaf: // Virtual PC - Spin Lock Acquisition Failed case STARS_NN_vmpushfd: // Virtual PC - Push virtualized flags register case STARS_NN_vmpopfd: // Virtual PC - Pop virtualized flags register case STARS_NN_vmcli: // Virtual PC - Clear Interrupt Flag case STARS_NN_vmsti: // Virtual PC - Set Interrupt Flag case STARS_NN_vmiretd: // Virtual PC - Return From Interrupt case STARS_NN_vmsgdt: // Virtual PC - Store Global Descriptor Table case STARS_NN_vmsidt: // Virtual PC - Store Interrupt Descriptor Table case STARS_NN_vmsldt: // Virtual PC - Store Local Descriptor Table case STARS_NN_vmstr: // Virtual PC - Store Task Register case STARS_NN_vmsdte: // Virtual PC - Store to Descriptor Table Entry case STARS_NN_vpcext: // Virtual PC - ISA extension SMP_fprintf(OutFile, "ERROR"); break; case STARS_NN_last: SMP_fprintf(OutFile, "ERROR"); break; default: SMP_fprintf(OutFile, "ERROR"); break; } return; } // end of PrintOpcode() // MACHINE DEPENDENT: Is operand type a known type that we want to analyze? bool MDKnownOperandType(const STARSOpndTypePtr &TempOp) { bool GoodOpType = (nullptr != TempOp) && TempOp->MDIsKnownOpType(); #if SMP_DEBUG_OPERAND_TYPES if (!GoodOpType && (! TempOp->IsVoidOp())) { SMP_msg("WARNING: Operand type %d \n", TempOp->GetOpType()); } #endif return GoodOpType; } // Meet function over any two types in the type lattice. SMPOperandType SMPTypeMeet(SMPOperandType Type1, SMPOperandType Type2, bool &ErrorFlag) { SMPOperandType MeetType = UNKNOWN; ErrorFlag = false; bool ProfDerived = IsProfDerived(Type1) || IsProfDerived(Type2); if (IsEqType(UNINIT, Type1)) MeetType = Type2; else if (IsEqType(UNINIT, Type2) || IsEqType(Type1, Type2) || IsUnknown(Type1)) MeetType = Type1; else if (IsNumeric(Type1)) { if (IsNumeric(Type2)) // one is NUMERIC, one is CODEPTR MeetType = CODEPTR; else if (IsDataPtr(Type2) || IsUnknown(Type2)) MeetType = UNKNOWN; else { SMP_msg("ERROR #1 in SMPTypeMeet.\n"); ErrorFlag = true; } } else if (IsDataPtr(Type1)) { if (IsDataPtr(Type2)) // two different POINTER subtypes MeetType = POINTER; else if (IsNumeric(Type2) || IsUnknown(Type2)) MeetType = UNKNOWN; else { SMP_msg("ERROR #2 in SMPTypeMeet.\n"); ErrorFlag = true; } } if (ProfDerived && IsNotEqType(UNINIT, MeetType)) MeetType = MakeProfDerived(MeetType); return MeetType; } // end of SMPTypeMeet() // Meet function for SCCP constant propagation; updates NewConstStruct void STARSConstantTypeMeet(struct STARS_SCCP_Const_Struct OldConstStruct, struct STARS_SCCP_Const_Struct &NewConstStruct) { if ((OldConstStruct.ConstType != STARS_CONST_BOTTOM) && (NewConstStruct.ConstType != STARS_CONST_TOP)) { // We have four possibilities. Three of them have NewConstStruct lower in the type lattice, which means the final // result is simply the NewConstStruct (i.e. if Old == TOP, New == CONST or BOTTOM; or Old == CONST, New == BOTTOM). // The fourth possibility is that Old == CONST, New == CONST, and we have to check the const values for consistency, // lowering NewConstStruct to BOTTOM if they are inconsistent. if ((OldConstStruct.ConstType == STARS_CONST_HAS_VALUE) && (NewConstStruct.ConstType == STARS_CONST_HAS_VALUE)) { if (OldConstStruct.ConstValue != NewConstStruct.ConstValue) { // inconsistent const values NewConstStruct.ConstType = STARS_CONST_BOTTOM; } } } else { NewConstStruct = OldConstStruct; } return; } // end of STARSConstantTypeMeet() // If one constant is greater width than another, trim it down. void HandleConstStructWidths(size_t LeftByteWidth, size_t RightByteWidth, struct STARS_SCCP_Const_Struct &LeftValue, struct STARS_SCCP_Const_Struct &RightValue) { size_t LesserByteWidth = LeftByteWidth; if (LeftByteWidth > RightByteWidth) { LesserByteWidth = RightByteWidth; if (RightByteWidth == 4) { LeftValue.ConstValue &= 0xffffffff; } else if (RightByteWidth == 2) { LeftValue.ConstValue &= 0xffff; } else if (RightByteWidth == 1) { LeftValue.ConstValue &= 0xff; } else { SMP_msg("ERROR: Const struct width of %zu\n", RightByteWidth); } } else if (RightByteWidth > LeftByteWidth) { if (LeftByteWidth == 4) { RightValue.ConstValue &= 0xffffffff; } else if (LeftByteWidth == 2) { RightValue.ConstValue &= 0xffff; } else if (LeftByteWidth == 1) { RightValue.ConstValue &= 0xff; } else { SMP_msg("ERROR: Const struct width of %zu\n", LeftByteWidth); } } if (LesserByteWidth <= 4) { // Solve potential problem even if Left and Right widths are the same. STARS_uval_t LimitValue = 0xffffffff; if (LesserByteWidth == 2) LimitValue = 0xffff; else if (LesserByteWidth == 1) LimitValue = 0xff; if (LeftValue.ConstValue > LimitValue) LeftValue.ConstValue &= LimitValue; if (RightValue.ConstValue > LimitValue) RightValue.ConstValue &= LimitValue; } return; } // end of HandleConstStructWidths() // ***************************************************************** // Class DisAsmString // ***************************************************************** DisAsmString::DisAsmString(void) { this->CurrAddr = STARS_BADADDR; this->StringLen = 0; this->CachedDisAsm[0] = '\0'; return; } char *DisAsmString::GetDisAsm(STARS_ea_t InstAddr, bool MarkerInst) { if (InstAddr != this->CurrAddr) { this->CurrAddr = InstAddr; if (MarkerInst) { this->SetMarkerInstText(InstAddr); } else { bool IDAsuccess = SMP_generate_disasm_line(InstAddr, this->CachedDisAsm, sizeof(this->CachedDisAsm) - 1); if (IDAsuccess) { // Remove interactive color-coding tags. this->StringLen = SMP_tag_remove(this->CachedDisAsm, this->CachedDisAsm, sizeof(this->CachedDisAsm) - 1); if (-1 >= StringLen) { SMP_msg("ERROR: tag_remove failed at addr %lx \n", (unsigned long) InstAddr); this->CachedDisAsm[0] = '\0'; } } else { SMP_msg("ERROR: generate_disasm_line failed at addr %lx \n", (unsigned long) InstAddr); this->CachedDisAsm[0] = '\0'; } } } return (char *) this->CachedDisAsm; } // end of DisAsmString::GetDisasm() // Set the disasm text for the SSA marker instructions, which have no IDA Pro disasm because // they are pseudo-instructions that we add at the top of each function to hold LiveIn name info. void DisAsmString::SetMarkerInstText(STARS_ea_t InstAddr) { if (InstAddr != this->CurrAddr) { this->CurrAddr = InstAddr; SMP_strncpy(this->CachedDisAsm, "\tfnop\t; Top of function SSA marker for SMP", sizeof(this->CachedDisAsm) - 1); this->StringLen = (STARS_ssize_t) strlen(this->CachedDisAsm); } return; } // end of DisAsmString::SetMarkerInstText() DisAsmString DisAsmText; // ***************************************************************** // Class DefOrUse // ***************************************************************** // Default constructor to make the compilers happy. DefOrUse::DefOrUse(void) { this->Operand = nullptr; this->SSANumber = -2; this->OpType = UNINIT; this->NonSpeculativeOpType = UNINIT; this->MetadataStatus = DEF_METADATA_UNANALYZED; this->booleans1 = 0; return; } // Constructor. DefOrUse::DefOrUse(STARSOpndTypePtr Ref, SMPOperandType Type, int SSASub) { if (Ref->IsRegOp()) { // We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis // and type inference systems. STARSOpndTypePtr Ref2 = CloneIfSubwordReg(Ref); CanonicalizeOpnd(Ref2); this->Operand = Ref2; } else { this->Operand = Ref; } this->SSANumber = SSASub; this->OpType = Type; #if 0 // Not true if we construct a reference for fptr shadowing late in our analyses. assert(!IsProfDerived(Type)); #endif this->NonSpeculativeOpType = Type; this->MetadataStatus = DEF_METADATA_UNANALYZED; this->booleans1 = 0; return; } // Copy constructor. DefOrUse::DefOrUse(const DefOrUse &CopyIn) { *this = CopyIn; return; } // Assignment operator for copy constructor use. DefOrUse &DefOrUse::operator=(const DefOrUse &rhs) { this->Operand = rhs.Operand; this->OpType = rhs.OpType; this->NonSpeculativeOpType = rhs.NonSpeculativeOpType; this->SSANumber = rhs.SSANumber; this->MetadataStatus = rhs.MetadataStatus; this->booleans1 = rhs.booleans1; return *this; } // Set the operand type for this DEF or USE - don't forget to take // into account the speculative (profiler) status. void DefOrUse::SetType(SMPOperandType Type, const SMPInstr *Instr) { SMPOperandType OldType = this->OpType; SMPOperandType NewType = Type; if (Instr->GetBlock()->GetFunc()->GetIsSpeculative()) { NewType = (SMPOperandType)(((int)NewType) | PROF_BASE); if (!IsProfDerived(OldType)) this->NonSpeculativeOpType = OldType; } this->OpType = NewType; } void DefOrUse::SetMetadataStatus(SMPMetadataType NewStatus) { // See if we are just updating explanation codes. bool OldUsed = ((this->MetadataStatus >= DEF_METADATA_USED) && (this->MetadataStatus < DEF_METADATA_REDUNDANT)); if (OldUsed) { bool NewUsed = ((NewStatus >= DEF_METADATA_USED) && (NewStatus < DEF_METADATA_REDUNDANT)); if (NewUsed) { // Union the explanation codes. int TempInt = (int) this->GetMetadataStatus(); TempInt |= (int) NewStatus; this->MetadataStatus = (SMPMetadataType) TempInt; return; } } this->MetadataStatus = NewStatus; return; } // Debug printing. void DefOrUse::Dump(void) const { PrintListOperand(this->Operand, this->SSANumber); if (IsEqType(this->OpType , NUMERIC)) SMP_msg("N "); else if (IsEqType(this->OpType , CODEPTR)) SMP_msg("C "); else if (IsEqType(this->OpType , POINTER)) SMP_msg("P "); else if (IsEqType(this->OpType , STACKPTR)) SMP_msg("S "); else if (IsEqType(this->OpType , GLOBALPTR)) SMP_msg("G "); else if (IsEqType(this->OpType , HEAPPTR)) SMP_msg("H "); else if (IsEqType(this->OpType , PTROFFSET)) SMP_msg("O "); else if (IsEqType(this->OpType , NEGATEDPTR)) SMP_msg("NegP "); else if (IsEqType(this->OpType , UNKNOWN)) SMP_msg("U "); /* emit the profile bit */ if (IsProfDerived(this->OpType)) SMP_msg("Pr "); // Don't write anything for UNINIT OpType // Emit the metadata status. if (DEF_METADATA_UNUSED == this->MetadataStatus) SMP_msg("Mn "); else if (DEF_METADATA_USED == this->MetadataStatus) SMP_msg("Mu "); else if (DEF_METADATA_REDUNDANT == this->MetadataStatus) SMP_msg("Mr "); // Is the DEF possibly aliased because of an indirect write in // the DEF-USE chain? if (this->HasIndirectWrite()) SMP_msg("Al* "); return; } // end of DefOrUse::Dump() // ***************************************************************** // Class DefOrUseSet // ***************************************************************** // Default constructor. DefOrUseSet::DefOrUseSet(void) { this->Refs.clear(); return; } // Destructor. DefOrUseSet::~DefOrUseSet() { this->Refs.clear(); return; } // Find the reference for a given operand type. set<DefOrUse, LessDefUse>::iterator DefOrUseSet::FindRef(const STARSOpndTypePtr &SearchOp) { set<DefOrUse, LessDefUse>::iterator CurrRef; DefOrUse DummyRef(SearchOp); CurrRef = this->Refs.find(DummyRef); return CurrRef; } std::set<DefOrUse, LessDefUse>::const_iterator DefOrUseSet::FindConstRef(const STARSOpndTypePtr &SearchOp) const { set<DefOrUse, LessDefUse>::const_iterator CurrRef; DefOrUse DummyRef(SearchOp); CurrRef = this->Refs.find(DummyRef); return CurrRef; } // Insert a new DEF or USE; must be new, insert must succeed else we assert. set<DefOrUse, LessDefUse>::iterator DefOrUseSet::InsertRef(DefOrUse Ref) { pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult; InsertResult = this->Refs.insert(Ref); assert(InsertResult.second); return InsertResult.first; } // Set a Def or Use into the list, along with its type. void DefOrUseSet::SetRef(STARSOpndTypePtr Ref, SMPOperandType Type, int SSASub) { pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult; DefOrUse CurrRef(Ref, Type, SSASub); InsertResult = this->Refs.insert(CurrRef); if ((!(InsertResult.second)) && (! Ref->IsRegOp())) { SMP_msg("WARNING: Inserted duplicate DEF or USE: "); CurrRef.Dump(); SMP_msg("\n"); } return; } // Change the indirect write status for a reference. set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetOp(set<DefOrUse, LessDefUse>::iterator CurrRef, STARSOpndTypePtr NewOp) { // To change a field within a set, we must grab a copy, change the copy, // delete the old set member, and insert the updated copy as a new member. assert(CurrRef != this->Refs.end()); DefOrUse NewCopy = (*CurrRef); NewCopy.SetOp(NewOp); this->Refs.erase(CurrRef); pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult; InsertResult = this->Refs.insert(NewCopy); assert(InsertResult.second); return InsertResult.first; } // end of DefOrUseSet::SetOp() // Change the SSA subscript for a reference. set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetSSANum(const STARSOpndTypePtr &CurrOp, int NewSSASub) { // To change a field within a set, we must grab a copy, change the copy, // delete the old set member, and insert the updated copy as a new member. set<DefOrUse, LessDefUse>::iterator CurrRef = this->FindRef(CurrOp); assert(CurrRef != this->Refs.end()); set<DefOrUse, LessDefUse>::iterator NextRef = CurrRef; ++NextRef; DefOrUse NewCopy = (*CurrRef); NewCopy.SetSSANum(NewSSASub); this->Refs.erase(CurrRef); CurrRef = this->Refs.insert(NextRef, NewCopy); return CurrRef; } // end of DefOrUseSet::SetSSANum() // Change the operand type for a reference. set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetType(const STARSOpndTypePtr &CurrOp, SMPOperandType Type, const SMPInstr* Instr) { // To change a field within a set, we must grab a copy, change the copy, // delete the old set member, and insert the updated copy as a new member. set<DefOrUse, LessDefUse>::iterator CurrRef = this->FindRef(CurrOp); assert(CurrRef != this->Refs.end()); #if 1 if (CurrOp->IsImmedOp()) { if (UNINIT != CurrRef->GetType() && Type != CurrRef->GetType()) { SMP_msg("ERROR: Changing type of immediate from %d to %d at %llx: ", CurrRef->GetType(), Type, (uint64_t) Instr->GetAddr()); CurrRef->Dump(); SMP_msg("\n"); Instr->Dump(); } } #endif DefOrUse NewCopy = (*CurrRef); NewCopy.SetType(Type,Instr); this->Refs.erase(CurrRef); pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult; InsertResult = this->Refs.insert(NewCopy); assert(InsertResult.second); CurrRef = InsertResult.first; return CurrRef; } // end of DefOrUseSet::SetType() // Change the Metadata type for a reference. set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetMetadata(const STARSOpndTypePtr &CurrOp, SMPMetadataType Status) { // To change a field within a set, we must grab a copy, change the copy, // delete the old set member, and insert the updated copy as a new member. set<DefOrUse, LessDefUse>::iterator CurrRef = this->FindRef(CurrOp); assert(CurrRef != this->Refs.end()); DefOrUse NewCopy = (*CurrRef); NewCopy.SetMetadataStatus(Status); this->Refs.erase(CurrRef); pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult; InsertResult = this->Refs.insert(NewCopy); assert(InsertResult.second); CurrRef = InsertResult.first; return CurrRef; } // end of DefOrUseSet::SetMetadata() // Change the indirect write status for a reference. set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetIndWrite(const STARSOpndTypePtr &CurrOp, bool IndWriteFlag) { // To change a field within a set, we must grab a copy, change the copy, // delete the old set member, and insert the updated copy as a new member. set<DefOrUse, LessDefUse>::iterator CurrRef = this->FindRef(CurrOp); assert(CurrRef != this->Refs.end()); DefOrUse NewCopy = (*CurrRef); NewCopy.SetIndWrite(IndWriteFlag); this->Refs.erase(CurrRef); pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult; InsertResult = this->Refs.insert(NewCopy); assert(InsertResult.second); CurrRef = InsertResult.first; return CurrRef; } // end of DefOrUseSet::SetIndWrite() // Change the ignore apparent truncation flag for a reference. set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetNoTruncation(const STARSOpndTypePtr &CurrOp, bool NoTruncFlag) { // To change a field within a set, we must grab a copy, change the copy, // delete the old set member, and insert the updated copy as a new member. set<DefOrUse, LessDefUse>::iterator CurrRef = this->FindRef(CurrOp); assert(CurrRef != this->Refs.end()); DefOrUse NewCopy = (*CurrRef); NewCopy.SetNoTruncation(NoTruncFlag); this->Refs.erase(CurrRef); pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult; InsertResult = this->Refs.insert(NewCopy); assert(InsertResult.second); CurrRef = InsertResult.first; return CurrRef; } // end of DefOrUseSet::SetNoTruncation() // Change the ignore apparent overflow flag for a reference. set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetNoOverflow(const STARSOpndTypePtr &CurrOp, bool NoOverflowFlag) { // To change a field within a set, we must grab a copy, change the copy, // delete the old set member, and insert the updated copy as a new member. set<DefOrUse, LessDefUse>::iterator CurrRef = this->FindRef(CurrOp); assert(CurrRef != this->Refs.end()); DefOrUse NewCopy = (*CurrRef); NewCopy.SetNoOverflow(NoOverflowFlag); this->Refs.erase(CurrRef); pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult; InsertResult = this->Refs.insert(NewCopy); assert(InsertResult.second); CurrRef = InsertResult.first; return CurrRef; } // end of DefOrUseSet::SetNoOverflow() // Set a DEF as being invariant for all loops in the func. set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetLoopInvariant(const STARSOpndTypePtr &CurrOp) { // To change a field within a set, we must grab a copy, change the copy, // delete the old set member, and insert the updated copy as a new member. set<DefOrUse, LessDefUse>::iterator CurrRef = this->FindRef(CurrOp); assert(CurrRef != this->Refs.end()); DefOrUse NewCopy = (*CurrRef); NewCopy.SetInvariantForAllLoops(); this->Refs.erase(CurrRef); pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult; InsertResult = this->Refs.insert(NewCopy); assert(InsertResult.second); CurrRef = InsertResult.first; return CurrRef; } // end of DefOrUseSet::SetLoopInvariant() // Set a DEF as being a safe memory write set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetSafeMemWrite(const STARSOpndTypePtr &CurrOp) { // To change a field within a set, we must grab a copy, change the copy, // delete the old set member, and insert the updated copy as a new member. set<DefOrUse, LessDefUse>::iterator CurrRef = this->FindRef(CurrOp); assert(CurrRef != this->Refs.end()); DefOrUse NewCopy = (*CurrRef); NewCopy.SetSafeMemWriteDef(); this->Refs.erase(CurrRef); pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult; InsertResult = this->Refs.insert(NewCopy); assert(InsertResult.second); CurrRef = InsertResult.first; return CurrRef; } // end of DefOrUseSet::SetSafeMemWrite() // Debug printing. void DefOrUseSet::Dump(void) const { set<DefOrUse, LessDefUse>::iterator CurrRef; for (CurrRef = this->Refs.begin(); CurrRef != this->Refs.end(); ++CurrRef) { CurrRef->Dump(); } SMP_msg("\n"); return; } // Do all types agree, ignoring any flags registers in the set? This is used // for conditional move instructions; if all types agree, it does not matter // whether the move happens or not. bool DefOrUseSet::TypesAgreeNoFlags(void) { bool FoundFirstUse = false; set<DefOrUse, LessDefUse>::iterator CurrUse; SMPOperandType UseType = UNINIT; for (CurrUse = this->Refs.begin(); CurrUse != this->Refs.end(); ++CurrUse) { if (!(CurrUse->GetOp()->MatchesReg(X86_FLAGS_REG))) { // ignore flags if (!FoundFirstUse) { FoundFirstUse = true; UseType = CurrUse->GetType(); } else { if (IsNotEqType(CurrUse->GetType(), UseType)) { return false; // inconsistent types } } } } return true; } // end of DefOrUseSet::TypesAgreeNoFlags() // ***************************************************************** // Class DefOrUseList // ***************************************************************** // Default constructor. DefOrUseList::DefOrUseList(void) { this->Refs.clear(); return; } // Set a Def or Use into the list, along with its type. void DefOrUseList::SetRef(STARSOpndTypePtr Ref, SMPOperandType Type, int SSASub) { DefOrUse CurrRef(Ref, Type, SSASub); this->Refs.push_back(CurrRef); return; } // Get a reference by index. DefOrUse DefOrUseList::GetRef(size_t index) const { return Refs[index]; } // Change the SSA subscript for a reference. void DefOrUseList::SetSSANum(size_t index, int NewSSASub) { this->Refs[index].SetSSANum(NewSSASub); return; } // Change the operand type for a reference. void DefOrUseList::SetType(size_t index, SMPOperandType Type, const SMPInstr* Instr) { this->Refs[index].SetType(Type,Instr); return; } void DefOrUseList::SetMaybeAliased(std::size_t index) { this->Refs[index].SetIndWrite(true); return; } // Debug printing. void DefOrUseList::Dump(void) const { for (size_t index = 0; index < this->Refs.size(); ++index) { Refs[index].Dump(); } SMP_msg("\n"); return; } // Erase duplicate entries, in case SMPInstr::MDFixupDefUseLists() adds one. void DefOrUseList::EraseDuplicates(void) { STARSOpndSet TempRefs; // Use STL set to find duplicates STARSOpndSet::iterator TempIter; vector<DefOrUse>::iterator RefIter; RefIter = this->Refs.begin(); while (RefIter != this->Refs.end()) { TempIter = TempRefs.find(RefIter->GetOp()); if (TempIter == TempRefs.end()) { // not already in set TempRefs.insert(RefIter->GetOp()); ++RefIter; } else { // found it in set already RefIter = this->Refs.erase(RefIter); } } return; } // end of DefOrUseList::EraseDuplicates() // ***************************************************************** // Class SMPPhiFunction // ***************************************************************** // Constructor SMPPhiFunction::SMPPhiFunction(int GlobIndex, const DefOrUse &Def) { this->index = GlobIndex; this->DefName = Def; this->SubscriptedOps.clear(); return; } DefOrUse SMPPhiFunction::GetDefCopy(void) const { DefOrUse DefCopy(this->DefName); return DefCopy; } // Add a phi item to the list void SMPPhiFunction::PushBack(DefOrUse Ref) { this->SubscriptedOps.SetRef(Ref.GetOp(), Ref.GetType(), Ref.GetSSANum()); return; } // Set the SSA number of the defined variable. void SMPPhiFunction::SetSSADef(int NewSSASub) { this->DefName.SetSSANum(NewSSASub); return; } // Set the SSA number of the input variable. void SMPPhiFunction::SetSSARef(size_t index, int NewSSASub) { this->SubscriptedOps.SetSSANum(index, NewSSASub); return; } // Set the type of the defined variable. void SMPPhiFunction::SetDefType(SMPOperandType Type, const SMPInstr* Instr) { this->DefName.SetType(Type, Instr); return; } // Set the type of the input variable. void SMPPhiFunction::SetRefType(size_t index, SMPOperandType Type, const SMPInstr* Instr) { this->SubscriptedOps.SetType(index, Type, Instr); return; } // Record that the memory DEF might be aliased. void SMPPhiFunction::SetDefMaybeAliased(void) { this->DefName.SetIndWrite(true); return; } // Record that the memory USE might be aliased. void SMPPhiFunction::SetRefMaybeAliased(std::size_t index) { this->SubscriptedOps.SetMaybeAliased(index); return; } // Set the metadata status of the DEF variable. void SMPPhiFunction::SetDefMetadata(SMPMetadataType Status) { this->DefName.SetMetadataStatus(Status); return; } // end of SMPPhiFunction::SetDefMetadata() // Does at least one USE have a type other than UNINIT? bool SMPPhiFunction::HasTypedUses(void) { size_t index; for (index = 0; index < this->GetPhiListSize(); ++index) { if (UNINIT != this->GetUseType(index)) return true; } return false; } // end of SMPPhiFunction::HasTypedUses() // Return the result of applying the conditional type propagation meet operator // over all the USE types. SMPOperandType SMPPhiFunction::ConditionalMeetType(SMPBasicBlock *CurrBlock) const { SMPOperandType MeetType; SMPOperandType PtrType = UNINIT; SMPOperandType NumericType = UNINIT; // can end up NUMERIC or CODEPTR bool FoundUNINIT = false; // any USE type UNINIT? bool FoundNUMERIC = false; // any USE type NUMERIC? bool FoundZero = false; // was DEF to zero? (could be POINTER or NUMERIC bool FoundPOINTER = false; // includes all POINTER subtypes bool FoundUNKNOWN = false; // any USE type UNKNOWN? bool FoundPTROFFSET = false; // any USE type PTROFFSET? bool FoundNEGATEDPTR = false; // any USE type NEGATEDPTR? bool ProfilerDerived = false; // was any USE type Profiler-derived? list<size_t> ZeroConstIndices; STARS_ea_t BlockStartAddr = CurrBlock->GetFirstAddr(); // for debugging STARSOpndTypePtr PhiOp = this->GetAnyOp(); for (size_t index = 0; index < this->GetPhiListSize(); ++index) { SMPOperandType UseType = this->GetUseType(index); if (IsEqType(UseType, UNINIT)) FoundUNINIT = true; else if (IsNumeric(UseType)) { // Check for possibility that we aggressively declared NUMERIC when register was set to zero. int UseSSANum = this->GetUseSSANum(index); bool CurrentUseZeroCase = false; if (MDIsDataFlowOpnd(PhiOp, false)) { STARS_ea_t DefAddr = CurrBlock->GetFunc()->GetGlobalDefAddr(PhiOp, UseSSANum); // Handle simple case: DEF is in an instruction. if ((STARS_BADADDR != DefAddr) && (DefAddr < STARS_PSEUDO_ID_MIN)) { SMPInstr *DefInst = CurrBlock->GetFunc()->GetInstFromAddr(DefAddr); CurrentUseZeroCase = DefInst->IsSetToZero(); } } if (CurrentUseZeroCase) { FoundZero = true; ZeroConstIndices.push_back(index); } else { FoundNUMERIC = true; if (IsEqType(NumericType, CODEPTR)) { // Already refined. If current type agrees, leave it // alone, else revert to generic type NUMERIC. if (IsNotEqType(UseType, NumericType)) NumericType = NUMERIC; } else { // Have not yet refined NumericType; might still be UNINIT. if (IsEqType(UNINIT, NumericType)) NumericType = UseType; else { // NumericType is NUMERIC; leave it as NUMERIC. assert(IsEqType(NUMERIC, NumericType)); } } } } else if (IsDataPtr(UseType)) { FoundPOINTER = true; // Perform a meet over the pointer types. if (IsRefinedDataPtr(PtrType)) { // Already refined. If current type agrees, leave it // alone, else revert to generic type POINTER. if (IsNotEqType(UseType, PtrType)) PtrType = POINTER; } else { // Have not yet refined PtrType; might still be UNINIT. if (IsEqType(UNINIT, PtrType)) PtrType = UseType; else { // PtrType is POINTER because we saw POINTER or // had a conflict between pointer refinements; leave // it as POINTER. assert(IsEqType(POINTER, PtrType)); } } } else if (IsEqType(PTROFFSET, UseType)) FoundPTROFFSET = true; else if (IsEqType(NEGATEDPTR, UseType)) FoundNEGATEDPTR = true; else if (IsUnknown(UseType)) FoundUNKNOWN = true; if (IsProfDerived(UseType)) ProfilerDerived = true; } // Use the boolean flags to compute the meet function. if (FoundUNKNOWN || (FoundNUMERIC && FoundPOINTER) || ((FoundNUMERIC || FoundPOINTER || FoundNEGATEDPTR) && FoundPTROFFSET) || ((FoundNUMERIC || FoundPOINTER || FoundPTROFFSET) && FoundNEGATEDPTR)) MeetType = UNKNOWN; else if (FoundNUMERIC) MeetType = NumericType; else if (FoundPOINTER) { MeetType = PtrType; if (FoundZero) { // mixture of POINTER and const zero DEFs, i.e. ptr := NULL; // Undo the aggressive NUMERIC inference when registers are set to zero. // NOTE: There cannot be any alterations to the reg between the zero DEF and // the current block on at least one path, or it would not show up in the Phi function with the // current SSA number. do { size_t ZeroConstIndex = ZeroConstIndices.front(); int UseSSANum = this->GetUseSSANum(ZeroConstIndex); STARS_ea_t DefAddr = CurrBlock->GetFunc()->GetGlobalDefAddr(PhiOp, UseSSANum); // Handle simple case: DEF is in an instruction. if ((STARS_BADADDR != DefAddr) && (DefAddr < STARS_PSEUDO_ID_MIN)) { SMPInstr *DefInst = CurrBlock->GetFunc()->GetInstFromAddr(DefAddr); set<DefOrUse, LessDefUse>::iterator DefIter = DefInst->SetDefType(PhiOp, PtrType); #if 0 SMP_msg("INFO: Converting zeroed reg from NUMERIC to POINTER at %lx for Block at %lx\n", (unsigned long) DefAddr, (unsigned long) BlockStartAddr); #endif CurrBlock->GetFunc()->ResetProcessedBlocks(); SMPBasicBlock *DefBlock = CurrBlock->GetFunc()->GetBlockFromInstAddr(DefAddr); #if 0 // Causes infinite loops, crashes; need to debug !!!!****!!!! DefBlock->PropagateGlobalDefType(PhiOp, PtrType, UseSSANum, false, true); #else DefBlock->PropagateGlobalDefType(PhiOp, PtrType, UseSSANum, false, false); #endif } ZeroConstIndices.pop_front(); } while (!ZeroConstIndices.empty()); } } else if (FoundPTROFFSET) MeetType = PTROFFSET; else if (FoundNEGATEDPTR) MeetType = NEGATEDPTR; else if (FoundZero && (!FoundUNINIT)) // nothing but zeroes MeetType = NUMERIC; else { assert(FoundUNINIT); MeetType = UNINIT; } if (ProfilerDerived) MeetType = MakeProfDerived(MeetType); return MeetType; } // end of SMPPhiFunction::ConditionalMeetType() // Debug printing. void SMPPhiFunction::Dump(void) const { SMP_msg(" DEF: "); this->DefName.Dump(); SMP_msg(" USEs: "); this->SubscriptedOps.Dump(); return; } // ***************************************************************** // Class SMPDefUseChain // ***************************************************************** // Constructors SMPDefUseChain::SMPDefUseChain(void) { this->SSAName = nullptr; this->RefInstrs.clear(); this->RefInstrs.push_back((unsigned short) STARS_BADADDR); this->IndWrite = false; return; } SMPDefUseChain::SMPDefUseChain(STARSOpndTypePtr Name, STARS_ea_t Def) { this->SetName(Name); this->RefInstrs.push_back(Def); this->IndWrite = false; return; } // Set the variable name. void SMPDefUseChain::SetName(STARSOpndTypePtr Name) { STARSOpndTypePtr Name2 = nullptr; if (Name->IsRegOp()) { // We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis // and type inference systems. Name2 = CloneIfSubwordReg(Name); CanonicalizeOpnd(Name2); } else { Name2 = Name; } this->SSAName = Name2; return; } // Set the DEF instruction. void SMPDefUseChain::SetDef(STARS_ea_t Def) { this->RefInstrs[0] = (unsigned short) Def; return; } // Push a USE onto the list void SMPDefUseChain::PushUse(STARS_ea_t Use) { this->RefInstrs.push_back((unsigned short) Use); return; } // Set the indirect memory write flag. void SMPDefUseChain::SetIndWrite(bool IndMemWrite) { this->IndWrite = IndMemWrite; return; } // DEBUG dump. void SMPDefUseChain::Dump(int SSANum) const { SMP_msg("DEF-USE chain for: "); PrintListOperand(this->SSAName, SSANum); if (this->RefInstrs.size() < 1) { SMP_msg(" no references.\n"); return; } SMP_msg("\n DEF: %x USEs: ", this->RefInstrs[0]); size_t index; for (index = 1; index < this->RefInstrs.size(); ++index) SMP_msg("%x ", this->RefInstrs[index]); SMP_msg("\n"); return; } // end of SMPDefUseChain::Dump() // ***************************************************************** // Class SMPDUChainArray // ***************************************************************** SMPDUChainArray::SMPDUChainArray(void) { this->SSAName = nullptr; this->DUChains.clear(); return; } SMPDUChainArray::SMPDUChainArray(STARSOpndTypePtr Name, STARS_ea_t FirstAddrMinusOne) { STARSOpndTypePtr Name2 = nullptr; if (Name->IsRegOp()) { // We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis // and type inference systems. Name2 = CloneIfSubwordReg(Name); CanonicalizeOpnd(Name2); } else { Name2 = Name; } this->SSAName = Name2; this->BaseAddr = FirstAddrMinusOne; this->DUChains.clear(); return; } STARS_ea_t SMPDUChainArray::GetLastUse(int SSANum) const { STARS_ea_t TempAddr = DUChains[(size_t)SSANum].GetLastUse(); if (STARS_BADADDR != TempAddr) { // If STARS_BADADDR, leave it as STARS_BADADDR. Otherwise, add in BaseAddr. TempAddr += this->BaseAddr; } return TempAddr; } void SMPDUChainArray::SetName(STARSOpndTypePtr Name, STARS_ea_t FirstAddrMinusOne) { STARSOpndTypePtr Name2 = nullptr; if (Name->IsRegOp()) { // We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis // and type inference systems. Name2 = CloneIfSubwordReg(Name); CanonicalizeOpnd(Name2); } else { Name2 = Name; } this->SSAName = Name2; this->BaseAddr = FirstAddrMinusOne; return; } // DEBUG dump. void SMPDUChainArray::Dump(void) const { for (size_t index = 0; index < this->GetSize(); ++index) { this->DUChains[index].Dump((int) index); } return; } // ***************************************************************** // Class SMPCompleteDUChains // ***************************************************************** // DEBUG dump. void SMPCompleteDUChains::Dump(void) const { for (size_t index = 0; index < this->ChainsByName.size(); ++index) { this->ChainsByName[index].Dump(); } return; } // end of SMPCompleteDUChains::Dump() // ***************************************************************** // Class STARSBitSet // ***************************************************************** // Constructors. STARSBitSet::STARSBitSet() { this->BitLimit = 0; } // Get methods bool STARSBitSet::GetBit(size_t BitIndex) const { size_t ByteIndex = BitIndex / 8; size_t BitNumber = BitIndex % 8; assert(BitIndex <= this->BitLimit); return (0 != (this->STARSBits[ByteIndex] & STARSBitMasks[BitNumber])); } uint8_t STARSBitSet::GetByte(std::size_t ByteIndex) const { assert(ByteIndex < this->STARSBits.size()); return this->STARSBits[ByteIndex]; } // Set methods void STARSBitSet::AllocateBits(size_t Size) { size_t Bytes = Size / 8; size_t ExtraBits = Size % 8; this->BitLimit = Size; if (0 != ExtraBits) { this->STARSBits.resize(1 + Bytes); } else { this->STARSBits.resize(Bytes); } for (Bytes = 0; Bytes < this->STARSBits.size(); ++Bytes) { this->STARSBits[Bytes] = 0; } } void STARSBitSet::SetBit(size_t BitIndex) { size_t ByteIndex = BitIndex / 8; size_t BitNumber = BitIndex % 8; assert(BitIndex <= this->BitLimit); this->STARSBits[ByteIndex] |= STARSBitMasks[BitNumber]; return; } void STARSBitSet::ResetBit(size_t BitIndex) { size_t ByteIndex = BitIndex / 8; size_t BitNumber = BitIndex % 8; assert(BitIndex <= this->BitLimit); this->STARSBits[ByteIndex] &= (~STARSBitMasks[BitNumber]); return; } void STARSBitSet::ResetAllBits(void) { size_t NumBytes = this->STARSBits.size(); for (size_t ByteIndex = 0; ByteIndex < NumBytes; ++ByteIndex) { this->STARSBits[ByteIndex] = 0; } return; } // end of STARSBitSet::ResetAllBits() // Query methods // Returns false if all bits are zero, true otherwise. bool STARSBitSet::IsAnyBitSet(void) const { bool FoundSetBit = false; size_t ByteIndex; for (ByteIndex = 0; ByteIndex < this->STARSBits.size(); ++ByteIndex) { if (0 != this->STARSBits[ByteIndex]) { FoundSetBit = true; break; } } return FoundSetBit; } // Return highest index set; -1 if no bits set. int STARSBitSet::FindHighestBitSet(void) const { bool FoundSetBit = false; size_t ByteIndex, BitIndex, BitSetSize = this->STARSBits.size(); assert(0 < BitSetSize); for (ByteIndex = BitSetSize; ByteIndex > 0; --ByteIndex) { if (0 != this->STARSBits[ByteIndex - 1]) { FoundSetBit = true; --ByteIndex; BitIndex = HighestBitSet(this->STARSBits[ByteIndex]); break; } } if (FoundSetBit) { return (int)(8 * ByteIndex + BitIndex); } else { return -1; } } // end of STARSBitSet::FindHighestBitSet() // Return lowest index set; -1 if no bits set. int STARSBitSet::FindLowestBitSet(void) const { bool FoundSetBit = false; size_t ByteIndex, BitIndex, BitSetSize = this->STARSBits.size(); assert(0 < BitSetSize); for (ByteIndex = 0; ByteIndex < BitSetSize; ++ByteIndex) { if (0 != this->STARSBits[ByteIndex]) { FoundSetBit = true; BitIndex = LowestBitSet(this->STARSBits[ByteIndex]); break; } } if (FoundSetBit) { return (int)(8 * ByteIndex + BitIndex); } else { return -1; } } // end of STARSBitSet::FindLowestBitSet() // return count of set bits size_t STARSBitSet::CountSetBits(void) const { size_t ByteIndex, BitCount = 0, BitSetSize = this->STARSBits.size(); assert(0 < BitSetSize); for (ByteIndex = 0; ByteIndex < BitSetSize; ++ByteIndex) { uint8_t CurrByte = this->STARSBits[ByteIndex]; if (0 != CurrByte) { BitCount += CountBitsSet((unsigned int) CurrByte); } } return BitCount; } // end of STARSBitSet::CountSetBits() // Debugging output of bits set void STARSBitSet::DumpBitsSet(void) const { size_t ByteIndex, BitCount = 0, BitSetSize = this->STARSBits.size(); assert(0 < BitSetSize); for (ByteIndex = 0; ByteIndex < BitSetSize; ++ByteIndex) { uint8_t CurrByte = this->STARSBits[ByteIndex]; if (0 != CurrByte) { size_t CurrBitLimit = 8 + (8 * ByteIndex); if (CurrBitLimit > this->GetNumBits()) CurrBitLimit = this->GetNumBits(); for (size_t BitIndex = 8 * ByteIndex; BitIndex < CurrBitLimit; ++BitIndex) { if (this->GetBit(BitIndex)) { SMP_msg("%zu ", BitIndex); } } } } return; } // end of STARSBitSet::DumpBitsSet() void STARSBitSet::SetByte(const std::size_t ByteIndex, const uint8_t ByteValue) { assert(ByteIndex < this->STARSBits.size()); this->STARSBits[ByteIndex] = ByteValue; return; } void STARSBitSet::UnionSets(const STARSBitSet &BitSet2) { assert(this->GetNumBits() == BitSet2.GetNumBits()); for (size_t ByteIndex = 0; ByteIndex < this->STARSBits.size(); ++ByteIndex) { this->STARSBits[ByteIndex] = (this->STARSBits[ByteIndex] | BitSet2.GetByte(ByteIndex)); } return; } // end of STARSBitSet::UnionSets() STARSBitSet STARSBitSetIntersection(const STARSBitSet &BitSet1, const STARSBitSet &BitSet2) { size_t NumBits = BitSet1.GetNumBits(); assert(NumBits == BitSet2.GetNumBits()); STARSBitSet ReturnBitSet; ReturnBitSet.AllocateBits(NumBits); size_t NumBytes = (NumBits / 8); if (0 != (NumBits % 8)) ++NumBytes; for (size_t ByteIndex = 0; ByteIndex < NumBytes; ++ByteIndex) { ReturnBitSet.SetByte(ByteIndex, (BitSet1.GetByte(ByteIndex) & BitSet2.GetByte(ByteIndex))); } return ReturnBitSet; } // end of STARSBitSetIntersection() STARSBitSet STARSBitSetUnion(const STARSBitSet &BitSet1, const STARSBitSet &BitSet2) { size_t NumBits = BitSet1.GetNumBits(); assert(NumBits == BitSet2.GetNumBits()); STARSBitSet ReturnBitSet; ReturnBitSet.AllocateBits(NumBits); size_t NumBytes = (NumBits / 8); if (0 != (NumBits % 8)) ++NumBytes; for (size_t ByteIndex = 0; ByteIndex < NumBytes; ++ByteIndex) { ReturnBitSet.SetByte(ByteIndex, (BitSet1.GetByte(ByteIndex) | BitSet2.GetByte(ByteIndex))); } return ReturnBitSet; } // end of STARSBitSetUnion() // Map system or library call name to FG info about its return value. map<string, struct FineGrainedInfo> ReturnRegisterTypeMap; // Map system or library call name to the annotation substring that // guides saturating arithmetic or other continuation policies in // the case of integer error detection of a value passed to that call. // If we don't care about a certain call, we return an empty string. static map<string, string> IntegerErrorCallSinkMap; void InitIntegerErrorCallSinkMap(void) { // in case STARS was invoked before. IntegerErrorCallSinkMap.clear(); pair<string, string> MapEntry; pair<map<string, string>::iterator, bool> InsertResult; MapEntry.first = string("malloc"); MapEntry.second = string("SINKMALLOC"); InsertResult = IntegerErrorCallSinkMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("calloc"); MapEntry.second = string("SINKMALLOC"); InsertResult = IntegerErrorCallSinkMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("realloc"); MapEntry.second = string("SINKMALLOC"); InsertResult = IntegerErrorCallSinkMap.insert(MapEntry); assert(InsertResult.second); return; } // Return sink string for call name from the sink map. // If we don't care find the call name, we return an empty string. void GetSinkStringForCallName(string CalleeName, string &SinkString) { map<string, string>::iterator MapIter; SinkString.clear(); // empty string, append map string if found later MapIter = IntegerErrorCallSinkMap.find(CalleeName); if (MapIter != IntegerErrorCallSinkMap.end()) { // found it SinkString.append(MapIter->second); } return; } // Map system or library call name to the argument number that // should have an unsigned value and should be guarded from the // signedness error that results from copying a signed value // into the outgoing argument. Argument numbers are zero-based. // We will return 0 when there is no argument to worry about // for a particular library or system call name. static map<string, unsigned int> UnsignedArgPositionMap; void InitUnsignedArgPositionMap(void) { // clear in case stars invoked multiple times. UnsignedArgPositionMap.clear(); pair<string, unsigned int> MapEntry; pair<map<string, unsigned int>::iterator, bool> InsertResult; // <string.h> MapEntry.first = string("memchr"); MapEntry.second = STARS_ARG_POS_2; InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("memcmp"); MapEntry.second = STARS_ARG_POS_2; InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("memcpy"); MapEntry.second = STARS_ARG_POS_2; InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("memmove"); MapEntry.second = STARS_ARG_POS_2; InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("memset"); MapEntry.second = STARS_ARG_POS_2; InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strncat"); MapEntry.second = STARS_ARG_POS_2; InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strncmp"); MapEntry.second = STARS_ARG_POS_2; InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strncpy"); MapEntry.second = STARS_ARG_POS_2; InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strxfrm"); MapEntry.second = STARS_ARG_POS_2; InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); // <stdlib.h> MapEntry.first = string("malloc"); MapEntry.second = STARS_ARG_POS_0; InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("calloc"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("realloc"); MapEntry.second = STARS_ARG_POS_1; InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("bsearch"); MapEntry.second = (STARS_ARG_POS_2 | STARS_ARG_POS_3); InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("qsort"); MapEntry.second = (STARS_ARG_POS_1 | STARS_ARG_POS_2); InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("mblen"); MapEntry.second = STARS_ARG_POS_1; InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("mbtowc"); MapEntry.second = STARS_ARG_POS_2; InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("mbstowcs"); MapEntry.second = STARS_ARG_POS_2; InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("wcstombs"); MapEntry.second = STARS_ARG_POS_2; InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); // <stdio.h> MapEntry.first = string("setvbuf"); MapEntry.second = STARS_ARG_POS_3; InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); // <time.h> MapEntry.first = string("strftime"); MapEntry.second = STARS_ARG_POS_1; InsertResult = UnsignedArgPositionMap.insert(MapEntry); assert(InsertResult.second); return; } // end of InitUnsignedArgPositionMap() // Return unsigned arg position bitset for call name from the unsigned arg map. // If we don't find the call name, we return 0 in ArgPosBits. void GetUnsignedArgPositionsForCallName(string CalleeName, unsigned int &ArgPosBits) { map<string, unsigned int>::iterator MapIter; ArgPosBits = 0; // Change if found later MapIter = UnsignedArgPositionMap.find(CalleeName); if (MapIter != UnsignedArgPositionMap.end()) { // found it ArgPosBits = MapIter->second; } return; } // Map of function names to arguments that are dangerous to supply // with user-tainted input values. static map<string, unsigned int> TaintWarningArgPositionMap; void InitTaintWarningArgPositionMap(void) { // clear in case STARS re-init'd. TaintWarningArgPositionMap.clear(); pair<string, unsigned int> MapEntry; pair<map<string, unsigned int>::iterator, bool> InsertResult; // <string.h> MapEntry.first = string("memchr"); MapEntry.second = STARS_ARG_POS_2; InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("memcmp"); MapEntry.second = STARS_ARG_POS_2; InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("memcpy"); MapEntry.second = STARS_ARG_POS_2; InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("memmove"); MapEntry.second = STARS_ARG_POS_2; InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("memset"); MapEntry.second = STARS_ARG_POS_2; InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strncat"); MapEntry.second = STARS_ARG_POS_2; InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strncmp"); MapEntry.second = STARS_ARG_POS_2; InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strncpy"); MapEntry.second = STARS_ARG_POS_2; InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strxfrm"); MapEntry.second = STARS_ARG_POS_2; InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); // <stdlib.h> MapEntry.first = string("malloc"); MapEntry.second = STARS_ARG_POS_0; InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("calloc"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("realloc"); MapEntry.second = STARS_ARG_POS_1; InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("bsearch"); MapEntry.second = (STARS_ARG_POS_2 | STARS_ARG_POS_3); InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("qsort"); MapEntry.second = (STARS_ARG_POS_1 | STARS_ARG_POS_2); InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("mblen"); MapEntry.second = STARS_ARG_POS_1; InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("mbtowc"); MapEntry.second = STARS_ARG_POS_2; InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("mbstowcs"); MapEntry.second = STARS_ARG_POS_2; InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("wcstombs"); MapEntry.second = STARS_ARG_POS_2; InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); // <stdio.h> MapEntry.first = string("setvbuf"); MapEntry.second = STARS_ARG_POS_3; InsertResult = TaintWarningArgPositionMap.insert(MapEntry); assert(InsertResult.second); return; } // end of InitTaintWarningArgPositionMap() // Return dangerous-to-taint arg position bitset for call name from the taint warning map. // If we don't find the call name, we return 0 in ArgPosBits. void GetTaintWarningArgPositionsForCallName(string CalleeName, unsigned int &ArgPosBits) { map<string, unsigned int>::iterator MapIter; ArgPosBits = 0; // Change if found later MapIter = TaintWarningArgPositionMap.find(CalleeName); if (MapIter != TaintWarningArgPositionMap.end()) { // found it ArgPosBits = MapIter->second; } return; } // Map of function names to POINTER argument positions. static map<string, unsigned int> PointerArgPositionMap; // Init map of system or library call name to the argument number that // should have a POINTER value. void InitPointerArgPositionMap(void) { // clear in case re-initing. PointerArgPositionMap.clear(); pair<string, unsigned int> MapEntry; pair<map<string, unsigned int>::iterator, bool> InsertResult; // <locale.h> MapEntry.first = string("setlocale"); MapEntry.second = STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); // <math.h> MapEntry.first = string("modf"); MapEntry.second = STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); // <string.h> MapEntry.first = string("memchr"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("memcmp"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("memcpy"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("memmove"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("memset"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strcat"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strncat"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strcmp"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strncmp"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strcpy"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strcpy_chk"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strncpy"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strcoll"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strxfrm"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strchr"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strcspn"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strpbrk"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strrchr"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strspn"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strstr"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strtok"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strlen"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); // <stdlib.h> MapEntry.first = string("atof"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("atoi"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("atol"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strtod"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strtol"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strtoul"); MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("free"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("realloc"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("getenv"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("system"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("bsearch"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("qsort"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("mblen"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("mbtowc"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("wctomb"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("mbstowcs"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("wcstombs"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); // <stdio.h> MapEntry.first = string("remove"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("rename"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("tmpnam"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("fclose"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("fflush"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("fopen"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("freopen"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1 | STARS_ARG_POS_2); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("setbuf"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("setvbuf"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("fprintf"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("fscanf"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("isoc99_fscanf"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("printf"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("scanf"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("isoc99_scanf"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("sprintf"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("sscanf"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("vfprintf"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("vprintf"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("vsprintf"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("fgetc"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("fgets"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_2); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("fputc"); MapEntry.second = STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("fputs"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("getc"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("gets"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("putc"); MapEntry.second = STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("puts"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("ungetc"); MapEntry.second = STARS_ARG_POS_1; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("fread"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_3); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("fwrite"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_3); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("fgetpos"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("fseek"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("fsetpos"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("ftell"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("rewind"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("clearerr"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("feof"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("ferror"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("perror"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); // <time.h> MapEntry.first = string("mktime"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("time"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("asctime"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("ctime"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("gmtime"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("localtime"); MapEntry.second = STARS_ARG_POS_0; InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); MapEntry.first = string("strftime"); MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_2 | STARS_ARG_POS_3); InsertResult = PointerArgPositionMap.insert(MapEntry); assert(InsertResult.second); return; } // end of InitPointerArgPositionMap() // Return POINTER arg position bitset for call name from the POINTER arg map. // If we don't find the call name, we return 0 in ArgPosBits. void GetPointerArgPositionsForCallName(string CalleeName, unsigned int &ArgPosBits) { map<string, unsigned int>::iterator MapIter; ArgPosBits = 0; // Change if found later MapIter = PointerArgPositionMap.find(CalleeName); if (MapIter != PointerArgPositionMap.end()) { // found it ArgPosBits = MapIter->second; } return; } static set<string> MathLibraryFuncNames; static set<string> StdioLibraryFuncNames; static set<string> StdlibLibraryFuncNames; static set<string> BufferArgLibraryFuncNames; void InitLibraryFuncNames(void) { // <math.h> MathLibraryFuncNames.insert("acos"); MathLibraryFuncNames.insert("cos"); MathLibraryFuncNames.insert("sin"); MathLibraryFuncNames.insert("asin"); MathLibraryFuncNames.insert("tan"); MathLibraryFuncNames.insert("atan"); MathLibraryFuncNames.insert("cosh"); MathLibraryFuncNames.insert("sinh"); MathLibraryFuncNames.insert("tanh"); MathLibraryFuncNames.insert("atan2"); MathLibraryFuncNames.insert("exp"); MathLibraryFuncNames.insert("ldexp"); MathLibraryFuncNames.insert("frexp"); MathLibraryFuncNames.insert("log"); MathLibraryFuncNames.insert("modf"); MathLibraryFuncNames.insert("log10"); MathLibraryFuncNames.insert("pow"); MathLibraryFuncNames.insert("sqrt"); MathLibraryFuncNames.insert("ceil"); MathLibraryFuncNames.insert("fmod"); MathLibraryFuncNames.insert("fabs"); MathLibraryFuncNames.insert("floor"); StdioLibraryFuncNames.insert("printf"); StdioLibraryFuncNames.insert("scanf"); StdioLibraryFuncNames.insert("isoc99_scanf"); StdioLibraryFuncNames.insert("printf_chk"); StdioLibraryFuncNames.insert("fprintf"); StdioLibraryFuncNames.insert("fscanf"); StdioLibraryFuncNames.insert("isoc99_fscanf"); StdioLibraryFuncNames.insert("sprintf"); StdioLibraryFuncNames.insert("sscanf"); StdioLibraryFuncNames.insert("vfprintf"); StdioLibraryFuncNames.insert("fgetc"); StdioLibraryFuncNames.insert("vprintf"); StdioLibraryFuncNames.insert("fgets"); StdioLibraryFuncNames.insert("vsprintf"); StdioLibraryFuncNames.insert("fputc"); StdioLibraryFuncNames.insert("getc"); StdioLibraryFuncNames.insert("fputs"); StdioLibraryFuncNames.insert("getchar"); StdioLibraryFuncNames.insert("putchar"); StdioLibraryFuncNames.insert("gets"); StdioLibraryFuncNames.insert("putc"); StdioLibraryFuncNames.insert("ungetc"); StdioLibraryFuncNames.insert("puts"); StdioLibraryFuncNames.insert("fwrite"); StdioLibraryFuncNames.insert("fread"); StdioLibraryFuncNames.insert("fgetpos"); StdioLibraryFuncNames.insert("printf"); StdioLibraryFuncNames.insert("fseek"); StdioLibraryFuncNames.insert("rewind"); StdioLibraryFuncNames.insert("fsetpos"); StdioLibraryFuncNames.insert("clearerr"); StdioLibraryFuncNames.insert("ftell"); StdioLibraryFuncNames.insert("perror"); StdioLibraryFuncNames.insert("feof"); StdioLibraryFuncNames.insert("remove"); StdioLibraryFuncNames.insert("ferror"); StdioLibraryFuncNames.insert("rename"); StdioLibraryFuncNames.insert("fopen"); StdioLibraryFuncNames.insert("tmpfile"); StdioLibraryFuncNames.insert("freopen"); StdioLibraryFuncNames.insert("tmpnam"); StdioLibraryFuncNames.insert("fclose"); StdioLibraryFuncNames.insert("setbuf"); StdioLibraryFuncNames.insert("fflush"); StdioLibraryFuncNames.insert("setvbuf"); StdlibLibraryFuncNames.insert("atol"); StdlibLibraryFuncNames.insert("atof"); StdlibLibraryFuncNames.insert("atoi"); StdlibLibraryFuncNames.insert("strtod"); StdlibLibraryFuncNames.insert("strtol"); StdlibLibraryFuncNames.insert("strtoul"); StdlibLibraryFuncNames.insert("rand"); StdlibLibraryFuncNames.insert("srand"); StdlibLibraryFuncNames.insert("calloc"); StdlibLibraryFuncNames.insert("free"); StdlibLibraryFuncNames.insert("malloc"); StdlibLibraryFuncNames.insert("realloc"); StdlibLibraryFuncNames.insert("abort"); StdlibLibraryFuncNames.insert("atexit"); StdlibLibraryFuncNames.insert("exit"); StdlibLibraryFuncNames.insert("getenv"); StdlibLibraryFuncNames.insert("system"); StdlibLibraryFuncNames.insert("bsearch"); StdlibLibraryFuncNames.insert("qsort"); StdlibLibraryFuncNames.insert("abs"); StdlibLibraryFuncNames.insert("div"); StdlibLibraryFuncNames.insert("labs"); StdlibLibraryFuncNames.insert("ldiv"); StdlibLibraryFuncNames.insert("mblen"); StdlibLibraryFuncNames.insert("mbtowc"); StdlibLibraryFuncNames.insert("wctomb"); StdlibLibraryFuncNames.insert("mbstowcs"); StdlibLibraryFuncNames.insert("wcstombs"); // Add special functions often inserted by gcc. StdlibLibraryFuncNames.insert("stack_chk_fail"); // Funcs with buffers as arguments; could analyze static size of buffers. BufferArgLibraryFuncNames.insert("strcpy"); BufferArgLibraryFuncNames.insert("strcpy_chk"); // GNU safer version, but crashes on error BufferArgLibraryFuncNames.insert("memcpy"); BufferArgLibraryFuncNames.insert("memmove"); BufferArgLibraryFuncNames.insert("strcat"); BufferArgLibraryFuncNames.insert("strcmp"); return; } // end of InitLibraryFuncNames() bool IsMathLibraryFunc(string CalleeName) { set<string>::const_iterator FuncIter = MathLibraryFuncNames.find(CalleeName); return (FuncIter != MathLibraryFuncNames.cend()); } bool IsStdioLibraryFunc(string CalleeName) { set<string>::const_iterator FuncIter = StdioLibraryFuncNames.find(CalleeName); return (FuncIter != StdioLibraryFuncNames.cend()); } bool IsStdlibLibraryFunc(string CalleeName) { set<string>::const_iterator FuncIter = StdlibLibraryFuncNames.find(CalleeName); return (FuncIter != StdlibLibraryFuncNames.cend()); } // Is FuncName a function that operates on buffers that might be of analyzeable buffer length? bool IsBufferArgFuncName(const string CalleeName) { set<string>::const_iterator FuncIter = BufferArgLibraryFuncNames.find(CalleeName); return (FuncIter != BufferArgLibraryFuncNames.cend()); } // Utility to count bits set in an unsigned int, e.g. ArgPosBits. unsigned int CountBitsSet(unsigned int ArgPosBits) { unsigned int count; // count accumulates the total bits set in ArgPosBits for (count = 0; ArgPosBits; ++count) { ArgPosBits &= (ArgPosBits - 1); // clear the least significant bit set } // Brian Kernighan's method goes through as many iterations as there are set bits. // So if we have a 32-bit word with only the high bit set, then it will only go once through the loop. // Published in 1988, the C Programming Language 2nd Ed. (by Brian W. Kernighan and Dennis M. Ritchie) mentions this in exercise 2-9. // On April 19, 2006 Don Knuth pointed out to me that this method "was first published by Peter Wegner in CACM 3 (1960), 322. // (Also discovered independently by Derrick Lehmer and published in 1964 in a book edited by Beckenbach.)" return count; } // Utility to get highest bit set in a byte, numbered 0 (lowest) to 7 (highest). unsigned int HighestBitSet(uint8_t Byte) { unsigned int RetVal = 0; if (Byte & 0xf0) { // check upper 4 bits RetVal |= 4; // at least bit 4 or higher is set Byte >>= 4; // shift upper nibble to lower nibble } if (Byte & 0xc) { // check upper two bits of lower nibble RetVal |= 2; // At least bit 2 or higher is set Byte >>= 2; // shift upper two bits of lower nibble into lowest two bits } if (Byte & 0x2) { // Check second least significant bit RetVal |= 1; } return RetVal; } // end of HighestBitSet() // Utility to get lowest bit set in a byte, numbered 0 (lowest) to 7 (highest). unsigned int LowestBitSet(unsigned char Byte) { unsigned int RetVal = 0; if (Byte & 0x03) { // check lower 2 bits RetVal = (Byte & 1) ? 0 : 1; } else if (Byte & 0x0c) { // check upper two bits of lower nibble RetVal = (Byte & 4) ? 2 : 3; } else if (Byte & 0x30) { // Check lower two bits of upper nibble RetVal = (Byte & 16) ? 4 : 5; } else { assert(Byte & 0xc0); RetVal = (Byte & 64) ? 6 : 7; } return RetVal; } // Utility to get highest bit set in an uint32_t, numbered 0 (lowest) to 31 (highest). // Assumes that UintVal is non-zero and has some bit set. unsigned int HighestBitSetInUint(uint32_t UintVal) { unsigned int RetVal = 0; uint8_t Byte0 = UintVal & 0xff; uint8_t Byte1 = UintVal & 0xff00; uint8_t Byte2 = UintVal & 0xff0000; uint8_t Byte3 = UintVal & 0xff000000; if (Byte3 > 0) { RetVal = HighestBitSet(Byte3) + 24; } else if (Byte2 > 0) { RetVal = HighestBitSet(Byte2) + 16; } else if (Byte1 > 0) { RetVal = HighestBitSet(Byte1) + 8; } else if (Byte0 > 0) { RetVal = HighestBitSet(Byte0); } return RetVal; } // end of HighestBitSetInUint() // Initialize the FG info for the return register from any library function // whose name implies that we know certain return values (e.g. atoi() returns // a signed integer, while strtoul() returns an unsigned long). void GetLibFuncFGInfo(string FuncName, struct FineGrainedInfo &InitFGInfo) { map<string, struct FineGrainedInfo>::iterator FindIter; FindIter = ReturnRegisterTypeMap.find(FuncName); if (FindIter == ReturnRegisterTypeMap.end()) { // not found InitFGInfo.SignMiscInfo = 0; InitFGInfo.SizeInfo = 0; } else { // found InitFGInfo = FindIter->second; } return; } // end of GetLibFuncFGInfo() // Is FuncName a standard library function name? bool IsLibFuncName(std::string CalleeName) { // Return true if we find the name in any of our function type maps. map<string, struct FineGrainedInfo>::iterator RetTypeIter = ReturnRegisterTypeMap.find(CalleeName); if (RetTypeIter != ReturnRegisterTypeMap.end()) { // found return true; } map<string, unsigned int>::iterator PtrArgIter = PointerArgPositionMap.find(CalleeName); if (PtrArgIter != PointerArgPositionMap.end()) { // found it return true; } map<string, unsigned int>::iterator TaintIter = TaintWarningArgPositionMap.find(CalleeName); if (TaintIter != TaintWarningArgPositionMap.end()) { // found it return true; } map<string, unsigned int>::iterator UnsignedIter = UnsignedArgPositionMap.find(CalleeName); if (UnsignedIter != UnsignedArgPositionMap.end()) { // found it return true; } map<string, string>::iterator SinkIter = IntegerErrorCallSinkMap.find(CalleeName); if (SinkIter != IntegerErrorCallSinkMap.end()) { // found it return true; } // Put searches for additional library function names here. if (0 == CalleeName.compare("setuid")) { return true; } else if (IsStdioLibraryFunc(CalleeName)) { return true; } else if (IsMathLibraryFunc(CalleeName)) { return true; } else if (IsStdlibLibraryFunc(CalleeName)) { return true; } return false; } // end of IsLibFuncName() // Is FuncName a startup func called before main(), or a wrapup function called by the system? bool IsStartupFuncName(const std::string FuncName) { bool NameMatched = false; char IDA_func_name[STARS_MAXSTR]; std::size_t SkipCount; SkipCount = strspn(FuncName.c_str(), "._"); std::string TempFuncName = FuncName.substr(SkipCount); // remove leading periods and underscores if (0 == TempFuncName.compare("init_proc")) { NameMatched = true; } else if (0 == TempFuncName.compare("init")) { NameMatched = true; } else if (0 == TempFuncName.compare("start")) { NameMatched = true; } else if (0 == TempFuncName.compare("gmon_start")) { NameMatched = true; } else if (0 == TempFuncName.compare("call_gmon_start")) { NameMatched = true; } else if (0 == TempFuncName.compare("libc_start_main")) { NameMatched = true; } else if (0 == TempFuncName.compare("call_gmon_start__")) { NameMatched = true; } else if (0 == TempFuncName.compare("libc_start_main__")) { NameMatched = true; } else if (0 == TempFuncName.compare("libc_csu_init")) { NameMatched = true; } else if (0 == TempFuncName.compare("libc_csu_fini")) { NameMatched = true; } else if (0 == TempFuncName.compare("do_global_dtors_aux")) { NameMatched = true; } else if (0 == TempFuncName.compare("term_proc")) { NameMatched = true; } else if (0 == TempFuncName.compare("fini")) { NameMatched = true; } else if (0 == TempFuncName.compare("frame_dummy")) { NameMatched = true; } return NameMatched; }