/// <summary> /// Returns the ELF module build id or the MachO module uuid /// </summary> /// <param name="address">module base address</param> /// <param name="size">module size</param> /// <returns>build id or null</returns> internal byte[] GetBuildId(ulong address, ulong size) { Debug.Assert(size > 0); Stream stream = MemoryService.CreateMemoryStream(address, size); byte[] buildId = null; try { if (Target.OperatingSystem == OSPlatform.Linux) { var elfFile = new ELFFile(new StreamAddressSpace(stream), 0, true); if (elfFile.IsValid()) { buildId = elfFile.BuildID; } } else if (Target.OperatingSystem == OSPlatform.OSX) { var machOFile = new MachOFile(new StreamAddressSpace(stream), 0, true); if (machOFile.IsValid()) { buildId = machOFile.Uuid; } } } catch (Exception ex) when(ex is InvalidVirtualAddressException || ex is BadInputFormatException || ex is IOException) { Trace.TraceError($"GetBuildId: {address:X16} exception {ex.Message}"); } return(buildId); }
public string ComputeIndexKey(string path, Stream fileStream) { try { string extension = Path.GetExtension(path); if (extension != ".dylib" && extension != ".dylib.dwarf") { return(null); } MachOFile machO = new MachOFile(new StreamAddressSpace(fileStream)); if (!machO.HeaderMagic.IsMagicValid.Check()) { return(null); } string filename = Path.GetFileName(path).ToLowerInvariant(); StringBuilder key = new StringBuilder(); key.Append(filename); key.Append("/mach-uuid-"); //TODO: it would be nice to really check if the file is stripped rather than // assuming it is based on the extension bool isStripped = extension == ".dylib"; key.Append(isStripped ? "" : "sym-"); key.Append(string.Concat(machO.Uuid.Select(b => b.ToString("x2"))).ToLowerInvariant()); key.Append("/"); key.Append(filename); return(key.ToString()); } catch (InputParsingException) { return(null); } }
/// <summary> /// Returns the ELF module build id or the MachO module uuid /// </summary> /// <param name="address">module base address</param> /// <returns>build id or null</returns> internal byte[] GetBuildId(ulong address) { // This code is called by the image mapping memory service so it needs to use the // original or raw memory service to prevent recursion so it can't use the ELFFile // or MachOFile instance that is available from the IModule.Services provider. Stream stream = RawMemoryService.CreateMemoryStream(); byte[] buildId = null; try { if (Target.OperatingSystem == OSPlatform.Linux) { var elfFile = new ELFFile(new StreamAddressSpace(stream), address, true); if (elfFile.IsValid()) { buildId = elfFile.BuildID; } } else if (Target.OperatingSystem == OSPlatform.OSX) { var machOFile = new MachOFile(new StreamAddressSpace(stream), address, true); if (machOFile.IsValid()) { buildId = machOFile.Uuid; } } } catch (Exception ex) when(ex is InvalidVirtualAddressException || ex is BadInputFormatException || ex is IOException) { Trace.TraceError($"GetBuildId: {address:X16} exception {ex.Message}"); } return(buildId); }
private KeyGenerator CreateGenerator(ELFLoadedImage loadedImage) { try { if (loadedImage.Image.IsValid()) { return(new ELFFileKeyGenerator(Tracer, loadedImage.Image, loadedImage.Path)); } // TODO - mikem 7/1/17 - need to figure out a better way to determine the file vs loaded layout bool layout = loadedImage.Path.StartsWith("/"); var reader = new RelativeAddressSpace(_core.DataSource, loadedImage.LoadAddress, _core.DataSource.Length); var peFile = new PEFile(reader, layout); if (peFile.IsValid()) { return(new PEFileKeyGenerator(Tracer, peFile, loadedImage.Path)); } // Check if this is a macho module in a ELF 5.0.x MacOS dump var machOFile = new MachOFile(reader, 0, true); if (machOFile.IsValid()) { return(new MachOFileKeyGenerator(Tracer, machOFile, loadedImage.Path)); } Tracer.Warning("Unknown ELF core image {0:X16} {1}", loadedImage.LoadAddress, loadedImage.Path); } catch (InvalidVirtualAddressException ex) { Tracer.Error("{0}: {1:X16} {2}", ex.Message, loadedImage.LoadAddress, loadedImage.Path); } return(null); }
/// <summary> /// Creates a key generator for the runtime module pointed to by the address/size. /// </summary> /// <param name="memoryService">memory service instance</param> /// <param name="config">Target configuration: Windows, Linux or OSX</param> /// <param name="moduleFilePath">module path</param> /// <param name="address">module base address</param> /// <param name="size">module size</param> /// <returns>KeyGenerator or null if error</returns> public static KeyGenerator GetKeyGenerator(this IMemoryService memoryService, OSPlatform config, string moduleFilePath, ulong address, ulong size) { Stream stream = memoryService.CreateMemoryStream(address, size); KeyGenerator generator = null; if (config == OSPlatform.Linux) { var elfFile = new ELFFile(new StreamAddressSpace(stream), 0, true); generator = new ELFFileKeyGenerator(Tracer.Instance, elfFile, moduleFilePath); } else if (config == OSPlatform.OSX) { var machOFile = new MachOFile(new StreamAddressSpace(stream), 0, true); generator = new MachOFileKeyGenerator(Tracer.Instance, machOFile, moduleFilePath); } else if (config == OSPlatform.Windows) { var peFile = new PEFile(new StreamAddressSpace(stream), true); generator = new PEFileKeyGenerator(Tracer.Instance, peFile, moduleFilePath); } else { Trace.TraceError("GetKeyGenerator: unsupported platform {0}", config); } return(generator); }
/// <summary> /// Get the version string from a Linux or MacOS image /// </summary> /// <param name="address">image base</param> /// <param name="size">image size</param> /// <returns>version string or null</returns> protected string GetVersionString(ulong address, ulong size) { Stream stream = MemoryService.CreateMemoryStream(address, size); try { if (Target.OperatingSystem == OSPlatform.Linux) { var elfFile = new ELFFile(new StreamAddressSpace(stream), 0, true); if (elfFile.IsValid()) { foreach (ELFProgramHeader programHeader in elfFile.Segments.Select((segment) => segment.Header)) { uint flags = MemoryService.PointerSize == 8 ? programHeader.Flags : programHeader.Flags32; if (programHeader.Type == ELFProgramHeaderType.Load && (flags & (uint)ELFProgramHeaderAttributes.Writable) != 0) { ulong loadAddress = programHeader.VirtualAddress.Value; long loadSize = (long)programHeader.VirtualSize; if (SearchVersionString(address + loadAddress, loadSize, out string productVersion)) { return(productVersion); } } } } } else if (Target.OperatingSystem == OSPlatform.OSX) { var machOFile = new MachOFile(new StreamAddressSpace(stream), 0, true); if (machOFile.IsValid()) { foreach (MachSegmentLoadCommand loadCommand in machOFile.Segments.Select((segment) => segment.LoadCommand)) { if (loadCommand.Command == LoadCommandType.Segment64 && (loadCommand.InitProt & VmProtWrite) != 0 && loadCommand.SegName.ToString() != "__LINKEDIT") { ulong loadAddress = loadCommand.VMAddress; long loadSize = (long)loadCommand.VMSize; if (SearchVersionString(address + loadAddress, loadSize, out string productVersion)) { return(productVersion); } } } } } else { Trace.TraceError("GetVersionString: unsupported platform {0}", Target.OperatingSystem); } } catch (Exception ex) when(ex is InvalidVirtualAddressException || ex is BadInputFormatException || ex is IOException) { Trace.TraceError($"GetVersionString: {address:X16} exception {ex.Message}"); } return(null); }
/// <summary> /// Finds or downloads the ELF module and creates a MachOFile instance for it. /// </summary> /// <param name="module">module instance</param> /// <returns>MachO file instance or null</returns> internal MachOFile GetMachOFile(IModule module) { string downloadFilePath = null; MachOFile machoFile = null; if (File.Exists(module.FileName)) { // TODO - Need to verify the build id matches this local file downloadFilePath = module.FileName; } else { if (SymbolService.IsSymbolStoreEnabled) { if (!module.BuildId.IsDefaultOrEmpty) { var key = MachOFileKeyGenerator.GetKeys(KeyTypeFlags.IdentityKey, module.FileName, module.BuildId.ToArray(), symbolFile: false, symbolFileName: null).SingleOrDefault(); if (key != null) { // Now download the module from the symbol server downloadFilePath = SymbolService.DownloadFile(key); } } } } if (!string.IsNullOrEmpty(downloadFilePath)) { Trace.TraceInformation("GetMachOFile: downloaded {0}", downloadFilePath); Stream stream; try { stream = File.OpenRead(downloadFilePath); } catch (Exception ex) when(ex is DirectoryNotFoundException || ex is FileNotFoundException || ex is UnauthorizedAccessException || ex is IOException) { Trace.TraceError($"GetMachOFile: OpenRead exception {ex.Message}"); return(null); } try { machoFile = new MachOFile(new StreamAddressSpace(stream), position: 0, dataSourceIsVirtualAddressSpace: false); if (!machoFile.IsValid()) { return(null); } } catch (Exception ex) when(ex is InvalidVirtualAddressException || ex is BadInputFormatException || ex is IOException) { Trace.TraceError($"GetMachOFile: exception {ex.Message}"); return(null); } } return(machoFile); }
/// <summary> /// Get the version string from a Linux or MacOS image /// </summary> /// <param name="module">module to get version string</param> /// <returns>version string or null</returns> protected string GetVersionString(IModule module) { try { ELFFile elfFile = module.Services.GetService <ELFFile>(); if (elfFile is not null) { foreach (ELFProgramHeader programHeader in elfFile.Segments.Select((segment) => segment.Header)) { uint flags = MemoryService.PointerSize == 8 ? programHeader.Flags : programHeader.Flags32; if (programHeader.Type == ELFProgramHeaderType.Load && (flags & (uint)ELFProgramHeaderAttributes.Writable) != 0) { ulong loadAddress = programHeader.VirtualAddress.Value; long loadSize = (long)programHeader.VirtualSize; if (SearchVersionString(module.ImageBase + loadAddress, loadSize, out string productVersion)) { return(productVersion); } } } Trace.TraceInformation($"GetVersionString: not found in ELF file {module}"); } else { MachOFile machOFile = module.Services.GetService <MachOFile>(); if (machOFile is not null) { foreach (MachSegmentLoadCommand loadCommand in machOFile.Segments.Select((segment) => segment.LoadCommand)) { if (loadCommand.Command == LoadCommandType.Segment64 && (loadCommand.InitProt & VmProtWrite) != 0 && loadCommand.SegName.ToString() != "__LINKEDIT") { ulong loadAddress = loadCommand.VMAddress + machOFile.PreferredVMBaseAddress; long loadSize = (long)loadCommand.VMSize; if (SearchVersionString(loadAddress, loadSize, out string productVersion)) { return(productVersion); } } } Trace.TraceInformation($"GetVersionString: not found in MachO file {module}"); } else { Trace.TraceError($"GetVersionString: unsupported module {module} or platform {Target.OperatingSystem}"); } } } catch (Exception ex) when(ex is InvalidVirtualAddressException || ex is BadInputFormatException || ex is IOException) { Trace.TraceError($"GetVersionString: {module} exception {ex.Message}"); } return(null); }
public void CheckDwarfIndexingInfo() { //https://dotnet.myget.org/feed/dotnet-core/package/nuget/runtime.osx.10.10-x64.Microsoft.NETCore.Runtime.CoreCLR/1.0.2 using (FileStream dwarf = File.OpenRead("TestBinaries\\libcoreclr.dylib.dwarf")) { StreamAddressSpace dataSource = new StreamAddressSpace(dwarf); MachOFile machO = new MachOFile(dataSource); Assert.Equal(Guid.Parse("c988806d-a15d-5e3d-9a26-42cedad97a2f"), new Guid(machO.Uuid)); } }
public static int Main(string[] args) { if (args.Length < 2 || string.IsNullOrEmpty(args[0]) || string.IsNullOrEmpty(args[1])) { throw new ArgumentException("Invalid command line arguments"); } string moduleFileName = args[0]; string outputFileName = args[1]; using (FileStream stream = File.OpenRead(moduleFileName)) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { var elfFile = new ELFFile(new StreamAddressSpace(stream)); byte[] buildId = elfFile.BuildID; if (buildId != null) { // First byte is the number of bytes total in the build id string outputText = string.Format("0x{0:x2}, {1}", buildId.Length, ToHexString(buildId)); File.WriteAllText(outputFileName, outputText); } else { throw new BadInputFormatException($"{moduleFileName} does not have a build id"); } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { var peFile = new PEFile(new StreamAddressSpace(stream)); // First byte is the number of bytes total in the index string outputText = string.Format("0x{0:x2}, {1} {2}", 8, ToHexString(peFile.Timestamp), ToHexString(peFile.SizeOfImage)); File.WriteAllText(outputFileName, outputText); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { var machoFile = new MachOFile(new StreamAddressSpace(stream)); byte[] uuid = machoFile.Uuid; if (uuid != null) { // First byte is the number of bytes total in the build id string outputText = string.Format("0x{0:x2}, {1}", uuid.Length, ToHexString(uuid)); File.WriteAllText(outputFileName, outputText); } else { throw new BadInputFormatException($"{moduleFileName} does not have a uuid"); } } else { throw new PlatformNotSupportedException(RuntimeInformation.OSDescription); } } return(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); } } }
public void CheckDwarfIndexingInfo() { // From a local build using (Stream dwarf = TestUtilities.OpenCompressedFile("TestBinaries/libclrjit.dylib.dwarf.gz")) { StreamAddressSpace dataSource = new StreamAddressSpace(dwarf); MachOFile machO = new MachOFile(dataSource); Assert.True(machO.IsValid()); Assert.Equal(Guid.Parse("0c235eb3-e98e-ef32-b6e6-e6ed18a604a8"), new Guid(machO.Uuid)); } }
public void CheckIndexingInfo() { // https://dotnet.myget.org/feed/dotnet-core/package/nuget/runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.CoreCLR/1.1.2 using (Stream dylib = TestUtilities.OpenCompressedFile("TestBinaries/libcoreclr.dylib.gz")) { StreamAddressSpace dataSource = new StreamAddressSpace(dylib); MachOFile machO = new MachOFile(dataSource); Assert.True(machO.IsValid()); Assert.Equal(Guid.Parse("da2b37b5-cdbc-f838-899b-6a782ceca847"), new Guid(machO.Uuid)); } }
public Module(ITarget target) { ServiceProvider = new ServiceProvider(); ServiceProvider.AddServiceFactoryWithNoCaching <PEFile>(() => GetPEInfo()); ServiceProvider.AddService <IExportSymbols>(this); ServiceProvider.AddServiceFactory <PEReader>(() => { if (!IndexTimeStamp.HasValue || !IndexFileSize.HasValue) { return(null); } return(Utilities.OpenPEReader(ModuleService.SymbolService.DownloadModuleFile(this))); }); if (target.OperatingSystem == OSPlatform.Linux) { ServiceProvider.AddServiceFactory <ELFModule>(() => { if (BuildId.IsDefaultOrEmpty) { return(null); } return(ELFModule.OpenFile(ModuleService.SymbolService.DownloadModuleFile(this))); }); ServiceProvider.AddServiceFactory <ELFFile>(() => { Stream stream = ModuleService.MemoryService.CreateMemoryStream(); var elfFile = new ELFFile(new StreamAddressSpace(stream), ImageBase, true); return(elfFile.IsValid() ? elfFile : null); }); } if (target.OperatingSystem == OSPlatform.OSX) { ServiceProvider.AddServiceFactory <MachOModule>(() => { if (BuildId.IsDefaultOrEmpty) { return(null); } return(MachOModule.OpenFile(ModuleService.SymbolService.DownloadModuleFile(this))); }); ServiceProvider.AddServiceFactory <MachOFile>(() => { Stream stream = ModuleService.MemoryService.CreateMemoryStream(); var machoFile = new MachOFile(new StreamAddressSpace(stream), ImageBase, true); return(machoFile.IsValid() ? machoFile : null); }); } _onChangeEvent = target.Services.GetService <ISymbolService>()?.OnChangeEvent.Register(() => { ServiceProvider.RemoveService(typeof(MachOModule)); ServiceProvider.RemoveService(typeof(ELFModule)); ServiceProvider.RemoveService(typeof(PEReader)); }); }
public void ParseCore() { using (FileStream core = File.OpenRead("TestBinaries\\core.12985")) { StreamAddressSpace dataSource = new StreamAddressSpace(core); // hard-coding the dylinker position so we don't pay to search for it each time // the code is capable of finding it by brute force search even if we don't provide the hint MachCore coreReader = new MachCore(dataSource, 0x00007fff68a59000); MachLoadedImage[] images = coreReader.LoadedImages.Where(i => i.Path.EndsWith("libcoreclr.dylib")).ToArray(); MachOFile libCoreclr = images[0].Image; Assert.Equal(Guid.Parse("c988806d-a15d-5e3d-9a26-42cedad97a2f"), new Guid(libCoreclr.Uuid)); } }
public void ContainsASymbolTable() { Stream lib = HelloSwiftAsLibrary(null); List <MachOFile> macho = MachO.Read(lib, null).ToList(); Assert.IsNotNull(macho); Assert.AreEqual(1, macho.Count); MachOFile file = macho [0]; bool hasSymbolTable = file.load_commands.Exists(lc => lc.cmd == (uint)MachO.LoadCommands.SymTab || lc.cmd == (uint)MachO.LoadCommands.DySymTab); Assert.IsTrue(hasSymbolTable); }
public void ParseCore() { using (Stream core = TestUtilities.DecompressFile("TestBinaries/core.gz", "TestBinaries/core")) { StreamAddressSpace dataSource = new StreamAddressSpace(core); // hard-coding the dylinker position so we don't pay to search for it each time // the code is capable of finding it by brute force search even if we don't provide the hint MachCore coreReader = new MachCore(dataSource, 0x000000010750c000); Assert.True(coreReader.IsValid()); MachLoadedImage[] images = coreReader.LoadedImages.Where(i => i.Path.EndsWith("libcoreclr.dylib")).ToArray(); MachOFile libCoreclr = images[0].Image; Assert.True(libCoreclr.IsValid()); Assert.Equal(Guid.Parse("c5660f3e-7352-b138-8141-e9d63b8ab415"), new Guid(libCoreclr.Uuid)); } }
public void HasOneRealPublicSymbol() { Stream lib = HelloSwiftAsLibrary(null); List <MachOFile> macho = MachO.Read(lib, null).ToList(); Assert.IsNotNull(macho); Assert.AreEqual(1, macho.Count); MachOFile file = macho [0]; List <SymTabLoadCommand> symbols = file.load_commands.OfType <SymTabLoadCommand> ().ToList(); Assert.AreEqual(1, symbols.Count); NListEntryType nlet = symbols [0].nlist [0].EntryType; List <NListEntry> entries = symbols [0].nlist. Where((nle, i) => nle.IsPublic && nle.EntryType == NListEntryType.InSection).ToList(); Assert.AreEqual(1, entries.Count); }
/// <summary> /// Finds or downloads the ELF module and creates a MachOFile instance for it. /// </summary> /// <param name="module">module instance</param> /// <returns>MachO file instance or null</returns> internal MachOFile GetMachOFile(IModule module) { if (module.BuildId.IsDefaultOrEmpty) { Trace.TraceWarning($"GetMachOFile: module {module.FileName} has no build id"); return(null); } SymbolStoreKey moduleKey = MachOFileKeyGenerator.GetKeys(KeyTypeFlags.IdentityKey, module.FileName, module.BuildId.ToArray(), symbolFile: false, symbolFileName: null).SingleOrDefault(); if (moduleKey is null) { Trace.TraceWarning($"GetMachOFile: no index generated for module {module.FileName} "); return(null); } if (File.Exists(module.FileName)) { MachOFile machOFile = OpenMachOFile(module.FileName); if (machOFile is not null) { var generator = new MachOFileKeyGenerator(Tracer.Instance, machOFile, module.FileName); IEnumerable <SymbolStoreKey> keys = generator.GetKeys(KeyTypeFlags.IdentityKey); foreach (SymbolStoreKey key in keys) { if (moduleKey.Equals(key)) { Trace.TraceInformation("GetMachOFile: local file match {0}", module.FileName); return(machOFile); } } } } // Now download the module from the symbol server if local file doesn't exists or doesn't have the right key string downloadFilePath = SymbolService.DownloadFile(moduleKey); if (!string.IsNullOrEmpty(downloadFilePath)) { Trace.TraceInformation("GetMachOFile: downloaded {0}", downloadFilePath); return(OpenMachOFile(downloadFilePath)); } return(null); }
void DisplaySegments(IModule module) { try { ELFFile elfFile = module.Services.GetService <ELFFile>(); if (elfFile is not null) { foreach (ELFProgramHeader programHeader in elfFile.Segments.Select((segment) => segment.Header)) { uint flags = MemoryService.PointerSize == 8 ? programHeader.Flags : programHeader.Flags32; ulong loadAddress = programHeader.VirtualAddress; ulong loadSize = programHeader.VirtualSize; ulong fileOffset = programHeader.FileOffset; string type = programHeader.Type.ToString(); WriteLine($" Segment: {loadAddress:X16} {loadSize:X16} {fileOffset:X16} {flags:x2} {type}"); } } else { MachOFile machOFile = module.Services.GetService <MachOFile>(); if (machOFile is not null) { WriteLine(" LoadAddress: {0:X16}", machOFile.LoadAddress); WriteLine(" LoadBias: {0:X16}", machOFile.PreferredVMBaseAddress); for (int i = 0; i < machOFile.Segments.Length; i++) { MachSegment segment = machOFile.Segments[i]; ulong loadAddress = segment.LoadCommand.VMAddress; ulong loadSize = segment.LoadCommand.VMSize; ulong fileOffset = segment.LoadCommand.FileOffset; uint prot = segment.LoadCommand.InitProt; string name = segment.LoadCommand.SegName.ToString(); WriteLine($" Segment {i}: {loadAddress:X16} {loadSize:X16} {fileOffset:X16} {prot:x2} {name}"); } } } } catch (Exception ex) when(ex is InvalidVirtualAddressException || ex is BadInputFormatException) { Trace.TraceError($"Exception displaying module segments: {ex}"); } }
static void TLFunctionsForStream(Stream stm, PlatformName platform, Dictionary <string, string> functions) { List <NListEntry> entries = null; List <MachOFile> macho = MachO.Read(stm, null).ToList(); MachOFile file = macho [0]; List <SymTabLoadCommand> symbols = file.load_commands.OfType <SymTabLoadCommand> ().ToList(); NListEntryType nlet = symbols [0].nlist [0].EntryType; entries = symbols [0].nlist. Where((nle, i) => nle.IsPublic && nle.EntryType == NListEntryType.InSection).ToList(); bool isOldVersion = IsOldVersion(entries); foreach (var entry in entries) { if (!entry.IsSwiftEntryPoint()) { continue; } TLDefinition def = null; try { def = Decomposer.Decompose(entry.str, isOldVersion, Offset(entry)); } catch { } if (def != null) { // this skips over privatized names var tlf = def as TLFunction; if (tlf != null && tlf.Name != null && tlf.Name.Name.Contains("...")) { continue; } if (tlf?.Name != null) { if (!functions.ContainsKey(tlf.Name.Name)) { functions.Add(tlf.Name.Name, tlf.MangledName); } } } } }
/// <summary> /// Opens and returns an MachOFile instance from the local file path /// </summary> /// <param name="filePath">MachO file to open</param> /// <returns>MachOFile instance or null</returns> private MachOFile OpenMachOFile(string filePath) { Stream stream = OpenFile(filePath); if (stream is not null) { try { var machoFile = new MachOFile(new StreamAddressSpace(stream), position: 0, dataSourceIsVirtualAddressSpace: false); if (!machoFile.IsValid()) { Trace.TraceError($"OpenMachOFile: not a valid file"); return(null); } return(machoFile); } catch (Exception ex) when(ex is InvalidVirtualAddressException || ex is BadInputFormatException || ex is IOException) { Trace.TraceError($"OpenMachOFile: exception {ex.Message}"); } } return(null); }
public MachOFileKeyGenerator(ITracer tracer, MachOFile machoFile, string path) : base(tracer) { _machoFile = machoFile; _path = path; }
static ModuleInventory FromStreamInto(Stream stm, ModuleInventory inventory, ErrorHandling errors, string fileName = null) { Ex.ThrowOnNull(errors, "errors"); Ex.ThrowOnNull(stm, "stm"); OffsetStream osstm = null; List <NListEntry> entries = null; try { List <MachOFile> macho = MachO.Read(stm, null).ToList(); MachOFile file = macho [0]; List <SymTabLoadCommand> symbols = file.load_commands.OfType <SymTabLoadCommand> ().ToList(); NListEntryType nlet = symbols [0].nlist [0].EntryType; entries = symbols [0].nlist. Where((nle, i) => nle.IsPublic && nle.EntryType == NListEntryType.InSection).ToList(); inventory.Architecture = file.Architecture; osstm = new OffsetStream(stm, file.StartOffset); } catch (Exception e) { errors.Add(ErrorHelper.CreateError(ReflectorError.kCantHappenBase + 58, e, "Unable to retrieve functions from {0}: {1}", fileName ?? "stream", e.Message)); return(inventory); } bool isOldVersion = IsOldVersion(entries); foreach (var entry in entries) { if (!entry.IsSwiftEntryPoint()) { continue; } TLDefinition def = null; try { def = Decomposer.Decompose(entry.str, isOldVersion, Offset(entry)); } catch (RuntimeException e) { var except = new RuntimeException(e.Code, false, e, $"error decomposing {entry.str}: {e.Message}, skipping"); errors.Add(except); } catch (Exception e) { var except = new RuntimeException(ReflectorError.kDecomposeBase + 0, false, e, $"unexpected error handling {entry.str}: {e.Message}, skipping."); errors.Add(except); } if (def != null) { // this skips over privatized names var tlf = def as TLFunction; if (tlf != null && tlf.Name != null && tlf.Name.Name.Contains("...")) { continue; } try { inventory.Add(def, osstm); } catch (RuntimeException e) { e = new RuntimeException(e.Code, e.Error, $"error dispensing top level definition of type {def.GetType ().Name} decomposed from {entry.str}: {e.Message}"); errors.Add(e); } } else { var ex = ErrorHelper.CreateWarning(ReflectorError.kInventoryBase + 18, $"entry {entry.str} uses an unsupported swift feature, skipping."); errors.Add(ex); } } return(inventory); }
public FileEntryPair(MachOFile file, NListEntry entry) { File = file; Entry = entry; }
public FileSymbolPair(MachOFile file, string symbol) { File = file; Symbol = symbol; }
public static bool AllFiles(MachOFile file) { return(true); }
/// <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="config">Target configuration: Windows, Linux or OSX</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> private void LoadNativeSymbols( IntPtr self, SymbolFileCallback callback, IntPtr parameter, RuntimeConfiguration config, string moduleFilePath, ulong address, uint size) { if (_symbolService.IsSymbolStoreEnabled) { try { Stream stream = MemoryService.CreateMemoryStream(address, size); KeyGenerator generator = null; if (config == RuntimeConfiguration.UnixCore) { var elfFile = new ELFFile(new StreamAddressSpace(stream), 0, true); generator = new ELFFileKeyGenerator(Tracer.Instance, elfFile, moduleFilePath); } else if (config == RuntimeConfiguration.OSXCore) { var machOFile = new MachOFile(new StreamAddressSpace(stream), 0, true); generator = new MachOFileKeyGenerator(Tracer.Instance, machOFile, moduleFilePath); } else if (config == RuntimeConfiguration.WindowsCore || config == RuntimeConfiguration.WindowsDesktop) { var peFile = new PEFile(new StreamAddressSpace(stream), true); generator = new PEFileKeyGenerator(Tracer.Instance, peFile, moduleFilePath); } else { Trace.TraceError("LoadNativeSymbols: unsupported config {0}", config); } if (generator != null) { IEnumerable <SymbolStoreKey> keys = generator.GetKeys(KeyTypeFlags.SymbolKey | KeyTypeFlags.DacDbiKeys); foreach (SymbolStoreKey key in keys) { string moduleFileName = Path.GetFileName(key.FullPathName); Trace.TraceInformation("{0} {1}", key.FullPathName, key.Index); string downloadFilePath = _symbolService.DownloadFile(key); if (downloadFilePath != null) { Trace.TraceInformation("{0}: {1}", moduleFileName, downloadFilePath); callback(parameter, moduleFileName, downloadFilePath); } } } } catch (Exception ex) when (ex is DiagnosticsException || ex is BadInputFormatException || ex is InvalidVirtualAddressException || ex is ArgumentOutOfRangeException || ex is IndexOutOfRangeException || ex is TaskCanceledException) { Trace.TraceError("{0} address {1:X16}: {2}", moduleFilePath, address, ex.Message); } } }
/// <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); } } }
internal void VerifyCoreDump() { foreach (string inputFile in GetInputFiles()) { Console.WriteLine($"{inputFile}"); using Stream inputStream = File.Open(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read); var dataSource = new StreamAddressSpace(inputStream); var core = new ELFCoreFile(dataSource); if (Tracer.Enabled) { foreach (ELFProgramSegment segment in core.Segments) { Tracer.Information("{0:X16}-{1:X16} {2:X8} {3:X8} {4}", segment.Header.VirtualAddress.Value, segment.Header.VirtualAddress + segment.Header.VirtualSize, segment.Header.FileOffset.Value, (ulong)segment.Header.FileSize, segment.Header.Type); } } foreach (ELFLoadedImage image in core.LoadedImages) { Console.WriteLine("{0:X16} {1}", image.LoadAddress, image.Path); Exception elfException = null; Exception machoException = null; Exception peException = null; try { ELFFile elfFile = image.Image; if (elfFile.IsValid()) { try { byte[] buildid = elfFile.BuildID; } catch (Exception ex) { Console.WriteLine(" ELF file invalid build id - {0}", ex.Message); } foreach (ELFProgramSegment segment in elfFile.Segments) { Tracer.Verbose(" {0:X16}-{1:X16} file off {2:X8} file size {3:X8} {4}", segment.Header.VirtualAddress.Value, segment.Header.VirtualAddress + segment.Header.VirtualSize, segment.Header.FileOffset.Value, (ulong)segment.Header.FileSize, segment.Header.Type); if (segment.Header.Type == ELFProgramHeaderType.Note || segment.Header.Type == ELFProgramHeaderType.Dynamic || segment.Header.Type == ELFProgramHeaderType.GnuEHFrame) { try { byte[] data = segment.Contents.Read(0, (uint)segment.Header.VirtualSize); } catch (Exception ex) { Console.WriteLine(" ELF file segment {0} virt addr {1:X16} virt size {2:X8} INVALID - {3}", segment.Header.Type, segment.Header.VirtualAddress, segment.Header.VirtualSize, ex.Message); } } } // The ELF module was valid try next module continue; } } catch (Exception ex) { elfException = ex; } IAddressSpace addressSpace = new RelativeAddressSpace(core.DataSource, image.LoadAddress, core.DataSource.Length); try { var machoFile = new MachOFile(addressSpace); if (machoFile.IsValid()) { try { byte[] uuid = machoFile.Uuid; } catch (Exception ex) { Console.WriteLine(" MachO file invalid uuid - {0}", ex.Message); } foreach (MachSegment segment in machoFile.Segments) { Tracer.Verbose(" {0:X16}-{1:X16} offset {2:X16} size {3:X16} {4} {5}", (ulong)segment.LoadCommand.VMAddress, segment.LoadCommand.VMAddress + segment.LoadCommand.VMSize, (ulong)segment.LoadCommand.FileOffset, (ulong)segment.LoadCommand.FileSize, segment.LoadCommand.Command, segment.LoadCommand.SegName); foreach (MachSection section in segment.Sections) { Tracer.Verbose(" addr {0:X16} size {1:X16} offset {2:X8} {3}", (ulong)section.Address, (ulong)section.Size, section.Offset, section.SectionName); } } // The MachO module was valid try next module continue; } } catch (Exception ex) { machoException = ex; } try { var peFile = new PEFile(addressSpace, true); if (peFile.IsValid()) { // The PE module was valid try next module continue; } } catch (Exception ex) { peException = ex; } Console.WriteLine("{0:X16} invalid image - {1}", image.LoadAddress, image.Path); if (elfException != null) { Tracer.Verbose("ELF {0}", elfException.Message); } if (machoException != null) { Tracer.Verbose("MachO {0}", machoException.Message); } if (peException != null) { Tracer.Verbose("PE {0}", peException.Message); } } ulong segmentsTotal = core.Segments.Max(s => s.Header.FileOffset + s.Header.FileSize); if (segmentsTotal > dataSource.Length) { Console.WriteLine($"ERROR: Core file not complete: file size 0x{dataSource.Length:X8} segments total 0x{segmentsTotal:X8}"); } } }
// return the ids found in a macho file List<Guid> GetUuids(MachOFile file) { var result = new List<Guid> (); foreach (var cmd in file.load_commands) { if (cmd is UuidCommand) { var uuidCmd = cmd as UuidCommand; result.Add (new Guid (uuidCmd.uuid)); } } return result; }