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); }
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()}"); } }
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; }
/// <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"); } }
/// <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); } }
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); } }
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); } }
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); }
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); }
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)); } } } }
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); }
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; } } }
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}"); } }
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); } }
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)); }
private bool IsDebugFileAvailable(SDCDModule module, string hash) { return(filesystem.GetFile(DebugFilePath(module.LocalPath, hash)).Exists); }
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)); }
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)); }