예제 #1
0
        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));
            });
        }
예제 #2
0
        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);
        }
예제 #3
0
        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));
        }
예제 #4
0
        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;
        }
예제 #5
0
        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);
        }
예제 #6
0
        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;
            }
        }
예제 #7
0
        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"));
        }
예제 #8
0
        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());
        }
예제 #9
0
        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("");
        }
예제 #10
0
        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);
        }
예제 #11
0
        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);
        }