コード例 #1
0
        private void MockFunctionData(uint startPosition, uint endPosition,
                                      string directory, string fileName)
        {
            SbBreakpointLocation location = mockBreakpoint.GetLocationAtIndex(0);

            SbAddress mockBreakpointAddress  = Substitute.For <SbAddress>();
            SbAddress mockStartAddress       = Substitute.For <SbAddress>();
            SbAddress mockFunctionEndAddress = Substitute.For <SbAddress>();
            SbAddress mockActualEndAddress   = Substitute.For <SbAddress>();

            SbLineEntry mockStartLineEntry = Substitute.For <SbLineEntry>();
            SbLineEntry mockEndLineEntry   = Substitute.For <SbLineEntry>();

            ulong address = 0x1234567;

            location.GetAddress().Returns(mockBreakpointAddress);
            mockBreakpointAddress.GetFunction().Returns(mockFunction);

            mockFunction.GetStartAddress().Returns(mockStartAddress);
            mockFunction.GetEndAddress().Returns(mockFunctionEndAddress);

            mockFunctionEndAddress.GetLoadAddress(mockTarget).Returns(address);
            mockTarget.ResolveLoadAddress(address - 1).Returns(mockActualEndAddress);

            mockStartAddress.GetLineEntry().Returns(mockStartLineEntry);
            mockActualEndAddress.GetLineEntry().Returns(mockEndLineEntry);

            mockStartLineEntry.GetLine().Returns(startPosition);
            mockStartLineEntry.GetDirectory().Returns(directory);
            mockStartLineEntry.GetFileName().Returns(fileName);
            mockEndLineEntry.GetLine().Returns(endPosition);
        }
コード例 #2
0
        public int GetCodeContext(ulong codeLocationId, out IDebugCodeContext2 codeContext)
        {
            // The codeContext is used, among other things, to link assembly instructions and
            // source code. The "Go To Source Code" functionality in disassembly view needs this
            // to be properly implemented.
            IDebugDocumentContext2 documentContext = null;

            if (_lineEntryCache.TryGetValue(codeLocationId, out LineEntryInfo lineEntry))
            {
                documentContext = _documentContextFactory.Create(lineEntry);
            }
            else
            {
                SbAddress address = _target.ResolveLoadAddress(codeLocationId);
                if (address != null)
                {
                    lineEntry       = address.GetLineEntry();
                    documentContext = _documentContextFactory.Create(lineEntry);
                }
            }

            string AddressToFuncName() =>
            _target.ResolveLoadAddress(codeLocationId)?.GetFunction()?.GetName() ??
            _codeContextName;

            codeContext = _codeContextFactory.Create(codeLocationId,
                                                     new Lazy <string>(AddressToFuncName),
                                                     documentContext, Guid.Empty);
            return(VSConstants.S_OK);
        }
コード例 #3
0
        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));
        }
コード例 #4
0
        public List <InstructionInfo> ReadInstructionInfos(SbAddress address,
                                                           uint count, string flavor)
        {
            ReadInstructionInfosResponse response = null;

            if (connection.InvokeRpc(() =>
            {
                response = client.ReadInstructionInfos(
                    new ReadInstructionInfosRequest
                {
                    Target = grpcSbTarget,
                    Address = new GrpcSbAddress {
                        Id = address.GetId()
                    },
                    Count = count,
                    Flavor = flavor,
                });
            }))
            {
                var instructions = new List <InstructionInfo>();
                foreach (var instruction in response.Instructions)
                {
                    instructions.Add(new InstructionInfo(
                                         instruction.Address,
                                         instruction.Operands,
                                         instruction.Comment,
                                         instruction.Mnemonic,
                                         instruction.SymbolName,
                                         FrameInfoUtils.CreateLineEntryInfo(instruction.LineEntry)));
                }
                return(instructions);
            }
            return(new List <InstructionInfo>());
        }
