Ejemplo n.º 1
0
 public static Scope ParseSymbol(Codebase owner, string symbol)
 {
     return(new Scope
     {
         Owner = owner,
         Name = ExtractScope(symbol),
         Functions = new List <Function>(),
         Lines = new List <LineOfCode>(),
         CalledFrom = new List <Scope>(),
         CallsTo = new List <Scope>(),
         Leaks = new List <Backtrace>()
     });
 }
Ejemplo n.º 2
0
 public static SourceFile Create(Codebase owner, Module parentModule, string path)
 {
     return(new SourceFile
     {
         Owner = owner,
         FullPath = path,
         ParentModule = parentModule,
         Filename = Path.GetFileName(path),
         Lines = new List <LineOfCode>(),
         CalledFrom = new List <SourceFile>(),
         CallsTo = new List <SourceFile>(),
         Leaks = new List <Backtrace>()
     });
 }
        public static LineOfCode Parse(Codebase owner, string line)
        {
            line = line.Trim();
            var result = new LineOfCode();

            result.Owner = owner;
            result.ID    = line;

            result.CalledFrom = new List <LineOfCode>();
            result.CallsTo    = new List <LineOfCode>();
            result.Leaks      = new List <Backtrace>();

            var match      = Regex.Match(line, "(?<moduleName>.*)\\!(?<symbolName>.*)\\+(?<rest>(.*))?$|(?<moduleName>.*)$");
            var moduleName = match.Groups["moduleName"].Value;
            var symbolName = match.Groups["symbolName"].Value; if (String.IsNullOrEmpty(symbolName))
            {
                symbolName = moduleName;
            }
            var rest = match.Groups["rest"].Success ? match.Groups["rest"].Value : "";

            result.Module   = owner.Modules.FirstOrDefault(x => x.Name == moduleName);
            result.Scope    = owner.GetScope(symbolName);
            result.Function = owner.GetFunction(symbolName);

            result.Scope.Lines.Add(result);                    // Add line to scope
            result.Function.Lines.AddOrGet(result);            // Add line to function

            result.Module.Scopes.AddOrGet(result.Scope);       // Add scope to module
            result.Module.Functions.AddOrGet(result.Function); // Add function to module
            result.Module.Lines.AddOrGet(result);              // Add line to module

            match = Regex.Match(rest, ".* \\((?<fileName>.*), (?<lineNum>\\d*)\\)");
            if (match.Success) // Is file,line present?
            {
                var filename = match.Groups["fileName"].Value;
                var lineNum  = Convert.ToInt32(match.Groups["lineNum"].Value);

                result.LineNumber = lineNum;
                result.SourceFile = owner.GetFile(filename, result.Module);
                result.SourceFile.Lines.AddOrGet(result);        // Add line to file

                result.Module.Files.AddOrGet(result.SourceFile); // Add file to module

                result.GeneratePreview(filename, lineNum);
            }

            return(result);
        }
Ejemplo n.º 4
0
 public static Module Create(Codebase owner, string name, string symbolsFile)
 {
     return(new Module
     {
         Name = name,
         Owner = owner,
         SymbolsFile = symbolsFile,
         Scopes = new List <Scope>(),
         Files = new List <SourceFile>(),
         Lines = new List <LineOfCode>(),
         Functions = new List <Function>(),
         CalledFrom = new List <Module>(),
         CallsTo = new List <Module>(),
         Leaks = new List <Backtrace>()
     });
 }
Ejemplo n.º 5
0
        public static Function ParseSymbol(Codebase owner, string symbol)
        {
            var match = Regex.Match(symbol, "((.+::)*)(?<functionName>.*)");
            var name  = match.Groups["functionName"].Value;

            var scope = owner.GetScope(symbol);

            var result = new Function
            {
                Owner          = owner,
                SymbolName     = symbol,
                Name           = name,
                DeclaringScope = scope,
                Lines          = new List <LineOfCode>(),
                CalledFrom     = new List <Function>(),
                CallsTo        = new List <Function>(),
                Leaks          = new List <Backtrace>()
            };

            scope.Functions.AddOrGet(result);

            return(result);
        }
