public static bool GetImageArchitecture(string filepath) { var file = new PEFile.PEFile(filepath); if (file.Header.IsManaged) { throw new BadImageFormatException(".NET assembly is not supported."); } return(!file.Header.IsPE64); }
static void Main(string[] args) { if (args.Length == 0) { return; } foreach (var file in args) { Console.WriteLine(); if (!System.IO.File.Exists(file)) { Console.WriteLine("{0} does not exists"); } using (PEFile.PEFile peFile = new PEFile.PEFile(file)) { var header = peFile.Header; Console.WriteLine("Information for file- {0}", file); Console.WriteLine("---------------------------------------------------------"); Console.WriteLine("Architecture: {0}", header.Machine.ToString()); Console.WriteLine("Build Date: {0}", header.TimeDateStamp.ToString()); Console.WriteLine("IsManaged: {0}", header.IsManaged.ToString()); string pdbFilePath = string.Empty; Guid guid; int age = 0; peFile.GetPdbSignature(out pdbFilePath, out guid, out age); Console.WriteLine("Pdb file Path: {0}", pdbFilePath); Console.WriteLine("Pdb file guid: {0}", guid); Console.WriteLine("\nHeader:"); Console.WriteLine("MajorOperatingSystemVersion: {0}", header.MajorOperatingSystemVersion); Console.WriteLine("MajorLinkerVersion: {0}", header.MajorLinkerVersion); Console.WriteLine("NumberOfSections: {0}", header.NumberOfSections); Console.WriteLine("NumberOfSymbols: {0}", header.NumberOfSymbols); Console.WriteLine("SizeOfImage: 0x{0:X}", header.SizeOfImage); Console.WriteLine("SizeOfCode: 0x{0:X}", header.SizeOfCode); } } }
/// <summary> /// Given an ETL file, returns a list of the full paths to DLLs that were loaded in the trace that need symbolic /// information (PDBs) so that the stack traces and CPU samples can be properly resolved. By default this only /// returns NGEN images since these are the ones that need to be resolved and generated at collection time. /// </summary> public static IEnumerable <string> GetModulesNeedingSymbols(string etlFile, ModuleSymbolOptions options = ModuleSymbolOptions.OnlyNGENImages) { var images = new List <ImageData>(300); var addressCounts = new Dictionary <Address, int>(); // Get the name of all DLLS (in the file, and the set of all address-process pairs in the file. using (var source = new ETWTraceEventSource(etlFile)) { source.Kernel.ImageGroup += delegate(ImageLoadTraceData data) { var fileName = data.FileName; if (fileName.IndexOf(".ni.", StringComparison.OrdinalIgnoreCase) < 0) { // READY_TO_RUN support generate PDBs for ready-to-run images. // TODO can rip this out when we don't package ready-to-run images var windowsIdx = fileName.IndexOf(@"\windows\", StringComparison.OrdinalIgnoreCase); if (0 <= windowsIdx && windowsIdx <= 2) { return; } if (!File.Exists(fileName)) { return; } try { using (var peFile = new PEFile.PEFile(fileName)) { if (!peFile.IsManagedReadyToRun) { return; } } } catch { return; } } var processId = data.ProcessID; images.Add(new ImageData(processId, fileName, data.ImageBase, data.ImageSize)); }; source.Kernel.StackWalkStack += delegate(StackWalkStackTraceData data) { if (data.ProcessID == 0) { return; } var processId = data.ProcessID; for (int i = 0; i < data.FrameCount; i++) { var address = (data.InstructionPointer(i) & 0xFFFFFFFFFFFF0000L) + ((Address)(processId & 0xFFFF)); addressCounts[address] = 1; } }; source.Clr.ClrStackWalk += delegate(ClrStackWalkTraceData data) { var processId = data.ProcessID; for (int i = 0; i < data.FrameCount; i++) { var address = (data.InstructionPointer(i) & 0xFFFFFFFFFFFF0000L) + ((Address)(processId & 0xFFFF)); addressCounts[address] = 1; } }; source.Kernel.PerfInfoSample += delegate(SampledProfileTraceData data) { if (data.ProcessID == 0) { return; } var processId = data.ProcessID; var address = (data.InstructionPointer & 0xFFFFFFFFFFFF0000L) + ((Address)(processId & 0xFFFF)); addressCounts[address] = 1; }; source.Process(); } // imageNames is a set of names that we want symbols for. var imageNames = new Dictionary <string, string>(100); foreach (var image in images) { if (!imageNames.ContainsKey(image.DllName)) { for (uint offset = 0; offset < (uint)image.Size; offset += 0x10000) { var key = image.BaseAddress + offset + (uint)(image.ProcessID & 0xFFFF); if (addressCounts.ContainsKey(key)) { imageNames[image.DllName] = image.DllName; break; } } } } // Find the PDBS for the given images. return(new List <string>(imageNames.Keys)); }
// These routines find a PDB based on something (either an DLL or a pdb 'signature') /// <summary> /// Finds the symbol file for 'exeFilePath' that exists on the current machine (we open /// it to find the needed info). Uses the SymbolReader.SymbolPath (including Symbol servers) to /// look up the PDB, and will download the PDB to the local cache if necessary. /// /// This routine looks in the EXEFile to find the PDB Guid signature and then calls FindSymbolFilePath /// /// returns null if the pdb can't be found. /// </summary> public string FindSymbolFilePathForModule(string dllFilePath) { Debug.Assert(!IsDisposed); try { dllFilePath = BypassSystem32FileRedirection(dllFilePath); if (File.Exists(dllFilePath)) { using (var peFile = new PEFile.PEFile(dllFilePath)) { string pdbName; Guid pdbGuid; int pdbAge; // TODO we get the NGEN pdb if we can. Is this what we want in general? if (peFile.GetPdbSignature(out pdbName, out pdbGuid, out pdbAge, true)) { string fileVersionString = null; var fileVersion = peFile.GetFileVersionInfo(); if (fileVersion != null) fileVersionString = fileVersion.FileVersion; // TODO FIX NOW should this be here? m_log.WriteLine("Exe {0} has pdb {1} GUID {2} age {3}", dllFilePath, pdbName, pdbGuid, pdbAge); return FindSymbolFilePath(pdbName, pdbGuid, pdbAge, dllFilePath, fileVersionString); } else m_log.WriteLine("File does not have a codeview debug signature."); } } else m_log.WriteLine("File does not exist."); } catch (Exception e) { m_log.WriteLine("Failure opening PE file: {0}", e.Message); } m_log.WriteLine("[Failed to find PDB file for {0}]", dllFilePath); return null; }
private void AddSamplesForDirectory(string directoryPath, StackSourceCallStackIndex directoryStack) { StackSourceSample sample = null; try { var directory = new FastDirectory(directoryPath); foreach (var member in directory.Members) { if (member.IsDirectory) { var stack = Interner.CallStackIntern(Interner.FrameIntern("DIR: " + member.Name), directoryStack); AddSamplesForDirectory(Path.Combine(directoryPath, member.Name), stack); } else { var stack = directoryStack; // Allow easy grouping by extension. var ext = Path.GetExtension(member.Name).ToLower(); // And whether the DLL/EXE is managed or not. var suffix = ""; if (string.Compare(ext, ".dll", true) == 0 || string.Compare(ext, ".exe", true) == 0 || string.Compare(ext, ".winmd", true) == 0) { suffix = ""; string fileName = Path.Combine(directoryPath, member.Name); try { using (var peFile = new PEFile.PEFile(fileName)) { suffix = peFile.Header.IsManaged ? " (MANAGED)" : " (UNMANAGED)"; if (peFile.Header.IsPE64) { suffix += " (64Bit)"; } if (peFile.HasPrecompiledManagedCode) { if (peFile.IsManagedReadyToRun) { short major, minor; peFile.ReadyToRunVersion(out major, out minor); suffix += " (ReadyToRun(" + major + "." + minor + "))"; } else { suffix += " (NGEN)"; } } } } catch (Exception) { m_log.WriteLine("Error: exception looking at file " + fileName); m_log.Flush(); } } stack = Interner.CallStackIntern(Interner.FrameIntern("EXT: " + ext + suffix), stack); // Finally the file name itself. stack = Interner.CallStackIntern(Interner.FrameIntern("FILE: " + member.Name), stack); if (sample == null) { sample = new StackSourceSample(this); } sample.Metric = member.Size; sample.StackIndex = stack; if (m_useWriteTime) { sample.TimeRelativeMSec = (m_nowUtc - member.LastWriteTimeUtc).TotalDays; } else { sample.TimeRelativeMSec = (m_nowUtc - member.LastAccessTimeUtc).TotalDays; } AddSample(sample); m_totalSize += member.Size; int count = SampleIndexLimit; if ((count % 1000) == 0) { m_log.WriteLine("[Processed " + count + " files, size " + (m_totalSize / 1000000).ToString("n0") + " MB in directory scan at " + Path.Combine(directoryPath, member.Name) + " ]"); } } } } catch (Exception e) { m_log.WriteLine("Error processing directory " + directoryPath + ": " + e.Message); } }