コード例 #5
0
        private List <SbInstruction> MockRead(uint instructionsToCreate, uint instructionsToRead,
                                              SbAddress startSbAddress, SbMemoryRegionInfo memoryRegion,
                                              ulong startAddress = TEST_ADDRESS, bool isMapped = true,
                                              bool hasAddress    = true, ulong regionEnd       = ulong.MaxValue)
        {
            var instructions = CreateMockInstructions(instructionsToCreate, startAddress,
                                                      hasAddress);

            mockTarget
            .ReadInstructions(startSbAddress, instructionsToRead, "intel")
            .Returns(instructions);

            startSbAddress.GetLoadAddress(mockTarget).Returns(startAddress);
            mockTarget.ResolveLoadAddress(startAddress).Returns(startSbAddress);

            memoryRegion.IsMapped().Returns(isMapped);
            if (!isMapped)
            {
                memoryRegion.GetRegionEnd().Returns(regionEnd);
            }

            SbMemoryRegionInfo memRegion;

            mockProcess.GetMemoryRegionInfo(startAddress, out memRegion).Returns(
                x =>
            {
                x[1] = memoryRegion;
                return(mockError);
            });

            return(instructions);
        }
コード例 #6
0
        public bool ApplyPlaceholderProperties(SbModule destModule,
                                               PlaceholderModuleProperties properties, RemoteTarget lldbTarget)
        {
            long      slide         = properties.Slide;
            SbAddress headerAddress = destModule.GetObjectFileHeaderAddress();

            if (headerAddress != null)
            {
                // For libraries this will generally equal 0, for executables it will equal
                // |placeholderBaseLoadAddress|.
                ulong fileBaseAddress = headerAddress.GetFileAddress();
                slide -= (long)fileBaseAddress;
            }

            SbError error = lldbTarget.SetModuleLoadAddress(destModule, slide);

            if (error.Fail())
            {
                Trace.WriteLine(
                    $"Failed to set load address on destination module: {error.GetCString()}.");
                return(false);
            }

            if (!destModule.SetPlatformFileSpec(properties.PlatformFileSpec))
            {
                Trace.WriteLine("Failed to set file spec on the destination module.");
                return(false);
            }

            return(true);
        }
コード例 #7
0
        private List <SbInstruction> CreateMockInstructions(uint count,
                                                            ulong startAddress = TEST_ADDRESS, bool hasAddress = true)
        {
            List <SbInstruction> instructions = new List <SbInstruction>();

            for (uint i = 0; i < count; i++)
            {
                SbAddress mockSbAddress = null;
                if (hasAddress)
                {
                    mockSbAddress = Substitute.For <SbAddress>();
                    mockSbAddress
                    .GetLoadAddress(mockTarget)
                    .Returns(startAddress + i);
                    mockSbAddress.GetSymbol().Returns((SbSymbol)null);
                    mockSbAddress.GetLineEntry().Returns((SbLineEntry)null);
                }

                var mockInstruction = Substitute.For <SbInstruction>();
                mockInstruction.GetAddress().Returns(mockSbAddress);
                mockInstruction.GetMnemonic(mockTarget).Returns(TEST_MNEMONIC + i);
                mockInstruction.GetOperands(mockTarget).Returns(TEST_OPERANDS + i);
                mockInstruction.GetComment(mockTarget).Returns(TEST_COMMENT);
                mockInstruction.GetByteSize().Returns(1u);

                instructions.Add(mockInstruction);
            }
            return(instructions);
        }
コード例 #8
0
        public override Task <GetFileAddressResponse> GetFileAddress(GetFileAddressRequest request,
                                                                     ServerCallContext context)
        {
            SbAddress address     = addressStore.GetObject(request.Address.Id);
            ulong     fileAddress = address.GetFileAddress();

            return(Task.FromResult(new GetFileAddressResponse {
                FileAddress = fileAddress
            }));
        }
