Example #1
0
void CDisAsmVu::DrawInstructionDetails(Framework::Win32::CDeviceContext& deviceContext, uint32 address, int y)
{
	assert((address & 0x07) == 0);

	uint32 lowerInstruction = GetInstruction(address + 0);
	uint32 upperInstruction = GetInstruction(address + 4);

	std::tstring instructionCode = lexical_cast_hex<std::tstring>(upperInstruction, 8) + _T(" ") + lexical_cast_hex<std::tstring>(lowerInstruction, 8);
	deviceContext.TextOut(100, y, instructionCode.c_str());
		
	{
		char disAsm[256];
		m_ctx->m_pArch->GetInstructionMnemonic(m_ctx, address + 4, upperInstruction, disAsm, 256);
		deviceContext.TextOut(250, y, string_cast<std::tstring>(disAsm).c_str());
	}

	{
		char disAsm[256];
		m_ctx->m_pArch->GetInstructionOperands(m_ctx, address + 4, upperInstruction, disAsm, 256);
		deviceContext.TextOut(350, y, string_cast<std::tstring>(disAsm).c_str());
	}

	{
		char disAsm[256];
		m_ctx->m_pArch->GetInstructionMnemonic(m_ctx, address + 0, lowerInstruction, disAsm, 256);
		deviceContext.TextOut(600, y, string_cast<std::tstring>(disAsm).c_str());
	}

	{
		char disAsm[256];
		m_ctx->m_pArch->GetInstructionOperands(m_ctx, address + 0, lowerInstruction, disAsm, 256);
		deviceContext.TextOut(700, y, string_cast<std::tstring>(disAsm).c_str());
	}
}
Example #2
0
bool VIRTUALMACHINE::step(bool skip)
{
	bool result= false;
	VMREGTYPE ip= 0;
	OPCODE opcode;
	
	if(GetRegister(IP,ip)
		&& GetInstruction((VPVOID)ip,opcode)
		&& opcode)
	{
		INSTRUCTIONMAP::iterator it= instructions.find(opcode);
		if(it!=instructions.end())
		{
			INSTRUCTION* inst= it->second;
			int operandlength= inst->GetOperands(opcode,(VPVOID)ip+sizeof(opcode));
			if(operandlength>=0)
			{
				ip+= sizeof(opcode)+operandlength;
				if(SetRegister(IP,(VMREGTYPE)ip))
				{
					result= skip || inst->execute();
				}
			}
		}
		else
		{
			BadOpcodeHandler(opcode,(VPVOID)ip);
		}
	}
	
	return result;
}
Example #3
0
/**	---------------------------------------------------------------------------
	\brief	calculate instruction length of Addr 

	\param	
	\return			
	\code
	\endcode		
-----------------------------------------------------------------------------*/
int GetInstructionLength(BYTE* Addr)
{

#ifdef _USE_LIBDASM_LIB		
	
	INSTRUCTION instr = {0};	
	int Len = get_instruction(&instr, 
						Addr,
						MODE_32);
	// check illegal opcode
	if (0 == Len)
	{
		_ASSERTE(!"get_instruction");
		return -1;
	}

	#ifdef _DEBUG
	char string[256] = {0};
	get_instruction_string(&instr, FORMAT_INTEL, 0, string, sizeof(string));
	_tprintf(TEXT("%s\n"), string);
	#endif
	
	return Len;		

#else

	DISASSEMBLER   Disassembler;
	INSTRUCTION *  Instruction = NULL;	
	if (TRUE != InitDisassembler(&Disassembler, ARCH_X86))
	{
		_ASSERTE(!"InitDisassembler");
		return -1;
	}

	ULONG Flags = DISASM_DISASSEMBLE | DISASM_DECODE | DISASM_STOPONERROR | 
					DISASM_STOPONANOMALY | DISASM_STOPONRETURN;
	Instruction = GetInstruction(&Disassembler, 
							(ULONG)Addr, 
							(PBYTE)Addr,
							Flags);
	if (!Instruction) 
	{
		_ASSERTE(!"GetInstruction");
		CloseDisassembler(&Disassembler);

		return -1;
	}

	#ifdef _DEBUG 
	DumpInstruction(Instruction, TRUE, TRUE);
	#endif
	

	int Len = Instruction->Length;
	CloseDisassembler(&Disassembler);
	return Len;

#endif//_USE_LIBDASM_LIB
}
Example #4
0
static size_t dpCopyInstructions(void *dst, void *src, size_t minlen)
{
#ifdef dpWithTDisasm

    size_t len = 0;
#ifdef _M_X64
    ARCHITECTURE_TYPE arch = ARCH_X64;
#elif defined _M_IX86
    ARCHITECTURE_TYPE arch = ARCH_X86;
#endif
    DISASSEMBLER dis;
    if(InitDisassembler(&dis, arch)) {
        INSTRUCTION* pins = NULL;
        U8* pLoc = (U8*)src;
        U8* pDst = (U8*)dst;
        DWORD dwFlags = DISASM_SUPPRESSERRORS;

        while( len<minlen ) {
            pins = GetInstruction(&dis, (ULONG_PTR)pLoc, pLoc, dwFlags);
            if(!pins) { break; }
            if(pins->Type == ITYPE_RET ) { break; }

            //// todo: call or jmp
            //if(pins->Type == ITYPE_BRANCH	) break;
            //if(pins->Type == ITYPE_BRANCHCC) break;
            //if(pins->Type == ITYPE_CALL	) break;
            //if(pins->Type == ITYPE_CALLCC	) break;

            switch(pLoc[0]) {
            // call & jmp
            case 0xE8:
            case 0xE9:
                {
                    int rva = *(int*)(pLoc+1);
                    pDst[0] = pLoc[0];
                    *(DWORD*)(pDst+1) = (DWORD)((ptrdiff_t)(pLoc+rva)-(ptrdiff_t)(pDst));
                }
                break;
            default:
                memcpy(pDst, pLoc, pins->Length);
                break;
            }

            len  += pins->Length;
            pLoc += pins->Length;
            pDst += pins->Length;
        }

        CloseDisassembler(&dis);
    }
    return len;

#else // dpWithTDisasm

    memcpy(dst, src, minlen);
    return minlen;

#endif // dpWithTDisasm
}
Example #5
0
std::tstring CDisAsmVu::GetInstructionDetailsText(uint32 address)
{
	assert((address & 0x07) == 0);

	uint32 lowerInstruction = GetInstruction(address + 0);
	uint32 upperInstruction = GetInstruction(address + 4);

	std::tstring result;

	result += lexical_cast_hex<std::tstring>(address, 8) + _T("    ");
	result += lexical_cast_hex<std::tstring>(upperInstruction,  8) + _T(" ") + lexical_cast_hex<std::tstring>(lowerInstruction,  8) + _T("    ");

	char disasm[256];

	m_ctx->m_pArch->GetInstructionMnemonic(m_ctx, address + 4, upperInstruction, disasm, countof(disasm));
	result += string_cast<std::tstring>(disasm);

	for(size_t j = strlen(disasm); j < 15; j++)
	{
		result += _T(" ");
	}

	m_ctx->m_pArch->GetInstructionOperands(m_ctx, address + 4, upperInstruction, disasm, countof(disasm));
	result += string_cast<std::tstring>(disasm);

	for(size_t j = strlen(disasm); j < 31; j++)
	{
		result += _T(" ");
	}

	m_ctx->m_pArch->GetInstructionMnemonic(m_ctx, address + 0, lowerInstruction, disasm, countof(disasm));
	result += string_cast<std::tstring>(disasm);

	for(size_t j = strlen(disasm); j < 16; j++)
	{
		result += _T(" ");
	}

	m_ctx->m_pArch->GetInstructionOperands(m_ctx, address + 0, lowerInstruction, disasm, countof(disasm));
	result += string_cast<std::tstring>(disasm);

	return result;
}
Example #6
0
//=========================================================================
// Examine the machine code at the target function's entry point, and
// skip bytes in a way that we'll always end on an instruction boundary.
// We also detect branches and subroutine calls (as well as returns)
// at which point disassembly must stop.
// Finally, detect and collect information on IP-relative instructions
// that we can patch.
static DWORD DisassembleAndSkip(PVOID pFunction, DWORD dwMinLen, MHOOKS_PATCHDATA* pdata) {
	DWORD dwRet = 0;
	pdata->nLimitDown = 0;
	pdata->nLimitUp = 0;
	pdata->nRipCnt = 0;
#ifdef _M_IX86
	ARCHITECTURE_TYPE arch = ARCH_X86;
#elif defined _M_X64
	ARCHITECTURE_TYPE arch = ARCH_X64;
#else
	#error unsupported platform
#endif
	DISASSEMBLER dis;
	if (InitDisassembler(&dis, arch)) {
		INSTRUCTION* pins = NULL;
		U8* pLoc = (U8*)pFunction;
		DWORD dwFlags = DISASM_DECODE | DISASM_DISASSEMBLE | DISASM_ALIGNOUTPUT;

		ODPRINTF((L"mhooks: DisassembleAndSkip: Disassembling %p", pLoc));
		while ( (dwRet < dwMinLen) && (pins = GetInstruction(&dis, (ULONG_PTR)pLoc, pLoc, dwFlags)) ) {
			ODPRINTF(("mhooks: DisassembleAndSkip: %p:(0x%2.2x) %s", pLoc, pins->Length, pins->String));
			if (pins->Type == ITYPE_RET		) break;
			if (pins->Type == ITYPE_BRANCH	) break;
			if (pins->Type == ITYPE_BRANCHCC) break;
			if (pins->Type == ITYPE_CALL	) break;
			if (pins->Type == ITYPE_CALLCC	) break;

			#if defined _M_X64
				BOOL bProcessRip = FALSE;
				// mov or lea to register from rip+imm32
				if ((pins->Type == ITYPE_MOV || pins->Type == ITYPE_LEA) && (pins->X86.Relative) && 
					(pins->X86.OperandSize == 8) && (pins->OperandCount == 2) &&
					(pins->Operands[1].Flags & OP_IPREL) && (pins->Operands[1].Register == AMD64_REG_RIP))
				{
					// rip-addressing "mov reg, [rip+imm32]"
					ODPRINTF((L"mhooks: DisassembleAndSkip: found OP_IPREL on operand %d with displacement 0x%x (in memory: 0x%x)", 1, pins->X86.Displacement, *(PDWORD)(pLoc+3)));
					bProcessRip = TRUE;
				}
				// mov or lea to rip+imm32 from register
				else if ((pins->Type == ITYPE_MOV || pins->Type == ITYPE_LEA) && (pins->X86.Relative) && 
					(pins->X86.OperandSize == 8) && (pins->OperandCount == 2) &&
					(pins->Operands[0].Flags & OP_IPREL) && (pins->Operands[0].Register == AMD64_REG_RIP))
				{
					// rip-addressing "mov [rip+imm32], reg"
					ODPRINTF((L"mhooks: DisassembleAndSkip: found OP_IPREL on operand %d with displacement 0x%x (in memory: 0x%x)", 0, pins->X86.Displacement, *(PDWORD)(pLoc+3)));
					bProcessRip = TRUE;
				}
				else if ( (pins->OperandCount >= 1) && (pins->Operands[0].Flags & OP_IPREL) )
				{
					// unsupported rip-addressing
					ODPRINTF((L"mhooks: DisassembleAndSkip: found unsupported OP_IPREL on operand %d", 0));
					// dump instruction bytes to the debug output
					for (DWORD i=0; i<pins->Length; i++) {
						ODPRINTF((L"mhooks: DisassembleAndSkip: instr byte %2.2d: 0x%2.2x", i, pLoc[i]));
					}
					break;
				}
				else if ( (pins->OperandCount >= 2) && (pins->Operands[1].Flags & OP_IPREL) )
				{
					// unsupported rip-addressing
					ODPRINTF((L"mhooks: DisassembleAndSkip: found unsupported OP_IPREL on operand %d", 1));
					// dump instruction bytes to the debug output
					for (DWORD i=0; i<pins->Length; i++) {
						ODPRINTF((L"mhooks: DisassembleAndSkip: instr byte %2.2d: 0x%2.2x", i, pLoc[i]));
					}
					break;
				}
				else if ( (pins->OperandCount >= 3) && (pins->Operands[2].Flags & OP_IPREL) )
				{
					// unsupported rip-addressing
					ODPRINTF((L"mhooks: DisassembleAndSkip: found unsupported OP_IPREL on operand %d", 2));
					// dump instruction bytes to the debug output
					for (DWORD i=0; i<pins->Length; i++) {
						ODPRINTF((L"mhooks: DisassembleAndSkip: instr byte %2.2d: 0x%2.2x", i, pLoc[i]));
					}
					break;
				}
				// follow through with RIP-processing if needed
				if (bProcessRip) {
					// calculate displacement relative to function start
					S64 nAdjustedDisplacement = pins->X86.Displacement + (pLoc - (U8*)pFunction);
					// store displacement values furthest from zero (both positive and negative)
					if (nAdjustedDisplacement < pdata->nLimitDown)
						pdata->nLimitDown = nAdjustedDisplacement;
					if (nAdjustedDisplacement > pdata->nLimitUp)
						pdata->nLimitUp = nAdjustedDisplacement;
					// store patch info
					if (pdata->nRipCnt < MHOOKS_MAX_RIPS) {
						pdata->rips[pdata->nRipCnt].dwOffset = dwRet + 3;
						pdata->rips[pdata->nRipCnt].nDisplacement = pins->X86.Displacement;
						pdata->nRipCnt++;
					} else {
						// no room for patch info, stop disassembly
						break;
					}
				}
			#endif

			dwRet += pins->Length;
			pLoc  += pins->Length;
		}

		CloseDisassembler(&dis);
	}

	return dwRet;
}
Example #7
0
    Token GetNextToken()
    {
        //When we read the source code line by line, we use two index to indicate the both ends of a source line.
        //At first, the right end index equals to the left end index: they both are 0.
        sasm.lexer.iIndex0 = sasm.lexer.iIndex1;
        if (sasm.lexer.iIndex0 >= strlen(sasm.sourceCode[sasm.lexer.iCurrentSourceLine]))
        {
            if (!SkipToNextLine())
                return ASM_END_OF_TOKEN_STREAM;
        }
    
        if (sasm.lexer.iState == ASM_LEX_STATE_END_STRING)
            sasm.lexer.iState = ASM_LEX_STATE_NO_STRING;
        //locate index to the first non-whitespace character of a source code line
        if (sasm.lexer.iState != ASM_LEX_STATE_IN_STRING)
        {
            while (TRUE)
            {
                if (!IsCharWhiteSpace((sasm.sourceCode[sasm.lexer.iCurrentSourceLine][sasm.lexer.iIndex0])))
                    break;
                sasm.lexer.iIndex0++;
            }
        }
        sasm.lexer.iIndex1 = sasm.lexer.iIndex0;

		int isGetEscapeChar = FALSE;
    
        //move iIndex1 to the location of next token end
        while (TRUE)
        {
            if (sasm.lexer.iState == ASM_LEX_STATE_IN_STRING)
            {
                if (sasm.lexer.iIndex1 >= strlen(sasm.sourceCode[sasm.lexer.iCurrentSourceLine]))
                {
                    sasm.lexer.currentToken = ASM_TOKEN_TYPE_INVALID;
                    return sasm.lexer.currentToken;
                }
                if (sasm.sourceCode[sasm.lexer.iCurrentSourceLine][sasm.lexer.iIndex1] == '\\')
                {
					//isGetEscapeChar = TRUE;
                    sasm.lexer.iIndex1 += 2;
                    continue;
                }
                if (sasm.sourceCode[sasm.lexer.iCurrentSourceLine][sasm.lexer.iIndex1] == '"')
                    break;
                sasm.lexer.iIndex1++;
            }
            else
            {
                if (sasm.lexer.iIndex1 >= strlen(sasm.sourceCode[sasm.lexer.iCurrentSourceLine]))
                    break;
                if (IsCharDelimiter(sasm.sourceCode[sasm.lexer.iCurrentSourceLine][sasm.lexer.iIndex1]))
                    break;
                sasm.lexer.iIndex1++;
            }
        }
    
        if (sasm.lexer.iIndex1 - sasm.lexer.iIndex0 == 0)
            sasm.lexer.iIndex1++;
    
        //Get the next lexeme
        unsigned int currentTargetIndex = 0;
        for (int i = sasm.lexer.iIndex0; i < sasm.lexer.iIndex1; i++)
        {
			if (sasm.lexer.iState == ASM_LEX_STATE_IN_STRING)
				if (sasm.sourceCode[sasm.lexer.iCurrentSourceLine][i] == '\\')
				{
					switch (sasm.sourceCode[sasm.lexer.iCurrentSourceLine][i + 1])
					{
					case 'a':
						 sasm.lexer.pCurrentLexeme[currentTargetIndex] = '\n';
						 break;
					case 'b':
						sasm.lexer.pCurrentLexeme[currentTargetIndex] = '\b';
						break;
					case 'f':
						sasm.lexer.pCurrentLexeme[currentTargetIndex] = '\f';
						break;
					case 'n':
						sasm.lexer.pCurrentLexeme[currentTargetIndex] = '\n';
						break;
					case 'r':
						sasm.lexer.pCurrentLexeme[currentTargetIndex] = '\r';
						break;
					case 't':
						sasm.lexer.pCurrentLexeme[currentTargetIndex] = '\t';
						break;
					case 'v':
						sasm.lexer.pCurrentLexeme[currentTargetIndex] = '\n';
						break;
					case '\\':
						sasm.lexer.pCurrentLexeme[currentTargetIndex] = '\\';
						break;
					case '\'':
						sasm.lexer.pCurrentLexeme[currentTargetIndex] = '\'';
						break;
					case '"':
						sasm.lexer.pCurrentLexeme[currentTargetIndex] = '\"';
						break;
					case '0':
						sasm.lexer.pCurrentLexeme[currentTargetIndex] = '\0';
						break;

					default:
						break;
					}
					currentTargetIndex += 1;
					i++;
					continue;
				}
            sasm.lexer.pCurrentLexeme[currentTargetIndex] = sasm.sourceCode[sasm.lexer.iCurrentSourceLine][i];
            currentTargetIndex++;
        }
        sasm.lexer.pCurrentLexeme[currentTargetIndex] = '\0';
    	/*if (sasm.lexer.iState != ASM_LEX_STATE_IN_STRING)
    	strtoupper(sasm.lexer.pCurrentLexeme);*/
    
        //Decide which token the lexeme is
        sasm.lexer.currentToken = ASM_TOKEN_TYPE_INVALID;
        if (strlen(sasm.lexer.pCurrentLexeme) > 1 || sasm.lexer.pCurrentLexeme[0] != '"')
        {
            if (sasm.lexer.iState == ASM_LEX_STATE_IN_STRING)
            {
                sasm.lexer.currentToken = ASM_TOKEN_TYPE_STRING;
                return ASM_TOKEN_TYPE_STRING;
            }
        }
    
        if (IsStringInt(sasm.lexer.pCurrentLexeme))
            sasm.lexer.currentToken = ASM_TOKEN_TYPE_INT;
    
        if (IsStringFloat(sasm.lexer.pCurrentLexeme))
            sasm.lexer.currentToken = ASM_TOKEN_TYPE_FLOAT;
    
        if (IsStringIdent(sasm.lexer.pCurrentLexeme))
            sasm.lexer.currentToken = ASM_TOKEN_TYPE_IDENT;
    
        if (strcmp(sasm.lexer.pCurrentLexeme, ASM_KW_SET_STACK_SIZE) == 0)
            sasm.lexer.currentToken = ASM_TOKEN_TYPE_SETSTACKSIZE;
    
        if (strcmp(sasm.lexer.pCurrentLexeme, ASM_KW_VAR) == 0)
            sasm.lexer.currentToken = ASM_TOKEN_TYPE_VAR;
    
        if (strcmp(sasm.lexer.pCurrentLexeme, ASM_KW_FUNCTION) == 0)
            sasm.lexer.currentToken = ASM_TOKEN_TYPE_FUNC;
    
        if (strcmp(sasm.lexer.pCurrentLexeme, ASM_KW_PARAM) == 0)
            sasm.lexer.currentToken = ASM_TOKEN_TYPE_PARAM;
    
        if (strcmp(sasm.lexer.pCurrentLexeme, ASM_KW_RETVAL) == 0)
            sasm.lexer.currentToken = ASM_TOKEN_TYPE_REG_RETVAL;
    
    	if (strlen(sasm.lexer.pCurrentLexeme) == 1)
    	{
    		switch (sasm.lexer.pCurrentLexeme[0])
    		{
    		case '"':
    			switch (sasm.lexer.iState)
    			{
    			case ASM_LEX_STATE_NO_STRING:
    				sasm.lexer.iState = ASM_LEX_STATE_IN_STRING;
    				break;
    			case ASM_LEX_STATE_IN_STRING:
    				sasm.lexer.iState = ASM_LEX_STATE_END_STRING;
    			}
    			sasm.lexer.currentToken = ASM_TOKEN_TYPE_QUATE;
    			break;
    		case ',':
    			sasm.lexer.currentToken = ASM_TOKEN_TYPE_COMMA;
    			break;
    		case ':':
    			sasm.lexer.currentToken = ASM_TOKEN_TYPE_COLON;
    			break;
    		case '[':
    			sasm.lexer.currentToken = ASM_TOKEN_TYPE_OPEN_BRACKET;
    			break;
    		case ']':
    			sasm.lexer.currentToken = ASM_TOKEN_TYPE_CLOSE_BRACKET;
    			break;
    		case '{':
    			sasm.lexer.currentToken = ASM_TOKEN_TYPE_OPEN_BRACE;
    			break;
    		case '}':
    			sasm.lexer.currentToken = ASM_TOKEN_TYPE_CLOSE_BRACE;
    			break;
    		case '\n':
    			sasm.lexer.currentToken = ASM_TOKEN_TYPE_NEWLINE;
    			break;
    		case '\r':
    			sasm.lexer.currentToken = ASM_TOKEN_TYPE_NEWLINE;
    			break;
    		}
    	}
    
        InstrLookup instrLookup;
        if (GetInstruction(sasm.instrLookup, sasm.lexer.pCurrentLexeme, &instrLookup))
            sasm.lexer.currentToken = ASM_TOKEN_TYPE_INSTR;
    
        return sasm.lexer.currentToken;
    }