Ejemplo n.º 6
0
        public static Backtrace FromLines(Codebase owner, List <string> lines, int startLine, int endLine)
        {
            var header    = lines[0];
            var subHeader = lines[1];

            var headerNumbers = Regex.Matches(header, "(?<number>^-\\s*\\d+)|(?<number>\\d+)( |\\))")   // first number must capture negative sign if exists.
                                .Cast <Match>()
                                .Select(x => x.Groups["number"].Value.Replace(" ", ""))
                                .Select(x => Convert.ToInt32(x))
                                .ToList();


            var subHeaderNumberMatches = Regex.Matches(subHeader, "(?<number>^-\\s*\\d+)|(?<number>\\d+)( |\\))");
            //var subHeaderNumbers = Regex.Matches(subHeader, "(?<number>^-\\s*\\d+)|(?<number>\\d+)( |\\))")  // first number must capture negative sign if exists.
            var subHeaderNumbers = subHeaderNumberMatches
                                   .Cast <Match>()
                                   .Select(x => x.Groups["number"].Value.Replace(" ", ""))
                                   .Select(x => Convert.ToInt32(x))
                                   .ToList();

            var bytesDelta = headerNumbers[0];
            var newBytes   = headerNumbers[1];
            var oldBytes   = headerNumbers[2];
            var countDelta = subHeaderNumbers[0];
            var newCount   = subHeaderNumbers[1];
            var oldCount   = subHeaderNumbers[2];

            var result = new Backtrace
            {
                TotalLeak = bytesDelta,
                Count     = countDelta,
                Owner     = owner,
                Lines     = new List <LineOfCode>(),
                StartLine = startLine,
                EndLine   = endLine
            };

            var        justLines = lines.Skip(2).Where(x => x.Trim() != string.Empty).ToList();
            LineOfCode prevLine  = null;

            foreach (var lineStr in justLines)
            {
                var line = owner.GetLine(lineStr);

                line.Leaks.AddOrGet(result);          // Add leak to line's leaks
                line.Function.Leaks.AddOrGet(result); // Add leak to line's function's leak
                line.Scope.Leaks.AddOrGet(result);    // Add leak to line's scope's leak
                if (line.SourceFile != null)
                {
                    line.SourceFile.Leaks.AddOrGet(result); // Add leak to line's file's leaks
                }
                line.Module.Leaks.AddOrGet(result);         // Add leak to line's module's leaks

                result.Lines.Add(line);                     // Add line to leak

                // Connect and update calls to and called from
                if (prevLine != null)
                {
                    line.CallsTo.AddOrGet(prevLine);                   // Line calls prevLine
                    line.Function.CallsTo.AddOrGet(prevLine.Function); // Line's function calls prevLine's function
                    line.Module.CallsTo.AddOrGet(prevLine.Module);     // Line's module calls prevLine's module

                    if (line.SourceFile != null && prevLine.SourceFile != null)
                    {
                        line.SourceFile.CallsTo.AddOrGet(prevLine.SourceFile);    // Line's file calls prevLine's file
                        prevLine.SourceFile.CalledFrom.AddOrGet(line.SourceFile); // PrevLine's file is called from line's file
                    }

                    prevLine.CalledFrom.AddOrGet(line);                   // PrevLine is called from line
                    prevLine.Function.CalledFrom.AddOrGet(line.Function); // PrevLine's function is called from line's function
                    prevLine.Module.CalledFrom.AddOrGet(line.Module);     // PrevLine's module is called from line's module
                }

                prevLine = line;
            }

            return(result);
        }
Ejemplo n.º 7
0
        public static Codebase Parse(string path, Action <int> onProgress = null)
        {
            if (!File.Exists(path))
            {
                throw new Exception("File \"" + path + "\" not found!");
            }

            var lines = File.ReadAllLines(path);

            if (onProgress != null)
            {
                onProgress(10);
            }

            var blocksStarts = new List <int>();

            // Detect block edges
            for (int i = 0; i < lines.Length; i++)
            {
                var line = lines[i];
                // Foreach block start
                foreach (Match match in Regex.Matches(line, "[+-]( )*\\d+ \\(( )*\\d+ \\-( )*\\d"))
                {
                    var start = match.Index;

                    if (blocksStarts.Any())
                    {
                        if (blocksStarts.Last() < i - 1)
                        {
                            blocksStarts.Add(i);
                        }
                    }
                    else
                    {
                        blocksStarts.Add(i);
                    }
                }
            }
            blocksStarts.Add(lines.Count() - 1);

            if (onProgress != null)
            {
                onProgress(20);
            }

            var codebase = new Codebase();

            codebase.RawData = File.ReadAllText(path);

            if (onProgress != null)
            {
                onProgress(30);
            }

            // Detect and parse modules
            for (int i = 0; i < blocksStarts[0]; i++)
            {
                var line  = lines[i];
                var match = Regex.Match(line, "DBGHELP\\: (?<moduleName>.*) - (?<label>.*)");
                if (match.Success)
                {
                    var symbolsFile = string.Empty;
                    if ("private symbols & lines " == match.Groups["label"].Value)
                    {
                        symbolsFile = lines[i + 1].Trim();
                    }
                    codebase.Modules.Add(Module.Create(codebase, match.Groups["moduleName"].Value, symbolsFile));
                }
            }
            // Fake module to match "Alias" entries in stack.
            codebase.Modules.Add(Module.Create(codebase, "Alias", ""));

            if (onProgress != null)
            {
                onProgress(50);
            }

            // Parse the backtraces
            for (int i = 0; i < blocksStarts.Count() - 1; i++)
            {
                var startIndex = blocksStarts[i];
                var endIndex   = blocksStarts[i + 1];
                var blockLines = lines.Skip(startIndex)
                                 .Take(endIndex - startIndex)
                                 .Where(x => x.Trim(' ', '\t') != string.Empty)
                                 .ToList();
                if (blockLines.Count() < 4)
                {
                    continue;
                }

                codebase.AddBacktrace(blockLines, blocksStarts[i], blocksStarts[i + 1]);

                if (onProgress != null)
                {
                    onProgress((int)(50 + 50 * ((double)blocksStarts[i + 1] / lines.Count())));
                }
            }
            codebase.Normalize();

            return(codebase);
        }