コード例 #9
0
        public BreakpointErrorPair CreateFunctionOffsetBreakpoint(string symbolName, uint offset)
        {
            RemoteBreakpoint functionBreakpoint = BreakpointCreateByName(symbolName);

            if (functionBreakpoint.GetNumLocations() < 1)
            {
                return(new BreakpointErrorPair(null, BreakpointError.NoFunctionLocation));
            }

            // At the moment if there are two functions with the same offset will be applied only
            // for one of them. In base VS 2017 the breakpoint is created only for one
            // function if there are overloaded functions.
            SbFunction function =
                functionBreakpoint.GetLocationAtIndex(0).GetAddress().GetFunction();

            // Delete the breakpoint as we don't need it anymore and don't want it to linger
            _sbTarget.BreakpointDelete(functionBreakpoint.GetId());

            if (function == null)
            {
                return(new BreakpointErrorPair(null, BreakpointError.NoFunctionFound));
            }

            SbLineEntry startLineEntry = function.GetStartAddress().GetLineEntry();

            uint startLine = startLineEntry.GetLine();

            // EndAddress points to the first address after the function so we
            // subtract one from that address and get the corresponding lineEntry.
            SbAddress endAddress = function.GetEndAddress();
            ulong     address    = endAddress.GetLoadAddress(_sbTarget);

            endAddress = ResolveLoadAddress(address - 1);
            uint endLine = endAddress.GetLineEntry().GetLine();

            uint newPosition = startLine + offset + 1;

            if (newPosition > endLine)
            {
                return(new BreakpointErrorPair(null, BreakpointError.PositionNotAvailable));
            }

            string fileName  = startLineEntry.GetFileName();
            string directory = startLineEntry.GetDirectory();
            string path      = Path.Combine(directory, fileName);

            RemoteBreakpoint breakpoint = BreakpointCreateByLocation(path, newPosition);

            return(new BreakpointErrorPair(breakpoint, BreakpointError.Success));
        }
コード例 #10
0
        public override Task <ResolveLoadAddressResponse> ResolveLoadAddress(
            ResolveLoadAddressRequest request, ServerCallContext context)
        {
            RemoteTarget target   = GrpcLookupUtils.GetTarget(request.Target, _targetStore);
            var          response = new ResolveLoadAddressResponse();
            SbAddress    address  = target.ResolveLoadAddress(request.Address);

            if (address != null)
            {
                response.Address = new GrpcSbAddress {
                    Id = _addressStore.AddObject(address),
                };
            }
            return(Task.FromResult(response));
        }
コード例 #11
0
        public override Task <GetObjectFileHeaderAddressResponse> GetObjectFileHeaderAddress(
            GetObjectFileHeaderAddressRequest request, ServerCallContext context)
        {
            var       module   = moduleStore.GetObject(request.Module.Id);
            SbAddress address  = module.GetObjectFileHeaderAddress();
            var       response = new GetObjectFileHeaderAddressResponse();

            if (address != null)
            {
                response.Address = new GrpcSbAddress {
                    Id = addressStore.AddObject(address)
                };
            }
            return(Task.FromResult(response));
        }
コード例 #12
0
        public void GetCodeContextNullAddressResolution()
        {
            SbAddress address        = null;
            var       newCodeContext = Substitute.For <IDebugCodeContext2>();

            _mockTarget.ResolveLoadAddress(_testAddress).Returns(address);
            _codeContextFactory.Create(_testAddress, Arg.Any <Lazy <string> >(), null, Guid.Empty)
            .Returns(newCodeContext);

            int getCodeContextResult =
                _disassemblyStream.GetCodeContext(_testAddress, out IDebugCodeContext2 codeContext);

            Assert.AreEqual(VSConstants.S_OK, getCodeContextResult);
            Assert.AreEqual(newCodeContext, codeContext);
        }
コード例 #13
0
        public void SetUp()
        {
            mockTarget   = Substitute.For <SbTarget>();
            remoteTarget = new RemoteTargetFactory(new RemoteBreakpointFactory())
                           .Create(mockTarget);
            mockAddress      = Substitute.For <SbAddress>();
            mockProcess      = Substitute.For <SbProcess>();
            mockMemoryRegion = Substitute.For <SbMemoryRegionInfo>();
            mockError        = Substitute.For <SbError>();
            mockBreakpoint   = Substitute.For <SbBreakpoint>();
            remoteBreakpoint = new RemoteBreakpointFactory().Create(mockBreakpoint);
            mockFunction     = Substitute.For <SbFunction>();

            mockTarget.GetProcess().Returns(mockProcess);
        }
