|
2 | 2 |
|
3 | 3 | using System; |
4 | 4 | using System.Collections.Generic; |
| 5 | +using System.Threading; |
5 | 6 | using dnlib.DotNet.Emit; |
6 | 7 |
|
7 | 8 | namespace dnlib.DotNet.Pdb { |
@@ -111,6 +112,16 @@ public enum PdbCustomDebugInfoKind { |
111 | 112 | /// <see cref="PdbCompilationOptionsCustomDebugInfo"/> |
112 | 113 | /// </summary> |
113 | 114 | CompilationOptions, |
| 115 | + |
| 116 | + /// <summary> |
| 117 | + /// <see cref="PdbTypeDefinitionDocumentsDebugInfo"/> |
| 118 | + /// </summary> |
| 119 | + TypeDefinitionDocuments, |
| 120 | + |
| 121 | + /// <summary> |
| 122 | + /// <see cref="PdbEditAndContinueStateMachineStateMapDebugInfo"/> |
| 123 | + /// </summary> |
| 124 | + EditAndContinueStateMachineStateMap, |
114 | 125 | } |
115 | 126 |
|
116 | 127 | /// <summary> |
@@ -665,7 +676,7 @@ public sealed class PortablePdbTupleElementNamesCustomDebugInfo : PdbCustomDebug |
665 | 676 |
|
666 | 677 | /// <summary> |
667 | 678 | /// Async method stepping info |
668 | | - /// |
| 679 | + /// |
669 | 680 | /// It's internal and translated to a <see cref="PdbAsyncMethodCustomDebugInfo"/> |
670 | 681 | /// </summary> |
671 | 682 | sealed class PdbAsyncMethodSteppingInformationCustomDebugInfo : PdbCustomDebugInfo { |
@@ -777,9 +788,9 @@ public sealed class PdbEmbeddedSourceCustomDebugInfo : PdbCustomDebugInfo { |
777 | 788 |
|
778 | 789 | /// <summary> |
779 | 790 | /// Gets the source code blob. |
780 | | - /// |
| 791 | + /// |
781 | 792 | /// It's not decompressed and converted to a string because the encoding isn't specified. |
782 | | - /// |
| 793 | + /// |
783 | 794 | /// https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PortablePdb-Metadata.md#embedded-source-c-and-vb-compilers |
784 | 795 | /// </summary> |
785 | 796 | public byte[] SourceCodeBlob { get; set; } |
@@ -1101,4 +1112,161 @@ public sealed class PdbCompilationOptionsCustomDebugInfo : PdbCustomDebugInfo { |
1101 | 1112 | /// </summary> |
1102 | 1113 | public PdbCompilationOptionsCustomDebugInfo() => Options = new List<KeyValuePair<string, string>>(); |
1103 | 1114 | } |
| 1115 | + |
| 1116 | + /// <summary> |
| 1117 | + /// Links a TypeDef with no method IL with a PDB document. |
| 1118 | + /// </summary> |
| 1119 | + public class PdbTypeDefinitionDocumentsDebugInfo : PdbCustomDebugInfo { |
| 1120 | + /// <summary> |
| 1121 | + /// Returns <see cref="PdbCustomDebugInfoKind.TypeDefinitionDocuments"/> |
| 1122 | + /// </summary> |
| 1123 | + public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.TypeDefinitionDocuments; |
| 1124 | + |
| 1125 | + /// <summary> |
| 1126 | + /// Gets the custom debug info guid, see <see cref="CustomDebugInfoGuids"/> |
| 1127 | + /// </summary> |
| 1128 | + public override Guid Guid => CustomDebugInfoGuids.TypeDefinitionDocuments; |
| 1129 | + |
| 1130 | + /// <summary> |
| 1131 | + /// List of documents associated with the type |
| 1132 | + /// </summary> |
| 1133 | + public IList<PdbDocument> Documents { |
| 1134 | + get { |
| 1135 | + if (documents is null) |
| 1136 | + InitializeDocuments(); |
| 1137 | + return documents; |
| 1138 | + } |
| 1139 | + } |
| 1140 | + /// <summary/> |
| 1141 | + protected IList<PdbDocument> documents; |
| 1142 | + /// <summary>Initializes <see cref="documents"/></summary> |
| 1143 | + protected virtual void InitializeDocuments() => |
| 1144 | + Interlocked.CompareExchange(ref documents, new List<PdbDocument>(), null); |
| 1145 | + } |
| 1146 | + |
| 1147 | + sealed class PdbTypeDefinitionDocumentsDebugInfoMD : PdbTypeDefinitionDocumentsDebugInfo { |
| 1148 | + readonly ModuleDef readerModule; |
| 1149 | + readonly IList<MDToken> documentTokens; |
| 1150 | + |
| 1151 | + protected override void InitializeDocuments() { |
| 1152 | + var list = new List<PdbDocument>(documentTokens.Count); |
| 1153 | + if (readerModule.PdbState is not null) { |
| 1154 | + for (var i = 0; i < documentTokens.Count; i++) { |
| 1155 | + if (readerModule.PdbState.tokenToDocument.TryGetValue(documentTokens[i], out var document)) |
| 1156 | + list.Add(document); |
| 1157 | + } |
| 1158 | + } |
| 1159 | + Interlocked.CompareExchange(ref documents, list, null); |
| 1160 | + } |
| 1161 | + |
| 1162 | + public PdbTypeDefinitionDocumentsDebugInfoMD(ModuleDef readerModule, IList<MDToken> documentTokens) { |
| 1163 | + this.readerModule = readerModule; |
| 1164 | + this.documentTokens = documentTokens; |
| 1165 | + } |
| 1166 | + } |
| 1167 | + |
| 1168 | + /// <summary> |
| 1169 | + /// Contains the EnC state machine state mapping |
| 1170 | + /// </summary> |
| 1171 | + public sealed class PdbEditAndContinueStateMachineStateMapDebugInfo : PdbCustomDebugInfo { |
| 1172 | + /// <summary> |
| 1173 | + /// Returns <see cref="PdbCustomDebugInfoKind.TypeDefinitionDocuments"/> |
| 1174 | + /// </summary> |
| 1175 | + public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.EditAndContinueStateMachineStateMap; |
| 1176 | + |
| 1177 | + /// <summary> |
| 1178 | + /// Gets the custom debug info guid, see <see cref="CustomDebugInfoGuids"/> |
| 1179 | + /// </summary> |
| 1180 | + public override Guid Guid => CustomDebugInfoGuids.EncStateMachineStateMap; |
| 1181 | + |
| 1182 | + /// <summary> |
| 1183 | + /// State machine states |
| 1184 | + /// </summary> |
| 1185 | + public List<StateMachineStateInfo> StateMachineStates { get; } |
| 1186 | + |
| 1187 | + /// <summary> |
| 1188 | + /// Constructor |
| 1189 | + /// </summary> |
| 1190 | + public PdbEditAndContinueStateMachineStateMapDebugInfo() => StateMachineStates = new List<StateMachineStateInfo>(); |
| 1191 | + } |
| 1192 | + |
| 1193 | + /// <summary> |
| 1194 | + /// State machine state information used by debuggers |
| 1195 | + /// </summary> |
| 1196 | + public struct StateMachineStateInfo { |
| 1197 | + /// <summary> |
| 1198 | + /// Syntax offset |
| 1199 | + /// </summary> |
| 1200 | + public readonly int SyntaxOffset; |
| 1201 | + |
| 1202 | + /// <summary> |
| 1203 | + /// State machine state |
| 1204 | + /// </summary> |
| 1205 | + public readonly StateMachineState State; |
| 1206 | + |
| 1207 | + /// <summary> |
| 1208 | + /// Constructor |
| 1209 | + /// </summary> |
| 1210 | + /// <param name="syntaxOffset">Syntax offset</param> |
| 1211 | + /// <param name="state">State machine state</param> |
| 1212 | + public StateMachineStateInfo(int syntaxOffset, StateMachineState state) { |
| 1213 | + SyntaxOffset = syntaxOffset; |
| 1214 | + State = state; |
| 1215 | + } |
| 1216 | + } |
| 1217 | + |
| 1218 | + /// <summary> |
| 1219 | + /// State machine state |
| 1220 | + /// from Roslyn: StateMachineState.cs |
| 1221 | + /// </summary> |
| 1222 | + public enum StateMachineState { |
| 1223 | + /// <summary> |
| 1224 | + /// First state of an async iterator state machine that is used to resume the machine after yield return. |
| 1225 | + /// Initial state is not used to resume state machine that yielded. State numbers decrease as the iterator makes progress. |
| 1226 | + /// </summary> |
| 1227 | + FirstResumableAsyncIteratorState = InitialAsyncIteratorState - 1, |
| 1228 | + |
| 1229 | + /// <summary> |
| 1230 | + /// Initial iterator state of an async iterator. |
| 1231 | + /// Distinct from <see cref="NotStartedOrRunningState"/> so that DisposeAsync can throw in latter case. |
| 1232 | + /// </summary> |
| 1233 | + InitialAsyncIteratorState = -3, |
| 1234 | + |
| 1235 | + /// <summary> |
| 1236 | + /// First state of an iterator state machine. State numbers decrease for subsequent finalize states. |
| 1237 | + /// </summary> |
| 1238 | + FirstIteratorFinalizeState = -3, |
| 1239 | + |
| 1240 | + /// <summary> |
| 1241 | + /// The last state of a state machine. |
| 1242 | + /// </summary> |
| 1243 | + FinishedState = -2, |
| 1244 | + |
| 1245 | + /// <summary> |
| 1246 | + /// State machine not started or is running |
| 1247 | + /// </summary> |
| 1248 | + NotStartedOrRunningState = -1, |
| 1249 | + |
| 1250 | + /// <summary> |
| 1251 | + /// First unused state |
| 1252 | + /// </summary> |
| 1253 | + FirstUnusedState = 0, |
| 1254 | + |
| 1255 | + /// <summary> |
| 1256 | + /// First state in async state machine that is used to resume the machine after await. |
| 1257 | + /// State numbers increase as the async computation makes progress. |
| 1258 | + /// </summary> |
| 1259 | + FirstResumableAsyncState = 0, |
| 1260 | + |
| 1261 | + /// <summary> |
| 1262 | + /// Initial iterator state of an iterator. |
| 1263 | + /// </summary> |
| 1264 | + InitialIteratorState = 0, |
| 1265 | + |
| 1266 | + /// <summary> |
| 1267 | + /// First state in iterator state machine that is used to resume the machine after yield return. |
| 1268 | + /// Initial state is not used to resume state machine that yielded. State numbers increase as the iterator makes progress. |
| 1269 | + /// </summary> |
| 1270 | + FirstResumableIteratorState = InitialIteratorState + 1, |
| 1271 | + } |
1104 | 1272 | } |
0 commit comments