Example #1
0
        public void TestExecutor_Execute()
        {
            JavaInstruction   ji       = new JavaInstruction((char)EnumJavaOpCode.aaload, "aaload", "无|将引用型数组指定索引的值推送至栈顶", null);
            NativeInterpreter executor = new NativeInterpreter();

            executor.Execute(EnumJavaOpCode.getstatic, null);
        }
Example #2
0
        public static JavaInstrArguments ArgsType(this JavaInstruction instr)
        {
            switch (instr)
            {
            case JavaInstruction.newarray:
                return(JavaInstrArguments.AType);

            case JavaInstruction.bipush:
                return(JavaInstrArguments.Byte);

            case JavaInstruction.ldc:
                return(JavaInstrArguments.ByteCpIndex);

            case JavaInstruction.iload:
            case JavaInstruction.lload:
            case JavaInstruction.fload:
            case JavaInstruction.dload:
            case JavaInstruction.aload:
            case JavaInstruction.istore:
            case JavaInstruction.lstore:
            case JavaInstruction.fstore:
            case JavaInstruction.dstore:
            case JavaInstruction.astore:
            case JavaInstruction.ret:
                return(JavaInstrArguments.LocalVarIndex);

            case JavaInstruction.ifeq:
            case JavaInstruction.ifne:
            case JavaInstruction.iflt:
            case JavaInstruction.ifge:
            case JavaInstruction.ifgt:
            case JavaInstruction.ifle:
            case JavaInstruction.if_icmpeq:
            case JavaInstruction.if_icmpne:
            case JavaInstruction.if_icmplt:
            case JavaInstruction.if_icmpge:
            case JavaInstruction.if_icmpgt:
            case JavaInstruction.if_icmple:
            case JavaInstruction.if_acmpeq:
            case JavaInstruction.if_acmpne:
            case JavaInstruction.@goto:
            case JavaInstruction.jsr:
            case JavaInstruction.ifnull:
            case JavaInstruction.ifnonnull:
                return(JavaInstrArguments.BranchOffset);

            case JavaInstruction.sipush:
                return(JavaInstrArguments.Short);

            case JavaInstruction.iinc:
                return(JavaInstrArguments.Iinc);

            case JavaInstruction.ldc_w:
            case JavaInstruction.ldc2_w:
            case JavaInstruction.getstatic:
            case JavaInstruction.putstatic:
            case JavaInstruction.getfield:
            case JavaInstruction.putfield:
            case JavaInstruction.invokevirtual:
            case JavaInstruction.invokespecial:
            case JavaInstruction.invokestatic:
            case JavaInstruction.@new:
            case JavaInstruction.anewarray:
            case JavaInstruction.checkcast:
            case JavaInstruction.instanceof:
                return(JavaInstrArguments.CpIndex);

            case JavaInstruction.wide:
                return(JavaInstrArguments.WidePrefix);

            case JavaInstruction.lookupswitch:
                return(JavaInstrArguments.LookupSwitch);

            case JavaInstruction.tableswitch:
                return(JavaInstrArguments.TableSwitch);

            case JavaInstruction.multianewarray:
                return(JavaInstrArguments.MultiNewArray);

            case JavaInstruction.goto_w:
            case JavaInstruction.jsr_w:
                return(JavaInstrArguments.WideBranchOffset);

            case JavaInstruction.invokedynamic:
                return(JavaInstrArguments.InvokeDynamic);

            case JavaInstruction.invokeinterface:
                return(JavaInstrArguments.InvokeInterface);

            default:
                return(JavaInstrArguments.Niladic);
            }
        }
Example #3
0
 protected JavaOp(int offset, JavaInstruction instr)
 {
     Offset = offset;
     Instr  = instr;
 }
Example #4
0
 public Niladic(int start, JavaInstruction instr) : base(start, instr)
 {
 }
