public void ReadOneInstructionWithSource() { uint numberInstructionsToCreate = 1; uint numberInstructionsToRead = 10; var mockInstructions = MockRead(numberInstructionsToCreate, numberInstructionsToRead); var lineEntry = CreateLineEntry(_testFilename, _testDirectory, 10u, 0u); mockInstructions[0].LineEntry = lineEntry; var disassembly = new DisassemblyData[numberInstructionsToRead]; Assert.AreEqual(VSConstants.S_OK, _disassemblyStream.Read((uint)disassembly.Length, enum_DISASSEMBLY_STREAM_FIELDS.DSF_ALL, out uint numberInstructionsRead, disassembly)); Assert.AreEqual(1, numberInstructionsRead); Assert.AreEqual(enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS | enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID | enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE | enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL | enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION | enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET | enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS, disassembly[0].dwFields); Assert.AreEqual(FormatUrl(_testDirectory, _testFilename), disassembly[0].bstrDocumentUrl); Assert.AreEqual(9u, disassembly[0].posEnd.dwLine); Assert.AreEqual(0u, disassembly[0].posBeg.dwLine); Assert.AreEqual(enum_DISASSEMBLY_FLAGS.DF_HASSOURCE | enum_DISASSEMBLY_FLAGS.DF_DOCUMENTCHANGE, disassembly[0].dwFlags); }
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 void ReadTwoInstructionsWithSourceSameLine() { uint numberInstructionsToCreate = 2; uint numberInstructionsToRead = 10; uint firstLine = 6u; var mockInstructions = MockRead(numberInstructionsToCreate, numberInstructionsToRead); var lineEntry = CreateLineEntry(_testFilename, _testDirectory, firstLine + 1u, 0u); mockInstructions[0].LineEntry = lineEntry; mockInstructions[1].LineEntry = lineEntry; var disassembly = new DisassemblyData[numberInstructionsToRead]; Assert.AreEqual(VSConstants.S_OK, _disassemblyStream.Read((uint)disassembly.Length, enum_DISASSEMBLY_STREAM_FIELDS.DSF_ALL, out uint numInstructionsRead, disassembly)); Assert.AreEqual(2, numInstructionsRead); Assert.AreEqual(enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS | enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID | enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE | enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL | enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION | enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET | enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS, disassembly[1].dwFields); // If the instruction are not on the same line, then the offset from the beginning // of the line must not be zero. VS does not seem to care about the precise value, // it only seems to care about the zero vs. non-zero distinction. Assert.AreNotEqual(0, disassembly[1].dwByteOffset); Assert.AreEqual(enum_DISASSEMBLY_FLAGS.DF_HASSOURCE, disassembly[1].dwFlags); }
public void ReadOneInstructionWithoutSource() { uint numberInstructionsToCreate = 1; uint numberInstructionsToRead = 10; MockRead(numberInstructionsToCreate, numberInstructionsToRead); var disassembly = new DisassemblyData[numberInstructionsToRead]; Assert.AreEqual(VSConstants.S_OK, _disassemblyStream.Read((uint)disassembly.Length, enum_DISASSEMBLY_STREAM_FIELDS.DSF_ALL, out uint numInstructionsRead, disassembly)); Assert.AreEqual(1, numInstructionsRead); Assert.AreEqual(enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS | enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID | enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE | enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL | enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS, disassembly[0].dwFields); Assert.AreEqual(_testAddress, disassembly[0].uCodeLocationId); Assert.AreEqual("0x0000123456789abc", disassembly[0].bstrAddress); Assert.AreEqual( $"{_testMnemonic + 0} {_testOperands + 0} # {_testComment}", disassembly[0].bstrOpcode); Assert.AreEqual((enum_DISASSEMBLY_FLAGS)0, disassembly[0].dwFlags); }
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 void ReadEmpty() { uint instructionsToRead = 10; MockRead(0, instructionsToRead); var disassembly = new DisassemblyData[instructionsToRead]; Assert.AreEqual(VSConstants.S_FALSE, _disassemblyStream.Read((uint)disassembly.Length, enum_DISASSEMBLY_STREAM_FIELDS.DSF_ALL, out uint numInstructionsRead, disassembly)); Assert.AreEqual(0, numInstructionsRead); }
public void ReadFull() { uint numberInstructions = 20; MockRead(numberInstructions, numberInstructions); var disassembly = new DisassemblyData[numberInstructions]; Assert.AreEqual(VSConstants.S_OK, _disassemblyStream.Read((uint)disassembly.Length, enum_DISASSEMBLY_STREAM_FIELDS.DSF_ALL, out uint numInstructionsRead, disassembly)); Assert.AreEqual(20, numInstructionsRead); }
public void ReadOneInstructionWithSourceSameFile() { uint numberInstructionsToCreate = 1; uint numberInstructionsToRead = 10; uint previousLine = 6u; uint endLine = 9u; var mockInstructions = MockRead(numberInstructionsToCreate, numberInstructionsToRead); var lineEntry = CreateLineEntry(_testFilename, _testDirectory, endLine + 1u, 0u); mockInstructions[0].LineEntry = lineEntry; var previousEntry = new LineEntryInfo { Line = previousLine + 1u, Directory = _testDirectory, FileName = _testFilename }; _mockTarget.ResolveLoadAddress(_testAddress - 1).GetLineEntry().Returns(previousEntry); var disassembly = new DisassemblyData[numberInstructionsToRead]; Assert.AreEqual(VSConstants.S_OK, _disassemblyStream.Read((uint)disassembly.Length, enum_DISASSEMBLY_STREAM_FIELDS.DSF_ALL, out uint numberInstructionsRead, disassembly)); Assert.AreEqual(1, numberInstructionsRead); Assert.AreEqual(enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS | enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID | enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE | enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL | enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION | enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET | enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS, disassembly[0].dwFields); Assert.AreEqual(FormatUrl(_testDirectory, _testFilename), disassembly[0].bstrDocumentUrl); Assert.AreEqual(previousLine + 1, disassembly[0].posBeg.dwLine); Assert.AreEqual(0, disassembly[0].dwByteOffset); Assert.AreEqual(enum_DISASSEMBLY_FLAGS.DF_HASSOURCE, disassembly[0].dwFlags); }
public void ReadTwoInstructionsWithSourceDifferentFile() { uint numberInstructionsToCreate = 2; uint numberInstructionsToRead = 10; string otherFilename = "other.cc"; uint line = 5u; var mockInstructions = MockRead(numberInstructionsToCreate, numberInstructionsToRead); var firstLineEntry = CreateLineEntry(_testFilename, _testDirectory, line + 1u, 0u); mockInstructions[0].LineEntry = firstLineEntry; var secondLineEntry = CreateLineEntry(otherFilename, _testDirectory, line + 1u, 0u); mockInstructions[1].LineEntry = secondLineEntry; var disassembly = new DisassemblyData[numberInstructionsToRead]; Assert.AreEqual(VSConstants.S_OK, _disassemblyStream.Read((uint)disassembly.Length, enum_DISASSEMBLY_STREAM_FIELDS.DSF_ALL, out uint numInstructionsRead, disassembly)); Assert.AreEqual(2, numInstructionsRead); Assert.AreEqual(enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS | enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID | enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE | enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL | enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION | enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET | enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS, disassembly[1].dwFields); Assert.AreEqual(FormatUrl(_testDirectory, otherFilename), disassembly[1].bstrDocumentUrl); Assert.AreEqual(0u, disassembly[1].posBeg.dwLine); Assert.AreEqual(line, disassembly[1].posEnd.dwLine); Assert.AreEqual(0, disassembly[1].dwByteOffset); Assert.AreEqual(enum_DISASSEMBLY_FLAGS.DF_HASSOURCE | enum_DISASSEMBLY_FLAGS.DF_DOCUMENTCHANGE, disassembly[1].dwFlags); }
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) { 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 static TextPositionTuple GetTextPositionOfFrame(PathConverter converter, IDebugStackFrame2 frame) { IDebugDocumentContext2 documentContext; var source = new Source(); if (frame.GetDocumentContext(out documentContext) == 0 && documentContext != null) { var beginPosition = new TEXT_POSITION[1]; var endPosition = new TEXT_POSITION[1]; documentContext.GetStatementRange(beginPosition, endPosition); string filePath; documentContext.GetName(enum_GETNAME_TYPE.GN_FILENAME, out filePath); string convertedFilePath = converter.ConvertDebuggerPathToClient(filePath); // save the filename as we need it in any case source.Name = Path.GetFileName(convertedFilePath); // we have debug info but do we actually have the source code? if (File.Exists(convertedFilePath)) { source.Path = convertedFilePath; int srcline = converter.ConvertDebuggerLineToClient((int)beginPosition[0].dwLine); int srccolumn = unchecked ((int)(beginPosition[0].dwColumn + 1)); return(new TextPositionTuple(source, srcline, srccolumn)); } } // this frame is lacking source code source.Name = Path.ChangeExtension(source.Name, ".s") ?? "???"; source.Path = null; source.Origin = "disassembly"; ulong startAddress; IDebugCodeContext2 codeContext; if (frame.GetCodeContext(out codeContext) != HRConstants.S_OK) { return(null); // we couldn't even find the current instruction, something's really wrong } var cinfos = new CONTEXT_INFO[1]; codeContext.GetInfo(enum_CONTEXT_INFO_FIELDS.CIF_ALLFIELDS, cinfos); DisassembledRange disRange; startAddress = (ulong)Convert.ToInt64(cinfos[0].bstrAddress, 16); int idx = DisasmRangesDict.FindUpperBound(startAddress); bool foundIt = false; int column = 0; int line = 0; if (idx > 0) { var kv = DisasmRangesDict.TryGet(idx - 1).Value; if (startAddress >= kv.Key && startAddress <= kv.Value.endAddress) { disRange = kv.Value; source.SourceReference = disRange.sourceReference; line = kv.Value.dasmData.FirstIndexWhere(d => (ulong)Convert.ToInt64(d.bstrAddress, 16) >= startAddress) ?? 0; ++line; column = 0; foundIt = true; } } if (!foundIt) { IDebugThread2 thread; frame.GetThread(out thread); IDebugProgram2 program; thread.GetProgram(out program); IDebugDisassemblyStream2 disasmStream; program.GetDisassemblyStream(enum_DISASSEMBLY_STREAM_SCOPE.DSS_FUNCTION, codeContext, out disasmStream); uint instructionsRead; var dasmData = new DisassemblyData[100]; if (disasmStream.Read(100, enum_DISASSEMBLY_STREAM_FIELDS.DSF_ALL, out instructionsRead, dasmData) == HRConstants.S_OK) { System.Array.Resize(ref dasmData, (int)instructionsRead); source.SourceReference = ++lastSourceReference; DisasmRangesDict.Add(startAddress, new DisassembledRange() { sourceReference = lastSourceReference, endAddress = (ulong)Convert.ToInt64(dasmData.Last().bstrAddress, 16), dasmData = dasmData }); line = 1; column = 0; } } return(new TextPositionTuple(source, line, column)); }
/// <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 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; } }