예제 #1
0
        public void Init()
        {
            module = new SDCDModule()
            {
                Version  = DEFAULT_MODULE_VERSION,
                FileName = MODULE_FILENAME,
                FilePath = MODULE_FILENAME
            };
            modules = new List <SDModule> {
                module
            };

            coredump = new Mock <IFileInfo>();
            var dir = new Mock <IDirectoryInfo>();

            coredump.Setup(cd => cd.Directory).Returns(dir.Object);
            dir.Setup(d => d.FullName).Returns(DIR_FULL_NAME);
            coredump.Setup(cd => cd.FullName).Returns(COREDUMP_PATH);

            filesystem = new Mock <IFilesystem>(MockBehavior.Strict);
            corelog    = new Mock <IFileInfo>();
            filesystem.Setup(fs => fs.GetFile(COREDUMP_LOG)).Returns(corelog.Object);

            this.analyzer = new CoreLogAnalyzer(filesystem.Object, coredump.Object, modules);
        }
예제 #2
0
        private async Task DownloadDebugSymbolsAsync(SDCDModule lib, string hash)
        {
            Console.WriteLine($"Trying to retrieve debug symbols for {lib.FilePath}");
            if (string.IsNullOrEmpty(Configuration.DEBUG_SYMBOL_URL_PATTERN))
            {
                Console.WriteLine("Debug symbol URL pattern is not set. No debug symbols will be downloaded.");
                return;
            }
            string url = Configuration.DEBUG_SYMBOL_URL_PATTERN.Replace("{hash}", hash).Replace("{file}", DebugFileName(lib.LocalPath));

            string localDebugFile = DebugFilePath(lib.LocalPath, hash);

            try {
                if (await requestHandler.DownloadFromUrlAsync(url, localDebugFile))
                {
                    Console.WriteLine($"Successfully downloaded debug symbols for {lib.FilePath}. Stored at {localDebugFile}");
                    lib.DebugSymbolPath = Path.GetFullPath(localDebugFile);
                }
                else
                {
                    Console.WriteLine($"Failed to download debug symbols for {lib.FilePath}. URL: {url}");
                }
            } catch (Exception e) {
                Console.WriteLine($"Failed to download debug symbol: {e.ToString()}");
            }
        }
예제 #3
0
		private bool IsDynatraceModule(SDCDModule module) {
			if (module.FileName.Contains("libruxit") || module.FileName.Contains("liboneagent")) {
				return true;
			}
			if (module.FilePath.Contains("/lib/ruxit") || module.FilePath.Contains("/lib64/ruxit") ||
				module.FilePath.Contains("/lib/oneagent") || module.FilePath.Contains("/lib64/oneagent")) {
				return true;
			}
			return false;
		}
예제 #4
0
        /// <summary>
        /// Overrides the original *.so with the unstripped binary
        /// </summary>
        private async Task UnstripLibrary(SDCDModule module, string hash)
        {
            if (IsDebugFileAvailable(module, hash))
            {
                filesystem.Move(module.LocalPath, module.LocalPath + ".old");
                await processHandler.ExecuteProcessAndGetOutputAsync("eu-unstrip",
                                                                     $"-o {module.LocalPath} {module.LocalPath}.old {DebugFilePath(module.LocalPath, hash)}");

                filesystem.Delete(module.LocalPath + ".old");
            }
        }
예제 #5
0
		/// <summary>
		/// Overrides the original *.so with the unstripped binary
		/// </summary>
		private async Task UnstripLibrary(SDCDModule module, string hash) {
			if (IsDebugFileAvailable(module, hash)) {
				string tempBinary = module.LocalPath + ".old";
				if (filesystem.GetFile(tempBinary).Exists) {
					filesystem.Delete(tempBinary);
				}
				filesystem.Move(module.LocalPath, tempBinary);
				await processHandler.ExecuteProcessAndGetOutputAsync("eu-unstrip",
					$"-o {module.LocalPath} {tempBinary} {DebugFilePath(module.LocalPath, hash)}");
				filesystem.Delete(tempBinary);
			}
		}
예제 #6
0
        private async Task ResolveSymlinks(IList <SDModule> modules)
        {
            foreach (SDModule module in modules)
            {
                SDCDModule cdModule = (SDCDModule)module;
                string     output   = await processHandler.ExecuteProcessAndGetOutputAsync("readlink", "-f " + cdModule.LocalPath);

                string path = output.Trim();
                cdModule.LocalPath = path;
                cdModule.FileName  = Path.GetFileName(path);
            }
        }
