public void GetInfo() { ulong testCodeLoadAddress = 456; ulong testCodeSize = 789; string testSymbolFile = "symbol file"; string testSymbolDirectory = "c:\\symbol\\dir"; string testPlatformFile = "platform file"; string testPlatformDirectory = "/platform/dir"; var mockPlatformFileSpec = Substitute.For <SbFileSpec>(); mockPlatformFileSpec.GetFilename().Returns(testPlatformFile); mockPlatformFileSpec.GetDirectory().Returns(testPlatformDirectory); var mockSymbolFileSpec = Substitute.For <SbFileSpec>(); mockSymbolFileSpec.GetFilename().Returns(testSymbolFile); mockSymbolFileSpec.GetDirectory().Returns(testSymbolDirectory); _mockModule.GetPlatformFileSpec().Returns(mockPlatformFileSpec); _mockModule.GetSymbolFileSpec().Returns(mockSymbolFileSpec); _mockModule.GetCodeLoadAddress().Returns(testCodeLoadAddress); _mockModule.GetCodeSize().Returns(testCodeSize); _mockModule.Is64Bit().Returns(true); _mockModuleUtil.HasSymbolsLoaded(_mockModule).Returns(true); var flags = enum_MODULE_INFO_FIELDS.MIF_NAME | enum_MODULE_INFO_FIELDS.MIF_URL | enum_MODULE_INFO_FIELDS.MIF_URLSYMBOLLOCATION | enum_MODULE_INFO_FIELDS.MIF_LOADADDRESS | enum_MODULE_INFO_FIELDS.MIF_PREFFEREDADDRESS | enum_MODULE_INFO_FIELDS.MIF_SIZE | enum_MODULE_INFO_FIELDS.MIF_LOADORDER | enum_MODULE_INFO_FIELDS.MIF_FLAGS; var moduleInfo = new MODULE_INFO[1]; Assert.Multiple(() => { Assert.That(_debugModule.GetInfo(flags, moduleInfo), Is.EqualTo(VSConstants.S_OK)); Assert.That(moduleInfo[0].dwValidFields, Is.EqualTo(flags)); Assert.That(moduleInfo[0].m_bstrName, Is.EqualTo(testPlatformFile)); Assert.That(moduleInfo[0].m_bstrUrl, Is.EqualTo(testPlatformDirectory + "/" + testPlatformFile)); Assert.That(moduleInfo[0].m_bstrUrlSymbolLocation, Is.EqualTo(testSymbolDirectory + "\\" + testSymbolFile)); Assert.That(moduleInfo[0].m_addrLoadAddress, Is.EqualTo(testCodeLoadAddress)); Assert.That(moduleInfo[0].m_dwSize, Is.EqualTo(testCodeSize)); Assert.That(moduleInfo[0].m_dwLoadOrder, Is.EqualTo(_testLoadOrder)); Assert.That(moduleInfo[0].m_dwModuleFlags, Is.EqualTo(enum_MODULE_FLAGS.MODULE_FLAG_64BIT | enum_MODULE_FLAGS.MODULE_FLAG_SYMBOLS)); }); }
bool AddSymbolFile(string filepath, SbModule module, TextWriter searchLog) { var command = "target symbols add"; var platformFileSpec = module.GetPlatformFileSpec(); if (platformFileSpec != null) { var platformPath = FileUtil.PathCombineLinux(platformFileSpec.GetDirectory(), platformFileSpec.GetFilename()); // The -s flag specifies the path of the module to add symbols to. command += " -s " + LldbCommandUtil.QuoteArgument(platformPath); } command += " " + LldbCommandUtil.QuoteArgument(filepath); SbCommandReturnObject commandResult; lldbCommandInterpreter.HandleCommand(command, out commandResult); Trace.WriteLine($"Executed LLDB command '{command}' with result:" + Environment.NewLine + commandResult.GetDescription()); if (!commandResult.Succeeded()) { searchLog.WriteLine("LLDB error: " + commandResult.GetError()); return(false); } searchLog.WriteLine("LLDB output: " + commandResult.GetOutput()); searchLog.WriteLine("Symbols loaded successfully."); Trace.WriteLine($"Successfully loaded symbol file '{filepath}'."); return(true); }
public PlaceholderModuleProperties GetPlaceholderProperties(SbModule placeholderModule, RemoteTarget lldbTarget) { SbSection placeholderSection = placeholderModule.FindSection(".module_image"); if (placeholderSection == null) { // Could be either an RPC error or a usage error. Hmm... throw new ArgumentException( "Placeholder properties can only be copied from placeholder modules."); } // The load address of the placeholder section represents the base load address of the // module as a whole in the original process. ulong placeholderBaseLoadAddress = placeholderSection.GetLoadAddress(lldbTarget); if (placeholderBaseLoadAddress == DebuggerConstants.INVALID_ADDRESS) { Trace.WriteLine("Failed to get load address from the placeholder section."); return(null); } // |slide| is how much we need to offset the module's load address by long slide = (long)placeholderBaseLoadAddress; SbFileSpec fileSpec = placeholderModule.GetPlatformFileSpec(); if (fileSpec == null) { Trace.WriteLine("Failed to get file spec from placeholder module."); return(null); } return(new PlaceholderModuleProperties(slide, fileSpec)); }
public void SetUp() { searchLog = new StringWriter(); mockTarget = Substitute.For <RemoteTarget>(); moduleReplacedHandler = Substitute.For <EventHandler <LldbModuleReplacedEventArgs> >(); mockModuleFileFinder = Substitute.For <IModuleFileFinder>(); mockModuleFileFinder.FindFileAsync(BINARY_FILENAME, UUID, false, searchLog) .Returns(Task.FromResult(PATH_IN_STORE)); placeholderModule = Substitute.For <SbModule>(); placeholderModule.GetPlatformFileSpec().GetFilename().Returns(BINARY_FILENAME); placeholderModule.GetUUIDString().Returns(UUID.ToString()); placeholderProperties = new PlaceholderModuleProperties(MODULE_SLIDE, Substitute.For <SbFileSpec>()); mockModuleUtil = Substitute.For <ILldbModuleUtil>(); mockModuleUtil.IsPlaceholderModule(placeholderModule).Returns(true); mockModuleUtil.GetPlaceholderProperties(Arg.Any <SbModule>(), Arg.Any <RemoteTarget>()) .ReturnsForAnyArgs(placeholderProperties); mockModuleUtil.ApplyPlaceholderProperties( Arg.Any <SbModule>(), Arg.Any <PlaceholderModuleProperties>(), Arg.Any <RemoteTarget>()) .ReturnsForAnyArgs(true); binaryLoader = new BinaryLoader(mockModuleUtil, mockModuleFileFinder, mockTarget); binaryLoader.LldbModuleReplaced += moduleReplacedHandler; }
public virtual async Task <(SbModule, bool)> LoadBinaryAsync( SbModule lldbModule, TextWriter searchLog) { if (lldbModule == null) { throw new ArgumentNullException(nameof(lldbModule)); } searchLog = searchLog ?? TextWriter.Null; if (!moduleUtil.IsPlaceholderModule(lldbModule)) { return(lldbModule, true); } var binaryName = lldbModule.GetPlatformFileSpec()?.GetFilename(); if (string.IsNullOrEmpty(binaryName)) { await searchLog.WriteLineAsync(ErrorStrings.BinaryFileNameUnknown); Trace.WriteLine(ErrorStrings.BinaryFileNameUnknown); return(lldbModule, false); } var binaryPath = await moduleFileFinder.FindFileAsync( binaryName, new BuildId(lldbModule.GetUUIDString()), false, searchLog); if (binaryPath == null) { return(lldbModule, false); } PlaceholderModuleProperties properties = moduleUtil.GetPlaceholderProperties(lldbModule, lldbTarget); if (properties == null) { return(lldbModule, false); } RemoveModule(lldbModule); var newModule = AddModule(binaryPath, lldbModule.GetUUIDString(), searchLog); if (newModule == null) { return(lldbModule, false); } if (!moduleUtil.ApplyPlaceholderProperties(newModule, properties, lldbTarget)) { return(lldbModule, false); } LldbModuleReplaced?.Invoke(Self, new LldbModuleReplacedEventArgs(newModule, lldbModule)); return(newModule, true); }
public void SetSearchLog(SbModule lldbModule, string log) { SbFileSpec platformFileSpec = lldbModule.GetPlatformFileSpec(); if (platformFileSpec != null) { string key = FileUtil.PathCombineLinux(platformFileSpec.GetDirectory(), platformFileSpec.GetFilename()); _logsByPlatformFileSpec[key] = log; } }
public void GetPlaceholderProperties_GetPlatformFileSpecFails() { SbModule placeholderModule = CreatePlaceholderModule(); placeholderModule.GetPlatformFileSpec().Returns((SbFileSpec)null); Assert.IsNull(moduleUtil.GetPlaceholderProperties(placeholderModule, mockTarget)); var output = logSpy.GetOutput(); Assert.That(output, Does.Contain("Failed to get file spec")); }
public async Task LoadBinary_NoBinaryNameAsync() { placeholderModule.GetPlatformFileSpec().Returns((SbFileSpec)null); var module = placeholderModule; bool ok; (module, ok) = await binaryLoader.LoadBinaryAsync(module, searchLog); Assert.False(ok); Assert.AreSame(module, placeholderModule); StringAssert.Contains(ErrorStrings.BinaryFileNameUnknown, searchLog.ToString()); }
public string GetSearchLog(SbModule lldbModule) { SbFileSpec platformFileSpec = lldbModule.GetPlatformFileSpec(); if (platformFileSpec == null) { return(""); } string key = FileUtil.PathCombineLinux(platformFileSpec.GetDirectory(), platformFileSpec.GetFilename()); if (_logsByPlatformFileSpec.TryGetValue(key, out string log)) { return(log); } return(""); }
public async Task <int> LoadModuleFilesAsync( IList <SbModule> modules, SymbolInclusionSettings symbolSettings, bool useSymbolStores, ICancelable task, IModuleFileLoadMetricsRecorder moduleFileLoadRecorder) { if (modules == null) { throw new ArgumentNullException(nameof(modules)); } if (task == null) { throw new ArgumentNullException(nameof(task)); } if (moduleFileLoadRecorder == null) { throw new ArgumentNullException(nameof(moduleFileLoadRecorder)); } // Add some metrics to the event proto before attempting to load symbols, so that they // are still recorded if the task is aborted or cancelled. moduleFileLoadRecorder.RecordBeforeLoad(modules); int result = VSConstants.S_OK; for (int i = 0; i < modules.Count; ++i) { SbModule module = modules[i]; TextWriter searchLog = new StringWriter(); string name = module.GetPlatformFileSpec()?.GetFilename() ?? "<unknown>"; try { task.ThrowIfCancellationRequested(); if (SkipModule(name, symbolSettings)) { await searchLog.WriteLineAsync( SymbolInclusionSettings.ModuleExcludedMessage); continue; } task.Progress.Report($"Loading binary for {name} ({i}/{modules.Count})"); (SbModule newModule, bool ok) = await _binaryLoader.LoadBinaryAsync(module, searchLog); if (!ok) { result = VSConstants.E_FAIL; continue; } module = newModule; task.ThrowIfCancellationRequested(); task.Progress.Report($"Loading symbols for {name} ({i}/{modules.Count})"); var loaded = await _symbolLoader.LoadSymbolsAsync(module, searchLog, useSymbolStores); if (!loaded) { result = VSConstants.E_FAIL; continue; } } finally { _moduleSearchLogHolder.SetSearchLog(module, searchLog.ToString()); modules[i] = module; } } moduleFileLoadRecorder.RecordAfterLoad(modules); return(result); }
public int GetInfo(enum_MODULE_INFO_FIELDS fields, MODULE_INFO[] moduleInfo) { var info = new MODULE_INFO(); SbFileSpec platformFileSpec = _lldbModule.GetPlatformFileSpec(); if ((enum_MODULE_INFO_FIELDS.MIF_NAME & fields) != 0) { if (platformFileSpec != null) { info.m_bstrName = platformFileSpec.GetFilename(); info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_NAME; } } // "URL" fills in the "Path" column in the Modules window. if ((enum_MODULE_INFO_FIELDS.MIF_URL & fields) != 0) { // The module paths are for remote files (on Linux). if (platformFileSpec != null) { info.m_bstrUrl = FileUtil.PathCombineLinux( platformFileSpec.GetDirectory(), platformFileSpec.GetFilename()); } info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_URL; } // "URLSYMBOLLOCATION" fills in the Symbol File Location column. if ((enum_MODULE_INFO_FIELDS.MIF_URLSYMBOLLOCATION & fields) != 0) { if (_moduleUtil.HasSymbolsLoaded(_lldbModule)) { // The symbol paths are for local files (on Windows). SbFileSpec symbolFileSpec = _lldbModule.GetSymbolFileSpec(); if (symbolFileSpec != null) { info.m_bstrUrlSymbolLocation = Path.Combine( symbolFileSpec.GetDirectory(), symbolFileSpec.GetFilename()); info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_URLSYMBOLLOCATION; } } } if ((enum_MODULE_INFO_FIELDS.MIF_LOADADDRESS & fields) != 0) { info.m_addrLoadAddress = _lldbModule.GetCodeLoadAddress(); info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_LOADADDRESS; } if ((enum_MODULE_INFO_FIELDS.MIF_PREFFEREDADDRESS & fields) != 0) { // TODO: Find the actual preferred load address rather than // pretending the module is loaded in the right place. // We may choose to ignore this, as samples do: extracting the preferred base // address from the library / executable seems nontrivial. // If m_addrLoadAddress is a different value, VS will show a warning on the icons // in the Modules window. info.m_addrPreferredLoadAddress = info.m_addrLoadAddress; info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_PREFFEREDADDRESS; } if ((enum_MODULE_INFO_FIELDS.MIF_SIZE & fields) != 0) { info.m_dwSize = (uint)_lldbModule.GetCodeSize(); info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_SIZE; } if ((enum_MODULE_INFO_FIELDS.MIF_LOADORDER & fields) != 0) { info.m_dwLoadOrder = _loadOrder; info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_LOADORDER; } if ((enum_MODULE_INFO_FIELDS.MIF_FLAGS & fields) != 0) { info.m_dwModuleFlags = 0; if (_moduleUtil.HasSymbolsLoaded(_lldbModule)) { info.m_dwModuleFlags |= enum_MODULE_FLAGS.MODULE_FLAG_SYMBOLS; } if (_lldbModule.Is64Bit()) { info.m_dwModuleFlags |= enum_MODULE_FLAGS.MODULE_FLAG_64BIT; } info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_FLAGS; } if ((enum_MODULE_INFO_FIELDS.MIF_DEBUGMESSAGE & fields) != 0) { if (!_moduleUtil.HasSymbolsLoaded(_lldbModule)) { var inclusionSetting = _symbolSettingsProvider.GetInclusionSettings(); if (!inclusionSetting.IsModuleIncluded(ModuleName)) { info.m_bstrDebugMessage = SymbolInclusionSettings.ModuleExcludedMessage; } } info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_DEBUGMESSAGE; } moduleInfo[0] = info; return(VSConstants.S_OK); }