//***************************************************************************** // This method will walk the byte codes of an IL method looking for tokens. // For each token found, it will check to see if it has been moved, and if // so, apply the new token value in its place. //***************************************************************************** HRESULT CeeFileGenWriter::MapTokensForMethod( CeeGenTokenMapper *pMapper, BYTE *pCode, LPCWSTR szMethodName) { mdToken tkTo; DWORD PC; COR_ILMETHOD_DECODER method((COR_ILMETHOD*) pCode); // If compressed IL is being emitted, this routine will have no idea how to walk the tokens, // so don't do it if (m_dwMacroDefinitionSize != 0) return S_OK; pCode = const_cast<BYTE*>(method.Code); PC = 0; while (PC < method.GetCodeSize()) { DWORD Len; DWORD i; OPCODE instr; instr = DecodeOpcode(&pCode[PC], &Len); if (instr == CEE_COUNT) { _ASSERTE(0 && "Instruction decoding error\n"); return E_FAIL; } PC += Len; switch (OpcodeInfo[instr].Type) { DWORD tk; default: { _ASSERTE(0 && "Unknown instruction\n"); return E_FAIL; } case InlineNone: break; case ShortInlineI: case ShortInlineVar: case ShortInlineBrTarget: PC++; break; case InlineVar: PC += 2; break; case InlineI: case ShortInlineR: case InlineBrTarget: case InlineRVA: PC += 4; break; case InlineI8: case InlineR: PC += 8; break; case InlinePhi: { DWORD cases = pCode[PC]; PC += 2 * cases + 1; break; } case InlineSwitch: { DWORD cases = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24); PC += 4; for (i = 0; i < cases; i++) { PC += 4; } // skip bottom of loop which prints szString continue; } case InlineTok: case InlineSig: case InlineMethod: case InlineField: case InlineType: case InlineString: { tk = GET_UNALIGNED_VAL32(&pCode[PC]); if (pMapper->HasTokenMoved(tk, tkTo)) { SET_UNALIGNED_VAL32(&pCode[PC], tkTo); } PC += 4; break; } } } return S_OK; }
void Peeper(uchar *ip, uchar *ip_end) { OpcodeInfo opi[4]; uchar *start_ip = ip; int n; int op_count = 0; for (n=0;n<4;n++) { if (ip > ip_end) break; ip = DecodeOpcode(&opi[n], ip); op_count++; } if (op_count != 4) return; // Double optimizer while(1) { /* ld r0,r14 ld r1,r15 ld r14,r0 ld r15,r1 */ // All are ldr if (opi[0].op != _LDR) break; if (opi[1].op != _LDR) break; if (opi[2].op != _LDR) break; if (opi[3].op != _LDR) break; // check r0's if (opi[0].rd != opi[2].rs) break; // check r1's if (opi[1].rd != opi[3].rs) break; // check r14's if (opi[0].rs != opi[2].rd) break; // check r15's if (opi[1].rs != opi[3].rd) break; *start_ip++ = 0; *start_ip++ = 0; *start_ip++ = 0; *start_ip++ = 0; *start_ip++ = 0; *start_ip++ = 0; *start_ip++ = 0; *start_ip++ = 0; *start_ip++ = 0; *start_ip++ = 0; *start_ip++ = 0; *start_ip++ = 0; return; } // Register to register switches while(1) { /* ld r0,r1 ld r1,r0 */ // All are ldr if (opi[0].op != _LDR) break; if (opi[1].op != _LDR) break; // check r0's if (opi[0].rd != opi[1].rs) break; // check r1's if (opi[1].rd != opi[0].rs) break; *start_ip++ = 0; *start_ip++ = 0; *start_ip++ = 0; *start_ip++ = 0; *start_ip++ = 0; *start_ip++ = 0; return; } //memset(start_ip, 0, start_ip - ip); }
void RebuildFunc(SYMBOL *sym) { OpcodeInfo thisOp; SYMBOL *ref; uchar *ip, *ip_end, *ip_last; int real_ip; char str[256]; if (!sym) return; RebuildEmit("\n//****************************************\n"); RebuildEmit("// Function: %s\n", sym->Name); RebuildEmit("//****************************************\n\n"); #if 0 //OLD if (strcmp(sym->Name, Code_EntryPoint) == 0) { RebuildEmit(".global %s\n", sym->Name); RebuildEmit(".func %s\n", sym->Name); } else { RebuildEmit(".func %s_%d\n", sym->Name, sym->LocalScope); } #else //New if (strcmp(sym->Name, Code_EntryPoint) == 0) { RebuildEmit(".global %s\n", sym->Name); RebuildEmit(".func %s, %d, %s\n", sym->Name, sym->Params, RebuildRetType(sym->RetType) ); } else { RebuildEmit(".func %s_%d, %d, %s\n", sym->Name, sym->LocalScope, sym->Params, RebuildRetType(sym->RetType)); } #endif ip_end = (uchar *) ArrayPtr(&CodeMemArray, sym->EndIP); ip = (uchar *) ArrayPtr(&CodeMemArray, sym->Value); real_ip = sym->Value; while(1) { ip_last = ip; if (ip > ip_end) break; // Print labels ref = (SYMBOL *) ArrayGet(&CodeLabelArray, real_ip); if (ref) { if (ref->LabelType == label_Local) RebuildEmit("%s_%d:\n", ref->Name, ref->LocalScope); } RebuildEmitStabs(real_ip); // Peeper(ip, ip_end); if (ArgSkipElim == 0) if (ArrayGet(&CodeTouchArray, real_ip) == 0) RebuildEmit("// "); CaseRef = 0; ip = DecodeOpcode(&thisOp, ip); DecodeAsmString(&thisOp, str, 1); RebuildEmit("\t%s", str); // DecodeAsmString(&thisOp, str, 0); // Sanity testing // CodeSanityChecker(thisOp.rip, str); if (ArgDebugRebuild) { int len = 4 + strlen(str); str[0] = 0; while(len < 40) { RebuildEmit(" ", str); len++; } RebuildEmit("; 0x%x - ", real_ip); DisassembleFromSource(real_ip, str); RebuildEmit("%s", str); } RebuildEmit("\n"); // Check for case statement, which need case data after them if (CaseRef) { RebuildEmit(".data\n"); Rebuild_Data(CaseRef); RebuildEmit(".code\n"); } real_ip += (ip - ip_last); } }
void CActiveReader::RunL() { // the read has completed - for the moment we are not really interested at the moment if (iAuto) { switch (iReadState) { case EReadHeader: iReaderOutputConsole->Printf(_L("Header byte recvd\n")); iReadState = (DecodeHeader() == KHCIUARTCommandHeader ? EReadOpcode : EReadConnectionHandleFlags); break; case EReadOpcode: { iReaderOutputConsole->Printf(_L("Opcode bytes recvd\n")); TInt opcode = DecodeOpcode(); if (opcode == 0) //NoOpCommand has no more parameters { iReadComplete = ETrue; iReadState = EReadHeader; // start again } else { iReadState = EReadCommandLength; } } break; case EReadCommandLength: iReaderOutputConsole->Printf(_L("Length byte recvd\n")); iReadState = EReadCommandRemainder; break; case EReadDataLength: iReaderOutputConsole->Printf(_L("Length byte recvd\n")); iReadState = EReadDataRemainder; break; case EReadConnectionHandleFlags: iReaderOutputConsole->Printf(_L("ConnectionHandle bytes recvd\n")); iReadState = EReadDataLength; break; case EReadCommandRemainder: case EReadDataRemainder: iReaderOutputConsole->Printf(_L("Remainder bytes recvd\n")); iReadComplete = ETrue; iReadState = EReadHeader; // start again break; default: __DEBUGGER(); } if (iReadComplete) { iReaderOutputConsole->Printf(_L("Decoding...\n")); if (DecodeHeader() == KHCIUARTCommandHeader) { iReaderOutputConsole->Printf(_L("Decode: Command\n")); iEmulator.CommandReceived(iOpcodeBuf, iRemainderBuf); } else { iReaderOutputConsole->Printf(_L("Decode: ACL Data\n")); iEmulator.ACLDataReceived(iConnectionHandleFlagsBuf, iRemainderBuf); } iReadComplete = EFalse; } } // queue another one DoRead(); }
void RebuildCppFunc(SYMBOL *sym, int isproto) { OpcodeInfo thisOp; SYMBOL *ref; uchar *ip, *ip_end, *ip_last; int real_ip; // char str[256]; if (!sym) return; // Say no returns yet ReturnCount = 0; // Enumerate this functions labels, unless we're generating a proto if (isproto == 0) EnumerateFunctionLabels(sym); ThisFunctionRegs = FunctionRegUsage(sym); ThisFunctionRetType = sym->RetType; if (ThisFunctionRegs == -1) return; RebuildCppProlog(sym, isproto); // if we're generating a proto return if (isproto) return; ip_end = (uchar *) ArrayPtr(&CodeMemArray, sym->EndIP); ip = (uchar *) ArrayPtr(&CodeMemArray, sym->Value); real_ip = sym->Value; while(1) { ip_last = ip; if (ip > ip_end) break; // Print labels ref = (SYMBOL *) ArrayGet(&CodeLabelArray, real_ip); if (ref) { if (ref->LabelType == label_Local) { #ifdef Cpp_DEBUG RebuildEmit("// %s_%d:\n", ref->Name, ref->LocalScope); #endif RebuildEmit("label_%d:;\n", ref->LabelEnum); } } if (ArrayGet(&CodeTouchArray, real_ip) == 0) RebuildEmit("// "); CaseRef = 0; ip = DecodeOpcode(&thisOp, ip); ThisFunctionExit = 0; if (ip > ip_end) ThisFunctionExit = 1; RebuildCppInst(&thisOp); // DecodeAsmString(&thisOp, str); // RebuildEmit("\t%s", str); #ifdef CPP_DEBUG { int len = 4 + strlen(str); str[0] = 0; while(len < 40) { RebuildEmit(" ", str); len++; } DisassembleFromSource(real_ip, str); RebuildEmit(";%s", str); } #endif // RebuildEmit("\n"); // Check for case statement, which need case data after them /* if (CaseRef) { RebuildEmit(".data\n"); Rebuild_Data(CaseRef); RebuildEmit(".code\n"); } */ real_ip += (ip - ip_last); } RebuildCppEpilog(sym); }
int FunctionRegAnalyse(SYMBOL *sym, FuncProp *fp) { OpcodeInfo thisOp; uchar *ip, *ip_end; int params,n; fp->src_reg = 0; fp->dst_reg = 0; fp->assign_reg = 0; fp->uninit_reg = 0; // Make sure we have a valid symbol if (!sym) return -1; // Make sure the symbol is a function if (sym->Type != SECT_code) return -1; // Get the start and end of the function in the code array ip_end = (uchar *) ArrayPtr(&CodeMemArray, sym->EndIP); ip = (uchar *) ArrayPtr(&CodeMemArray, sym->Value); // Set up the parameter regs params = sym->Params; for (n=0;n<params;n++) { fp->assign_reg |= REGBIT(REG_i0 + n); } // Scan the function #ifdef AFDEBUG printf("\n"); #endif while(1) { if (ip > ip_end) break; #ifdef AFDEBUG { char buf[2560]; buf[0] = 0; DisassembleFromSource(ip - CodeMemArray.array, buf); printf("%s\n", buf); } #endif ip = DecodeOpcode(&thisOp, ip); // Ignor push and pop if (thisOp.op == _PUSH) continue; if (thisOp.op == _POP) continue; //----------------------------------------- // Deal with syscalls // for some strange reason rd is the syscallId which will // tag unused registers as used for void functions //----------------------------------------- if(thisOp.op == _SYSCALL) { FunctionReg_Syscall(&thisOp, fp); } // Check for a dest reg else if (thisOp.flags & fetch_d) { if (thisOp.rd < 32) { // Since this is a dst regs we say its initialized fp->assign_reg |= REGBIT(thisOp.rd); // Say this reg was used as a dst reg fp->dst_reg |= REGBIT(thisOp.rd); } } // Check for a source reg if (thisOp.flags & fetch_s) { if (thisOp.rs < 32) { // check if this reg was assigned previously, if it was'nt it is uninitialized before use int is_assigned = fp->assign_reg & REGBIT(thisOp.rs); if (!is_assigned) fp->uninit_reg |= REGBIT(thisOp.rs); fp->src_reg |= REGBIT(thisOp.rs); } } //----------------------------------------- // Deal with immediate calls //----------------------------------------- // Add the call parameters to the used list if (thisOp.op == _CALLI) { FunctionReg_Calli(&thisOp, fp); } //----------------------------------------- // Deal with register calls //----------------------------------------- // Add the call parameters to the used list if (thisOp.op == _CALL) { FunctionReg_CallReg(&thisOp, fp); } } #ifdef AFDEBUG printf("\n"); printf(" rrrrrrrrrrrrrrrriiiiddddddddfrsz\n"); printf(" fedcba9876543210321076543210rtpr\n"); printf("src_reg = %s\n", Bin32(fp->src_reg)); printf("dst_reg = %s\n", Bin32(fp->dst_reg)); printf("assign_reg = %s\n", Bin32(fp->assign_reg)); printf("uninit_reg = %s\n", Bin32(fp->uninit_reg)); if (fp->uninit_reg) printf(""); #endif // Make sure zr is never uninitialized fp->uninit_reg &= ~REGBIT(REG_zero); // Make a composit of which reg's were used fp->reg_used = fp->src_reg | fp->dst_reg; return fp->reg_used; }