예제 #7
0
		private async Task DownloadDebugSymbolForModuleAsync(SDCDModule module) {
			if (module.LocalPath != null && IsDynatraceModule(module)) {
				string hash = filesystem.Md5FromFile(module.LocalPath);
				if (IsDebugFileAvailable(module, hash)) {
					module.DebugSymbolPath = Path.GetFullPath(DebugFilePath(module.LocalPath, hash));
				} else {
					await DownloadDebugSymbolsAsync(module, hash);
				}

				await UnstripLibrary(module, hash);
			}
		}
예제 #8
0
        private SDCDModule PrepareSampleModule(ulong instrPtr, string moduleName)
        {
            result.SystemContext         = new SDCDSystemContext();
            result.SystemContext.Modules = new List <SDModule>();

            SDCDModule module = new SDCDModule()
            {
                StartAddress = instrPtr - 1,
                EndAddress   = instrPtr + 1,
                FileName     = moduleName
            };

            result.SystemContext.Modules.Add(module);
            return(module);
        }
예제 #9
0
        public void Init()
        {
            this.filesystem     = new Mock <IFilesystem>();
            this.requestHandler = new Mock <IHttpRequestHandler>();
            this.resolver       = new DebugSymbolResolver(filesystem.Object, requestHandler.Object);

            this.modules = new List <SDModule>();
            this.module  = new SDCDModule()
            {
                LocalPath = $"./lib/ruxit/somelib.so",
                FileName  = "somelib.so",
                FilePath  = $"/lib/ruxit/somelib.so"
            };
            this.modules.Add(module);
        }
예제 #10
0
 private IEnumerable <Task> StartSourceRetrievalTasks()
 {
     foreach (var threadInfo in this.analysisResult.ThreadInformation)
     {
         foreach (var stackFrame in threadInfo.Value.StackTrace)
         {
             SDCDModule module = FindModuleAtAddress(this.analysisResult.SystemContext.Modules, stackFrame.InstructionPointer);
             if (module?.LocalPath != null)
             {
                 stackFrame.ModuleName = module.FileName;
                 yield return(AddSourceInfoAsync(stackFrame, module));
             }
         }
     }
 }
예제 #11
0
 private SDCDModule FindModuleAtAddress(IList <SDModule> modules, ulong instrPtr)
 {
     foreach (SDModule module in modules)
     {
         if (module.GetType() != typeof(SDCDModule))
         {
             throw new InvalidCastException("Plain SDModule found in module list. SDCDModule expected.");
         }
         SDCDModule cdModule = (SDCDModule)module;
         if (cdModule.StartAddress < instrPtr && cdModule.EndAddress > instrPtr)
         {
             return(cdModule);
         }
     }
     return(null);
 }
예제 #12
0
        private async Task AddSourceInfoAsync(SDCombinedStackFrame stackFrame, SDCDModule module)
        {
            Tuple <SDFileAndLineNumber, string> methodSource = await Address2MethodSourceAsync(stackFrame.InstructionPointer, module);

            SDFileAndLineNumber sourceInfo = methodSource.Item1;
            string methodName = methodSource.Item2;

            if (methodName != "??")
            {
                stackFrame.MethodName = methodName;
                if (sourceInfo.File != null && sourceInfo.File != "??")
                {
                    stackFrame.SourceInfo = sourceInfo;
                }
            }
        }
예제 #13
0
        private async Task DownloadDebugSymbolsAsync(SDCDModule lib, string hash)
        {
            Console.WriteLine($"Trying to retrieve debug symbols for {lib.FilePath}");
            string url = Constants.DEBUG_SYMBOL_URL_PATTERN.Replace("{hash}", hash).Replace("{file}", DebugFileName(lib.LocalPath));

            string localDebugFile = DebugFilePath(lib.LocalPath, hash);

            try {
                if (await requestHandler.DownloadFromUrlAsync(url, localDebugFile))
                {
                    Console.WriteLine($"Successfully downloaded debug symbols for {lib.FilePath}. Stored at {localDebugFile}");
                    lib.DebugSymbolPath = Path.GetFullPath(localDebugFile);
                }
                else
                {
                    Console.WriteLine($"Failed to download debug symbols for {lib.FilePath}. URL: {url}");
                }
            } catch (Exception e) {
                Console.WriteLine($"Failed to download debug symbol: {e.Message}");
            }
        }
