private DisassemblyData FetchBadInstruction(enum_DISASSEMBLY_STREAM_FIELDS dwFields) { DisassemblyData dis = new DisassemblyData(); if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS) != 0) { dis.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS; dis.bstrAddress = EngineUtils.AsAddr(_addr, _engine.DebuggedProcess.Is64BitArch); } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID) != 0) { dis.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID; dis.uCodeLocationId = _addr; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL) != 0) { dis.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL; dis.bstrSymbol = string.Empty; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE) != 0) { dis.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE; dis.bstrOpcode = "??"; } return(dis); }
public int Read(uint dwInstructions, enum_DISASSEMBLY_STREAM_FIELDS dwFields, out uint pdwInstructionsRead, DisassemblyData[] prgDisassembly) { uint iOp = 0; DebuggedProcess process = DebuggedProcess.g_Process; IEnumerable <DisasmInstruction> instructions = null; process.WorkerThread.RunOperation(async() => { instructions = await process.Disassembly.FetchInstructions(_addr, (int)dwInstructions); }); if (instructions != null) { foreach (DisasmInstruction instruction in instructions) { if (iOp >= dwInstructions) { break; } _addr = instruction.Addr; if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS) != 0) { prgDisassembly[iOp].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS; prgDisassembly[iOp].bstrAddress = instruction.AddressString; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID) != 0) { prgDisassembly[iOp].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID; prgDisassembly[iOp].uCodeLocationId = instruction.Addr; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL) != 0) { if (instruction.Offset == 0) { prgDisassembly[iOp].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL; prgDisassembly[iOp].bstrSymbol = instruction.Symbol ?? string.Empty; } } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE) != 0) { prgDisassembly[iOp].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE; prgDisassembly[iOp].bstrOpcode = instruction.Opcode; } iOp++; } ; } pdwInstructionsRead = iOp; return(pdwInstructionsRead != 0 ? Constants.S_OK : Constants.S_FALSE); }
public int Read(uint dwInstructions, enum_DISASSEMBLY_STREAM_FIELDS dwFields, out uint pdwInstructionsRead, DisassemblyData[] prgDisassembly) { uint iOp = 0; //IEnumerable<DisasmInstruction> instructions = null; //_engine.DebuggedProcess.WorkerThread.RunOperation(async () => //{ // instructions = await _engine.DebuggedProcess.Disassembly.FetchInstructions(_addr, (int)dwInstructions); //}); //if (instructions != null) //{ // foreach (DisasmInstruction instruction in instructions) // { // if (iOp >= dwInstructions) // { // break; // } // _addr = instruction.Addr; // if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS) != 0) // { // prgDisassembly[iOp].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS; // prgDisassembly[iOp].bstrAddress = instruction.AddressString; // } // if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID) != 0) // { // prgDisassembly[iOp].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID; // prgDisassembly[iOp].uCodeLocationId = instruction.Addr; // } // if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL) != 0) // { // if (instruction.Offset == 0) // { // prgDisassembly[iOp].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL; // prgDisassembly[iOp].bstrSymbol = instruction.Symbol ?? string.Empty; // } // } // if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE) != 0) // { // prgDisassembly[iOp].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE; // prgDisassembly[iOp].bstrOpcode = instruction.Opcode; // } // iOp++; // }; //} pdwInstructionsRead = iOp; return(pdwInstructionsRead != 0 ? VSConstants.S_OK : VSConstants.S_FALSE); }
public int Read(uint dwInstructions, enum_DISASSEMBLY_STREAM_FIELDS dwFields, out uint pdwInstructionsRead, DisassemblyData[] prgDisassembly) { uint iOp = 0; IEnumerable<DisasmInstruction> instructions = null; _engine.DebuggedProcess.WorkerThread.RunOperation(async () => { instructions = await _engine.DebuggedProcess.Disassembly.FetchInstructions(_addr, (int)dwInstructions); }); if (instructions != null) { foreach (DisasmInstruction instruction in instructions) { if (iOp >= dwInstructions) { break; } _addr = instruction.Addr; if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS) != 0) { prgDisassembly[iOp].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS; prgDisassembly[iOp].bstrAddress = instruction.AddressString; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID) != 0) { prgDisassembly[iOp].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID; prgDisassembly[iOp].uCodeLocationId = instruction.Addr; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL) != 0) { if (instruction.Offset == 0) { prgDisassembly[iOp].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL; prgDisassembly[iOp].bstrSymbol = instruction.Symbol ?? string.Empty; } } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE) != 0) { prgDisassembly[iOp].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE; prgDisassembly[iOp].bstrOpcode = instruction.Opcode; } iOp++; }; } pdwInstructionsRead = iOp; return pdwInstructionsRead != 0 ? Constants.S_OK : Constants.S_FALSE; }
public int Read(uint dwInstructions, enum_DISASSEMBLY_STREAM_FIELDS dwFields, out uint pdwInstructionsRead, DisassemblyData[] prgDisassembly) { pdwInstructionsRead = 0; if (_method == null) return HResults.E_DISASM_NOTAVAILABLE; var method = _method.Method; var insCount = method.Body.Instructions.Count; bool wantsDocumentUrl = (dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL) != 0; bool wantsPosition = (dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION) != 0; bool wantsByteOffset = (dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET) != 0; bool wantsFlags = (dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS) != 0; for (pdwInstructionsRead = 0; pdwInstructionsRead < dwInstructions; ++pdwInstructionsRead, ++_instructionPointer) { int ip = _instructionPointer; if (ip >= insCount) break; var insd = new DisassemblyData(); var ins = method.Body.Instructions[ip]; if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS) != 0) { insd.bstrAddress = _method.FormatAddress(ins); insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID) != 0) { insd.uCodeLocationId = (ulong)ins.Offset; insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE) != 0) { insd.bstrOpcode = _method.FormatOpCode(ins); insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS) != 0) { insd.bstrOperands = _method.FormatOperands(ins); insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS; } if (wantsDocumentUrl || wantsPosition || wantsByteOffset || wantsFlags) { var source = _method.FindSourceCode(ins.Offset); var hasSource = source != null && !source.IsSpecial; bool isSameDocAsPrevious, isSameDocPos; if (hasSource) { isSameDocAsPrevious = _prevSource != null && !_prevSource.IsSpecial && _prevSource.Document.Path == source.Document.Path; isSameDocPos = _prevSource != null && !_prevSource.IsSpecial && isSameDocAsPrevious && source.Position.CompareTo(_prevSource.Position) == 0; } else { isSameDocAsPrevious = (source == null && _prevSource == null) || (source != null && _prevSource != null && _prevSource.IsSpecial); isSameDocPos = isSameDocAsPrevious; } if (wantsDocumentUrl && (!isSameDocAsPrevious || _justSeeked)) { if (hasSource) { insd.bstrDocumentUrl = "file://" + source.Document.Path; insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL; } // how do I clear the document? } int byteOffset = 0; if ((wantsByteOffset || wantsPosition) && hasSource) { if (isSameDocPos) byteOffset = ins.Offset - _prevSourceInstructionOffset; else { byteOffset = 0; _prevSourceInstructionOffset = ins.Offset; } } if (wantsPosition && hasSource && !isSameDocPos) { var pos = source.Position; insd.posBeg.dwLine = (uint)(pos.Start.Line - 1); insd.posBeg.dwColumn = (uint)(pos.Start.Column - 1); insd.posEnd.dwLine = (uint)(pos.End.Line - 1); insd.posEnd.dwColumn = (uint)(pos.End.Column - 1); if (insd.posEnd.dwLine - insd.posBeg.dwLine > 3) // never show more than 3 lines. insd.posEnd.dwLine = insd.posBeg.dwLine + 3; // Is this just me? I have no idea why my VS throws an exception when using this. //insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION; } if (wantsByteOffset && hasSource) { insd.dwByteOffset = (uint)byteOffset; insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET; } if (wantsFlags) { if(!isSameDocAsPrevious) insd.dwFlags |= enum_DISASSEMBLY_FLAGS.DF_DOCUMENTCHANGE; if(hasSource) insd.dwFlags |= enum_DISASSEMBLY_FLAGS.DF_HASSOURCE; //if (_loc.Location.Index == (ulong)ins.Offset) // insd.dwFlags |= enum_DISASSEMBLY_FLAGS.DF_INSTRUCTION_ACTIVE; insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS_SYMBOLS) != 0) { if (!hasSource && !isSameDocPos) { insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS_SYMBOLS; insd.bstrSymbol = "(generated instructions)"; } else if (hasSource && !isSameDocPos) { // workaround to show something at least if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS_SYMBOLS) != 0) { insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS_SYMBOLS; insd.bstrSymbol = "File Position: " + source.Position.Start + " - " + source.Position.End; } } } _justSeeked = false; _prevSource = source; } prgDisassembly[pdwInstructionsRead] = insd; } return pdwInstructionsRead == 0 || _instructionPointer >= insCount ? VSConstants.S_FALSE : VSConstants.S_OK; }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int Read(uint dwInstructions, enum_DISASSEMBLY_STREAM_FIELDS dwFields, out uint pdwInstructionsRead, DisassemblyData [] prgDisassembly) { // // Reads instructions starting from the current position in the disassembly stream. // LoggingUtils.PrintFunction(); try { ulong startAddress = m_codeContext.Address.MemoryAddress; ulong endAddress = startAddress + ((ulong)(dwInstructions) * 4); // TODO: 4 for a 32-bit instruction set? string disassemblyCommand = string.Format("-data-disassemble -s 0x{0:X8} -e 0x{1:X8} -- 1", startAddress, endAddress); MiResultRecord resultRecord = m_debugger.GdbClient.SendSyncCommand(disassemblyCommand); MiResultRecord.RequireOk(resultRecord, disassemblyCommand); if (!resultRecord.HasField("asm_insns")) { throw new InvalidOperationException("-data-disassemble result missing 'asm_insns' field"); } MiResultValueList assemblyRecords = (MiResultValueList)resultRecord ["asm_insns"] [0]; long maxInstructions = Math.Min(assemblyRecords.Values.Count, dwInstructions); if (maxInstructions == 0) { throw new InvalidOperationException(); } int currentInstruction = 0; for (int i = 0; i < assemblyRecords.Values.Count; ++i) { MiResultValue recordValue = assemblyRecords [i]; if (recordValue.Variable.Equals("src_and_asm_line")) { // // Parse mixed-mode disassembly reports. // uint line = recordValue ["line"] [0].GetUnsignedInt(); string file = recordValue ["file"] [0].GetString(); MiResultValueList lineAsmInstructionValues = (MiResultValueList)recordValue ["line_asm_insn"] [0]; foreach (MiResultValue instructionValue in lineAsmInstructionValues.Values) { string address = instructionValue ["address"] [0].GetString(); if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS) != 0) { prgDisassembly [currentInstruction].bstrAddress = address; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESSOFFSET) != 0) { string offset = instructionValue ["offset"] [0].GetString(); prgDisassembly [currentInstruction].bstrAddressOffset = offset; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESSOFFSET; } if (((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE) != 0) || ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS) != 0) || ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS_SYMBOLS) != 0)) { string inst = instructionValue ["inst"] [0].GetString(); string [] operations = inst.Split(new string [] { "\\t" }, StringSplitOptions.None); if (operations.Length > 0) { prgDisassembly [currentInstruction].bstrOpcode = operations [0]; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE; } if (operations.Length > 1) { prgDisassembly [currentInstruction].bstrOperands = operations [1]; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS; } if (operations.Length > 2) { prgDisassembly [currentInstruction].bstrOperands += " " + operations [2]; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS_SYMBOLS; } } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL) != 0) { string functionName = instructionValue ["func-name"] [0].GetString(); prgDisassembly [currentInstruction].bstrSymbol = functionName; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID) != 0) { DebuggeeAddress instructionAddress = new DebuggeeAddress(address); prgDisassembly [currentInstruction].uCodeLocationId = instructionAddress.MemoryAddress; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION) != 0) { prgDisassembly [currentInstruction].posBeg.dwLine = line; prgDisassembly [currentInstruction].posBeg.dwColumn = 0; prgDisassembly [currentInstruction].posEnd.dwLine = line; prgDisassembly [currentInstruction].posEnd.dwColumn = uint.MaxValue; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL) != 0) { prgDisassembly [currentInstruction].bstrDocumentUrl = "file://" + file; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET) != 0) { uint offset = instructionValue ["offset"] [0].GetUnsignedInt(); prgDisassembly [currentInstruction].dwByteOffset = offset; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS) != 0) { prgDisassembly [currentInstruction].dwFlags |= enum_DISASSEMBLY_FLAGS.DF_HASSOURCE; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS; } if (++currentInstruction >= maxInstructions) { break; } } } } pdwInstructionsRead = (uint)currentInstruction; return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); pdwInstructionsRead = 0; return(Constants.E_FAIL); } }
/// <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()) { string depth = _evaluationStackDepths != null ? string.Format("[{0}]", _evaluationStackDepths[_currentInstructionIndex + i]) : string.Empty; prgDisassembly[i].bstrOpcode = string.Format("{0}{1}", depth, 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; }
public int Read(uint numInstructions, enum_DISASSEMBLY_STREAM_FIELDS fields, out uint numInstructionsRead, DisassemblyData[] disassembly) { numInstructionsRead = 0; SbAddress sbAddress = _target.ResolveLoadAddress(_address); if (sbAddress == null) { return(VSConstants.S_FALSE); } bool withSource = ((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION) != 0) || ((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL) != 0) || ((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET) != 0); List <Instruction> instructions = GetInstructions(sbAddress, numInstructions, withSource); for (int i = 0; i < instructions.Count; i++) { Instruction instruction = instructions[i]; _address = instruction.Address; if ((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS) != 0) { disassembly[i].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS; disassembly[i].bstrAddress = $"0x{instruction.Address:x16}"; } if ((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID) != 0) { disassembly[i].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID; disassembly[i].uCodeLocationId = instruction.Address; } if ((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE) != 0) { disassembly[i].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE; disassembly[i].bstrOpcode = instruction.Text; } if ((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL) != 0) { if (instruction.Symbol != null) { disassembly[i].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL; disassembly[i].bstrSymbol = instruction.Symbol; } } if ((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL) != 0) { disassembly[i].bstrDocumentUrl = instruction.Document; disassembly[i].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL; } if ((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION) != 0) { if (instruction.HasSource) { disassembly[i].posBeg.dwColumn = 0; disassembly[i].posBeg.dwLine = instruction.StartLine; disassembly[i].posEnd.dwColumn = 0; disassembly[i].posEnd.dwLine = instruction.EndLine; disassembly[i].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION; } } if ((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS) != 0) { disassembly[i].dwFlags = instruction.HasSource ? enum_DISASSEMBLY_FLAGS.DF_HASSOURCE : 0; if (instruction.DocumentChanged) { disassembly[i].dwFlags |= enum_DISASSEMBLY_FLAGS.DF_DOCUMENTCHANGE; } disassembly[i].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS; } if ((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET) != 0) { if (instruction.HasSource) { disassembly[i].dwByteOffset = instruction.ByteOffset; disassembly[i].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET; } } } numInstructionsRead = Convert.ToUInt32(instructions.Count); return(numInstructionsRead > 0 ? VSConstants.S_OK : VSConstants.S_FALSE); }
/// <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); }
/// <summary> /// Initialize/use the uCodeLocationId field. /// </summary> public static bool GetCodeLocationId(this enum_DISASSEMBLY_STREAM_FIELDS fields) { return((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID) != 0); }
public int Read(uint dwInstructions, enum_DISASSEMBLY_STREAM_FIELDS dwFields, out uint pdwInstructionsRead, DisassemblyData[] prgDisassembly) { uint iOp = 0; IEnumerable <DisasmInstruction> instructions = null; _engine.DebuggedProcess.WorkerThread.RunOperation(async() => { instructions = await _engine.DebuggedProcess.Disassembly.FetchInstructions(_addr, (int)dwInstructions); }); if (instructions == null || (instructions.First().Addr - _addr > dwInstructions)) { // bad address range, return '??' for (iOp = 0; iOp < dwInstructions; _addr++, ++iOp) { prgDisassembly[iOp] = FetchBadInstruction(dwFields); } pdwInstructionsRead = iOp; return(Constants.S_OK); } // return '??' for bad addresses at start of range for (iOp = 0; _addr < instructions.First().Addr; _addr++, iOp++) { prgDisassembly[iOp] = FetchBadInstruction(dwFields); } foreach (DisasmInstruction instruction in instructions) { if (iOp >= dwInstructions) { break; } _addr = instruction.Addr; if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS) != 0) { prgDisassembly[iOp].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS; prgDisassembly[iOp].bstrAddress = instruction.AddressString; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID) != 0) { prgDisassembly[iOp].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID; prgDisassembly[iOp].uCodeLocationId = instruction.Addr; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL) != 0) { if (instruction.Offset == 0) { prgDisassembly[iOp].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL; prgDisassembly[iOp].bstrSymbol = instruction.Symbol ?? string.Empty; } } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE) != 0) { prgDisassembly[iOp].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE; prgDisassembly[iOp].bstrOpcode = instruction.Opcode; } iOp++; } ; if (iOp < dwInstructions) { // Didn't get enough instructions. Must have run out of valid memory address range. Tuple <ulong, ulong> range = new Tuple <ulong, ulong>(0, 0); _engine.DebuggedProcess.WorkerThread.RunOperation(async() => { range = await _engine.DebuggedProcess.FindValidMemoryRange(_addr, 10, 0); }); // return '??' for bad addresses at end of range for (_addr = range.Item2; iOp < dwInstructions; _addr++, iOp++) { prgDisassembly[iOp] = FetchBadInstruction(dwFields); } } pdwInstructionsRead = iOp; return(pdwInstructionsRead != 0 ? Constants.S_OK : Constants.S_FALSE); }
/// <summary> /// Include symbol names in the bstrOperands field. /// </summary> public static bool GetOperandsSymbols(this enum_DISASSEMBLY_STREAM_FIELDS fields) { return((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS_SYMBOLS) != 0); }
/// <summary> /// Initialize/use the bstrAddress field. /// </summary> public static bool GetAddress(this enum_DISASSEMBLY_STREAM_FIELDS fields) { return((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS) != 0); }
/// <summary> /// Initialize/use the dwFlags field. /// </summary> public static bool GetFlags(this enum_DISASSEMBLY_STREAM_FIELDS fields) { return((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS) != 0); }
/// <summary> /// Initialize/use the dwByteOffset field. /// </summary> public static bool GetByteOffset(this enum_DISASSEMBLY_STREAM_FIELDS fields) { return((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET) != 0); }
/// <summary> /// Initialize/use the bstrDocumentUrl field. /// </summary> public static bool GetDocumentUrl(this enum_DISASSEMBLY_STREAM_FIELDS fields) { return((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL) != 0); }
/// <summary> /// Initialize/use the posBeg and posEnd fields. /// </summary> public static bool GetPosition(this enum_DISASSEMBLY_STREAM_FIELDS fields) { return((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION) != 0); }
/// <summary> /// Initialize/use the bstrOpCode field. /// </summary> public static bool GetOpCode(this enum_DISASSEMBLY_STREAM_FIELDS fields) { return((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE) != 0); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int Read (uint dwInstructions, enum_DISASSEMBLY_STREAM_FIELDS dwFields, out uint pdwInstructionsRead, DisassemblyData [] prgDisassembly) { // // Reads instructions starting from the current position in the disassembly stream. // LoggingUtils.PrintFunction (); try { ulong startAddress = m_codeContext.Address.MemoryAddress; ulong endAddress = startAddress + ((ulong)(dwInstructions) * 4); // TODO: 4 for a 32-bit instruction set? string disassemblyCommand = string.Format ("-data-disassemble -s 0x{0:X8} -e 0x{1:X8} -- 1", startAddress, endAddress); MiResultRecord resultRecord = m_debugger.GdbClient.SendSyncCommand (disassemblyCommand); MiResultRecord.RequireOk (resultRecord, disassemblyCommand); if (!resultRecord.HasField ("asm_insns")) { throw new InvalidOperationException ("-data-disassemble result missing 'asm_insns' field"); } MiResultValueList assemblyRecords = (MiResultValueList) resultRecord ["asm_insns"] [0]; long maxInstructions = Math.Min (assemblyRecords.Values.Count, dwInstructions); if (maxInstructions == 0) { throw new InvalidOperationException (); } int currentInstruction = 0; for (int i = 0; i < assemblyRecords.Values.Count; ++i) { MiResultValue recordValue = assemblyRecords [i]; if (recordValue.Variable.Equals ("src_and_asm_line")) { // // Parse mixed-mode disassembly reports. // uint line = recordValue ["line"] [0].GetUnsignedInt (); string file = recordValue ["file"] [0].GetString (); MiResultValueList lineAsmInstructionValues = (MiResultValueList) recordValue ["line_asm_insn"] [0]; foreach (MiResultValue instructionValue in lineAsmInstructionValues.Values) { string address = instructionValue ["address"] [0].GetString (); if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS) != 0) { prgDisassembly [currentInstruction].bstrAddress = address; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESSOFFSET) != 0) { string offset = instructionValue ["offset"] [0].GetString (); prgDisassembly [currentInstruction].bstrAddressOffset = offset; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESSOFFSET; } if (((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE) != 0) || ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS) != 0) || ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS_SYMBOLS) != 0)) { string inst = instructionValue ["inst"] [0].GetString (); string [] operations = inst.Split (new string [] { "\\t" }, StringSplitOptions.None); if (operations.Length > 0) { prgDisassembly [currentInstruction].bstrOpcode = operations [0]; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE; } if (operations.Length > 1) { prgDisassembly [currentInstruction].bstrOperands = operations [1]; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS; } if (operations.Length > 2) { prgDisassembly [currentInstruction].bstrOperands += " " + operations [2]; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS_SYMBOLS; } } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL) != 0) { string functionName = instructionValue ["func-name"] [0].GetString (); prgDisassembly [currentInstruction].bstrSymbol = functionName; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID) != 0) { DebuggeeAddress instructionAddress = new DebuggeeAddress (address); prgDisassembly [currentInstruction].uCodeLocationId = instructionAddress.MemoryAddress; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION) != 0) { prgDisassembly [currentInstruction].posBeg.dwLine = line; prgDisassembly [currentInstruction].posBeg.dwColumn = 0; prgDisassembly [currentInstruction].posEnd.dwLine = line; prgDisassembly [currentInstruction].posEnd.dwColumn = uint.MaxValue; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL) != 0) { prgDisassembly [currentInstruction].bstrDocumentUrl = "file://" + file; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET) != 0) { uint offset = instructionValue ["offset"] [0].GetUnsignedInt (); prgDisassembly [currentInstruction].dwByteOffset = offset; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS) != 0) { prgDisassembly [currentInstruction].dwFlags |= enum_DISASSEMBLY_FLAGS.DF_HASSOURCE; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS; } if (++currentInstruction >= maxInstructions) { break; } } } } pdwInstructionsRead = (uint) currentInstruction; return Constants.S_OK; } catch (Exception e) { LoggingUtils.HandleException (e); pdwInstructionsRead = 0; return Constants.E_FAIL; } }
/// <summary> /// Initialize/use the bstrSymbol field. /// </summary> public static bool GetSymbol(this enum_DISASSEMBLY_STREAM_FIELDS fields) { return((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL) != 0); }
public int Read(uint dwInstructions, enum_DISASSEMBLY_STREAM_FIELDS dwFields, out uint pdwInstructionsRead, DisassemblyData[] prgDisassembly) { pdwInstructionsRead = 0; if (_method == null) { return(HResults.E_DISASM_NOTAVAILABLE); } var method = _method.Method; var insCount = method.Body.Instructions.Count; bool wantsDocumentUrl = (dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL) != 0; bool wantsPosition = (dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION) != 0; bool wantsByteOffset = (dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET) != 0; bool wantsFlags = (dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS) != 0; for (pdwInstructionsRead = 0; pdwInstructionsRead < dwInstructions; ++pdwInstructionsRead, ++_instructionPointer) { int ip = _instructionPointer; if (ip >= insCount) { break; } var insd = new DisassemblyData(); var ins = method.Body.Instructions[ip]; if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS) != 0) { insd.bstrAddress = _method.FormatAddress(ins); insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID) != 0) { insd.uCodeLocationId = (ulong)ins.Offset; insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE) != 0) { insd.bstrOpcode = _method.FormatOpCode(ins); insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS) != 0) { insd.bstrOperands = _method.FormatOperands(ins); insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS; } if (wantsDocumentUrl || wantsPosition || wantsByteOffset || wantsFlags) { var source = _method.FindSourceCode(ins.Offset); var hasSource = source != null && !source.IsSpecial; bool isSameDocAsPrevious, isSameDocPos; if (hasSource) { isSameDocAsPrevious = _prevSource != null && !_prevSource.IsSpecial && _prevSource.Document.Path == source.Document.Path; isSameDocPos = _prevSource != null && !_prevSource.IsSpecial && isSameDocAsPrevious && source.Position.CompareTo(_prevSource.Position) == 0; } else { isSameDocAsPrevious = (source == null && _prevSource == null) || (source != null && _prevSource != null && _prevSource.IsSpecial); isSameDocPos = isSameDocAsPrevious; } if (wantsDocumentUrl && (!isSameDocAsPrevious || _justSeeked)) { if (hasSource) { insd.bstrDocumentUrl = "file://" + source.Document.Path; insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL; } // how do I clear the document? } int byteOffset = 0; if ((wantsByteOffset || wantsPosition) && hasSource) { if (isSameDocPos) { byteOffset = ins.Offset - _prevSourceInstructionOffset; } else { byteOffset = 0; _prevSourceInstructionOffset = ins.Offset; } } if (wantsPosition && hasSource && !isSameDocPos) { var pos = source.Position; insd.posBeg.dwLine = (uint)(pos.Start.Line - 1); insd.posBeg.dwColumn = (uint)(pos.Start.Column - 1); insd.posEnd.dwLine = (uint)(pos.End.Line - 1); insd.posEnd.dwColumn = (uint)(pos.End.Column - 1); if (insd.posEnd.dwLine - insd.posBeg.dwLine > 3) // never show more than 3 lines. { insd.posEnd.dwLine = insd.posBeg.dwLine + 3; } // Is this just me? I have no idea why my VS throws an exception when using this. //insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION; } if (wantsByteOffset && hasSource) { insd.dwByteOffset = (uint)byteOffset; insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET; } if (wantsFlags) { if (!isSameDocAsPrevious) { insd.dwFlags |= enum_DISASSEMBLY_FLAGS.DF_DOCUMENTCHANGE; } if (hasSource) { insd.dwFlags |= enum_DISASSEMBLY_FLAGS.DF_HASSOURCE; } //if (_loc.Location.Index == (ulong)ins.Offset) // insd.dwFlags |= enum_DISASSEMBLY_FLAGS.DF_INSTRUCTION_ACTIVE; insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS_SYMBOLS) != 0) { if (!hasSource && !isSameDocPos) { insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS_SYMBOLS; insd.bstrSymbol = "(generated instructions)"; } else if (hasSource && !isSameDocPos) { // workaround to show something at least if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS_SYMBOLS) != 0) { insd.dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS_SYMBOLS; insd.bstrSymbol = "File Position: " + source.Position.Start + " - " + source.Position.End; } } } _justSeeked = false; _prevSource = source; } prgDisassembly[pdwInstructionsRead] = insd; } return(pdwInstructionsRead == 0 || _instructionPointer >= insCount ? VSConstants.S_FALSE : VSConstants.S_OK); }
/// <summary> /// Initialize/use the bstrCodeBytes field. /// </summary> public static bool GetCodeBytes(this enum_DISASSEMBLY_STREAM_FIELDS fields) { return((fields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODEBYTES) != 0); }