예제 #1
0
파일: Program.cs 프로젝트: tmat/symstore
        internal async Task DownloadFiles()
        {
            using (SymbolStore symbolStore = BuildSymbolStore())
            {
                bool verifyPackages = Packages && OutputDirectory == null;

                KeyTypeFlags flags = KeyTypeFlags.None;
                if (Symbols)
                {
                    flags |= KeyTypeFlags.SymbolKey;
                }
                if (Modules)
                {
                    flags |= KeyTypeFlags.IdentityKey;
                }
                if (Debugging)
                {
                    flags |= KeyTypeFlags.ClrKeys;
                }
                if (flags == KeyTypeFlags.None)
                {
                    if (verifyPackages)
                    {
                        // If we are verifing symbol packages then only check the identity and clr keys.
                        flags = KeyTypeFlags.IdentityKey | KeyTypeFlags.ClrKeys;
                    }
                    else
                    {
                        // The default is to download everything
                        flags = KeyTypeFlags.IdentityKey | KeyTypeFlags.SymbolKey | KeyTypeFlags.ClrKeys;
                    }
                }
                if (ForceWindowsPdbs)
                {
                    flags |= KeyTypeFlags.ForceWindowsPdbs;
                }

                foreach (SymbolStoreKeyWrapper wrapper in GetKeys(flags).Distinct())
                {
                    SymbolStoreKey key = wrapper.Key;
                    Tracer.Information("Key: {0} - {1}{2}", key.Index, key.FullPathName, key.IsClrSpecialFile ? "*" : "");

                    if (symbolStore != null)
                    {
                        using (SymbolStoreFile symbolFile = await symbolStore.GetFile(key, CancellationToken.None))
                        {
                            if (symbolFile != null)
                            {
                                await WriteFile(symbolFile, wrapper);
                            }
                            // If there is no output directory verify the file exists in the symbol store
                            if (OutputDirectory == null)
                            {
                                Tracer.WriteLine("Key {0}found {1} - {2}", symbolFile != null ? "" : "NOT ", key.Index, key.FullPathName);
                            }
                        }
                    }
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Load native symbols and modules (i.e. dac, dbi).
        /// </summary>
        /// <param name="callback">called back for each symbol file loaded</param>
        /// <param name="parameter">callback parameter</param>
        /// <param name="tempDirectory">temp directory unique to this instance of SOS</param>
        /// <param name="moduleFilePath">module path</param>
        /// <param name="address">module base address</param>
        /// <param name="size">module size</param>
        /// <param name="readMemory">read memory callback delegate</param>
        public static void LoadNativeSymbols(SymbolFileCallback callback, IntPtr parameter, string tempDirectory, string moduleFilePath, ulong address, int size, ReadMemoryDelegate readMemory)
        {
            if (IsSymbolStoreEnabled())
            {
                Debug.Assert(s_tracer != null);
                Stream       stream    = new TargetStream(address, size, readMemory);
                KeyTypeFlags flags     = KeyTypeFlags.SymbolKey | KeyTypeFlags.ClrKeys;
                KeyGenerator generator = null;

                if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                {
                    var elfFile = new ELFFile(new StreamAddressSpace(stream), 0, true);
                    generator = new ELFFileKeyGenerator(s_tracer, elfFile, moduleFilePath);
                }
                else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                {
                    var machOFile = new MachOFile(new StreamAddressSpace(stream), 0, true);
                    generator = new MachOFileKeyGenerator(s_tracer, machOFile, moduleFilePath);
                }
                else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    var peFile = new PEFile(new StreamAddressSpace(stream), true);
                    generator = new PEFileKeyGenerator(s_tracer, peFile, moduleFilePath);
                }
                else
                {
                    return;
                }

                try
                {
                    IEnumerable <SymbolStoreKey> keys = generator.GetKeys(flags);
                    foreach (SymbolStoreKey key in keys)
                    {
                        string moduleFileName = Path.GetFileName(key.FullPathName);
                        s_tracer.Verbose("{0} {1}", key.FullPathName, key.Index);

                        // Don't download the sos binaries that come with the runtime
                        if (moduleFileName != "SOS.NETCore.dll" && !moduleFileName.StartsWith("libsos."))
                        {
                            string downloadFilePath = GetSymbolFile(key, tempDirectory);
                            if (downloadFilePath != null)
                            {
                                s_tracer.Information("{0}: {1}", moduleFileName, downloadFilePath);
                                callback(parameter, moduleFileName, downloadFilePath);
                            }
                        }
                    }
                }
                catch (Exception ex) when(ex is BadInputFormatException || ex is InvalidVirtualAddressException)
                {
                    s_tracer.Error("{0}/{1:X16}: {2}", moduleFilePath, address, ex.Message);
                }
            }
        }
예제 #3
0
        private async Task ScanFileAsync([NotNull] string sourceDir, [NotNull] string sourceFile, [NotNull] ITracer tracer)
        {
            var srcFile = Path.GetRelativePath(sourceDir, sourceFile);

            tracer.Information($"  Scanning {srcFile}...");
            foreach (var key in GetKeyInfos(tracer, sourceFile))
            {
                var index = key.Item1.Index;
                if (!SymbolStoreKey.IsKeyValid(index))
                {
                    tracer.Error($"Invalid key index in file {index}");
                }
                else if (key.Item2 == KeyType.Elf && Path.GetExtension(sourceFile) == ".debug" && !index.EndsWith("/_.debug"))
                {
                    // Bug: Check that ELF .debug was processed right way! See https://github.com/dotnet/symstore/issues/158
                    tracer.Error($"ELF file {sourceFile} was processed incorrectly because Microsoft.SymbolStore doesn't support .debug extension");
                }
                else
                {
                    var dstFile = index.NormalizeSystem();
                    if (
                        myCompressWPdb && key.Item2 == KeyType.WPdb ||
                        myCompressPe && key.Item2 == KeyType.Pe)
                    {
                        await myProcessCompressed(sourceDir, srcFile, Path.ChangeExtension(dstFile, PathUtil.GetPackedExtension(Path.GetExtension(dstFile))));

                        if (myIsKeepNonCompressed)
                        {
                            await myProcessNormal(sourceDir, srcFile, dstFile);
                        }
                    }
                    else
                    {
                        await myProcessNormal(sourceDir, srcFile, dstFile);
                    }
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Load native symbols and modules (i.e. dac, dbi).
        /// </summary>
        /// <param name="callback">called back for each symbol file loaded</param>
        /// <param name="parameter">callback parameter</param>
        /// <param name="moduleDirectory">module path</param>
        /// <param name="moduleFileName">module file name</param>
        /// <param name="address">module base address</param>
        /// <param name="size">module size</param>
        /// <param name="readMemory">read memory callback delegate</param>
        internal static void LoadNativeSymbols(SymbolFileCallback callback, IntPtr parameter, string tempDirectory, string moduleDirectory, string moduleFileName,
                                               ulong address, int size, ReadMemoryDelegate readMemory)
        {
            if (s_symbolStore != null)
            {
                Debug.Assert(s_tracer != null);
                string       path      = Path.Combine(moduleDirectory, moduleFileName);
                Stream       stream    = new TargetStream(address, size, readMemory);
                KeyTypeFlags flags     = KeyTypeFlags.SymbolKey | KeyTypeFlags.ClrKeys;
                KeyGenerator generator = null;

                if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                {
                    var elfFile = new ELFFile(new StreamAddressSpace(stream), 0, true);
                    generator = new ELFFileKeyGenerator(s_tracer, elfFile, path);
                }
                else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                {
                    var machOFile = new MachOFile(new StreamAddressSpace(stream), 0, true);
                    generator = new MachOFileKeyGenerator(s_tracer, machOFile, path);
                }
                else
                {
                    return;
                }

                try
                {
                    IEnumerable <SymbolStoreKey> keys = generator.GetKeys(flags);
                    foreach (SymbolStoreKey key in keys)
                    {
                        string symbolFileName = Path.GetFileName(key.FullPathName);
                        s_tracer.Verbose("{0} {1}", key.FullPathName, key.Index);

                        // Don't download the sos binaries that come with the runtime
                        if (symbolFileName != "SOS.NETCore.dll" && !symbolFileName.StartsWith("libsos."))
                        {
                            using (SymbolStoreFile file = GetSymbolStoreFile(key))
                            {
                                if (file != null)
                                {
                                    try
                                    {
                                        string downloadFileName = file.FileName;

                                        // If the downloaded doesn't already exists on disk in the cache, then write it to a temporary location.
                                        if (!File.Exists(downloadFileName))
                                        {
                                            downloadFileName = Path.Combine(tempDirectory, symbolFileName);

                                            using (Stream destinationStream = File.OpenWrite(downloadFileName)) {
                                                file.Stream.CopyTo(destinationStream);
                                            }
                                            s_tracer.WriteLine("Downloaded symbol file {0}", key.FullPathName);
                                        }
                                        s_tracer.Information("{0}: {1}", symbolFileName, downloadFileName);
                                        callback(parameter, symbolFileName, downloadFileName);
                                    }
                                    catch (Exception ex) when(ex is UnauthorizedAccessException || ex is DirectoryNotFoundException)
                                    {
                                        s_tracer.Error("{0}", ex.Message);
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception ex) when(ex is BadInputFormatException || ex is InvalidVirtualAddressException)
                {
                    s_tracer.Error("Exception: {0}/{1}: {2:X16}", moduleDirectory, moduleFileName, address);
                }
            }
        }
예제 #5
0
        internal static void Validate(ITracer tracer, Stream pdbStream, IEnumerable <PdbChecksum> pdbChecksums)
        {
            uint offset = 0;

            byte[] bytes = new byte[pdbStream.Length];
            byte[] pdbId = new byte[pdbIdSize];
            if (pdbStream.Read(bytes, offset: 0, count: bytes.Length) != bytes.Length)
            {
                throw new InvalidChecksumException("Unexpected stream length");
            }

            try
            {
                offset = GetPdbStreamOffset(pdbStream);
            }
            catch (Exception ex)
            {
                tracer.Error(ex.Message);
                throw;
            }

            // Make a copy of the pdb Id
            Array.Copy(bytes, offset, pdbId, 0, pdbIdSize);

            // Zero out the pdb Id
            for (int i = 0; i <= pdbIdSize; i++)
            {
                bytes[i + offset] = 0;
            }

            bool algorithmNameKnown = false;

            foreach (var checksum in pdbChecksums)
            {
                tracer.Information($"Testing checksum: {checksum}");

                var algorithm = HashAlgorithm.Create(checksum.AlgorithmName);
                if (algorithm != null)
                {
                    algorithmNameKnown = true;
                    var hash = algorithm.ComputeHash(bytes);
                    if (hash.SequenceEqual(checksum.Checksum))
                    {
                        // If any of the checksums are OK, we're good
                        tracer.Information($"Found checksum match {checksum}");
                        // Restore the pdb Id
                        Array.Copy(pdbId, 0, bytes, offset, pdbIdSize);
                        // Restore the steam position
                        pdbStream.Seek(0, SeekOrigin.Begin);

                        return;
                    }
                }
            }

            if (!algorithmNameKnown)
            {
                var algorithmNames = string.Join(" ", pdbChecksums.Select(c => c.AlgorithmName));
                throw new InvalidChecksumException($"Unknown hash algorithm: {algorithmNames}");
            }

            throw new InvalidChecksumException("PDB checksum mismatch");
        }