public override Task <ReadInstructionInfosResponse> ReadInstructionInfos( ReadInstructionInfosRequest request, ServerCallContext context) { RemoteTarget target = GrpcLookupUtils.GetTarget(request.Target, _targetStore); SbAddress address = _addressStore.GetObject(request.Address.Id); var response = new ReadInstructionInfosResponse(); List <InstructionInfo> instructions = target.ReadInstructionInfos(address, request.Count, request.Flavor); if (instructions != null) { foreach (InstructionInfo instruction in instructions) { var instructionInfo = new GrpcInstructionInfo { Address = instruction.Address, Operands = instruction.Operands ?? "", Comment = instruction.Comment ?? "", Mnemonic = instruction.Mnemonic ?? "", SymbolName = instruction.SymbolName ?? "" }; if (instruction.LineEntry != null) { instructionInfo.LineEntry = new GrpcLineEntryInfo { FileName = instruction.LineEntry.FileName ?? "", Directory = instruction.LineEntry.Directory ?? "", Line = instruction.LineEntry.Line, Column = instruction.LineEntry.Column }; } response.Instructions.Add(instructionInfo); } } return(Task.FromResult(response)); }
List <Instruction> GetInstructions(SbAddress sbAddress, uint numInstructions, bool withSource) { _lineEntryCache.Clear(); var instructions = new List <Instruction>(); // If we need source information, we look at the previous instruction to find out // if it is on the same line and/or in the same file. var position = SourcePosition.Empty; if (withSource) { // Find previous instruction and initialize lineAddress and lastLine here. SbAddress previousSbAddress = _target.ResolveLoadAddress(sbAddress.GetLoadAddress(_target) - 1); if (previousSbAddress != null) { position = GetPositionForAddress(previousSbAddress); } } uint numInstructionsRead = 0; List <InstructionInfo> cachedInstructions = _target.ReadInstructionInfos(sbAddress, numInstructions, _flavor); for (int i = 0; i < cachedInstructions.Count; i++) { Instruction currentInstruction = new Instruction(); if (numInstructionsRead >= numInstructions) { break; } numInstructionsRead++; InstructionInfo instruction = cachedInstructions[i]; _lineEntryCache.Add(instruction.Address, instruction.LineEntry); currentInstruction.Address = instruction.Address; // Since Visual Studio doesn't do a good job formatting opcode and operands, in // addition to not providing a field to show instruction comments, do all the // formatting ourselves and put the entire string in the opcode field. string operands = instruction.Operands; string comment = instruction.Comment; string instructionString = $"{instruction.Mnemonic,-10}"; if (string.IsNullOrEmpty(comment)) { instructionString += $" {operands}"; } else { instructionString += $" {operands,-30} # {comment}"; } currentInstruction.Text = instructionString; if (!string.IsNullOrEmpty(instruction.SymbolName)) { currentInstruction.Symbol = instruction.SymbolName; } // If we so far believe we should get source position, let us get it here. if (withSource) { SourcePosition lastPosition = position; position = GetPositionFor(instruction.LineEntry); WritePositionToInstruction(lastPosition, position, i == 0, ref currentInstruction); } instructions.Add(currentInstruction); } return(instructions); }
public void SeekNegativeInvalidStartInstruction() { var mockAddress = Substitute.For <SbAddress>(); _mockTarget.ResolveLoadAddress(_testAddress).Returns(mockAddress); _mockTarget.ReadInstructionInfos(mockAddress, 1, _flavor) .Returns(new List <InstructionInfo>()); Assert.AreEqual( VSConstants.E_FAIL, _disassemblyStream.Seek(enum_SEEK_START.SEEK_START_CURRENT, null, 0, -10)); // Location shouldn't change. _disassemblyStream.GetCurrentLocation(out ulong newLocation); Assert.AreEqual(_testAddress, newLocation); }
public void ReadFull() { uint numberInstructions = 20; MockRead(numberInstructions, numberInstructions, mockAddress, mockMemoryRegion); var instructions = remoteTarget.ReadInstructionInfos(mockAddress, numberInstructions, "intel"); Assert.AreEqual(numberInstructions, instructions.Count); Assert.IsNull(instructions[0].SymbolName); }