private void WritePDBDataHelper(string dllPath, IEnumerable <MethodInfo> methods) { // This will try to open the managed PDB if lines info was requested. This is a // likely failure point, so intentionally do this before creating the NGEN PDB file // on disk. bool isILPDBProvided = false; if (_pdbExtraData.HasFlag(PDBExtraData.kPDBLines)) { // line mapping not ported from crossgen yet. throw new NotImplementedException(); } string originalDllPath = dllPath; // Currently DiaSymReader does not work properly generating NGEN PDBS unless // the DLL whose PDB is being generated ends in .ni.*. Unfortunately, readyToRun // images do not follow this convention and end up producing bad PDBS. To fix // this (without changing diasymreader.dll which ships indepdendently of .NET Core) // we copy the file to somethign with this convention before generating the PDB // and delete it when we are done. if (!dllPath.EndsWith(".ni.dll", StringComparison.OrdinalIgnoreCase) && !dllPath.EndsWith(".ni.exe", StringComparison.OrdinalIgnoreCase)) { _tempSourceDllName = Path.Combine(Path.GetDirectoryName(dllPath), Path.GetFileNameWithoutExtension(dllPath) + ".ni" + Path.GetExtension(dllPath)); File.Copy(dllPath, _tempSourceDllName); dllPath = _tempSourceDllName; } _ngenWriter = CreateNGenWriter(dllPath, _pdbPath + "\\"); { // PDB file is now created. Get its path and initialize _pdbFilePath so the PDB file // can be deleted if we don't make it successfully to the end StringBuilder pdbFilePathBuilder = new StringBuilder(); pdbFilePathBuilder.Capacity = 1024; _ngenWriter.QueryPDBNameExW(pdbFilePathBuilder, new IntPtr(pdbFilePathBuilder.Capacity)); _pdbFilePath = pdbFilePathBuilder.ToString(); } _ngenWriter.OpenModW(originalDllPath, Path.GetFileName(originalDllPath), out _pdbMod); WriteStringTable(); WriteFileChecksums(); ushort?iCodeSection = null; uint rvaOfTextSection = 0; using (var peReader = new PEReader(new FileStream(dllPath, FileMode.Open), PEStreamOptions.Default)) { var sections = peReader.PEHeaders.SectionHeaders; for (int i = 0; i < sections.Length; i++) { ushort pdbSectionNumber = checked ((ushort)(i + 1)); _ngenWriter.AddSection(pdbSectionNumber, OMF.StandardText, 0, sections[i].SizeOfRawData); if (sections[i].Name == ".text") { iCodeSection = pdbSectionNumber; rvaOfTextSection = (uint)sections[i].VirtualAddress; } _ngenWriter.ModAddSecContribEx(_pdbMod, pdbSectionNumber, 0, sections[i].SizeOfRawData, (uint)sections[i].SectionCharacteristics, 0, 0); } } // To support lines info, we need a "dummy" section, indexed as 0, for use as a // sentinel when MSPDB sets up its section contribution table _ngenWriter.AddSection(0, // Dummy section 0 OMF.SentinelType, 0, unchecked ((int)0xFFFFFFFF)); foreach (var method in methods) { WriteMethodPDBData(iCodeSection.Value, method, Path.GetFileNameWithoutExtension(originalDllPath), rvaOfTextSection, isILPDBProvided); } }
private extern static void CreateNGenPdbWriter( [MarshalAs(UnmanagedType.LPWStr)] string ngenImagePath, [MarshalAs(UnmanagedType.LPWStr)] string pdbPath, [MarshalAs(UnmanagedType.Interface)] out ISymNGenWriter2 ngenPdbWriter);