public int Seek(enum_SEEK_START dwSeekStart, IDebugCodeContext2 pCodeContext, ulong uCodeLocationId, long iInstructions) { if (dwSeekStart == enum_SEEK_START.SEEK_START_CODECONTEXT) { AD7MemoryAddress addr = pCodeContext as AD7MemoryAddress; _addr = addr.Address; } else if (dwSeekStart == enum_SEEK_START.SEEK_START_CODELOCID) { _addr = (uint)uCodeLocationId; } //if (iInstructions != 0) //{ // IEnumerable<DisasmInstruction> instructions = null; // _engine.DebuggedProcess.WorkerThread.RunOperation(async () => // { // instructions = await _engine.DebuggedProcess.Disassembly.FetchInstructions(_addr, (int)iInstructions); // }); // if (instructions == null) // { // return VSConstants.E_FAIL; // } // _addr = instructions.ElementAt(0).Addr; //} return(VSConstants.S_OK); }
public int Seek(enum_SEEK_START dwSeekStart, IDebugCodeContext2 pCodeContext, ulong uCodeLocationId, long iInstructions) { if (dwSeekStart == enum_SEEK_START.SEEK_START_CODECONTEXT) { AD7MemoryAddress addr = pCodeContext as AD7MemoryAddress; _addr = addr.Address; } else if (dwSeekStart == enum_SEEK_START.SEEK_START_CODELOCID) { _addr = (uint)uCodeLocationId; } if (iInstructions != 0) { DebuggedProcess process = DebuggedProcess.g_Process; IEnumerable <DisasmInstruction> instructions = null; process.WorkerThread.RunOperation(async() => { instructions = await process.Disassembly.FetchInstructions(_addr, (int)iInstructions); }); if (instructions == null) { return(Constants.E_FAIL); } _addr = instructions.ElementAt(0).Addr; } return(Constants.S_OK); }
/// <summary> /// Moves the read pointer in the disassembly stream a given number of instructions relative to a specified position. /// </summary> /// <param name="dwSeekStart"> /// [in] A value from the SEEK_START enumeration that specifies the relative position to begin the seek process. /// </param> /// <param name="pCodeContext"> /// [in] The IDebugCodeContext2 object representing the code context that the seek operation is relative to. This /// parameter is used only if dwSeekStart = SEEK_START_CODECONTEXT; otherwise, this parameter is ignored and can be /// a null value. /// </param> /// <param name="uCodeLocationId"> /// [in] The code location identifier that the seek operation is relative to. This parameter is used if /// dwSeekStart = SEEK_START_CODELOCID; otherwise, this parameter is ignored and can be set to 0. See the Remarks /// section for the IDebugDisassemblyStream2.GetCodeLocationId method for a description of a code location identifier. /// </param> /// <param name="iInstructions"> /// [in] The number of instructions to move relative to the position specified in dwSeekStart. This value can be /// negative to move backwards. /// </param> /// <returns> /// If successful, returns S_OK. Returns S_FALSE if the seek position was to a point beyond the list of available /// instructions. Otherwise, returns an error code. /// </returns> /// <remarks> /// If the seek was to a position before the beginning of the list, the read position is set to the first instruction /// in the list. If the see was to a position after the end of the list, the read position is set to the last /// instruction in the list. /// </remarks> public int Seek(enum_SEEK_START dwSeekStart, IDebugCodeContext2 pCodeContext, ulong uCodeLocationId, long iInstructions) { switch (dwSeekStart) { case enum_SEEK_START.SEEK_START_BEGIN: _currentInstructionIndex = 0; break; case enum_SEEK_START.SEEK_START_CODECONTEXT: int error = GetCodeLocationId(pCodeContext, out uCodeLocationId); if (!ErrorHandler.Succeeded(error)) { return(error); } goto case enum_SEEK_START.SEEK_START_CODELOCID; case enum_SEEK_START.SEEK_START_CODELOCID: _currentInstructionIndex = _disassembledMethod.Instructions.FindIndex(i => i.Offset == (int)uCodeLocationId); if (_currentInstructionIndex < 0) { throw new ArgumentException(); } break; case enum_SEEK_START.SEEK_START_CURRENT: break; case enum_SEEK_START.SEEK_START_END: _currentInstructionIndex = _disassembledMethod.Instructions.Count; break; default: throw new ArgumentException("Invalid seek start location."); } _currentInstructionIndex += (int)iInstructions; if (_currentInstructionIndex >= 0 && _currentInstructionIndex <= _disassembledMethod.Instructions.Count) { return(VSConstants.S_OK); } _currentInstructionIndex = Math.Max(0, _currentInstructionIndex); _currentInstructionIndex = Math.Min(_disassembledMethod.Instructions.Count, _currentInstructionIndex); return(VSConstants.S_FALSE); }
public int Seek(enum_SEEK_START dwSeekStart, IDebugCodeContext2 pCodeContext, ulong uCodeLocationId, long iInstructions) { _justSeeked = true; _prevSource = null; _prevSourceInstructionOffset = -1; if (_method == null) { return(HResults.E_DISASM_NOTAVAILABLE); } var method = _method.Method; var insCount = method.Body.Instructions.Count; int newPos; switch (dwSeekStart) { case enum_SEEK_START.SEEK_START_BEGIN: newPos = (int)iInstructions; break; case enum_SEEK_START.SEEK_START_END: newPos = insCount + (int)iInstructions; break; case enum_SEEK_START.SEEK_START_CURRENT: newPos = _instructionPointer + (int)iInstructions; break; default: return(VSConstants.E_NOTIMPL); } _instructionPointer = newPos < 0 ? 0 : newPos >= insCount ? insCount - 1 : newPos; if (newPos < 0 || newPos >= insCount) { return(VSConstants.S_FALSE); } return(VSConstants.S_OK); }
public int Seek(enum_SEEK_START dwSeekStart, IDebugCodeContext2 pCodeContext, ulong uCodeLocationId, long iInstructions) { if (dwSeekStart == enum_SEEK_START.SEEK_START_CODECONTEXT) { AD7MemoryAddress addr = pCodeContext as AD7MemoryAddress; _addr = addr.Address; } else if (dwSeekStart == enum_SEEK_START.SEEK_START_CODELOCID) { _addr = uCodeLocationId; } if (iInstructions >= 0) { return(SeekForward(iInstructions)); } else { return(SeekBack(-iInstructions)); } }
public int Seek(enum_SEEK_START dwSeekStart, IDebugCodeContext2 pCodeContext, ulong uCodeLocationId, long iInstructions) { if (dwSeekStart == enum_SEEK_START.SEEK_START_CODECONTEXT) { AD7MemoryAddress addr = pCodeContext as AD7MemoryAddress; _addr = addr.Address; } else if (dwSeekStart == enum_SEEK_START.SEEK_START_CODELOCID) { _addr = (uint)uCodeLocationId; } if (iInstructions != 0) { IEnumerable<DisasmInstruction> instructions = null; _engine.DebuggedProcess.WorkerThread.RunOperation(async () => { instructions = await _engine.DebuggedProcess.Disassembly.FetchInstructions(_addr, (int)iInstructions); }); if (instructions == null) { return Constants.E_FAIL; } _addr = instructions.ElementAt(0).Addr; } return Constants.S_OK; }
public int Seek(enum_SEEK_START dwSeekStart, IDebugCodeContext2 pCodeContext, ulong uCodeLocationId, long iInstructions) { _justSeeked = true; _prevSource = null; _prevSourceInstructionOffset = -1; if (_method == null) return HResults.E_DISASM_NOTAVAILABLE; var method = _method.Method; var insCount = method.Body.Instructions.Count; int newPos; switch (dwSeekStart) { case enum_SEEK_START.SEEK_START_BEGIN: newPos = (int)iInstructions; break; case enum_SEEK_START.SEEK_START_END: newPos = insCount + (int)iInstructions; break; case enum_SEEK_START.SEEK_START_CURRENT: newPos = _instructionPointer + (int)iInstructions; break; default: return VSConstants.E_NOTIMPL; } _instructionPointer = newPos < 0 ? 0 : newPos >= insCount ? insCount - 1 : newPos; if (newPos < 0 || newPos >= insCount) return VSConstants.S_FALSE; return VSConstants.S_OK; }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int Seek(enum_SEEK_START dwSeekStart, IDebugCodeContext2 pCodeContext, ulong uCodeLocationId, long iInstructions) { // // Moves the read pointer in the disassembly stream a given number of instructions relative to a specified position. // LoggingUtils.PrintFunction(); try { switch (dwSeekStart) { case enum_SEEK_START.SEEK_START_BEGIN: { // // Starts seeking at the beginning of the current document. // throw new NotImplementedException(); } case enum_SEEK_START.SEEK_START_END: { // // Starts seeking at the end of the current document. // throw new NotImplementedException(); } case enum_SEEK_START.SEEK_START_CURRENT: { // // Starts seeking at the current position of the current document. // ulong offsetAddress = m_codeContext.Address.MemoryAddress; if (iInstructions > 0) { offsetAddress += (ulong)(iInstructions * 4); } else if (iInstructions < 0) { offsetAddress += (ulong)(Math.Abs(iInstructions) * 4); } m_codeContext.Address = new DebuggeeAddress(offsetAddress); break; } case enum_SEEK_START.SEEK_START_CODECONTEXT: { // // Starts seeking at the given code context of the current document. // DebuggeeCodeContext codeContext = (pCodeContext as DebuggeeCodeContext); ulong offsetAddress = codeContext.Address.MemoryAddress; if (iInstructions > 0) { offsetAddress += (ulong)(iInstructions * 4); } else if (iInstructions < 0) { offsetAddress += (ulong)(Math.Abs(iInstructions) * 4); } m_codeContext.Address = new DebuggeeAddress(offsetAddress); break; } case enum_SEEK_START.SEEK_START_CODELOCID: { // // Starts seeking at the given code location identifier. // ulong offsetAddress = uCodeLocationId; if (iInstructions > 0) { offsetAddress += (ulong)(iInstructions * 4); } else if (iInstructions < 0) { offsetAddress += (ulong)(Math.Abs(iInstructions) * 4); } m_codeContext.Address = new DebuggeeAddress(offsetAddress); break; } } return(Constants.S_OK); } catch (NotImplementedException e) { LoggingUtils.HandleException(e); return(Constants.E_NOTIMPL); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
/// <summary> /// Moves the read pointer in the disassembly stream a given number of instructions relative to a specified position. /// </summary> /// <param name="dwSeekStart"> /// [in] A value from the SEEK_START enumeration that specifies the relative position to begin the seek process. /// </param> /// <param name="pCodeContext"> /// [in] The IDebugCodeContext2 object representing the code context that the seek operation is relative to. This /// parameter is used only if dwSeekStart = SEEK_START_CODECONTEXT; otherwise, this parameter is ignored and can be /// a null value. /// </param> /// <param name="uCodeLocationId"> /// [in] The code location identifier that the seek operation is relative to. This parameter is used if /// dwSeekStart = SEEK_START_CODELOCID; otherwise, this parameter is ignored and can be set to 0. See the Remarks /// section for the IDebugDisassemblyStream2.GetCodeLocationId method for a description of a code location identifier. /// </param> /// <param name="iInstructions"> /// [in] The number of instructions to move relative to the position specified in dwSeekStart. This value can be /// negative to move backwards. /// </param> /// <returns> /// If successful, returns S_OK. Returns S_FALSE if the seek position was to a point beyond the list of available /// instructions. Otherwise, returns an error code. /// </returns> /// <remarks> /// If the seek was to a position before the beginning of the list, the read position is set to the first instruction /// in the list. If the see was to a position after the end of the list, the read position is set to the last /// instruction in the list. /// </remarks> public int Seek(enum_SEEK_START dwSeekStart, IDebugCodeContext2 pCodeContext, ulong uCodeLocationId, long iInstructions) { switch (dwSeekStart) { case enum_SEEK_START.SEEK_START_BEGIN: _currentInstructionIndex = 0; break; case enum_SEEK_START.SEEK_START_CODECONTEXT: int error = GetCodeLocationId(pCodeContext, out uCodeLocationId); if (!ErrorHandler.Succeeded(error)) return error; goto case enum_SEEK_START.SEEK_START_CODELOCID; case enum_SEEK_START.SEEK_START_CODELOCID: _currentInstructionIndex = _disassembledMethod.Instructions.FindIndex(i => i.Offset == (int)uCodeLocationId); if (_currentInstructionIndex < 0) throw new ArgumentException(); break; case enum_SEEK_START.SEEK_START_CURRENT: break; case enum_SEEK_START.SEEK_START_END: _currentInstructionIndex = _disassembledMethod.Instructions.Count; break; default: throw new ArgumentException("Invalid seek start location."); } _currentInstructionIndex += (int)iInstructions; if (_currentInstructionIndex >= 0 && _currentInstructionIndex <= _disassembledMethod.Instructions.Count) return VSConstants.S_OK; _currentInstructionIndex = Math.Max(0, _currentInstructionIndex); _currentInstructionIndex = Math.Min(_disassembledMethod.Instructions.Count, _currentInstructionIndex); return VSConstants.S_FALSE; }
public int Seek(enum_SEEK_START seekStart, IDebugCodeContext2 codeContext, ulong codeLocationId, long numInstructions) { if (seekStart == enum_SEEK_START.SEEK_START_CODECONTEXT) { _address = codeContext.GetAddress(); } else if (seekStart == enum_SEEK_START.SEEK_START_CODELOCID) { _address = codeLocationId; } SbAddress sbAddress = _target.ResolveLoadAddress(_address); if (sbAddress == null) { return(VSConstants.E_FAIL); } if (numInstructions > 0) { // seek forward numInstructions++; List <InstructionInfo> instructions = _target.ReadInstructionInfos(sbAddress, (uint)numInstructions, _flavor); if (instructions.Count > 0) { numInstructions = Math.Min(numInstructions, instructions.Count); _address = instructions[(int)numInstructions - 1].Address; } } else if (numInstructions < 0) { // TODO: Get opcode sizes from LLDB. // Hard-code the opcode sizes for x86_64. Currently LLDB doesn't expose this // information, and this is the only architecture we support. uint minOpcodeSize = 1; uint maxOpcodeSize = 15; // When seeking backwards we don't know the exact address since x86_64 is a variable // size instruction architecture. Instead we figure out the max range to fit a // specific number of instructions. uint maxRangeForInstructions = (uint)Math.Abs(numInstructions) * maxOpcodeSize; // Since x86_64 is a variable size instruction architecture we don't know the exact // number of instructions in a specific address range. Assume the smallest opcode // size and that will be the number of instructions we need to read. uint maxNumberInstructions = maxRangeForInstructions / minOpcodeSize; // Using the start address and the max possible range, we can determine the lower // bound for where we should start reading instructions from. ulong endAddress = _address - maxRangeForInstructions; // The instruction where we should start the seek. List <InstructionInfo> startInstructionList = _target.ReadInstructionInfos(sbAddress, 1, _flavor); if (startInstructionList.Count == 0) { Trace.WriteLine( "Failed to seek backwards. Unable to read " + $"instruction at 0x{_address:X} so we have no start point for the seek"); return(VSConstants.E_FAIL); } InstructionInfo startInstruction = startInstructionList[0]; // We know there is an instruction around the |endAddress| but we don't know exactly // where it starts (because variable size instructions). LLDB will stop reading if // it runs into a bad instruction. We use that to our advantage and start reading // instructions from the |endAddress| + offset until LLDB returns us the number of // instructions we requested. We can then be fairly certain |endAddress| + offset is // the address to a valid instruction. int startIndex = -1; List <InstructionInfo> validInstructions = null; for (ulong i = 0; i < maxOpcodeSize; i++) { ulong seekAddress = endAddress + i; SbAddress seekSbAddress = _target.ResolveLoadAddress(seekAddress); List <InstructionInfo> instructions = _target.ReadInstructionInfos( seekSbAddress, maxNumberInstructions + 1, _flavor); // Shortcut: Continue if we did not get enough instructions. if (instructions == null || instructions.Count < Math.Abs(numInstructions)) { continue; } // Only accept the instructions if our start instruction is there. try { startIndex = instructions.BinarySearch(startInstruction, new InstructionComparator()); if (startIndex >= 0) { validInstructions = instructions; break; } } catch (InvalidOperationException e) { Trace.WriteLine(e); } } if (startIndex < 0) { Trace.WriteLine( "Failed to seek backwards. Unable to find an instruction with " + $"address 0x{_address:X} so we have no start point for the seek"); return(VSConstants.E_FAIL); } // Add the |startIndex| and the negative |numInstructions| to get the index of the // instruction to which we want to seek. int seekIndex = startIndex + (int)numInstructions; if (validInstructions == null || seekIndex < 0 || seekIndex >= validInstructions.Count) { Trace.WriteLine($"Failed to seek backwards. Seek index {seekIndex} is out " + "of range"); return(VSConstants.E_FAIL); } _address = validInstructions[seekIndex].Address; } return(VSConstants.S_OK); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int Seek (enum_SEEK_START dwSeekStart, IDebugCodeContext2 pCodeContext, ulong uCodeLocationId, long iInstructions) { // // Moves the read pointer in the disassembly stream a given number of instructions relative to a specified position. // LoggingUtils.PrintFunction (); try { switch (dwSeekStart) { case enum_SEEK_START.SEEK_START_BEGIN: { // // Starts seeking at the beginning of the current document. // throw new NotImplementedException (); } case enum_SEEK_START.SEEK_START_END: { // // Starts seeking at the end of the current document. // throw new NotImplementedException (); } case enum_SEEK_START.SEEK_START_CURRENT: { // // Starts seeking at the current position of the current document. // ulong offsetAddress = m_codeContext.Address.MemoryAddress; if (iInstructions > 0) { offsetAddress += (ulong)(iInstructions * 4); } else if (iInstructions < 0) { offsetAddress += (ulong)(Math.Abs (iInstructions) * 4); } m_codeContext.Address = new DebuggeeAddress (offsetAddress); break; } case enum_SEEK_START.SEEK_START_CODECONTEXT: { // // Starts seeking at the given code context of the current document. // DebuggeeCodeContext codeContext = (pCodeContext as DebuggeeCodeContext); ulong offsetAddress = codeContext.Address.MemoryAddress; if (iInstructions > 0) { offsetAddress += (ulong)(iInstructions * 4); } else if (iInstructions < 0) { offsetAddress += (ulong)(Math.Abs (iInstructions) * 4); } m_codeContext.Address = new DebuggeeAddress (offsetAddress); break; } case enum_SEEK_START.SEEK_START_CODELOCID: { // // Starts seeking at the given code location identifier. // ulong offsetAddress = uCodeLocationId; if (iInstructions > 0) { offsetAddress += (ulong)(iInstructions * 4); } else if (iInstructions < 0) { offsetAddress += (ulong)(Math.Abs (iInstructions) * 4); } m_codeContext.Address = new DebuggeeAddress (offsetAddress); break; } } return Constants.S_OK; } catch (NotImplementedException e) { LoggingUtils.HandleException (e); return Constants.E_NOTIMPL; } catch (Exception e) { LoggingUtils.HandleException (e); return Constants.E_FAIL; } }