예제 #14
0
        private async Task AddBackingFiles(IList <SDModule> modules)
        {
            foreach (SDModule module in modules)
            {
                SDCDModule cdModule = (SDCDModule)module;
                string     output   = await processHandler.ExecuteProcessAndGetOutputAsync("readelf", "-S " + cdModule.LocalPath);

                foreach (string line in output.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries))
                {
                    if (line.Contains(".text"))
                    {
                        Match match = ReadelfSectionRegex.Match(line);
                        if (match.Success)
                        {
                            ulong textOffset = Convert.ToUInt64(match.Groups[2].Value, 16);
                            cdModule.StartAddress -= textOffset;
                            break;
                        }
                    }
                }
                addBackingFileAtAddr(cdModule.LocalPath, cdModule.StartAddress);
            }
        }
예제 #15
0
        private async Task <Tuple <SDFileAndLineNumber, string> > Address2MethodSourceAsync(ulong instrPtr, SDCDModule module)
        {
            ulong  relativeIp     = instrPtr;
            string mainExecutable = ((SDCDSystemContext)analysisResult.SystemContext).FileName;

            mainExecutable = Path.GetFileName(mainExecutable);
            if (mainExecutable != module.FileName)
            {
                // Subtract modules start address unless it's the main executable
                relativeIp -= module.StartAddress + 1;
            }
            string output = await processHandler.ExecuteProcessAndGetOutputAsync("addr2line", $"-f -C -e {module.LocalPath} 0x{relativeIp.ToString("X")}");

            string[] lines = output.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
            if (lines.Length < 2)
            {
                Console.WriteLine($"Output of addr2line is invalid ({lines.Length} lines)! First line: {lines?[0]}");
                return(Tuple.Create <SDFileAndLineNumber, string>(new SDFileAndLineNumber(), null));
            }
            string methodName = lines[0];
            string fileLine   = lines[1];
            SDFileAndLineNumber sourceInfo = RetrieveSourceInfo(fileLine);

            return(Tuple.Create(sourceInfo, methodName));
        }
예제 #16
0
 private bool IsDebugFileAvailable(SDCDModule module, string hash)
 {
     return(filesystem.GetFile(DebugFilePath(module.LocalPath, hash)).Exists);
 }
예제 #17
0
        private async Task <Tuple <SDFileAndLineNumber, string> > Address2MethodSourceAsync(ulong instrPtr, SDCDModule module)
        {
            ulong relativeIp    = instrPtr;
            var   systemContext = (SDCDSystemContext)analysisResult.SystemContext;

            // Calculate the relative IP to the base module.
            // For this we must subtract the start address of the whole module from the IP
            // The module start address from the parameter is only the start address of the segment.
            // We get the real module start address by subtracting the page offset multiplied by the page size from the segment start.
            ulong moduleStartAddress = module.StartAddress - (module.Offset * (uint)systemContext.PageSize);

            relativeIp -= moduleStartAddress + 1;

            string output = await processHandler.ExecuteProcessAndGetOutputAsync("addr2line", $"-f -C -e {module.LocalPath} 0x{relativeIp.ToString("X")}");

            string[] lines = output.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
            if (lines.Length < 2)
            {
                Console.WriteLine($"Output of addr2line is invalid ({lines.Length} lines)! First line: {lines?[0]}");
                return(Tuple.Create <SDFileAndLineNumber, string>(new SDFileAndLineNumber(), null));
            }
            string methodName = lines[0];
            string fileLine   = lines[1];
            SDFileAndLineNumber sourceInfo = RetrieveSourceInfo(fileLine);

            return(Tuple.Create(sourceInfo, methodName));
        }
예제 #18
0
        private async Task <Tuple <SDFileAndLineNumber, string> > Address2MethodSourceAsync(ulong instrPtr, SDCDModule module)
        {
            ulong relativeIp = instrPtr;

            if (module.DebugSymbolPath != null && module.DebugSymbolPath != "")
            {
                // If there is a debug file, link it (required for addr2line to find the dbg file)
                LinkDebugFile(module.LocalPath, module.DebugSymbolPath);
            }
            string output = await processHandler.ExecuteProcessAndGetOutputAsync("addr2line", $"-f -C -e {module.LocalPath} 0x{relativeIp.ToString("X")}");

            string[] lines = output.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
            if (lines.Length < 2)
            {
                Console.WriteLine($"Output of addr2line is invalid ({lines.Length} lines)! First line: {lines?[0]}");
                return(Tuple.Create <SDFileAndLineNumber, string>(new SDFileAndLineNumber(), null));
            }
            string methodName = lines[0];
            string fileLine   = lines[1];
            SDFileAndLineNumber sourceInfo = RetrieveSourceInfo(fileLine);

            return(Tuple.Create(sourceInfo, methodName));
        }