コード例 #14
0
        public void GetBreakpointResolutionNullAddress()
        {
            SbBreakpointLocation breakpointLocationNullAddress =
                Substitute.For <SbBreakpointLocation>();
            const SbAddress NULL_ADDRESS = null;

            breakpointLocationNullAddress.GetAddress().Returns(NULL_ADDRESS);
            IDebugBoundBreakpoint2 boundBreakpointNullAddress = boundBreakpointFactory.Create(
                mockPendingBreakpoint, breakpointLocationNullAddress, mockprogram, Guid.Empty);
            IDebugBreakpointResolution2 breakpointResolutionNullAddress;

            Assert.AreEqual(VSConstants.E_FAIL,
                            boundBreakpointNullAddress.GetBreakpointResolution(
                                out breakpointResolutionNullAddress));
            Assert.AreEqual(null, breakpointResolutionNullAddress);
        }
コード例 #15
0
        public void GetCodeContext()
        {
            const ulong newAddress = 0x123456789a;

            SbAddress address         = Substitute.For <SbAddress>();
            var       documentContext = Substitute.For <IDebugDocumentContext2>();
            var       newCodeContext  = Substitute.For <IDebugCodeContext2>();

            _mockTarget.ResolveLoadAddress(newAddress).Returns(address);
            _documentContextFactory.Create(address.GetLineEntry()).Returns(documentContext);
            _codeContextFactory
            .Create(newAddress, Arg.Any <Lazy <string> >(), documentContext, Guid.Empty)
            .Returns(newCodeContext);

            Assert.AreEqual(VSConstants.S_OK, _disassemblyStream.GetCodeContext(
                                newAddress, out IDebugCodeContext2 codeContext));
            Assert.AreEqual(newCodeContext, codeContext);
        }
コード例 #16
0
        public void ReadEmpty()
        {
            uint instructionsToRead = 10;

            for (uint i = 0; i < instructionsToRead; i++)
            {
                var mockInvalidAddress = Substitute.For <SbAddress>();
                if (i == 0)
                {
                    mockAddress = mockInvalidAddress;
                }
                ulong address = TEST_ADDRESS + i;
                MockRead(0, instructionsToRead - i, mockInvalidAddress, mockMemoryRegion, address);
            }

            var instructions = remoteTarget.ReadInstructionInfos(mockAddress, instructionsToRead,
                                                                 "intel");

            Assert.AreEqual(instructionsToRead, instructions.Count);
        }
コード例 #17
0
        /// <summary>
        /// Figures out the address of the next instruction and adds it as an invalid instruction
        /// to |instructions|.
        /// </summary>
        /// <returns> The address after the invalid instruction. </returns>
        ulong AddInvalidInstruction(SbAddress address, List <SbInstruction> sbInstructions,
                                    List <InstructionInfo> instructions)
        {
            ulong instructionAddress;

            // Figure out what the address of the invalid instruction should be
            if (sbInstructions.Count > 0)
            {
                // The address of the next instruction should be the address
                // of the last instruction + its byte size.
                SbInstruction lastInstruction = sbInstructions[sbInstructions.Count - 1];
                instructionAddress = lastInstruction.GetAddress().GetLoadAddress(_sbTarget) +
                                     lastInstruction.GetByteSize();
            }
            else
            {
                // If we haven't got any instructions yet we use the starting address
                if (instructions.Count == 0)
                {
                    instructionAddress = address.GetLoadAddress(_sbTarget);
                }
                // If we got no new instructions and we already have some instructions,
                // use the address of the last instruction + 1 since the last instruction
                // must have been invalid and therefore the byte size is one.
                else
                {
                    instructionAddress = instructions[instructions.Count - 1].Address + 1;
                }
            }

            // Add the invalid instruction, we represent them with setting both the
            // operands and mnemonic to question marks
            instructions.Add(new InstructionInfo {
                Address  = instructionAddress, Operands = "??",
                Mnemonic = "??"
            });

            return(instructionAddress + 1);
        }
コード例 #18
0
        /// <summary>
        /// Creates unknown/invalid instructions for an unmapped region.
        /// </summary>
        /// <returns> The address of the next instruction. </returns>
        ulong AddUnmappedInstructions(SbAddress address, uint instructionsLeft,
                                      SbMemoryRegionInfo memoryRegion,
                                      List <InstructionInfo> instructions)
        {
            // SbMemoryRegionInfo holds information about the end address even for unmapped
            // memory regions so we can use that to determine how far we can pad with
            // invalid/unknown instructions before checking again.
            ulong memoryRegionEndAddress = memoryRegion.GetRegionEnd();

            ulong startAddress = address.GetLoadAddress(_sbTarget);
            ulong endAddress   = Math.Min(memoryRegionEndAddress, startAddress + instructionsLeft);

            for (ulong currentAddress = startAddress; currentAddress < endAddress; currentAddress++)
            {
                instructions.Add(new InstructionInfo {
                    Address  = currentAddress, Operands = "??",
                    Mnemonic = "??"
                });
            }

            return(endAddress);
        }
