/// <summary> /// Returns information about the PE file. /// </summary> /// <param name="isVirtual">the memory layout of the module</param> /// <param name="address">module base address</param> /// <param name="size">module size</param> /// <param name="pdbInfo">the pdb record or null</param> /// <param name="version">the PE version or null</param> /// <param name="flags">module flags</param> /// <returns>PEImage instance or null</returns> private PEImage GetPEInfo(bool isVirtual, ulong address, ulong size, ref PdbInfo pdbInfo, ref VersionInfo?version, ref Module.Flags flags) { Stream stream = MemoryService.CreateMemoryStream(address, size); try { stream.Position = 0; var peImage = new PEImage(stream, leaveOpen: false, isVirtual); if (peImage.IsValid) { flags |= Module.Flags.IsPEImage; flags |= peImage.IsManaged ? Module.Flags.IsManaged : Module.Flags.None; pdbInfo = peImage.DefaultPdb; if (!version.HasValue) { FileVersionInfo fileVersionInfo = peImage.GetFileVersionInfo(); if (fileVersionInfo != null) { version = fileVersionInfo.VersionInfo; } } flags &= ~(Module.Flags.IsLoadedLayout | Module.Flags.IsFileLayout); flags |= isVirtual ? Module.Flags.IsLoadedLayout : Module.Flags.IsFileLayout; return(peImage); } else { Trace.TraceError($"GetPEInfo: PE invalid {address:X16} isVirtual {isVirtual}"); } } catch (Exception ex) when(ex is BadImageFormatException || ex is EndOfStreamException || ex is IOException) { Trace.TraceError($"GetPEInfo: loaded {address:X16} isVirtual {isVirtual} exception {ex.Message}"); } return(null); }
/// <summary> /// Returns information about the PE file for a specific layout. /// </summary> /// <param name="isVirtual">the memory layout of the module</param> /// <param name="address">module base address</param> /// <param name="size">module size</param> /// <param name="pdbs">pdb infos</param> /// <param name="flags">module flags</param> /// <returns>PEFile instance or null</returns> private PEFile GetPEInfo(bool isVirtual, ulong address, ulong size, out List <PdbFileInfo> pdbs, out Module.Flags flags) { pdbs = null; flags = 0; try { Stream stream = RawMemoryService.CreateMemoryStream(address, size); PEFile peFile = new(new StreamAddressSpace(stream), isVirtual); if (peFile.IsValid()) { flags |= Module.Flags.IsPEImage; flags |= peFile.IsILImage ? Module.Flags.IsManaged : Module.Flags.None; pdbs = peFile.Pdbs.Select((pdb) => pdb.ToPdbFileInfo()).ToList(); flags |= isVirtual ? Module.Flags.IsLoadedLayout : Module.Flags.IsFileLayout; return(peFile); } else { Trace.TraceError($"GetPEInfo: PE invalid {address:X16} isVirtual {isVirtual}"); } } catch (Exception ex) when(ex is InvalidVirtualAddressException || ex is BadInputFormatException) { Trace.TraceError($"GetPEInfo: {address:X16} isVirtual {isVirtual} exception {ex.Message}"); } return(null); }
/// <summary> /// Returns the PE file's PDB info from the debug directory /// </summary> /// <param name="address">module base address</param> /// <param name="size">module size</param> /// <param name="pdbInfo">the pdb record or null</param> /// <param name="version">the PE version or null</param> /// <param name="flags">module flags</param> /// <returns>PEImage instance or null</returns> internal PEImage GetPEInfo(ulong address, ulong size, ref PdbInfo pdbInfo, ref VersionInfo?version, ref Module.Flags flags) { PEImage peImage = null; // None of the modules that lldb (on either Linux/MacOS) provides are PEs if (Target.Host.HostType != HostType.Lldb) { // First try getting the PE info as load layout (native Windows DLLs and most managed PEs on Linux/MacOS). peImage = GetPEInfo(isVirtual: true, address, size, ref pdbInfo, ref version, ref flags); if (peImage == null) { if (Target.OperatingSystem != OSPlatform.Windows) { // Then try getting the PE info as file layout (some managed PEs on Linux/MacOS). peImage = GetPEInfo(isVirtual: false, address, size, ref pdbInfo, ref version, ref flags); } } } return(peImage); }
/// <summary> /// Returns the PE file's PDB info from the debug directory /// </summary> /// <param name="address">module base address</param> /// <param name="size">module size</param> /// <param name="pdbFileInfos">the pdb records or null</param> /// <param name="moduleFlags">module flags</param> /// <returns>PEImage instance or null</returns> internal PEFile GetPEInfo(ulong address, ulong size, out IEnumerable <PdbFileInfo> pdbFileInfos, ref Module.Flags moduleFlags) { PEFile peFile = null; // Start off with no pdb infos and as a native non-PE non-managed module pdbFileInfos = Array.Empty <PdbFileInfo>(); moduleFlags &= ~(Module.Flags.IsPEImage | Module.Flags.IsManaged | Module.Flags.IsLoadedLayout | Module.Flags.IsFileLayout); // None of the modules that lldb (on either Linux/MacOS) provides are PEs if (Target.Host.HostType != HostType.Lldb) { // First try getting the PE info as loaded layout (native Windows DLLs and most managed PEs). peFile = GetPEInfo(isVirtual: true, address, size, out List <PdbFileInfo> pdbs, out Module.Flags flags); if (peFile is null || pdbs.Count == 0) { // If PE file is invalid or there are no PDB records, try getting the PE info as file layout. No PDB records can mean // that either the layout is wrong or that there really no PDB records. If file layout doesn't have any pdb records // either default to loaded layout PEFile. PEFile peFileLayout = GetPEInfo(isVirtual: false, address, size, out List <PdbFileInfo> pdbsFileLayout, out Module.Flags flagsFileLayout); if (peFileLayout is not null && (peFile is null || pdbsFileLayout.Count > 0)) { flags = flagsFileLayout; pdbs = pdbsFileLayout; peFile = peFileLayout; } } if (peFile is not null) { moduleFlags |= flags; pdbFileInfos = pdbs; } } return(peFile); }