protected override PdbCustomDebugInfo CloneOther(PdbCustomDebugInfo source) { switch (source) { case PdbAsyncMethodCustomDebugInfo i: var n = new PdbAsyncMethodCustomDebugInfo(i.StepInfos.Count) { CatchHandlerInstruction = GetInstruction(i.CatchHandlerInstruction), KickoffMethod = Importer.Import(i.KickoffMethod).ResolveMethodDefThrow() }; for (var j = 0; j < i.StepInfos.Count; j++) { n.StepInfos.Add(new PdbAsyncStepInfo( GetInstruction(i.StepInfos[j].YieldInstruction), Importer.Import(i.StepInfos[j].BreakpointMethod).ResolveMethodDefThrow(), GetInstruction(i.StepInfos[j].BreakpointInstruction) )); } return(n); case PdbStateMachineHoistedLocalScopesCustomDebugInfo i: var nls = new PdbStateMachineHoistedLocalScopesCustomDebugInfo(i.Scopes.Count); foreach (var si in nls.Scopes) { nls.Scopes.Add(new StateMachineHoistedLocalScope( GetInstruction(si.Start), GetInstruction(si.End))); } return(nls); case PdbIteratorMethodCustomDebugInfo i: var im = new PdbIteratorMethodCustomDebugInfo { KickoffMethod = Importer.Import(i.KickoffMethod).ResolveMethodDefThrow() }; return(im); case PdbDynamicLocalsCustomDebugInfo i: var ndl = new PdbDynamicLocalsCustomDebugInfo(i.Locals.Count); foreach (var si in ndl.Locals) { ndl.Locals.Add(Clone(si)); } return(ndl); case PdbEditAndContinueLocalSlotMapCustomDebugInfo i2: case PdbEditAndContinueLambdaMapCustomDebugInfo i3: return(source); } return(null); }
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)); } }