Example #8
0
bool csPixelShaderParser::ParseProgram (iDataBuffer* program)
{
  version = CS_PS_INVALID;

  csString prog;
  prog.Append ((char*)program->GetData(), program->GetSize());

  // Trim any leading/trailing blank lines
  prog.Trim ();

  size_t len = prog.Length ();

  if (len == 0)
  {
    Report (CS_REPORTER_SEVERITY_ERROR, 
      "Empty program!");
    return false;
  }


  max_registers[CS_PS_REG_TEX] = 4;
  max_registers[CS_PS_REG_TEMP] = 2;
  max_registers[CS_PS_REG_CONSTANT] = 8;
  max_registers[CS_PS_REG_COLOR] = 2;

  bool hasVersion = false;
  csStringReader reader (prog);
  csString line;
  int lineCount = 0;
  while (reader.HasMoreLines ())
  {
    if (!reader.GetLine (line)) break;
    lineCount++;
    csPSProgramInstruction inst;
    if(!GetInstruction (line, inst)) return false;

    // Probably a blank line or comment ... ignore
    if(inst.instruction == CS_PS_INS_INVALID) continue;

    // Identify the version
    bool isVerInstr = (inst.instruction >= CS_PS_INS_PS_1_1) &&
      (inst.instruction <= CS_PS_INS_PS_1_4);
    if (!hasVersion)
    {
      if (!isVerInstr)
      {
	Report (CS_REPORTER_SEVERITY_WARNING, 
	  "Expected version, got %s", GetInstructionName (inst.instruction));
	return false;
      }

      switch (inst.instruction)
      {
	case CS_PS_INS_PS_1_1:
	  version = CS_PS_1_1;
	  hasVersion = true;
	  break;
	case CS_PS_INS_PS_1_2:
	  version = CS_PS_1_2;
	  hasVersion = true;
	  break;
	case CS_PS_INS_PS_1_3:
	  version = CS_PS_1_3;
	  hasVersion = true;
	  break;
	case CS_PS_INS_PS_1_4:
	  version = CS_PS_1_4;
	  hasVersion = true;
	  max_registers[CS_PS_REG_TEX] = 6;
	  max_registers[CS_PS_REG_TEMP] = 6;
	  break;
	default:
	  break;
      }
    }
    else if (isVerInstr)
    {
      Report (CS_REPORTER_SEVERITY_WARNING, 
	"Invalid version instruction %s in line %d", 
	GetInstructionName (inst.instruction), lineCount);
      return false;
    }

    if(!(version & PS_Instructions[inst.instruction].versions))
    {
      Report (CS_REPORTER_SEVERITY_ERROR, 
	"Pixel Shader version %s does not support instruction %s",
	GetVersionString (version),
	CS::Quote::Single (GetInstructionName (inst.instruction)));
      return false;
    }

    if (!isVerInstr)
      program_instructions.Push (inst);
  }

  return true;
}