/// <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); }
public string GetSymbolFileName() { if (InitializeValue(Flags.InitializeSymbolFileName)) { if (Target.OperatingSystem == OSPlatform.Linux) { try { Stream stream = ModuleService.RawMemoryService.CreateMemoryStream(); var elfFile = new ELFFile(new StreamAddressSpace(stream), ImageBase, true); if (elfFile.IsValid()) { ELFSection section = elfFile.FindSectionByName(".gnu_debuglink"); if (section != null) { _symbolFileName = section.Contents.Read <string>(0); } } } catch (Exception ex) when (ex is InvalidVirtualAddressException || ex is ArgumentOutOfRangeException || ex is IndexOutOfRangeException || ex is BadInputFormatException) { Trace.TraceWarning("ELF .gnu_debuglink section in {0}: {1}", this, ex.Message); } } } return(_symbolFileName); }
public void CheckIndexingInfo() { using (Stream libcoreclr = TestUtilities.OpenCompressedFile("TestBinaries/libcoreclr.so.gz")) { StreamAddressSpace dataSource = new StreamAddressSpace(libcoreclr); ELFFile elf = new ELFFile(dataSource); Assert.True(elf.IsValid()); Assert.True(elf.Header.Type == ELFHeaderType.Shared); string buildId = TestUtilities.ToHexString(elf.BuildID); //this is the build id for libcoreclr.so from package: // https://dotnet.myget.org/feed/dotnet-core/package/nuget/runtime.ubuntu.14.04-x64.Microsoft.NETCore.Runtime.CoreCLR/2.0.0-preview3-25428-01 Assert.Equal("ef8f58a0b402d11c68f78342ef4fcc7d23798d4c", buildId); } // 32 bit arm ELF binary using (Stream apphost = TestUtilities.OpenCompressedFile("TestBinaries/apphost.gz")) { StreamAddressSpace dataSource = new StreamAddressSpace(apphost); ELFFile elf = new ELFFile(dataSource); Assert.True(elf.IsValid()); Assert.True(elf.Header.Type == ELFHeaderType.Executable); string buildId = TestUtilities.ToHexString(elf.BuildID); //this is the build id for apphost from package: // https://dotnet.myget.org/F/dotnet-core/symbols/runtime.linux-arm.Microsoft.NETCore.DotNetAppHost/2.1.0-preview2-25512-03 Assert.Equal("316d55471a8d5ebd6f2cb0631f0020518ab13dc0", buildId); } }
/// <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 static bool TryGetElfIndex(Stream stream, out string uuid) { uuid = null; try { var elf = new ELFFile(new StreamAddressSpace(stream)); if (!elf.Ident.IsIdentMagicValid.Check()) { return(false); } if (elf.BuildID == null || elf.BuildID.Length != 20) { return(false); } uuid = string.Concat(elf.BuildID.Select(b => b.ToString("x2"))).ToLowerInvariant(); return(true); } catch (InputParsingException) { return(false); } }
/// <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 static List<ProgrammableRegion> BuildFLASHImages(string targetPath, Dictionary<string, string> bspDict, Dictionary<string, string> debugMethodConfig, LiveMemoryLineHandler lineHandler) { string bspPath = bspDict["SYS:BSP_ROOT"]; string toolchainPath = bspDict["SYS:TOOLCHAIN_ROOT"]; string freq, mode, size; debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_freq", out freq); debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_mode", out mode); debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_size", out size); string partitionTable, bootloader, txtAppOffset; bspDict.TryGetValue("com.sysprogs.esp32.partition_table_file", out partitionTable); bspDict.TryGetValue("com.sysprogs.esp32.bootloader_file", out bootloader); bspDict.TryGetValue("com.sysprogs.esp32.app_offset", out txtAppOffset); uint appOffset; if (txtAppOffset == null) appOffset = 0; else if (txtAppOffset.StartsWith("0x")) uint.TryParse(txtAppOffset.Substring(2), NumberStyles.HexNumber, null, out appOffset); else uint.TryParse(txtAppOffset, out appOffset); if (appOffset == 0) throw new Exception("Application FLASH offset not defined. Please check your settings."); partitionTable = VariableHelper.ExpandVariables(partitionTable, bspDict, debugMethodConfig); bootloader = VariableHelper.ExpandVariables(bootloader, bspDict, debugMethodConfig); if (!string.IsNullOrEmpty(partitionTable) && !Path.IsPathRooted(partitionTable)) partitionTable = Path.Combine(bspDict["SYS:PROJECT_DIR"], partitionTable); if (!string.IsNullOrEmpty(bootloader) && !Path.IsPathRooted(bootloader)) bootloader = Path.Combine(bspDict["SYS:PROJECT_DIR"], bootloader); if (string.IsNullOrEmpty(partitionTable) || !File.Exists(partitionTable)) throw new Exception("Unspecified or missing partition table file: " + partitionTable); if (string.IsNullOrEmpty(bootloader) || !File.Exists(bootloader)) throw new Exception("Unspecified or missing bootloader file: " + bootloader); List<ProgrammableRegion> regions = new List<ProgrammableRegion>(); using (var elfFile = new ELFFile(targetPath)) { string pathBase = Path.Combine(Path.GetDirectoryName(targetPath), Path.GetFileName(targetPath)); var img = ESP8266BinaryImage.MakeESP32ImageFromELFFile(elfFile, new ESP8266BinaryImage.ParsedHeader(freq, mode, size)); //Bootloader/partition table offsets are hardcoded in ESP-IDF regions.Add(new ProgrammableRegion { FileName = bootloader, Offset = 0x1000, Size = GetFileSize(bootloader) }); regions.Add(new ProgrammableRegion { FileName = partitionTable, Offset = 0x8000, Size = GetFileSize(partitionTable) }); string fn = pathBase + "-esp32.bin"; using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { img.Save(fs); regions.Add(new ProgrammableRegion { FileName = fn, Offset = (int)appOffset, Size = (int)fs.Length }); } } return regions; }
/// <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 ELFFile instance for it. /// </summary> /// <param name="module">module instance</param> /// <returns>ELFFile instance or null</returns> internal ELFFile GetELFFile(IModule module) { string downloadFilePath = null; ELFFile elfFile = 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 = ELFFileKeyGenerator.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("GetELFFile: 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($"GetELFFile: OpenRead exception {ex.Message}"); return(null); } try { elfFile = new ELFFile(new StreamAddressSpace(stream), position: 0, isDataSourceVirtualAddressSpace: false); if (!elfFile.IsValid()) { return(null); } } catch (Exception ex) when(ex is InvalidVirtualAddressException || ex is BadInputFormatException || ex is IOException) { Trace.TraceError($"GetELFFile: exception {ex.Message}"); return(null); } } return(elfFile); }
/// <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); }
/// <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 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); }
public void CheckFreeBSDIndexingInfo() { using (Stream stream = File.OpenRead("TestBinaries/ilasm.dbg")) { StreamAddressSpace dataSource = new StreamAddressSpace(stream); ELFFile elf = new ELFFile(dataSource); Assert.True(elf.IsValid()); Assert.True(elf.Header.Type == ELFHeaderType.Executable); string buildId = TestUtilities.ToHexString(elf.BuildID); Assert.Equal("4a91e41002a1307ef4097419d7875df001969daa", buildId); } }
public void CheckDbgIndexingInfo() { using (Stream stream = TestUtilities.OpenCompressedFile("TestBinaries/libcoreclrtraceptprovider.so.dbg.gz")) { StreamAddressSpace dataSource = new StreamAddressSpace(stream); ELFFile elf = new ELFFile(dataSource); Assert.True(elf.IsValid()); Assert.True(elf.Header.Type == ELFHeaderType.Shared); string buildId = TestUtilities.ToHexString(elf.BuildID); Assert.Equal("ce4ce0558d878a05754dff246ccea2a70a1db3a8", buildId); } }
public void CheckCustomNamedBuildIdSection() { using (Stream stream = File.OpenRead("TestBinaries/renamed_build_id_section")) { StreamAddressSpace dataSource = new StreamAddressSpace(stream); ELFFile elf = new ELFFile(dataSource); Assert.True(elf.IsValid()); Assert.True(elf.Header.Type == ELFHeaderType.Shared); string buildId = TestUtilities.ToHexString(elf.BuildID); Assert.Equal("1bd6a199dcb6f234558d9439cfcbba2727f1e1d9", buildId); } }
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 CheckIndexingInfo() { using (FileStream libcoreclr = File.OpenRead("TestBinaries\\libcoreclr.so")) { StreamAddressSpace dataSource = new StreamAddressSpace(libcoreclr); ELFFile elf = new ELFFile(dataSource); string buildId = string.Concat(elf.BuildID.Select(b => b.ToString("x2"))); //this is the build id for libcoreclr.so from package: // https://dotnet.myget.org/feed/dotnet-core/package/nuget/runtime.ubuntu.14.04-x64.Microsoft.NETCore.Runtime.CoreCLR/1.0.2 Assert.Equal("bc0d85e535168f1a21a2dd79a466b3988bd274aa", buildId); } }
public static ELFProcess LoadProcess_FromELFExe(File ELFExeFile, bool UserMode) { //bool reenable = Scheduler.Enabled; //if (reenable) //{ // Scheduler.Disable(); //} ELFProcess result = new ELFFile(ELFExeFile).LoadExecutable(UserMode); //if (reenable) //{ // Scheduler.Enable(); //} return(result); }
public static ELFSharedObject LoadLibrary_FromELFSO(File ELFSharedObjectFile, ELFProcess theProcess) { //bool reenable = Scheduler.Enabled; //if (reenable) //{ // Scheduler.Disable(); //} ELFSharedObject result = new ELFFile(ELFSharedObjectFile).LoadSharedObject(theProcess); //if (reenable) //{ // Scheduler.Enable(); //} return(result); }
void DisplaySegments(ulong address) { try { if (Target.OperatingSystem == OSPlatform.Linux) { Stream stream = MemoryService.CreateMemoryStream(); var elfFile = new ELFFile(new StreamAddressSpace(stream), address, true); if (elfFile.IsValid()) { 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 if (Target.OperatingSystem == OSPlatform.OSX) { Stream stream = MemoryService.CreateMemoryStream(); MachOFile machOFile = new(new StreamAddressSpace(stream), address, true); if (machOFile.IsValid()) { 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}"); } }
/// <summary> /// Finds or downloads the ELF module and creates a ELFFile instance for it. /// </summary> /// <param name="module">module instance</param> /// <returns>ELFFile instance or null</returns> internal ELFFile GetELFFile(IModule module) { if (module.BuildId.IsDefaultOrEmpty) { Trace.TraceWarning($"GetELFFile: module {module.FileName} has no build id"); return(null); } SymbolStoreKey moduleKey = ELFFileKeyGenerator.GetKeys(KeyTypeFlags.IdentityKey, module.FileName, module.BuildId.ToArray(), symbolFile: false, symbolFileName: null).SingleOrDefault(); if (moduleKey is null) { Trace.TraceWarning($"GetELFFile: no index generated for module {module.FileName} "); return(null); } if (File.Exists(module.FileName)) { ELFFile elfFile = OpenELFFile(module.FileName); if (elfFile is not null) { var generator = new ELFFileKeyGenerator(Tracer.Instance, elfFile, module.FileName); IEnumerable <SymbolStoreKey> keys = generator.GetKeys(KeyTypeFlags.IdentityKey); foreach (SymbolStoreKey key in keys) { if (moduleKey.Equals(key)) { Trace.TraceInformation("GetELFFile: local file match {0}", module.FileName); return(elfFile); } } } } // 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("GetELFFile: downloaded {0}", downloadFilePath); return(OpenELFFile(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}"); } }
public string ComputeIndexKey(string path, Stream fileStream) { try { string extension = Path.GetExtension(path); if (!string.IsNullOrEmpty(extension) && extension != ".so" && extension != ".dbg") { return(null); } ELFFile elf = new ELFFile(new StreamAddressSpace(fileStream)); if (!elf.Ident.IsIdentMagicValid.Check()) { return(null); } if (elf.BuildID == null || elf.BuildID.Length != 20) { Console.WriteLine("WARNING: ELF file is missing build id - " + path); return(null); } string filename = Path.GetFileName(path).ToLowerInvariant(); StringBuilder key = new StringBuilder(); key.Append(filename); key.Append("/elf-buildid-"); //TODO: it would be nice to check if the file is really stripped rather than blindly //trusting the file extension bool isStripped = extension != ".dbg"; key.Append(isStripped ? "" : "sym-"); key.Append(string.Concat(elf.BuildID.Select(b => b.ToString("x2"))).ToLowerInvariant()); key.Append("/"); key.Append(filename); return(key.ToString()); } catch (InputParsingException) { return(null); } }
/// <summary> /// Opens and returns an ELFFile instance from the local file path /// </summary> /// <param name="filePath">ELF file to open</param> /// <returns>ELFFile instance or null</returns> private ELFFile OpenELFFile(string filePath) { Stream stream = OpenFile(filePath); if (stream is not null) { try { ELFFile elfFile = new ELFFile(new StreamAddressSpace(stream), position: 0, isDataSourceVirtualAddressSpace: false); if (!elfFile.IsValid()) { Trace.TraceError($"OpenELFFile: not a valid file"); return(null); } return(elfFile); } catch (Exception ex) when(ex is InvalidVirtualAddressException || ex is BadInputFormatException || ex is IOException) { Trace.TraceError($"OpenELFFile: exception {ex.Message}"); } } return(null); }
public CustomStartupSequence BuildSequence(string targetPath, Dictionary<string, string> bspDict, Dictionary<string, string> debugMethodConfig, LiveMemoryLineHandler lineHandler) { if (!File.Exists(targetPath)) throw new Exception(targetPath + " not found. Debugging will not be possible."); bool stubFound = false; using (var elf = new ELFFile(targetPath)) { foreach (var sym in elf.LoadAllSymbols()) { if (sym.Name == "gdbstub_init") { stubFound = true; break; } } } if (!stubFound) { var wrp = new ResultWrapper(); _SyncContext.Send(o => ((ResultWrapper)o).Result = MessageBox.Show("The programmed image does not contain the GDB stub. Do you want to open instructions on debugging with ESP8266 GDB stub?", "VisualGDB", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Information), wrp); switch(wrp.Result) { case DialogResult.Yes: Process.Start("http://visualgdb.com/KB/esp8266gdbstub"); goto case DialogResult.Cancel; case DialogResult.No: break; case DialogResult.Cancel: throw new OperationCanceledException(); } } string val; if (!debugMethodConfig.TryGetValue("com.sysprogs.esp8266.program_flash", out val) || val != "0") { var wrp = new ResultWrapper(); _SyncContext.Send(o => ((ResultWrapper)o).Result = MessageBox.Show("Please reboot your ESP8266 into the bootloader mode and press OK.", "VisualGDB", MessageBoxButtons.OKCancel, MessageBoxIcon.Information), wrp); if (wrp.Result != DialogResult.OK) throw new OperationCanceledException(); using (var serialPort = new SerialPortStream(debugMethodConfig["com.sysprogs.esp8266.gdbstub.com_port"], int.Parse(debugMethodConfig["com.sysprogs.esp8266.gdbstub.bl_baud"]), System.IO.Ports.Handshake.None)) { serialPort.AllowTimingOutWithZeroBytes = true; int resetDelay; if (!debugMethodConfig.TryGetValue("com.sysprogs.esp8266.reset_delay", out val) || !int.TryParse(val, out resetDelay)) resetDelay = 25; string seq; debugMethodConfig.TryGetValue("com.sysprogs.esp8266.gdbstub.reset_sequence", out seq); ESP8266BootloaderClient client = new ESP8266BootloaderClient(serialPort, resetDelay, seq); client.Sync(); var regions = ESP8266StartupSequence.BuildFLASHImages(targetPath, bspDict, debugMethodConfig, lineHandler); ProgramProgressForm frm = null; _SyncContext.Post(o => { frm = new ProgramProgressForm(); frm.ShowDialog(); }, null); int totalSize = 0; foreach (var r in regions) totalSize += r.Size; ESP8266BootloaderClient.BlockWrittenHandler handler = (s, a, len) => frm.UpdateProgressAndThrowIfCanceled(a, len, totalSize); bool useDIO = false; try { client.BlockWritten += handler; foreach (var r in regions) { var data = File.ReadAllBytes(r.FileName); if (r.Offset == 0 && data.Length >= 4) useDIO = (data[2] == 2); client.ProgramFLASH((uint)r.Offset, data); } } finally { client.BlockWritten -= handler; _SyncContext.Post(o => { frm.Close(); frm.Dispose(); }, null); } client.RunProgram(useDIO, false); } } string tmp = null; if (debugMethodConfig?.TryGetValue("SYS:PROGRAM_WITHOUT_DEBUGGING", out tmp) == true && tmp == "1") return null; //Suppress connecting to gdb return new CustomStartupSequence { Steps = new List<CustomStartStep> { new CustomStartStep("set serial baud $$com.sysprogs.esp8266.gdbstub.baud$$"), new CustomStartStep(@"target remote \\.\$$com.sysprogs.esp8266.gdbstub.com_port$$"), } }; }
static void Run(string[] args) { Console.WriteLine("ESP8266 image tool v1.0 [http://sysprogs.com/]"); if (args.Length < 1) { PrintUsage(); return; } string port = null; string bootloader = null; int otaPort = 0; int baud = 115200; bool erase = false; bool esp32mode = false; List <string> files = new List <string>(); string frequency = null, mode = null, size = null; for (int i = 0; i < args.Length; i++) { if (args[i] == "--esp32") { esp32mode = true; } else if (args[i] == "--boot") { if (i >= (args.Length - 1)) { throw new Exception("--boot must be followed by the bootloader image"); } bootloader = args[++i]; } else if (args[i] == "--program") { if (i >= (args.Length - 1)) { throw new Exception("--program must be followed by port number"); } port = args[++i]; if ((i + 1) < args.Length && !args[i + 1].StartsWith("-")) { baud = int.Parse(args[++i]); } } else if (args[i] == "--mode") { if (i >= (args.Length - 1)) { throw new Exception("--mode must be followed by FLASH mode"); } mode = args[++i]; } else if (args[i] == "--size") { if (i >= (args.Length - 1)) { throw new Exception("--size must be followed by FLASH mode"); } size = args[++i]; } else if (args[i] == "--freq") { if (i >= (args.Length - 1)) { throw new Exception("--freq must be followed by FLASH mode"); } frequency = args[++i]; } else if (args[i].ToLower() == "--ota") { if (i >= (args.Length - 1)) { throw new Exception("--OTA must be followed by port number"); } otaPort = int.Parse(args[++i]); } else if (args[i] == "--erase") { erase = true; } else { files.Add(args[i]); } } ESP8266BinaryImage.ParsedHeader hdr = new ESP8266BinaryImage.ParsedHeader(frequency, mode, size); Console.WriteLine("FLASH Parameters:"); Console.WriteLine("\tFrequency: " + DumpEnumValue(hdr.Frequency)); Console.WriteLine("\tMode: " + DumpEnumValue(hdr.Mode)); Console.WriteLine("\tSize: " + DumpEnumValue(hdr.Size)); if (otaPort != 0) { OTAServer.ServeOTAFiles(otaPort, hdr, files.ToArray()); return; } foreach (var elf in files) { string pathBase = Path.ChangeExtension(elf, ".").TrimEnd('.'); List <ProgrammableRegion> regions = new List <ProgrammableRegion>(); Console.WriteLine("Processing " + elf + "..."); using (var elfFile = new ELFFile(elf)) { string status; if (esp32mode) { var img = ESP8266BinaryImage.MakeESP32ImageFromELFFile(elfFile, hdr); string fn = pathBase + "-esp32.bin"; using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { img.Save(fs); regions.Add(new ProgrammableRegion { FileName = fn, Offset = 0, Size = (int)fs.Length }); } } else { int appMode = ESP8266BinaryImage.DetectAppMode(elfFile, out status); Console.WriteLine(status); if (appMode == 0) { var img = ESP8266BinaryImage.MakeNonBootloaderImageFromELFFile(elfFile, hdr); string fn = pathBase + "-0x00000.bin"; using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { img.Save(fs); regions.Add(new ProgrammableRegion { FileName = fn, Offset = 0, Size = (int)fs.Length }); } foreach (var sec in ESP8266BinaryImage.GetFLASHSections(elfFile)) { fn = string.Format("{0}-0x{1:x5}.bin", pathBase, sec.OffsetInFLASH); using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { fs.Write(sec.Data, 0, sec.Data.Length); regions.Add(new ProgrammableRegion { FileName = fn, Offset = (int)sec.OffsetInFLASH, Size = sec.Data.Length }); } } } else { string fn; var img = ESP8266BinaryImage.MakeBootloaderBasedImageFromELFFile(elfFile, hdr, appMode); if (bootloader == null) { Console.WriteLine("Warning: no bootloader specified. Skipping bootloader..."); } else { if (!File.Exists(bootloader)) { throw new Exception(bootloader + " not found. Cannot program OTA images."); } byte[] data = File.ReadAllBytes(bootloader); data[2] = (byte)img.Header.Mode; data[3] = (byte)(((byte)img.Header.Size << 4) | (byte)img.Header.Frequency); fn = string.Format("{0}-boot.bin", pathBase); File.WriteAllBytes(fn, data); regions.Add(new ProgrammableRegion { FileName = fn, Offset = 0, Size = File.ReadAllBytes(fn).Length }); } fn = string.Format("{0}-user{1}.bin", pathBase, appMode); using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { img.Save(fs); regions.Add(new ProgrammableRegion { FileName = fn, Offset = (int)img.BootloaderImageOffset, Size = (int)fs.Length }); } } } } if (port != null) { using (var serialPort = new SerialPortStream(port, baud, System.IO.Ports.Handshake.None) { AllowTimingOutWithZeroBytes = true }) { ESP8266BootloaderClient client = new ESP8266BootloaderClient(serialPort, 50, null); Console.WriteLine("Connecting to bootloader on {0}...", port); client.Sync(); if (erase) { Console.WriteLine("Erasing FLASH..."); client.EraseFLASH(); Console.WriteLine("FLASH erased. Please restart your ESP8266 into the bootloader mode again.\r\nPress any key when done..."); Console.ReadKey(); client.Sync(); } foreach (var region in regions) { DateTime start = DateTime.Now; Console.WriteLine("Programming " + Path.GetFileName(region.FileName) + "..."); var tracker = new ProgressTracker(region); client.BlockWritten += tracker.BlockWritten; client.ProgramFLASH((uint)region.Offset, File.ReadAllBytes(region.FileName)); client.BlockWritten -= tracker.BlockWritten; Console.WriteLine("\rProgrammed in {0} seconds ", (int)(DateTime.Now - start).TotalSeconds); } } } else { int fileNameLen = Path.GetFileName(args[0]).Length + 10; Console.WriteLine("\r\nCreated the following files:"); Console.WriteLine("File".PadRight(fileNameLen) + " FLASH Offset Size"); foreach (var region in regions) { Console.WriteLine(Path.GetFileName(region.FileName).PadRight(fileNameLen) + " " + string.Format("0x{0:x8} {1}KB", region.Offset, region.Size / 1024)); } } } }
public static List<ProgrammableRegion> BuildFLASHImages(string targetPath, Dictionary<string, string> bspDict, Dictionary<string, string> debugMethodConfig, LiveMemoryLineHandler lineHandler) { string bspPath = bspDict["SYS:BSP_ROOT"]; string toolchainPath = bspDict["SYS:TOOLCHAIN_ROOT"]; Regex rgBinFile = new Regex("^" + Path.GetFileName(targetPath) + "-0x([0-9a-fA-F]+)\\.bin$", RegexOptions.IgnoreCase); foreach (var fn in Directory.GetFiles(Path.GetDirectoryName(targetPath))) if (rgBinFile.IsMatch(Path.GetFileName(fn))) File.Delete(fn); string freq, mode, size; debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_freq", out freq); debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_mode", out mode); debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_size", out size); List<ProgrammableRegion> regions = new List<ProgrammableRegion>(); using (var elfFile = new ELFFile(targetPath)) { string pathBase = Path.Combine(Path.GetDirectoryName(targetPath), Path.GetFileName(targetPath)); string status; int appMode = ESP8266BinaryImage.DetectAppMode(elfFile, out status); if (status != null && lineHandler != null) lineHandler(status, true); if (appMode == 0) { var img = ESP8266BinaryImage.MakeNonBootloaderImageFromELFFile(elfFile, new ESP8266BinaryImage.ParsedHeader(freq, mode, size)); string fn = pathBase + "-0x00000.bin"; using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { img.Save(fs); regions.Add(new ProgrammableRegion { FileName = fn, Offset = 0, Size = (int)fs.Length }); } foreach (var sec in ESP8266BinaryImage.GetFLASHSections(elfFile)) { fn = string.Format("{0}-0x{1:x5}.bin", pathBase, sec.OffsetInFLASH); using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { fs.Write(sec.Data, 0, sec.Data.Length); regions.Add(new ProgrammableRegion { FileName = fn, Offset = (int)sec.OffsetInFLASH, Size = sec.Data.Length }); } } } else { var img = ESP8266BinaryImage.MakeBootloaderBasedImageFromELFFile(elfFile, new ESP8266BinaryImage.ParsedHeader(freq, mode, size), appMode); string bspRoot, bootloader; if (!bspDict.TryGetValue("SYS:BSP_ROOT", out bspRoot) || !bspDict.TryGetValue("com.sysprogs.esp8266.bootloader", out bootloader)) throw new Exception("Cannot determine bootloader image path. Please check your BSP consistency."); string fn = Path.Combine(bspRoot, bootloader); if (!File.Exists(fn)) throw new Exception(fn + " not found. Cannot program OTA images."); byte[] data = File.ReadAllBytes(fn); data[2] = (byte)img.Header.Mode; data[3] = (byte)(((byte)img.Header.Size << 4) | (byte)img.Header.Frequency); fn = string.Format("{0}-0x00000.bin", pathBase); File.WriteAllBytes(fn, data); regions.Add(new ProgrammableRegion { FileName = fn, Offset = 0, Size = File.ReadAllBytes(fn).Length }); fn = string.Format("{0}-0x{1:x5}.bin", pathBase, img.BootloaderImageOffset); using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { img.Save(fs); regions.Add(new ProgrammableRegion { FileName = fn, Offset = (int)img.BootloaderImageOffset, Size = (int)fs.Length }); } } } return regions; }
public CustomStartupSequence BuildSequence(string targetPath, Dictionary<string, string> bspDict, Dictionary<string, string> debugMethodConfig, LiveMemoryLineHandler lineHandler) { bool isOpenOCD = debugMethodConfig.ContainsKey("com.sysprogs.esp8266.openocd.iface_script"); List<CustomStartStep> cmds = new List<CustomStartStep>(); cmds.Add(new CustomStartStep(isOpenOCD ? "mon reset halt" : "maint packet R", "-exec-next-instruction", "set $com_sysprogs_esp8266_wdcfg=0", "set $vecbase=0x40000000", "$$com.sysprogs.esp8266.interrupt_disable_command$$", "set $ccompare=0", "set $intclear=-1", "set $intenable=0", "set $eps2=0x20", "set $icountlevel=0")); var result = new CustomStartupSequence { Steps = cmds }; string val; if (bspDict.TryGetValue("com.sysprogs.esp8266.load_flash", out val) && val == "1") //Not a FLASHless project { if (debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.program_flash", out val) && val != "0") { string bspPath = bspDict["SYS:BSP_ROOT"]; List<ProgrammableRegion> regions = BuildFLASHImages(targetPath, bspDict, debugMethodConfig, lineHandler); string loader = bspPath + @"\sysprogs\flashprog\ESP8266FlashProg.bin"; if (!File.Exists(loader)) throw new Exception("FLASH loader not found: " + loader); var parsedLoader = new ParsedFLASHLoader(loader); cmds.Add(new CustomStartStep("print *((int *)0x60000900)", "set *((int *)0x60000900)=0")); cmds.Add(parsedLoader.QueueInvocation(0, "$$com.sysprogs.esp8266.xt-ocd.prog_sector_size$$", "$$com.sysprogs.esp8266.xt-ocd.erase_sector_size$$", null, 0, 0, true)); foreach (var region in regions) parsedLoader.QueueRegionProgramming(cmds, region); } if (!debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_start_mode", out val)) val = "soft_reset"; if (val == "soft_reset") { try { using (var elfFile = new ELFFile(targetPath)) { string pathBase = Path.Combine(Path.GetDirectoryName(targetPath), Path.GetFileName(targetPath)); string status; int appMode = ESP8266BinaryImage.DetectAppMode(elfFile, out status); if (appMode != 0) { if (System.Windows.Forms.MessageBox.Show("The soft reset mechanism is not compatible with the OTA images. Use the jump-to-entry reset instead?", "VisualGDB", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Warning) == System.Windows.Forms.DialogResult.Yes) val = "entry_point"; } } } catch { } } if (val == "soft_reset" || val == "entry_point") { string entry = "0x40000080"; if (val == "entry_point") { using (ELFFile elf = new ELFFile(targetPath)) { foreach (var sec in elf.AllSections) { if (!sec.PresentInMemory || !sec.HasData || sec.Type != ELFFile.SectionType.SHT_PROGBITS) continue; bool isInRAM = false; if (sec.VirtualAddress >= 0x3FFE8000 && sec.VirtualAddress < (0x3FFE8000 + 81920)) isInRAM = true; else if (sec.VirtualAddress >= 0x40100000 && sec.VirtualAddress <= (0x40100000 + 32768)) isInRAM = true; if (isInRAM) { cmds.Add(new CustomStartStep(string.Format("restore {0} binary 0x{1:x} 0x{2:x} 0x{3:x}", targetPath.Replace('\\', '/'), sec.VirtualAddress - sec.OffsetInFile, sec.OffsetInFile, sec.OffsetInFile + sec.Size)) { CheckResult = true, ErrorMessage = "Failed to program the " + sec.SectionName + " section" }); } } } entry = "$$DEBUG:ENTRY_POINT$$"; } cmds.Add(new CustomStartStep("set $ps=0x20", "set $epc2=" + entry, "set $sp=$$DEBUG:INITIAL_STACK_POINTER$$", "set $vecbase=0x40000000", "$$com.sysprogs.esp8266.interrupt_disable_command$$", "set $intclear=-1", "set $intenable=0", "set $eps2=0x20", "set $icountlevel=0")); result.InitialHardBreakpointExpression = "*$$DEBUG:ENTRY_POINT$$"; } else cmds.Add(new CustomStartStep(isOpenOCD ? "mon reset halt" : "maint packet R")); } else { cmds.Add(new CustomStartStep("load", "set $ps=0x20", "set $epc2=$$DEBUG:ENTRY_POINT$$", "set $sp=$$DEBUG:INITIAL_STACK_POINTER$$", "set $vecbase=0x40000000", "$$com.sysprogs.esp8266.interrupt_disable_command$$", "set $ccompare=0", "set $intclear=-1", "set $intenable=0", "set $eps2=0x20", "set $icountlevel=0")); } return result; }
/// <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); } } }
public ELFFileKeyGenerator(ITracer tracer, ELFFile elfFile, string path) : base(tracer) { _elfFile = elfFile; _path = path; }
/// <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}"); } } }
public static void ServeOTAFiles(int port, ESP8266BinaryImage.ParsedHeader hdr, params string[] elfFiles) { TcpListener listener = new TcpListener(port); byte[] buffer = new byte[1024]; OTAImage[] images = new OTAImage[2]; foreach (var fn in elfFiles) if (fn != null) using (var elfFile = new ELFFile(fn)) { string status; int appMode = ESP8266BinaryImage.DetectAppMode(elfFile, out status); if (appMode == 0) { Console.WriteLine(fn + " is not an OTA ELF file. Skipping..."); continue; } var img = ESP8266BinaryImage.MakeBootloaderBasedImageFromELFFile(elfFile, hdr, appMode); using (var ms = new MemoryStream()) { img.Save(ms); images[appMode - 1].Data = ms.ToArray(); images[appMode - 1].File = fn; } } Console.WriteLine($"Ready to serve the following files:"); Console.WriteLine($"APP1: {images[0].File ?? "(none)"}"); Console.WriteLine($"APP2: {images[1].File ?? "(none)"}"); Console.WriteLine($"Waiting for connection on port {port}..."); listener.Start(); for (;;) { using (var sock = listener.AcceptSocket()) { Console.WriteLine($"Incoming connection from {(sock.RemoteEndPoint as IPEndPoint).Address}"); StringBuilder requestBuilder = new StringBuilder(); while (!requestBuilder.ToString().Contains("\r\n\r")) { int done = sock.Receive(buffer); requestBuilder.Append(Encoding.UTF8.GetString(buffer, 0, done)); } string request = requestBuilder.ToString(); string[] parts = request.Split(' '); if (parts.Length < 3) throw new Exception("Invalid HTTP request: " + request); string url = parts[1]; Console.WriteLine("Received request for " + url); int otaIndex = (url.ToLower().Contains("user2") ? 1 : 0); if (images[otaIndex].Data == null) throw new Exception($"No OTA image for app{otaIndex + 1} is provided. Please check your linker scripts."); string reply = string.Format("HTTP/1.0 200 OK\r\nContent-Type: application/octet-stream\r\nContent-Length: {0}\r\n\r\n", images[otaIndex].Data.Length); var r = Encoding.UTF8.GetBytes(reply); sock.Send(r); if (parts[0] == "GET") { Console.Write($"Serving {Path.GetFileName(images[otaIndex].File)}...\r\n"); using (var ms = new MemoryStream(images[otaIndex].Data)) { int totalDone = 0; for (;;) { int done = ms.Read(buffer, 0, buffer.Length); if (done == 0) break; sock.Send(buffer, done, SocketFlags.None); totalDone += done; int percent = (int)((totalDone * 100) / ms.Length); int progress = percent / 5; Console.Write($"\r[{new string('#', progress).PadRight(20)}] {percent}%"); } } Console.WriteLine("\r\nFile sent successfully\n"); break; } } } listener.Stop(); }
public static void ServeOTAFiles(int port, ESP8266BinaryImage.ESP8266ImageHeader hdr, params string[] elfFiles) { TcpListener listener = new TcpListener(port); byte[] buffer = new byte[1024]; OTAImage[] images = new OTAImage[2]; foreach (var fn in elfFiles) { if (fn != null) { using (var elfFile = new ELFFile(fn)) { string status; int appMode = ESP8266BinaryImage.DetectAppMode(elfFile, out status); if (appMode == 0) { Console.WriteLine(fn + " is not an OTA ELF file. Skipping..."); continue; } var img = ESP8266BinaryImage.MakeBootloaderBasedImageFromELFFile(elfFile, hdr, appMode); using (var ms = new MemoryStream()) { img.Save(ms); images[appMode - 1].Data = ms.ToArray(); images[appMode - 1].File = fn; } } } } Console.WriteLine($"Ready to serve the following files:"); Console.WriteLine($"APP1: {images[0].File ?? "(none)"}"); Console.WriteLine($"APP2: {images[1].File ?? "(none)"}"); Console.WriteLine($"Waiting for connection on port {port}..."); listener.Start(); for (;;) { using (var sock = listener.AcceptSocket()) { Console.WriteLine($"Incoming connection from {(sock.RemoteEndPoint as IPEndPoint).Address}"); StringBuilder requestBuilder = new StringBuilder(); while (!requestBuilder.ToString().Contains("\r\n\r")) { int done = sock.Receive(buffer); requestBuilder.Append(Encoding.UTF8.GetString(buffer, 0, done)); } string request = requestBuilder.ToString(); string[] parts = request.Split(' '); if (parts.Length < 3) { throw new Exception("Invalid HTTP request: " + request); } string url = parts[1]; Console.WriteLine("Received request for " + url); int otaIndex = (url.ToLower().Contains("user2") ? 1 : 0); if (images[otaIndex].Data == null) { throw new Exception($"No OTA image for app{otaIndex + 1} is provided. Please check your linker scripts."); } string reply = string.Format("HTTP/1.0 200 OK\r\nContent-Type: application/octet-stream\r\nContent-Length: {0}\r\n\r\n", images[otaIndex].Data.Length); var r = Encoding.UTF8.GetBytes(reply); sock.Send(r); if (parts[0] == "GET") { Console.Write($"Serving {Path.GetFileName(images[otaIndex].File)}...\r\n"); using (var ms = new MemoryStream(images[otaIndex].Data)) { int totalDone = 0; for (;;) { int done = ms.Read(buffer, 0, buffer.Length); if (done == 0) { break; } sock.Send(buffer, done, SocketFlags.None); totalDone += done; int percent = (int)((totalDone * 100) / ms.Length); int progress = percent / 5; Console.Write($"\r[{new string('#', progress).PadRight(20)}] {percent}%"); } } Console.WriteLine("\r\nFile sent successfully\n"); break; } } } listener.Stop(); }