void ConvertScope(PdbScope scope) { ConvertSlots (scope.slots); foreach (var s in scope.scopes) ConvertScope (s); }
void Write(MethodDef method, List <PdbCustomDebugInfo> cdiBuilder) { uint rid = metadata.GetRid(method); if (rid == 0) { Error("Method {0} ({1:X8}) is not defined in this module ({2})", method, method.MDToken.Raw, module); return; } var info = new CurrentMethod(this, method, instrToOffset); var body = method.Body; var symbolToken = new MDToken(MD.Table.Method, rid); writer.OpenMethod(symbolToken); seqPointsHelper.Write(this, info.Method.Body.Instructions); var pdbMethod = body.PdbMethod; if (pdbMethod == null) { body.PdbMethod = pdbMethod = new PdbMethod(); } var scope = pdbMethod.Scope; if (scope == null) { pdbMethod.Scope = scope = new PdbScope(); } if (scope.Namespaces.Count == 0 && scope.Variables.Count == 0 && scope.Constants.Count == 0) { if (scope.Scopes.Count == 0) { // We must open at least one sub scope (the sym writer creates the 'method' scope // which covers the whole method) or the native PDB reader will fail to read all // sequence points. writer.OpenScope(0); writer.CloseScope((int)info.BodySize); } else { var scopes = scope.Scopes; int count = scopes.Count; for (int i = 0; i < count; i++) { WriteScope(ref info, scopes[i], 0); } } } else { // C++/.NET (some methods) WriteScope(ref info, scope, 0); } GetPseudoCustomDebugInfos(method.CustomDebugInfos, cdiBuilder, out var asyncMethod); if (cdiBuilder.Count != 0) { customDebugInfoWriterContext.Logger = GetLogger(); var cdiData = PdbCustomDebugInfoWriter.Write(metadata, method, customDebugInfoWriterContext, cdiBuilder); if (cdiData != null) { writer.SetSymAttribute(symbolToken, "MD2", cdiData); } } if (asyncMethod != null) { if (!writer.SupportsAsyncMethods) { Error("PDB symbol writer doesn't support writing async methods"); } else { WriteAsyncMethod(ref info, asyncMethod); } } writer.CloseMethod(); }
/// <summary> /// Allocates a range of CLR IL operations that comprise a lexical scope, specified as an IL offset and a length. /// </summary> internal PdbLocalScope(IMethodBody methodBody, PdbScope pdbScope) { this.methodBody = methodBody; this.pdbScope = pdbScope; }
private void Add(PdbScope scope) { AddToStack(scope); }
static ImportDebugInformation GetImport(PdbScope scope, ModuleDefinition module) { if (scope.usedNamespaces.IsNullOrEmpty()) { return(null); } var import = new ImportDebugInformation(); foreach (var used_namespace in scope.usedNamespaces) { if (string.IsNullOrEmpty(used_namespace)) { continue; } ImportTarget target = null; var value = used_namespace.Substring(1); switch (used_namespace [0]) { case 'U': target = new ImportTarget(ImportTargetKind.ImportNamespace) { @namespace = value }; break; case 'T': { var type = module.GetType(value, runtimeName: true); if (type != null) { target = new ImportTarget(ImportTargetKind.ImportType) { type = type } } ; break; } case 'A': var index = used_namespace.IndexOf(' '); if (index < 0) { target = new ImportTarget(ImportTargetKind.ImportNamespace) { @namespace = used_namespace }; break; } var alias_value = used_namespace.Substring(1, index - 1); var alias_target_value = used_namespace.Substring(index + 2); switch (used_namespace [index + 1]) { case 'U': target = new ImportTarget(ImportTargetKind.DefineNamespaceAlias) { alias = alias_value, @namespace = alias_target_value }; break; case 'T': var type = module.GetType(alias_target_value, runtimeName: true); if (type != null) { target = new ImportTarget(ImportTargetKind.DefineTypeAlias) { alias = alias_value, type = type } } ; break; } break; case '*': target = new ImportTarget(ImportTargetKind.ImportNamespace) { @namespace = value }; break; case '@': if (!value.StartsWith("P:")) { continue; } target = new ImportTarget(ImportTargetKind.ImportNamespace) { @namespace = value.Substring(2) }; break; } if (target != null) { import.Targets.Add(target); } } return(import); } void ReadSequencePoints(PdbFunction function, MethodDebugInformation info) { if (function.lines == null) { return; } info.sequence_points = new Collection <SequencePoint> (); foreach (PdbLines lines in function.lines) { ReadLines(lines, info); } } void ReadLines(PdbLines lines, MethodDebugInformation info) { var document = GetDocument(lines.file); foreach (var line in lines.lines) { ReadLine(line, document, info); } }
ScopeDebugInformation ReadScopeAndLocals(PdbScope scope, MethodDebugInformation info) { var parent = new ScopeDebugInformation(); parent.Start = new InstructionOffset((int)scope.offset); parent.End = new InstructionOffset((int)(scope.offset + scope.length)); if (!scope.slots.IsNullOrEmpty()) { parent.variables = new Collection <VariableDebugInformation> (scope.slots.Length); foreach (PdbSlot slot in scope.slots) { if (slot.flags == 1) // parameter names { continue; } var index = (int)slot.slot; var variable = new VariableDebugInformation(index, slot.name); if (slot.flags == 4) { variable.IsDebuggerHidden = true; } parent.variables.Add(variable); } } if (!scope.constants.IsNullOrEmpty()) { parent.constants = new Collection <ConstantDebugInformation> (scope.constants.Length); foreach (var constant in scope.constants) { var type = info.Method.Module.Read(constant, (c, r) => r.ReadConstantSignature(new MetadataToken(c.token))); var value = constant.value; // Object "null" is encoded as integer if (type != null && !type.IsValueType && value is int && (int)value == 0) { value = null; } parent.constants.Add(new ConstantDebugInformation(constant.name, type, value)); } } if (!scope.usedNamespaces.IsNullOrEmpty()) { ImportDebugInformation import; if (imports.TryGetValue(scope, out import)) { parent.import = import; } else { import = GetImport(scope, info.Method.Module); imports.Add(scope, import); parent.import = import; } } parent.scopes = ReadScopeAndLocals(scope.scopes, info); return(parent); }
internal Scope(PdbScope scope) : this() { this.Offset = (int)scope.offset; this.Length = (int)scope.length; this.ReadScope(scope.slots, scope.constants, scope.scopes); }