コード例 #1
0
        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));
        }