diff options
author | Kyungwoo Lee <kyulee@microsoft.com> | 2015-11-13 00:38:04 +0300 |
---|---|---|
committer | Kyungwoo Lee <kyulee@microsoft.com> | 2015-11-13 23:44:34 +0300 |
commit | 8c3050e8e954944ed80c18b2cd5667cb1b36fabc (patch) | |
tree | 20a05cde6e0787995ca6aca31d01ab314d764061 /src/JitInterface | |
parent | e4d356590fd1ffd394833eb49a1f04beea8ca9b9 (diff) |
Emit DebugLocInfo/DebugFileInfo for Windows
This allows to place break point into C# source and step into callee.
Jit reports il to native offsets. EE has source line to il offset.
Basically when Jit reports such table, I build native offset to source location table (DebugLocInfo).
File names are uniquely aggregated and referenced by the index -- DebugFileInfo.
The latter table is a global thing which is emitted once in the beginning
The former table is for each function.
I didn't share ILEmitter code but just copy it for now since it only uses line info.
Eventually this needs to factored.
I also adapted codeview emission code from LLVM for native Object writer, which also needs to be refactored.
It's under review -- https://github.com/dotnet/llilc/pull/936
ObjectWriter version should be also updated accordingly.
Diffstat (limited to 'src/JitInterface')
-rw-r--r-- | src/JitInterface/src/CorInfoImpl.cs | 72 |
1 files changed, 70 insertions, 2 deletions
diff --git a/src/JitInterface/src/CorInfoImpl.cs b/src/JitInterface/src/CorInfoImpl.cs index 1eb16931f..82947a0ed 100644 --- a/src/JitInterface/src/CorInfoImpl.cs +++ b/src/JitInterface/src/CorInfoImpl.cs @@ -54,6 +54,12 @@ namespace Internal.JitInterface } } + struct SequencePoint + { + public string Document; + public int LineNumber; + } + public MethodCode CompileMethod(MethodDesc method) { try @@ -65,8 +71,24 @@ namespace Internal.JitInterface CorJitFlag.CORJIT_FLG_SKIP_VERIFICATION | CorJitFlag.CORJIT_FLG_READYTORUN | CorJitFlag.CORJIT_FLG_RELOC | + CorJitFlag.CORJIT_FLG_DEBUG_INFO | CorJitFlag.CORJIT_FLG_PREJIT); + if (!_compilation.Options.NoLineNumbers) + { + CompilerTypeSystemContext typeSystemContext = _compilation.TypeSystemContext; + IEnumerable<ILSequencePoint> ilSequencePoints = typeSystemContext.GetSequencePointsForMethod(method); + if (ilSequencePoints != null) + { + Dictionary<int, SequencePoint> sequencePoints = new Dictionary<int, SequencePoint>(); + foreach (var point in ilSequencePoints) + { + sequencePoints.Add(point.Offset, new SequencePoint() { Document = point.Document, LineNumber = point.LineNumber }); + } + _sequencePoints = sequencePoints; + } + } + IntPtr nativeEntry; uint codeSize; _compile(_jit, _comp, ref methodInfo, flags, out nativeEntry, out codeSize); @@ -84,7 +106,8 @@ namespace Internal.JitInterface Relocs = (_relocs != null) ? _relocs.ToArray() : null, - FrameInfos = _frameInfos + FrameInfos = _frameInfos, + DebugLocInfos = _debugLocInfos }; } finally @@ -131,6 +154,9 @@ namespace Internal.JitInterface _numFrameInfos = 0; _usedFrameInfos = 0; _frameInfos = null; + + _sequencePoints = null; + _debugLocInfos = null; } Dictionary<Object, IntPtr> _objectToHandle = new Dictionary<Object, IntPtr>(); @@ -1198,10 +1224,49 @@ namespace Internal.JitInterface pILOffsets = null; *implicitBoundaries = BoundaryTypes.DEFAULT_BOUNDARIES; } + + // Create a DebugLocInfo which is a table from native offset to sourece line. + // using native to il offset (pMap) and il to source line (_sequencePoints). void setBoundaries(IntPtr _this, CORINFO_METHOD_STRUCT_* ftn, uint cMap, OffsetMapping* pMap) { - // TODO: Debugging + Debug.Assert(_debugLocInfos == null); + // No interest if sequencePoints is not populated before. + if (_sequencePoints == null) + { + return; + } + + List<DebugLocInfo> debugLocInfos = new List<DebugLocInfo>(); + for (int i = 0; i < cMap; i++) + { + SequencePoint s; + if (_sequencePoints.TryGetValue((int)pMap[i].ilOffset, out s)) + { + Debug.Assert(!string.IsNullOrEmpty(s.Document)); + int nativeOffset = (int)pMap[i].nativeOffset; + DebugLocInfo loc = new DebugLocInfo(nativeOffset, s.Document, s.LineNumber); + + // We often miss line number at 0 offset, which prevents debugger from + // stepping into callee. + // Synthesize a location info at 0 offset assuming line number is minus one + // from the first entry. + if (debugLocInfos.Count == 0 && nativeOffset != 0) + { + DebugLocInfo firstLoc = loc; + firstLoc.NativeOffset = 0; + firstLoc.LineNumber--; + debugLocInfos.Add(firstLoc); + } + + debugLocInfos.Add(loc); + } + } + + if (debugLocInfos.Count > 0) { + _debugLocInfos = debugLocInfos.ToArray(); + } } + void getVars(IntPtr _this, CORINFO_METHOD_STRUCT_* ftn, ref uint cVars, ILVarInfo** vars, [MarshalAs(UnmanagedType.U1)] ref bool extendOthers) { // TODO: Debugging @@ -1839,6 +1904,9 @@ namespace Internal.JitInterface int _usedFrameInfos; FrameInfo[] _frameInfos; + Dictionary<int, SequencePoint> _sequencePoints; + DebugLocInfo[] _debugLocInfos; + void allocMem(IntPtr _this, uint hotCodeSize, uint coldCodeSize, uint roDataSize, uint xcptnsCount, CorJitAllocMemFlag flag, ref void* hotCodeBlock, ref void* coldCodeBlock, ref void* roDataBlock) { hotCodeBlock = (void *)GetPin(_code = new byte[hotCodeSize]); |