Example #5
0
        /// <summary>
        /// Reads instructions starting from the current position in the disassembly stream.
        /// </summary>
        /// <param name="dwInstructions">[in] The number of instructions to disassemble. This value is also the maximum length of the prgDisassembly array.</param>
        /// <param name="dwFields">[in] A combination of flags from the DISASSEMBLY_STREAM_FIELDS enumeration that indicate which fields of prgDisassembly are to be filled out.</param>
        /// <param name="pdwInstructionsRead">[out] Returns the number of instructions actually disassembled.</param>
        /// <param name="prgDisassembly">[out] An array of DisassemblyData structures that is filled in with the disassembled code, one structure per disassembled instruction. The length of this array is dictated by the dwInstructions parameter.</param>
        /// <returns>If successful, returns S_OK; otherwise, returns an error code.</returns>
        /// <remarks>
        /// The maximum number of instructions that are available in the current scope can be obtained by calling the IDebugDisassemblyStream2.GetSize method.
        ///
        /// The current position where the next instruction is read from can be changed by calling the IDebugDisassemblyStream2.Seek method.
        ///
        /// The DSF_OPERANDS_SYMBOLS flag can be added to the DSF_OPERANDS flag in the dwFields parameter to indicate that symbol names should be used when disassembling instructions.
        /// </remarks>
        public int Read(uint dwInstructions, enum_DISASSEMBLY_STREAM_FIELDS dwFields, out uint pdwInstructionsRead, DisassemblyData[] prgDisassembly)
        {
            pdwInstructionsRead = 0;

            uint actualInstructions = Math.Min(dwInstructions, (uint)(_disassembledMethod.Instructions.Count - _currentInstructionIndex));

            if (prgDisassembly == null || prgDisassembly.Length < dwInstructions)
            {
                return(VSConstants.E_INVALIDARG);
            }

            IMethod method = _executionContext.Location.GetMethod();
            ReadOnlyCollection <ILocalVariable>    localVariables = method.GetHasVariableInfo() ? method.GetVariables() : new ReadOnlyCollection <ILocalVariable>(new ILocalVariable[0]);
            ReadOnlyCollection <ConstantPoolEntry> constantPool   = _executionContext.Location.GetDeclaringType().GetConstantPool();

            int addressFieldWidth = 1;
            int addressFieldRange = 10 * addressFieldWidth;

            while (addressFieldRange <= _bytecode.Length)
            {
                addressFieldWidth++;
                addressFieldRange *= 10;
            }

            for (int i = 0; i < actualInstructions; i++)
            {
                JavaInstruction instruction      = _disassembledMethod.Instructions[_currentInstructionIndex + i];
                int             instructionStart = instruction.Offset;
                int             instructionSize  = instruction.Size;

#if false // bstrAddress is supposed to refer to an absolute offset
                if (dwFields.GetAddress())
                {
                    prgDisassembly[i].bstrAddress = string.Format("{0," + addressFieldWidth + "}", instructionStart);
                    prgDisassembly[i].dwFields   |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS;
                }
#endif

                if (dwFields.GetCodeBytes())
                {
                    prgDisassembly[i].bstrCodeBytes = string.Join(" ", _bytecode.Skip(instructionStart).Take(instructionSize).Select(x => x.ToString("X2")));
                    prgDisassembly[i].dwFields     |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODEBYTES;
                }

                if (dwFields.GetCodeLocationId())
                {
                    prgDisassembly[i].uCodeLocationId = (ulong)instructionStart;
                    prgDisassembly[i].dwFields       |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID;
                }

                if (dwFields.GetOpCode())
                {
                    prgDisassembly[i].bstrOpcode = string.Format("[{0}]{1}", _evaluationStackDepths[_currentInstructionIndex + i], instruction.OpCode.Name ?? "???");
                    prgDisassembly[i].dwFields  |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE;
                }

                if (dwFields.GetAddressOffset())
                {
                    prgDisassembly[i].bstrAddressOffset = string.Format("{0," + addressFieldWidth + "}", instructionStart);
                    prgDisassembly[i].dwFields         |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESSOFFSET;
                }

                if (dwFields.GetDocumentUrl())
                {
                    // "For text documents that can be represented as file names, the bstrDocumentUrl
                    // field is filled in with the file name where the source can be found, using the
                    // format file://file name."
                    string sourcePath = _executionContext.Location.GetSourcePath();
                    Uri    sourceUri;
                    if (!string.IsNullOrEmpty(sourcePath) && Uri.TryCreate(sourcePath, UriKind.Absolute, out sourceUri))
                    {
                        prgDisassembly[i].bstrDocumentUrl = sourceUri.AbsoluteUri;
                        // if it starts with file:/// one of the / characters will show in disassembly view
                        if (prgDisassembly[i].bstrDocumentUrl.StartsWith("file:///"))
                        {
                            prgDisassembly[i].bstrDocumentUrl = "file://" + prgDisassembly[i].bstrDocumentUrl.Substring("file:///".Length);
                        }

                        prgDisassembly[i].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL;
                    }
                }

                if (dwFields.GetOperands())
                {
                    prgDisassembly[i].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS;

                    bool includeSymbolNames = dwFields.GetOperandsSymbols();
                    if (includeSymbolNames)
                    {
                        prgDisassembly[i].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS_SYMBOLS;
                    }

                    // operand 0
                    switch (instruction.OpCode.OperandType)
                    {
                    case JavaOperandType.InlineI1:
                        prgDisassembly[i].bstrOperands = instruction.Operands.InlineSByte.ToString();
                        break;

                    case JavaOperandType.InlineI2:
                        prgDisassembly[i].bstrOperands = instruction.Operands.InlineInt16.ToString();
                        break;

                    case JavaOperandType.InlineShortBranchTarget:
                    case JavaOperandType.InlineBranchTarget:
                        prgDisassembly[i].bstrOperands = (instructionStart + instruction.Operands.Operand1).ToString();
                        break;

                    case JavaOperandType.InlineLookupSwitch:
                        prgDisassembly[i].bstrOperands = "Switch?";
                        break;

                    case JavaOperandType.InlineTableSwitch:
                        prgDisassembly[i].bstrOperands = "TableSwitch?";
                        break;

                    case JavaOperandType.InlineVar:
                    case JavaOperandType.InlineVar_I1:
                        if (includeSymbolNames)
                        {
                            int localIndex   = _bytecode[instructionStart + 1];
                            int testLocation = instructionStart;
                            if (instruction.OpCode.StackBehaviorPop != JavaStackBehavior.Pop0)
                            {
                                // this is a store instruction - the variable might not be visible until the following instruction
                                testLocation += instruction.Size;
                            }

                            ILocation currentLocation = _executionContext.Location.GetMethod().GetLocationOfCodeIndex(testLocation);
                            var       local           = localVariables.SingleOrDefault(variable => variable.GetSlot() == localIndex && variable.GetIsVisible(currentLocation));
                            if (local != null)
                            {
                                prgDisassembly[i].bstrOperands = local.GetName();
                            }
                        }

                        if (string.IsNullOrEmpty(prgDisassembly[i].bstrOperands))
                        {
                            prgDisassembly[i].bstrOperands = "#" + instruction.Operands.VariableSlot.ToString();
                        }

                        break;

                    case JavaOperandType.InlineShortConst:
                    case JavaOperandType.InlineConst:
                    case JavaOperandType.InlineField:
                    case JavaOperandType.InlineMethod:
                    case JavaOperandType.InlineMethod_U1_0:
                    case JavaOperandType.InlineType:
                    case JavaOperandType.InlineType_U1:
                        if (includeSymbolNames)
                        {
                            int index = instruction.Operands.ConstantPoolIndex;
                            var entry = constantPool[index - 1];
                            prgDisassembly[i].bstrOperands = entry.ToString(constantPool);
                        }

                        if (string.IsNullOrEmpty(prgDisassembly[i].bstrOperands))
                        {
                            prgDisassembly[i].bstrOperands = "#" + instruction.Operands.ConstantPoolIndex.ToString();
                        }

                        break;

                    case JavaOperandType.InlineArrayType:
                        prgDisassembly[i].bstrOperands = "T_" + instruction.Operands.ArrayType.ToString().ToUpperInvariant();
                        break;

                    case JavaOperandType.InlineNone:
                        if (includeSymbolNames)
                        {
                            int?localIndex = null;

                            switch (instruction.OpCode.OpCode)
                            {
                            case JavaOpCodeTag.Aload_0:
                            case JavaOpCodeTag.Astore_0:
                            case JavaOpCodeTag.Dload_0:
                            case JavaOpCodeTag.Dstore_0:
                            case JavaOpCodeTag.Fload_0:
                            case JavaOpCodeTag.Fstore_0:
                            case JavaOpCodeTag.Iload_0:
                            case JavaOpCodeTag.Istore_0:
                            case JavaOpCodeTag.Lload_0:
                            case JavaOpCodeTag.Lstore_0:
                                localIndex = 0;
                                break;

                            case JavaOpCodeTag.Aload_1:
                            case JavaOpCodeTag.Astore_1:
                            case JavaOpCodeTag.Dload_1:
                            case JavaOpCodeTag.Dstore_1:
                            case JavaOpCodeTag.Fload_1:
                            case JavaOpCodeTag.Fstore_1:
                            case JavaOpCodeTag.Iload_1:
                            case JavaOpCodeTag.Istore_1:
                            case JavaOpCodeTag.Lload_1:
                            case JavaOpCodeTag.Lstore_1:
                                localIndex = 1;
                                break;

                            case JavaOpCodeTag.Aload_2:
                            case JavaOpCodeTag.Astore_2:
                            case JavaOpCodeTag.Dload_2:
                            case JavaOpCodeTag.Dstore_2:
                            case JavaOpCodeTag.Fload_2:
                            case JavaOpCodeTag.Fstore_2:
                            case JavaOpCodeTag.Iload_2:
                            case JavaOpCodeTag.Istore_2:
                            case JavaOpCodeTag.Lload_2:
                            case JavaOpCodeTag.Lstore_2:
                                localIndex = 2;
                                break;

                            case JavaOpCodeTag.Aload_3:
                            case JavaOpCodeTag.Astore_3:
                            case JavaOpCodeTag.Dload_3:
                            case JavaOpCodeTag.Dstore_3:
                            case JavaOpCodeTag.Fload_3:
                            case JavaOpCodeTag.Fstore_3:
                            case JavaOpCodeTag.Iload_3:
                            case JavaOpCodeTag.Istore_3:
                            case JavaOpCodeTag.Lload_3:
                            case JavaOpCodeTag.Lstore_3:
                                localIndex = 3;
                                break;
                            }

                            if (localIndex.HasValue)
                            {
                                int testLocation = instructionStart;
                                if (instruction.OpCode.StackBehaviorPop != JavaStackBehavior.Pop0)
                                {
                                    // this is a store instruction - the variable might not be visible until the following instruction
                                    testLocation += instruction.Size;
                                }

                                ILocation currentLocation = _executionContext.Location.GetMethod().GetLocationOfCodeIndex(testLocation);
                                var       local           = localVariables.SingleOrDefault(variable => variable.GetSlot() == localIndex && variable.GetIsVisible(currentLocation));
                                if (local != null)
                                {
                                    prgDisassembly[i].bstrOperands = local.GetName();
                                }
                            }
                        }

                        break;

                    default:
                        prgDisassembly[i].bstrOperands = string.Empty;
                        break;
                    }

                    // operand 1
                    switch (instruction.OpCode.OperandType)
                    {
                    case JavaOperandType.InlineVar_I1:
                        prgDisassembly[i].bstrOperands += " " + instruction.Operands.Increment.ToString();
                        break;

                    case JavaOperandType.InlineMethod_U1_0:
                        prgDisassembly[i].bstrOperands += " " + instruction.Operands.Operand2.ToString();
                        break;

                    case JavaOperandType.InlineType_U1:
                        prgDisassembly[i].bstrOperands += " " + instruction.Operands.Dimensions.ToString();
                        break;

                    default:
                        break;
                    }

                    // operand 2
                    if (instruction.OpCode.OperandType == JavaOperandType.InlineMethod_U1_0)
                    {
                        prgDisassembly[i].bstrOperands += " 0";
                    }
                }

                if (dwFields.GetPosition())
                {
                    try
                    {
                        ILocation location = _executionContext.Location.GetMethod().GetLocationOfCodeIndex(instructionStart);
                        prgDisassembly[i].posBeg.dwLine   = (uint)location.GetLineNumber();
                        prgDisassembly[i].posBeg.dwColumn = 0;
                        prgDisassembly[i].posEnd          = prgDisassembly[i].posBeg;
                        prgDisassembly[i].dwFields       |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION;
                    }
                    catch (Exception e)
                    {
                        if (ErrorHandler.IsCriticalException(e))
                        {
                            throw;
                        }

                        prgDisassembly[i].posBeg    = default(TEXT_POSITION);
                        prgDisassembly[i].posEnd    = default(TEXT_POSITION);
                        prgDisassembly[i].dwFields &= ~enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION;
                    }
                }

                if (dwFields.GetFlags())
                {
                    // TODO: determine when the following condition is met?
                    //   "Indicates that this instruction is one of the next instructions to be executed (there may be more than one)."
                    bool active = false;
                    if (active)
                    {
                        prgDisassembly[i].dwFlags |= enum_DISASSEMBLY_FLAGS.DF_INSTRUCTION_ACTIVE;
                    }

                    // Check for location information to determine when this condition is met:
                    //   "Indicates that this instruction has source. Some instructions, such as profiling or garbage collection code, have no corresponding source."
                    bool hasSource = prgDisassembly[i].dwFields.GetPosition();
                    if (hasSource)
                    {
                        prgDisassembly[i].dwFlags |= enum_DISASSEMBLY_FLAGS.DF_HASSOURCE;
                    }

                    // The current single-method disassembly only includes source from a single file, so this is for all but the first line:
                    //   "Indicates that this instruction is in a different document than the previous one."
                    bool documentChange = i == 0 && _currentInstructionIndex == 0;
                    if (documentChange)
                    {
                        prgDisassembly[i].dwFlags |= enum_DISASSEMBLY_FLAGS.DF_DOCUMENTCHANGE;
                    }

                    // Javac removes code that is statically determined to be unreachable (even in debug mode), so this is false:
                    //   "Indicates that this instruction will not be executed."
                    bool disabled = false;
                    if (disabled)
                    {
                        prgDisassembly[i].dwFlags |= enum_DISASSEMBLY_FLAGS.DF_DISABLED;
                    }

                    // This is always false in bytecode:
                    //   "Indicates that this instruction is really data (not code)."
                    bool data = false;
                    if (data)
                    {
                        prgDisassembly[i].dwFlags |= enum_DISASSEMBLY_FLAGS.DF_DATA;
                    }

                    // The Java debugging information format does not include document checksum information
                    bool documentChecksum = false;
                    if (documentChecksum)
                    {
                        prgDisassembly[i].dwFlags |= enum_DISASSEMBLY_FLAGS.DF_DOCUMENT_CHECKSUM;
                    }

                    prgDisassembly[i].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS;
                }

                if (dwFields.GetByteOffset() && prgDisassembly[i].dwFields.GetPosition())
                {
                    //   "The number of bytes the instruction is from the beginning of the code line."
                    int byteOffset = 0;
                    for (int j = _currentInstructionIndex + i - 1; j >= 0; j--)
                    {
                        JavaInstruction priorInstruction = _disassembledMethod.Instructions[j];
                        try
                        {
                            ILocation location = _executionContext.Location.GetMethod().GetLocationOfCodeIndex(priorInstruction.Offset);
                            if (location.GetLineNumber() != prgDisassembly[i].posBeg.dwLine)
                            {
                                break;
                            }

                            byteOffset = instruction.Offset - priorInstruction.Offset;
                        }
                        catch (Exception e)
                        {
                            if (ErrorHandler.IsCriticalException(e))
                            {
                                throw;
                            }

                            break;
                        }
                    }

                    prgDisassembly[i].dwByteOffset = (uint)Math.Max(0, byteOffset);
                    prgDisassembly[i].dwFields    |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET;
                }

                if (dwFields.GetSymbol())
                {
                    switch (instruction.OpCode.OperandType)
                    {
                    case JavaOperandType.InlineLookupSwitch:
                        prgDisassembly[i].bstrSymbol = "// switch";
                        break;

                    case JavaOperandType.InlineTableSwitch:
                        prgDisassembly[i].bstrSymbol = "// table switch";
                        break;

                    default:
                        break;
                    }

                    if (prgDisassembly[i].bstrSymbol != null)
                    {
                        prgDisassembly[i].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL;
                    }
                }
            }

            _currentInstructionIndex += (int)actualInstructions;
            pdwInstructionsRead       = actualInstructions;
            return(actualInstructions == dwInstructions ? VSConstants.S_OK : VSConstants.S_FALSE);
        }