コード例 #19
0
        public void SetUp()
        {
            string name = "";

            mockBreakpoint         = Substitute.For <RemoteBreakpoint>();
            lineEntry              = new LineEntryInfo();
            mockPendingBreakpoint  = Substitute.For <IDebugPendingBreakpoint2>();
            mockBreakpointLocation = Substitute.For <SbBreakpointLocation>();
            mockAddress            = Substitute.For <SbAddress>();
            mockAddress.GetLineEntry().Returns(lineEntry);
            mockBreakpointLocation.GetHitCount().Returns(HIT_COUNT);
            mockBreakpointLocation.GetLoadAddress().Returns(ADDRESS);
            mockBreakpointLocation.GetBreakpoint().Returns(mockBreakpoint);
            mockBreakpointLocation.GetId().Returns(ID);
            mockBreakpointLocation.GetAddress().Returns(mockAddress);
            mockprogram         = Substitute.For <IDebugProgram2>();
            mockDocumentContext = Substitute.For <IDebugDocumentContext2>();
            mockDocumentContext.GetName(enum_GETNAME_TYPE.GN_NAME, out name).Returns(
                x =>
            {
                x[1] = NAME;
                return(VSConstants.S_OK);
            });
            mockBreakpointResolution   = Substitute.For <IDebugBreakpointResolution2>();
            mockDocumentContextFactory = Substitute.For <DebugDocumentContext.Factory>();
            mockDocumentContextFactory.Create(lineEntry).Returns(mockDocumentContext);
            mockCodeContext        = Substitute.For <IDebugCodeContext2>();
            mockCodeContextFactory = Substitute.For <DebugCodeContext.Factory>();
            mockCodeContextFactory.Create(ADDRESS, NAME,
                                          mockDocumentContext, Guid.Empty).Returns(mockCodeContext);
            mockBreakpointResolutionFactory =
                Substitute.For <DebugBreakpointResolution.Factory>();
            mockBreakpointResolutionFactory.Create(mockCodeContext, mockprogram).Returns(
                mockBreakpointResolution);
            boundBreakpointFactory = new DebugBoundBreakpoint.Factory(mockDocumentContextFactory,
                                                                      mockCodeContextFactory, mockBreakpointResolutionFactory);
            boundBreakpoint = boundBreakpointFactory.Create(
                mockPendingBreakpoint, mockBreakpointLocation, mockprogram, Guid.Empty);
        }
コード例 #20
0
        // Constructor with factories for tests.
        DebugBoundBreakpoint(DebugDocumentContext.Factory documentContextFactory,
                             DebugCodeContext.Factory codeContextFactory,
                             DebugBreakpointResolution.Factory breakpointResolutionFactory,
                             IDebugPendingBreakpoint2 pendingBreakpoint,
                             SbBreakpointLocation breakpointLocation, IDebugProgram2 program,
                             Guid languageGuid)
        {
            _pendingBreakpoint  = pendingBreakpoint;
            _breakpointLocation = breakpointLocation;

            _enabled             = true;
            _deleted             = false;
            _disabledByPassCount = false;

            SbAddress address = breakpointLocation.GetAddress();

            if (address != null)
            {
                LineEntryInfo          lineEntry       = address.GetLineEntry();
                IDebugDocumentContext2 documentContext = null;
                string name = "";

                // |lineEntry| is null if the breakpoint is set on an external function.
                if (lineEntry != null)
                {
                    documentContext = documentContextFactory.Create(lineEntry);
                    documentContext.GetName(enum_GETNAME_TYPE.GN_NAME, out name);
                }
                IDebugCodeContext2 codeContext = codeContextFactory.Create(
                    breakpointLocation.GetLoadAddress(), name, documentContext, languageGuid);
                _breakpointResolution = breakpointResolutionFactory.Create(codeContext, program);
            }
            else
            {
                Trace.WriteLine("Warning: Unable to obtain address from breakpoint location." +
                                " No breakpoint resolution created.");
            }
        }
