/// <summary> /// Returns symbols for the locals emitted in the original method, /// based on the local signatures from the IL and the names and /// slots from the PDB. The actual locals are needed to ensure the /// local slots in the generated method match the original. /// </summary> public static void GetLocals( ArrayBuilder <TLocalSymbol> builder, EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProvider, ImmutableArray <string> names, ImmutableArray <LocalInfo <TTypeSymbol> > localInfo, ImmutableDictionary <int, ImmutableArray <bool> > dynamicLocalMapOpt, ImmutableDictionary <int, ImmutableArray <string> > tupleLocalConstantMapOpt) { if (localInfo.Length == 0) { // When debugging a .dmp without a heap, localInfo will be empty although // names may be non-empty if there is a PDB. Since there's no type info, the // locals are dropped. Note this means the local signature of any generated // method will not match the original signature, so new locals will overlap // original locals. That is ok since there is no live process for the debugger // to update (any modified values exist in the debugger only). return; } Debug.Assert(localInfo.Length >= names.Length); for (int i = 0; i < localInfo.Length; i++) { string name = (i < names.Length) ? names[i] : null; var dynamicFlags = default(ImmutableArray <bool>); dynamicLocalMapOpt?.TryGetValue(i, out dynamicFlags); var tupleElementNames = default(ImmutableArray <string>); tupleLocalConstantMapOpt?.TryGetValue(i, out tupleElementNames); builder.Add(symbolProvider.GetLocalVariable(name, i, localInfo[i], dynamicFlags, tupleElementNames)); } }
private static bool TryCreateImportRecordFromCSharpImportString(EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProvider, string importString, out ImportRecord record) { ImportTargetKind targetKind; string externAlias; string alias; string targetString; if (CustomDebugInfoReader.TryParseCSharpImportString(importString, out alias, out externAlias, out targetString, out targetKind)) { ITypeSymbol type = null; if (targetKind == ImportTargetKind.Type) { type = symbolProvider.GetTypeSymbolForSerializedType(targetString); targetString = null; } record = new ImportRecord( targetKind: targetKind, alias: alias, targetType: type, targetString: targetString, targetAssembly: null, targetAssemblyAlias: externAlias); return(true); } record = default(ImportRecord); return(false); }
public static MethodDebugInfo <TTypeSymbol, TLocalSymbol> ReadFromPortable( MetadataReader reader, int methodToken, int ilOffset, EESymbolProvider <TTypeSymbol, TLocalSymbol>?symbolProvider, bool isVisualBasicMethod) { ImmutableDictionary <int, ImmutableArray <bool> >? dynamicLocalMap; ImmutableDictionary <int, ImmutableArray <string?> >?tupleLocalMap; ImmutableArray <ImmutableArray <ImportRecord> > importGroups; ImmutableArray <ExternAliasRecord> externAliases; ImmutableArray <string> localVariableNames; ImmutableArray <TLocalSymbol> localConstants; ILSpan reuseSpan; var methodHandle = GetDeltaRelativeMethodDefinitionHandle(reader, methodToken); // TODO: only null in DTEE case where we looking for default namesapace if (symbolProvider != null) { ReadLocalScopeInformation( reader, methodHandle, ilOffset, symbolProvider, isVisualBasicMethod, out importGroups, out externAliases, out localVariableNames, out dynamicLocalMap, out tupleLocalMap, out localConstants, out reuseSpan); } else { dynamicLocalMap = null; tupleLocalMap = null; importGroups = ImmutableArray <ImmutableArray <ImportRecord> > .Empty; externAliases = ImmutableArray <ExternAliasRecord> .Empty; localVariableNames = ImmutableArray <string> .Empty; localConstants = ImmutableArray <TLocalSymbol> .Empty; reuseSpan = ILSpan.MaxValue; } ReadMethodCustomDebugInformation(reader, methodHandle, out var hoistedLocalScopes, out var defaultNamespace); return(new MethodDebugInfo <TTypeSymbol, TLocalSymbol>( hoistedLocalScopes, importGroups, externAliases, dynamicLocalMap, tupleLocalMap, defaultNamespace, localVariableNames, localConstants, reuseSpan)); }
private static void GetConstants( ArrayBuilder <TLocalSymbol> builder, EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProvider, ArrayBuilder <ISymUnmanagedScope> scopes, ImmutableDictionary <string, ImmutableArray <bool> > dynamicLocalConstantMapOpt, ImmutableDictionary <LocalNameAndScope, ImmutableArray <string> > tupleLocalConstantMapOpt) { foreach (var scope in scopes) { foreach (var constant in scope.GetConstants()) { string name = constant.GetName(); object rawValue = constant.GetValue(); var signature = constant.GetSignature().ToImmutableArray(); TTypeSymbol type; try { type = symbolProvider.DecodeLocalVariableType(signature); } catch (Exception e) when(e is UnsupportedSignatureContent || e is BadImageFormatException) { // ignore continue; } if (type.Kind == SymbolKind.ErrorType) { continue; } ConstantValue constantValue = PdbHelpers.GetSymConstantValue(type, rawValue); // TODO (https://github.com/dotnet/roslyn/issues/1815): report error properly when the symbol is used if (constantValue.IsBad) { continue; } var dynamicFlags = default(ImmutableArray <bool>); if (dynamicLocalConstantMapOpt != null) { dynamicLocalConstantMapOpt.TryGetValue(name, out dynamicFlags); } var tupleElementNames = default(ImmutableArray <string>); if (tupleLocalConstantMapOpt != null) { int scopeStart = scope.GetStartOffset(); int scopeEnd = scope.GetEndOffset(); tupleLocalConstantMapOpt.TryGetValue(new LocalNameAndScope(name, scopeStart, scopeEnd), out tupleElementNames); } builder.Add(symbolProvider.GetLocalConstant(name, type, constantValue, dynamicFlags, tupleElementNames)); } } }
private static void PopulateImports( MetadataReader reader, ImportScopeHandle handle, EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProvider, bool isVisualBasicMethod, ArrayBuilder <ImmutableArray <ImportRecord> > importGroupsBuilder, ArrayBuilder <ExternAliasRecord> externAliasesBuilder ) { var importGroupBuilder = ArrayBuilder <ImportRecord> .GetInstance(); while (!handle.IsNil) { var importScope = reader.GetImportScope(handle); try { PopulateImports( reader, importScope, symbolProvider, importGroupBuilder, externAliasesBuilder ); } catch (BadImageFormatException) { // ignore invalid imports } // Portable PDBs represent project-level scope as the root of the chain of scopes. // This scope might contain aliases for assembly references, but is not considered // to be part of imports groups. if (isVisualBasicMethod || !importScope.Parent.IsNil) { importGroupsBuilder.Add(importGroupBuilder.ToImmutable()); importGroupBuilder.Clear(); } else { // C# currently doesn't support global imports in PDBs // https://github.com/dotnet/roslyn/issues/21862 Debug.Assert(importGroupBuilder.Count == 0); } handle = importScope.Parent; } importGroupBuilder.Free(); }
private static void PopulateImports( MetadataReader reader, ImportScopeHandle handle, EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProvider, bool isVisualBasicMethod, ArrayBuilder <ImmutableArray <ImportRecord> > importGroupsBuilder, ArrayBuilder <ExternAliasRecord> externAliasesBuilder) { var importGroupBuilder = ArrayBuilder <ImportRecord> .GetInstance(); while (!handle.IsNil) { var importScope = reader.GetImportScope(handle); try { PopulateImports(reader, importScope, symbolProvider, importGroupBuilder, externAliasesBuilder); } catch (BadImageFormatException) { // ignore invalid imports } // VB always expects two import groups (even if they are empty). // TODO: consider doing this for C# as well and handle empty groups in the binder. if (isVisualBasicMethod || importGroupBuilder.Count > 0) { importGroupsBuilder.Add(importGroupBuilder.ToImmutable()); importGroupBuilder.Clear(); } handle = importScope.Parent; } importGroupBuilder.Free(); }
/// <exception cref="BadImageFormatException">Invalid data format.</exception> private static void PopulateImports( MetadataReader reader, ImportScope importScope, EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProvider, ArrayBuilder <ImportRecord> importGroupBuilder, ArrayBuilder <ExternAliasRecord> externAliasesBuilder ) { foreach (ImportDefinition import in importScope.GetImports()) { switch (import.Kind) { case ImportDefinitionKind.ImportNamespace: importGroupBuilder.Add( new ImportRecord( ImportTargetKind.Namespace, targetString: ReadUtf8String(reader, import.TargetNamespace) ) ); break; case ImportDefinitionKind.ImportAssemblyNamespace: importGroupBuilder.Add( new ImportRecord( ImportTargetKind.Namespace, targetString: ReadUtf8String(reader, import.TargetNamespace), targetAssembly: symbolProvider.GetReferencedAssembly( import.TargetAssembly ) ) ); break; case ImportDefinitionKind.ImportType: importGroupBuilder.Add( new ImportRecord( ImportTargetKind.Type, targetType: symbolProvider.GetType(import.TargetType) ) ); break; case ImportDefinitionKind.ImportXmlNamespace: importGroupBuilder.Add( new ImportRecord( ImportTargetKind.XmlNamespace, alias: ReadUtf8String(reader, import.Alias), targetString: ReadUtf8String(reader, import.TargetNamespace) ) ); break; case ImportDefinitionKind.ImportAssemblyReferenceAlias: importGroupBuilder.Add( new ImportRecord( ImportTargetKind.Assembly, alias: ReadUtf8String(reader, import.Alias) ) ); break; case ImportDefinitionKind.AliasAssemblyReference: externAliasesBuilder.Add( new ExternAliasRecord( alias: ReadUtf8String(reader, import.Alias), targetAssembly: symbolProvider.GetReferencedAssembly( import.TargetAssembly ) ) ); break; case ImportDefinitionKind.AliasNamespace: importGroupBuilder.Add( new ImportRecord( ImportTargetKind.Namespace, alias: ReadUtf8String(reader, import.Alias), targetString: ReadUtf8String(reader, import.TargetNamespace) ) ); break; case ImportDefinitionKind.AliasAssemblyNamespace: importGroupBuilder.Add( new ImportRecord( ImportTargetKind.Namespace, alias: ReadUtf8String(reader, import.Alias), targetString: ReadUtf8String(reader, import.TargetNamespace), targetAssembly: symbolProvider.GetReferencedAssembly( import.TargetAssembly ) ) ); break; case ImportDefinitionKind.AliasType: importGroupBuilder.Add( new ImportRecord( ImportTargetKind.Type, alias: ReadUtf8String(reader, import.Alias), targetType: symbolProvider.GetType(import.TargetType) ) ); break; } } }
private static void ReadLocalScopeInformation( MetadataReader reader, MethodDefinitionHandle methodHandle, int ilOffset, EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProvider, bool isVisualBasicMethod, out ImmutableArray <ImmutableArray <ImportRecord> > importGroups, out ImmutableArray <ExternAliasRecord> externAliases, out ImmutableArray <string> localVariableNames, out ImmutableDictionary <int, ImmutableArray <bool> >?dynamicLocalMap, out ImmutableDictionary <int, ImmutableArray <string?> >?tupleLocalMap, out ImmutableArray <TLocalSymbol> localConstants, out ILSpan reuseSpan ) { var localVariableNamesBuilder = ArrayBuilder <string> .GetInstance(); var localConstantsBuilder = ArrayBuilder <TLocalSymbol> .GetInstance(); ImmutableDictionary <int, ImmutableArray <bool> > .Builder? lazyDynamicLocalsBuilder = null; ImmutableDictionary <int, ImmutableArray <string?> > .Builder?lazyTupleLocalsBuilder = null; var innerMostImportScope = default(ImportScopeHandle); uint reuseSpanStart = 0; uint reuseSpanEnd = uint.MaxValue; try { foreach (var scopeHandle in reader.GetLocalScopes(methodHandle)) { try { var scope = reader.GetLocalScope(scopeHandle); if (ilOffset < scope.StartOffset) { // scopes are sorted by StartOffset, hence all scopes that follow can't contain ilOffset reuseSpanEnd = Math.Min(reuseSpanEnd, (uint)scope.StartOffset); break; } if (ilOffset >= scope.EndOffset) { // ilOffset is not in this scope, go to next one reuseSpanStart = Math.Max(reuseSpanStart, (uint)scope.EndOffset); continue; } // reuse span is a subspan of the inner-most scope containing the IL offset: reuseSpanStart = Math.Max(reuseSpanStart, (uint)scope.StartOffset); reuseSpanEnd = Math.Min(reuseSpanEnd, (uint)scope.EndOffset); // imports (use the inner-most): innerMostImportScope = scope.ImportScope; // locals (from all contained scopes): foreach (var variableHandle in scope.GetLocalVariables()) { var variable = reader.GetLocalVariable(variableHandle); if ((variable.Attributes & LocalVariableAttributes.DebuggerHidden) != 0) { continue; } localVariableNamesBuilder.SetItem( variable.Index, reader.GetString(variable.Name) ); var dynamicFlags = ReadDynamicCustomDebugInformation( reader, variableHandle ); if (!dynamicFlags.IsDefault) { lazyDynamicLocalsBuilder ??= ImmutableDictionary.CreateBuilder < int, ImmutableArray <bool> >(); lazyDynamicLocalsBuilder[variable.Index] = dynamicFlags; } var tupleElementNames = ReadTupleCustomDebugInformation( reader, variableHandle ); if (!tupleElementNames.IsDefault) { lazyTupleLocalsBuilder ??= ImmutableDictionary.CreateBuilder < int, ImmutableArray <string?> >(); lazyTupleLocalsBuilder[variable.Index] = tupleElementNames; } } // constants (from all contained scopes): foreach (var constantHandle in scope.GetLocalConstants()) { var constant = reader.GetLocalConstant(constantHandle); var sigReader = reader.GetBlobReader(constant.Signature); symbolProvider.DecodeLocalConstant( ref sigReader, out var typeSymbol, out var value ); var name = reader.GetString(constant.Name); var dynamicFlags = ReadDynamicCustomDebugInformation( reader, constantHandle ); var tupleElementNames = ReadTupleCustomDebugInformation( reader, constantHandle ); localConstantsBuilder.Add( symbolProvider.GetLocalConstant( name, typeSymbol, value, dynamicFlags, tupleElementNames ) ); } } catch (Exception e) when(e is UnsupportedSignatureContent || e is BadImageFormatException) { // ignore scopes with invalid data } } } finally { localVariableNames = localVariableNamesBuilder.ToImmutableAndFree(); localConstants = localConstantsBuilder.ToImmutableAndFree(); dynamicLocalMap = lazyDynamicLocalsBuilder?.ToImmutable(); tupleLocalMap = lazyTupleLocalsBuilder?.ToImmutable(); reuseSpan = new ILSpan(reuseSpanStart, reuseSpanEnd); } var importGroupsBuilder = ArrayBuilder <ImmutableArray <ImportRecord> > .GetInstance(); var externAliasesBuilder = ArrayBuilder <ExternAliasRecord> .GetInstance(); if (!innerMostImportScope.IsNil) { PopulateImports( reader, innerMostImportScope, symbolProvider, isVisualBasicMethod, importGroupsBuilder, externAliasesBuilder ); } importGroups = importGroupsBuilder.ToImmutableAndFree(); externAliases = externAliasesBuilder.ToImmutableAndFree(); }
public unsafe static MethodDebugInfo <TTypeSymbol, TLocalSymbol> ReadMethodDebugInfo( ISymUnmanagedReader3 symReader, EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProviderOpt, // TODO: only null in DTEE case where we looking for default namesapace int methodToken, int methodVersion, int ilOffset, bool isVisualBasicMethod) { // no symbols if (symReader == null) { return(None); } if (symReader is ISymUnmanagedReader5 symReader5) { int hr = symReader5.GetPortableDebugMetadataByVersion(methodVersion, out byte *metadata, out int size); ThrowExceptionForHR(hr); if (hr == S_OK) { var mdReader = new MetadataReader(metadata, size); try { return(ReadFromPortable(mdReader, methodToken, ilOffset, symbolProviderOpt, isVisualBasicMethod)); } catch (BadImageFormatException) { // bad CDI, ignore return(None); } } } var allScopes = ArrayBuilder <ISymUnmanagedScope> .GetInstance(); var containingScopes = ArrayBuilder <ISymUnmanagedScope> .GetInstance(); try { var symMethod = symReader.GetMethodByVersion(methodToken, methodVersion); if (symMethod != null) { symMethod.GetAllScopes(allScopes, containingScopes, ilOffset, isScopeEndInclusive: isVisualBasicMethod); } ImmutableArray <ImmutableArray <ImportRecord> > importRecordGroups; ImmutableArray <ExternAliasRecord> externAliasRecords; string defaultNamespaceName; if (isVisualBasicMethod) { ReadVisualBasicImportsDebugInfo( symReader, methodToken, methodVersion, out importRecordGroups, out defaultNamespaceName); externAliasRecords = ImmutableArray <ExternAliasRecord> .Empty; } else { Debug.Assert(symbolProviderOpt != null); ReadCSharpNativeImportsInfo( symReader, symbolProviderOpt, methodToken, methodVersion, out importRecordGroups, out externAliasRecords); defaultNamespaceName = ""; } // VB should read hoisted scope information from local variables: var hoistedLocalScopeRecords = isVisualBasicMethod ? default(ImmutableArray <HoistedLocalScopeRecord>) : ImmutableArray <HoistedLocalScopeRecord> .Empty; ImmutableDictionary <int, ImmutableArray <bool> > dynamicLocalMap = null; ImmutableDictionary <string, ImmutableArray <bool> > dynamicLocalConstantMap = null; ImmutableDictionary <int, ImmutableArray <string> > tupleLocalMap = null; ImmutableDictionary <LocalNameAndScope, ImmutableArray <string> > tupleLocalConstantMap = null; byte[] customDebugInfo = GetCustomDebugInfoBytes(symReader, methodToken, methodVersion); if (customDebugInfo != null) { if (!isVisualBasicMethod) { var customDebugInfoRecord = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(customDebugInfo, CustomDebugInfoKind.StateMachineHoistedLocalScopes); if (!customDebugInfoRecord.IsDefault) { hoistedLocalScopeRecords = CustomDebugInfoReader.DecodeStateMachineHoistedLocalScopesRecord(customDebugInfoRecord) .SelectAsArray(s => new HoistedLocalScopeRecord(s.StartOffset, s.Length)); } GetCSharpDynamicLocalInfo( customDebugInfo, allScopes, out dynamicLocalMap, out dynamicLocalConstantMap); } GetTupleElementNamesLocalInfo( customDebugInfo, out tupleLocalMap, out tupleLocalConstantMap); } var constantsBuilder = ArrayBuilder <TLocalSymbol> .GetInstance(); if (symbolProviderOpt != null) // TODO { GetConstants(constantsBuilder, symbolProviderOpt, containingScopes, dynamicLocalConstantMap, tupleLocalConstantMap); } var reuseSpan = GetReuseSpan(allScopes, ilOffset, isVisualBasicMethod); return(new MethodDebugInfo <TTypeSymbol, TLocalSymbol>( hoistedLocalScopeRecords, importRecordGroups, externAliasRecords, dynamicLocalMap, tupleLocalMap, defaultNamespaceName, containingScopes.GetLocalNames(), constantsBuilder.ToImmutableAndFree(), reuseSpan)); } catch (InvalidOperationException) { // bad CDI, ignore return(None); } finally { allScopes.Free(); containingScopes.Free(); } }
private static void ReadCSharpNativeImportsInfo( ISymUnmanagedReader3 reader, EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProvider, int methodToken, int methodVersion, out ImmutableArray <ImmutableArray <ImportRecord> > importRecordGroups, out ImmutableArray <ExternAliasRecord> externAliasRecords) { ImmutableArray <string> externAliasStrings; var importStringGroups = CustomDebugInfoReader.GetCSharpGroupedImportStrings( methodToken, KeyValuePair.Create(reader, methodVersion), getMethodCustomDebugInfo: (token, arg) => GetCustomDebugInfoBytes(arg.Key, token, arg.Value), getMethodImportStrings: (token, arg) => GetImportStrings(arg.Key, token, arg.Value), externAliasStrings: out externAliasStrings); Debug.Assert(importStringGroups.IsDefault == externAliasStrings.IsDefault); ArrayBuilder <ImmutableArray <ImportRecord> > importRecordGroupBuilder = null; ArrayBuilder <ExternAliasRecord> externAliasRecordBuilder = null; if (!importStringGroups.IsDefault) { importRecordGroupBuilder = ArrayBuilder <ImmutableArray <ImportRecord> > .GetInstance(importStringGroups.Length); foreach (var importStringGroup in importStringGroups) { var groupBuilder = ArrayBuilder <ImportRecord> .GetInstance(importStringGroup.Length); foreach (var importString in importStringGroup) { ImportRecord record; if (TryCreateImportRecordFromCSharpImportString(symbolProvider, importString, out record)) { groupBuilder.Add(record); } else { Debug.WriteLine($"Failed to parse import string {importString}"); } } importRecordGroupBuilder.Add(groupBuilder.ToImmutableAndFree()); } if (!externAliasStrings.IsDefault) { externAliasRecordBuilder = ArrayBuilder <ExternAliasRecord> .GetInstance(externAliasStrings.Length); foreach (string externAliasString in externAliasStrings) { string alias; string externAlias; string target; ImportTargetKind kind; if (!CustomDebugInfoReader.TryParseCSharpImportString(externAliasString, out alias, out externAlias, out target, out kind)) { Debug.WriteLine($"Unable to parse extern alias '{externAliasString}'"); continue; } Debug.Assert(kind == ImportTargetKind.Assembly, "Programmer error: How did a non-assembly get in the extern alias list?"); Debug.Assert(alias != null); // Name of the extern alias. Debug.Assert(externAlias == null); // Not used. Debug.Assert(target != null); // Name of the target assembly. AssemblyIdentity targetIdentity; if (!AssemblyIdentity.TryParseDisplayName(target, out targetIdentity)) { Debug.WriteLine($"Unable to parse target of extern alias '{externAliasString}'"); continue; } externAliasRecordBuilder.Add(new ExternAliasRecord(alias, targetIdentity)); } } } importRecordGroups = importRecordGroupBuilder?.ToImmutableAndFree() ?? ImmutableArray <ImmutableArray <ImportRecord> > .Empty; externAliasRecords = externAliasRecordBuilder?.ToImmutableAndFree() ?? ImmutableArray <ExternAliasRecord> .Empty; }
public unsafe static MethodDebugInfo <TTypeSymbol, TLocalSymbol> ReadMethodDebugInfo( ISymUnmanagedReader symReader, EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProviderOpt, // TODO: only null in DTEE case where we looking for default namesapace int methodToken, int methodVersion, int ilOffset, bool isVisualBasicMethod) { // no symbols if (symReader == null) { return(None); } var symReader4 = symReader as ISymUnmanagedReader4; if (symReader4 != null) // TODO: VB Portable PDBs { byte *metadata; int size; // TODO: version int hr = symReader4.GetPortableDebugMetadata(out metadata, out size); SymUnmanagedReaderExtensions.ThrowExceptionForHR(hr); if (metadata != null) { var mdReader = new MetadataReader(metadata, size); try { return(ReadFromPortable(mdReader, methodToken, ilOffset, symbolProviderOpt, isVisualBasicMethod)); } catch (BadImageFormatException) { // bad CDI, ignore return(None); } } } var allScopes = ArrayBuilder <ISymUnmanagedScope> .GetInstance(); var containingScopes = ArrayBuilder <ISymUnmanagedScope> .GetInstance(); try { ImmutableArray <HoistedLocalScopeRecord> hoistedLocalScopeRecords; ImmutableArray <ImmutableArray <ImportRecord> > importRecordGroups; ImmutableArray <ExternAliasRecord> externAliasRecords; ImmutableDictionary <int, ImmutableArray <bool> > dynamicLocalMap; ImmutableDictionary <string, ImmutableArray <bool> > dynamicLocalConstantMap; string defaultNamespaceName; var symMethod = symReader.GetMethodByVersion(methodToken, methodVersion); if (symMethod != null) { symMethod.GetAllScopes(allScopes, containingScopes, ilOffset, isScopeEndInclusive: isVisualBasicMethod); } if (isVisualBasicMethod) { ReadVisualBasicImportsDebugInfo( symReader, methodToken, methodVersion, out importRecordGroups, out defaultNamespaceName); hoistedLocalScopeRecords = ImmutableArray <HoistedLocalScopeRecord> .Empty; externAliasRecords = ImmutableArray <ExternAliasRecord> .Empty; dynamicLocalMap = null; dynamicLocalConstantMap = null; } else { Debug.Assert(symbolProviderOpt != null); ReadCSharpNativeImportsInfo( symReader, symbolProviderOpt, methodToken, methodVersion, out importRecordGroups, out externAliasRecords); ReadCSharpNativeCustomDebugInfo( symReader, methodToken, methodVersion, allScopes, out hoistedLocalScopeRecords, out dynamicLocalMap, out dynamicLocalConstantMap); defaultNamespaceName = ""; } var constantsBuilder = ArrayBuilder <TLocalSymbol> .GetInstance(); if (symbolProviderOpt != null) // TODO { GetConstants(constantsBuilder, symbolProviderOpt, containingScopes, dynamicLocalConstantMap); } var reuseSpan = GetReuseSpan(allScopes, ilOffset, isVisualBasicMethod); return(new MethodDebugInfo <TTypeSymbol, TLocalSymbol>( hoistedLocalScopeRecords, importRecordGroups, externAliasRecords, dynamicLocalMap, defaultNamespaceName, containingScopes.GetLocalNames(), constantsBuilder.ToImmutableAndFree(), reuseSpan)); } catch (InvalidOperationException) { // bad CDI, ignore return(None); } finally { allScopes.Free(); containingScopes.Free(); } }
/// <exception cref="BadImageFormatException">Invalid data format.</exception> public static MethodDebugInfo <TTypeSymbol, TLocalSymbol> ReadFromPortable(MetadataReader reader, int methodToken, int ilOffset, EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProvider, bool isVisualBasicMethod) { string defaultNamespace; ImmutableArray <HoistedLocalScopeRecord> hoistedLocalScopes; ImmutableDictionary <int, ImmutableArray <bool> > dynamicLocalMap; ImmutableDictionary <int, ImmutableArray <string> > tupleLocalMap; ImmutableArray <ImmutableArray <ImportRecord> > importGroups; ImmutableArray <ExternAliasRecord> externAliases; ImmutableArray <string> localVariableNames; ImmutableArray <TLocalSymbol> localConstants; ILSpan reuseSpan; var methodHandle = (MethodDefinitionHandle)MetadataTokens.EntityHandle(methodToken); ReadLocalScopeInformation( reader, methodHandle, ilOffset, symbolProvider, isVisualBasicMethod, out importGroups, out externAliases, out localVariableNames, out dynamicLocalMap, out tupleLocalMap, out localConstants, out reuseSpan); ReadMethodCustomDebugInformation(reader, methodHandle, out hoistedLocalScopes, out defaultNamespace); return(new MethodDebugInfo <TTypeSymbol, TLocalSymbol>( hoistedLocalScopes, importGroups, externAliases, dynamicLocalMap, tupleLocalMap, defaultNamespace, localVariableNames, localConstants, reuseSpan)); }
/// <exception cref="BadImageFormatException">Invalid data format.</exception> private static void PopulateImports( MetadataReader reader, ImportScopeHandle handle, EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProvider, bool isVisualBasicMethod, ArrayBuilder <ImmutableArray <ImportRecord> > importGroupsBuilder, ArrayBuilder <ExternAliasRecord> externAliasesBuilder) { var importGroupBuilder = ArrayBuilder <ImportRecord> .GetInstance(); while (!handle.IsNil) { var importScope = reader.GetImportScope(handle); foreach (ImportDefinition import in importScope.GetImports()) { switch (import.Kind) { case ImportDefinitionKind.ImportNamespace: importGroupBuilder.Add(new ImportRecord( ImportTargetKind.Namespace, targetString: ReadUtf8String(reader, import.TargetNamespace))); break; case ImportDefinitionKind.ImportAssemblyNamespace: importGroupBuilder.Add(new ImportRecord( ImportTargetKind.Namespace, targetString: ReadUtf8String(reader, import.TargetNamespace), targetAssembly: symbolProvider.GetReferencedAssembly(import.TargetAssembly))); break; case ImportDefinitionKind.ImportType: importGroupBuilder.Add(new ImportRecord( ImportTargetKind.Type, targetType: symbolProvider.GetType(import.TargetType))); break; case ImportDefinitionKind.ImportXmlNamespace: importGroupBuilder.Add(new ImportRecord( ImportTargetKind.XmlNamespace, alias: ReadUtf8String(reader, import.Alias), targetString: ReadUtf8String(reader, import.TargetNamespace))); break; case ImportDefinitionKind.ImportAssemblyReferenceAlias: importGroupBuilder.Add(new ImportRecord( ImportTargetKind.Assembly, alias: ReadUtf8String(reader, import.Alias))); break; case ImportDefinitionKind.AliasAssemblyReference: externAliasesBuilder.Add(new ExternAliasRecord( alias: ReadUtf8String(reader, import.Alias), targetAssembly: symbolProvider.GetReferencedAssembly(import.TargetAssembly))); break; case ImportDefinitionKind.AliasNamespace: importGroupBuilder.Add(new ImportRecord( ImportTargetKind.Namespace, alias: ReadUtf8String(reader, import.Alias), targetString: ReadUtf8String(reader, import.TargetNamespace))); break; case ImportDefinitionKind.AliasAssemblyNamespace: importGroupBuilder.Add(new ImportRecord( ImportTargetKind.Namespace, alias: ReadUtf8String(reader, import.Alias), targetString: ReadUtf8String(reader, import.TargetNamespace), targetAssembly: symbolProvider.GetReferencedAssembly(import.TargetAssembly))); break; case ImportDefinitionKind.AliasType: importGroupBuilder.Add(new ImportRecord( ImportTargetKind.Type, alias: ReadUtf8String(reader, import.Alias), targetType: symbolProvider.GetType(import.TargetType))); break; } } // VB always expects two import groups (even if they are empty). // TODO: consider doing this for C# as well and handle empty groups in the binder. if (isVisualBasicMethod || importGroupBuilder.Count > 0) { importGroupsBuilder.Add(importGroupBuilder.ToImmutable()); importGroupBuilder.Clear(); } handle = importScope.Parent; } importGroupBuilder.Free(); }