/// <summary> /// Constructor /// </summary> /// <param name="kind">Custom debug info kind</param> /// <param name="data">Raw custom debug info data</param> public PdbUnknownCustomDebugInfo(PdbCustomDebugInfoKind kind, byte[] data) { if (data == null) { throw new ArgumentNullException("data"); } this.kind = kind; this.data = data; }
/// <summary> /// Constructor /// </summary> /// <param name="guid">Custom debug info guid</param> /// <param name="data">Raw custom debug info data</param> public PdbUnknownCustomDebugInfo(Guid guid, byte[] data) { if (data == null) { throw new ArgumentNullException("data"); } this.kind = PdbCustomDebugInfoKind.Unknown; this.data = data; this.guid = guid; }
PdbCustomDebugInfo ReadRecord(PdbCustomDebugInfoKind recKind, ulong recPosEnd) { IMethodDefOrRef method; byte[] data; Local local; int count; int localIndex; switch (recKind) { case PdbCustomDebugInfoKind.UsingGroups: count = reader.ReadUInt16(); if (count < 0) { return(null); } var usingCountRec = new PdbUsingGroupsCustomDebugInfo(count); for (int i = 0; i < count; i++) { usingCountRec.UsingCounts.Add(reader.ReadUInt16()); } return(usingCountRec); case PdbCustomDebugInfoKind.ForwardMethodInfo: method = module.ResolveToken(reader.ReadUInt32(), gpContext) as IMethodDefOrRef; if (method == null) { return(null); } return(new PdbForwardMethodInfoCustomDebugInfo(method)); case PdbCustomDebugInfoKind.ForwardModuleInfo: method = module.ResolveToken(reader.ReadUInt32(), gpContext) as IMethodDefOrRef; if (method == null) { return(null); } return(new PdbForwardModuleInfoCustomDebugInfo(method)); case PdbCustomDebugInfoKind.StateMachineHoistedLocalScopes: if (bodyOpt == null) { return(null); } count = reader.ReadInt32(); if (count < 0) { return(null); } var smScope = new PdbStateMachineHoistedLocalScopesCustomDebugInfo(count); for (int i = 0; i < count; i++) { uint startOffset = reader.ReadUInt32(); uint endOffset = reader.ReadUInt32(); if (startOffset > endOffset) { return(null); } // Try to detect synthesized locals, whose start==end==0. The problem is that endOffset // read from the PDB is inclusive (add 1 to get 'end'), so a synthesized local and a // local at [0, 1) will be encoded the same {0, 0}. if (endOffset == 0) { smScope.Scopes.Add(new StateMachineHoistedLocalScope()); } else { var start = GetInstruction(startOffset); var end = GetInstruction(endOffset + 1); if (start == null) { return(null); } smScope.Scopes.Add(new StateMachineHoistedLocalScope(start, end)); } } return(smScope); case PdbCustomDebugInfoKind.StateMachineTypeName: var name = ReadUnicodeZ(recPosEnd, needZeroChar: true); if (name == null) { return(null); } var type = GetNestedType(name); if (type == null) { return(null); } return(new PdbStateMachineTypeNameCustomDebugInfo(type)); case PdbCustomDebugInfoKind.DynamicLocals: if (bodyOpt == null) { return(null); } count = reader.ReadInt32(); const int dynLocalRecSize = 64 + 4 + 4 + 2 * 64; if (reader.Position + (ulong)(uint)count * dynLocalRecSize > recPosEnd) { return(null); } var dynLocListRec = new PdbDynamicLocalsCustomDebugInfo(count); for (int i = 0; i < count; i++) { reader.Position += 64; int flagsCount = reader.ReadInt32(); if ((uint)flagsCount > 64) { return(null); } var dynLocRec = new PdbDynamicLocal(flagsCount); var afterPos = reader.Position; reader.Position -= 64 + 4; for (int j = 0; j < flagsCount; j++) { dynLocRec.Flags.Add(reader.ReadByte()); } reader.Position = afterPos; localIndex = reader.ReadInt32(); // 'const' locals have index -1 but they're encoded as 0 by Roslyn if (localIndex != 0 && (uint)localIndex >= (uint)bodyOpt.Variables.Count) { return(null); } var nameEndPos = reader.Position + 2 * 64; name = ReadUnicodeZ(nameEndPos, needZeroChar: false); reader.Position = nameEndPos; local = localIndex < bodyOpt.Variables.Count ? bodyOpt.Variables[localIndex] : null; // Roslyn writes 0 to localIndex if it's a 'const' local, try to undo that now if (localIndex == 0 && local != null && local.Name != name) { local = null; } if (local != null && local.Name == name) { name = null; } dynLocRec.Name = name; dynLocRec.Local = local; dynLocListRec.Locals.Add(dynLocRec); } return(dynLocListRec); case PdbCustomDebugInfoKind.EditAndContinueLocalSlotMap: data = reader.ReadBytes((int)(recPosEnd - reader.Position)); return(new PdbEditAndContinueLocalSlotMapCustomDebugInfo(data)); case PdbCustomDebugInfoKind.EditAndContinueLambdaMap: data = reader.ReadBytes((int)(recPosEnd - reader.Position)); return(new PdbEditAndContinueLambdaMapCustomDebugInfo(data)); case PdbCustomDebugInfoKind.TupleElementNames: if (bodyOpt == null) { return(null); } count = reader.ReadInt32(); if (count < 0) { return(null); } var tupleListRec = new PdbTupleElementNamesCustomDebugInfo(count); for (int i = 0; i < count; i++) { int nameCount = reader.ReadInt32(); if ((uint)nameCount >= 10000) { return(null); } var tupleInfo = new PdbTupleElementNames(nameCount); for (int j = 0; j < nameCount; j++) { var s = ReadUTF8Z(recPosEnd); if (s == null) { return(null); } tupleInfo.TupleElementNames.Add(s); } localIndex = reader.ReadInt32(); uint scopeStart = reader.ReadUInt32(); uint scopeEnd = reader.ReadUInt32(); name = ReadUTF8Z(recPosEnd); if (name == null) { return(null); } Debug.Assert(localIndex >= -1); // -1 = 'const' local. Only 'const' locals have a scope Debug.Assert((localIndex == -1) ^ (scopeStart == 0 && scopeEnd == 0)); if (localIndex == -1) { local = null; tupleInfo.ScopeStart = GetInstruction(scopeStart); tupleInfo.ScopeEnd = GetInstruction(scopeEnd); if (tupleInfo.ScopeStart == null) { return(null); } } else { if ((uint)localIndex >= (uint)bodyOpt.Variables.Count) { return(null); } local = bodyOpt.Variables[localIndex]; } if (local != null && local.Name == name) { name = null; } tupleInfo.Local = local; tupleInfo.Name = name; tupleListRec.Names.Add(tupleInfo); } return(tupleListRec); default: Debug.Fail("Unknown custom debug info kind: 0x" + ((int)recKind).ToString("X")); data = reader.ReadBytes((int)(recPosEnd - reader.Position)); return(new PdbUnknownCustomDebugInfo(recKind, data)); } }
/// <summary> /// Constructor /// </summary> /// <param name="guid">Custom debug info guid</param> /// <param name="data">Raw custom debug info data</param> public PdbUnknownCustomDebugInfo(Guid guid, byte[] data) { kind = PdbCustomDebugInfoKind.Unknown; this.data = data ?? throw new ArgumentNullException(nameof(data)); this.guid = guid; }
/// <summary> /// Constructor /// </summary> /// <param name="kind">Custom debug info kind</param> /// <param name="data">Raw custom debug info data</param> public PdbUnknownCustomDebugInfo(PdbCustomDebugInfoKind kind, byte[] data) { this.kind = kind; this.data = data ?? throw new ArgumentNullException(nameof(data)); guid = Guid.Empty; }