コード例 #21
0
 static SourcePosition GetPositionForAddress(SbAddress address) =>
 GetPositionFor(address?.GetLineEntry());
コード例 #22
0
        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);
        }
コード例 #23
0
        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);
        }
コード例 #24
0
 public List <InstructionInfo> ReadInstructionInfos(SbAddress address,
                                                    uint count, string flavor)
 {
     throw new NotImplementedTestDoubleException();
 }
コード例 #25
0
        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);
        }
コード例 #26
0
 public List <SbInstruction> ReadInstructions(SbAddress baseAddress, uint count,
                                              string flavor) =>
 _sbTarget.ReadInstructions(baseAddress, count, flavor);
コード例 #27
0
        public List <InstructionInfo> ReadInstructionInfos(SbAddress address, uint count,
                                                           string flavor)
        {
            SbProcess process      = _sbTarget.GetProcess();
            var       instructions = new List <InstructionInfo>();

            while (instructions.Count < count)
            {
                SbMemoryRegionInfo memoryRegion = null;
                SbError            error        = process.GetMemoryRegionInfo(address.GetLoadAddress(_sbTarget),
                                                                              out memoryRegion);

                if (error.Fail())
                {
                    Trace.WriteLine("Unable to retrieve memory region info.");
                    return(new List <InstructionInfo>());
                }

                // If the address we are given is not mapped we should not try to disassemble it.
                if (!memoryRegion.IsMapped())
                {
                    uint instructionsLeft = count - (uint)instructions.Count;

                    ulong nextAddress = AddUnmappedInstructions(address, instructionsLeft,
                                                                memoryRegion, instructions);

                    address = _sbTarget.ResolveLoadAddress(nextAddress);

                    // Continue in case we still need more instructions
                    continue;
                }

                List <SbInstruction> sbInstructions =
                    _sbTarget.ReadInstructions(address, count - (uint)instructions.Count, flavor);
                foreach (SbInstruction sbInstruction in sbInstructions)
                {
                    SbAddress sbAddress = sbInstruction.GetAddress();
                    if (sbAddress == null)
                    {
                        // It should never happen that we cannot get an address for an instruction
                        Trace.WriteLine("Unable to retrieve address.");
                        return(new List <InstructionInfo>());
                    }

                    ulong instructionAddress = sbAddress.GetLoadAddress(_sbTarget);

                    SbSymbol symbol = sbAddress.GetSymbol();

                    string symbolName = null;
                    // Only set symbolName if it is the start of a function
                    SbAddress startAddress = symbol?.GetStartAddress();
                    if (startAddress != null &&
                        startAddress.GetLoadAddress(_sbTarget) == instructionAddress)
                    {
                        symbolName = symbol.GetName();
                    }

                    SbLineEntry   lineEntry     = sbAddress.GetLineEntry();
                    LineEntryInfo lineEntryInfo = null;
                    if (lineEntry != null)
                    {
                        lineEntryInfo = new LineEntryInfo {
                            FileName  = lineEntry.GetFileName(),
                            Directory = lineEntry.GetDirectory(),
                            Line      = lineEntry.GetLine(),
                            Column    = lineEntry.GetColumn(),
                        };
                    }

                    // Create a new instruction and fill in the values
                    var instruction = new InstructionInfo {
                        Address    = instructionAddress,
                        Operands   = sbInstruction.GetOperands(_sbTarget),
                        Comment    = sbInstruction.GetComment(_sbTarget),
                        Mnemonic   = sbInstruction.GetMnemonic(_sbTarget),
                        SymbolName = symbolName,
                        LineEntry  = lineEntryInfo,
                    };
                    instructions.Add(instruction);
                }

                // If we haven't managed to retrieve all the instructions we wanted, add
                // an invalid instruction and keep going from the next address.
                if (instructions.Count < count)
                {
                    ulong nextAddress =
                        AddInvalidInstruction(address, sbInstructions, instructions);

                    // Set the address to the next address after the invalid instruction
                    address = _sbTarget.ResolveLoadAddress(nextAddress);
                }
            }
            return(instructions);
        }