public void Close() { var localScope = new LocalScopeTable(); var localVariable = new LocalVariableTable(); var importScope = new ImportScopeTable(); CreateLocalScopeAndLocalVariables(localScope, localVariable, importScope); Strings.Freeze(); UserStrings.Freeze(); Guids.Freeze(); Blobs.Freeze(); using (var fs = System.IO.File.Create(fileName)) { var tablesForRowCountOnly = moduleBuilder.GetTables(); var tables = new Table[64]; tables[DocumentTable.Index] = Document; tables[MethodDebugInformationTable.Index] = CreateMethodDebugInformation(); tables[LocalScopeTable.Index] = localScope; tables[LocalVariableTable.Index] = localVariable; tables[ImportScopeTable.Index] = importScope; for (var i = 0; i < tables.Length; i++) { if (tables[i] != null) { tablesForRowCountOnly[i] = tables[i]; } } var mw = new PortablePdbMetadataWriter(fs, tables, tablesForRowCountOnly, Strings.IsBig, Guids.IsBig, Blobs.IsBig); Tables.Freeze(mw); var pdb = new PdbHeap(guid, timestamp, moduleBuilder.GetTables(), GetEntryPointToken()); mw.WriteMetadata("PDB v1.0", pdb, Tables, Strings, UserStrings, Guids, Blobs); if (IsDeterministic) { byte[] hash; using (var sha1 = System.Security.Cryptography.SHA1.Create()) { fs.Seek(0, System.IO.SeekOrigin.Begin); hash = sha1.ComputeHash(fs); } timestamp = (uint)BitConverter.ToInt32(hash, 16) | 0x80000000; Array.Resize(ref hash, 16); // set GUID type to "version 4" (random) hash[7] &= 0x0F; hash[7] |= 0x40; hash[8] &= 0x3F; hash[8] |= 0x80; guid = new Guid(hash); fs.Position = pdb.PositionPdbId; PdbHeap.WritePdbId(mw, guid, timestamp); } } }
private void CreateLocalScopeAndLocalVariables(LocalScopeTable localScope, LocalVariableTable localVariable, ImportScopeTable importScope) { var methods = this.methods.ToArray(); Array.Sort(methods, (m1, m2) => tokenMap[m1.Token].CompareTo(tokenMap[m2.Token])); for (var i = 0; i < methods.Length; i++) { var scopes = methods[i].Scopes; Array.Sort(scopes, (s1, s2) => s1.StartOffset != s2.StartOffset ? s1.StartOffset.CompareTo(s2.StartOffset) : s2.Length.CompareTo(s1.Length)); for (var j = 0; j < scopes.Length; j++) { LocalScopeTable.Record scope; scope.Method = tokenMap[methods[i].Token] & 0xFFFFFF; // TODO we don't set the parent ImportScope, because Visual Studio doesn't seem to need it scope.ImportScope = importScope.FindOrAddRecord(0, CreateNamespaceImportBlob(scopes[j].Namespaces)); scope.VariableList = localVariable.RowCount + 1; scope.ConstantList = 1; scope.StartOffset = scopes[j].StartOffset; scope.Length = scopes[j].Length; localScope.AddRecord(scope); for (var k = 0; k < scopes[j].VariableList.Count; k++) { LocalVariableTable.Record variable; variable.Attributes = 0; variable.Index = (short)scopes[j].VariableList[k].Index; variable.Name = Strings.Add(scopes[j].VariableList[k].Name); localVariable.AddRecord(variable); } } } }