Example #1
0
        public void dumpSymbolInfo(System.IO.TextWriter tw, CruncherSymbol info)
        {
            tw.WriteLine("Symbol: " + info.Name);
            tw.WriteLine("Size: " + info.Size.ToString());
            tw.WriteLine("Total padding: " + info.CalcTotalPadding().ToString());
            tw.WriteLine("Members");
            tw.WriteLine("-------");

            foreach (CruncherSymbol child in info.m_children)
            {
                if (child.Padding > 0)
                {
                    long paddingOffset = child.Offset - child.Padding;
                    tw.WriteLine(String.Format("{0,-40} {1,5} {2,5}", "****Padding", paddingOffset, child.Padding));
                }

                tw.WriteLine(String.Format("{0,-40} {1,5} {2,5}", child.Name, child.Offset, child.Size));
            }
            // Final structure padding.
            if (info.Padding > 0)
            {
                long paddingOffset = (long)info.Size - info.Padding;
                tw.WriteLine(String.Format("{0,-40} {1,5} {2,5}", "****Padding", paddingOffset, info.Padding));
            }
        }
        private bool ProcessChild(IDiaSymbol symbol, out CruncherSymbol info)
        {
            info = new CruncherSymbol();
            if (symbol.isStatic != 0 || (symbol.symTag != (uint)SymTagEnum.SymTagData && symbol.symTag != (uint)SymTagEnum.SymTagBaseClass))
            {
                return(false);
            }
            if (symbol.locationType != LocationType.IsThisRel && symbol.locationType != LocationType.IsNull && symbol.locationType != LocationType.IsBitField)
            {
                return(false);
            }

            ulong      len        = symbol.length;
            IDiaSymbol typeSymbol = symbol.type;

            if (typeSymbol != null)
            {
                len = typeSymbol.length;
            }

            string symbolName = symbol.name;

            if (symbol.symTag == (uint)SymTagEnum.SymTagBaseClass)
            {
                symbolName = "Base: " + symbolName;
            }

            info.Set(symbolName, (typeSymbol != null ? typeSymbol.name : ""), len, symbol.offset);

            return(true);
        }
        public void ProcessChildren(IDiaSymbol symbol)
        {
            IDiaEnumSymbols children;

            symbol.findChildren(SymTagEnum.SymTagNull, null, 0, out children);

            foreach (IDiaSymbol child in children)
            {
                CruncherSymbol childInfo;
                if (ProcessChild(child, out childInfo))
                {
                    AddChild(childInfo);
                }
            }
            // Sort children by offset, recalc padding.
            // Sorting is not needed normally (for data fields), but sometimes base class order is wrong.
            if (HasChildren)
            {
                m_children.Sort(CompareOffsets);
                for (int i = 0; i < m_children.Count; ++i)
                {
                    CruncherSymbol child = m_children[i];
                    child.Padding = CalcPadding(child.Offset, i);
                }
                Padding = CalcPadding((long)Size, m_children.Count);
            }
        }
 private void AddChild(CruncherSymbol child)
 {
     if (m_children == null)
     {
         m_children = new List <CruncherSymbol>();
     }
     m_children.Add(child);
 }
        void ShowSelectedSymbolInfo()
        {
            dataGridViewSymbolInfo.Rows.Clear();
            CruncherSymbol info = FindSelectedSymbolInfo();

            if (info != null)
            {
                ShowSymbolInfo(info);
            }
        }
        private void copyTypeLayoutToClipboardToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CruncherSymbol info = FindSelectedSymbolInfo();

            if (info != null)
            {
                System.IO.StringWriter tw = new System.IO.StringWriter();
                m_CruncherData.dumpSymbolInfo(tw, info);
                Clipboard.SetText(tw.ToString());
            }
        }
        private long CalcPadding(long offset, int index)
        {
            long padding = 0;

            if (HasChildren && index > 0)
            {
                CruncherSymbol lastInfo = m_children[index - 1];
                padding = offset - (lastInfo.Offset + (long)lastInfo.Size);
            }
            return(padding > 0 ? padding : 0);
        }
 private void dataGridViewSymbolInfo_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
 {
     if (dataGridViewSymbolInfo.SelectedRows.Count != 0)
     {
         DataGridViewRow selectedRow = dataGridViewSymbolInfo.SelectedRows[0];
         CruncherSymbol  info        = selectedRow.Tag as CruncherSymbol;
         if (info != null && info.TypeName != null)
         {
             textBoxFilter.Text = info.TypeName.Replace("*", "[*]");
         }
     }
 }
Example #9
0
        void PopulateDataTable(DataTable table, IDiaEnumSymbols symbols, BackgroundWorker LoadingWorker)
        {
            int TotalSymbolCount = symbols.count;
            int CurSymIndex      = 0;

            string msg = String.Format("Loading {0} symbols...", TotalSymbolCount);

            Console.WriteLine(msg);
            LoadingWorker?.ReportProgress(0, msg);

            System.Diagnostics.Stopwatch watch = new Stopwatch();
            watch.Start();

            table.BeginLoadData();
            foreach (IDiaSymbol sym in symbols)
            {
                if (sym.length > 0 && !HasSymbol(sym.name))
                {
                    CruncherSymbol info = new CruncherSymbol(sym.name, "", sym.length, 0);
                    info.ProcessChildren(sym);

                    long totalPadding = info.CalcTotalPadding();

                    DataRow row        = table.NewRow();
                    string  symbolName = sym.name;
                    row["Symbol"]       = symbolName;
                    row["Size"]         = info.Size;
                    row["Padding"]      = totalPadding;
                    row["Padding/Size"] = (double)totalPadding / info.Size;
                    table.Rows.Add(row);

                    m_SymbolMap.Add(info.Name, info);

                    // Report progress to loading bar
                    int percentProgress = (int)Math.Round((double)(100 * CurSymIndex++) / TotalSymbolCount);
                    percentProgress = Math.Max(Math.Min(percentProgress, 99), 1);
                    LoadingWorker?.ReportProgress(percentProgress, String.Format("Adding symbol {0} of {1}", CurSymIndex, TotalSymbolCount));
                }
            }
            table.EndLoadData();
            watch.Stop();

            // Format and display the TimeSpan value.
            TimeSpan ts          = watch.Elapsed;
            string   elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                                                 ts.Hours, ts.Minutes, ts.Seconds,
                                                 ts.Milliseconds / 10);
            string CompleteMessage = String.Format("Finished processing {0} symbols in {1}", TotalSymbolCount, elapsedTime);

            Console.WriteLine(CompleteMessage);
            LoadingWorker?.ReportProgress(100, CompleteMessage);
        }
        CruncherSymbol FindSelectedSymbolInfo()
        {
            if (dataGridSymbols.SelectedRows.Count == 0)
            {
                return(null);
            }

            DataGridViewRow selectedRow = dataGridSymbols.SelectedRows[0];
            string          symbolName  = selectedRow.Cells[0].Value.ToString();

            CruncherSymbol info = m_CruncherData.FindSymbolInfo(symbolName);

            return(info);
        }
        private static int CompareOffsets(CruncherSymbol x, CruncherSymbol y)
        {
            // Base classes have to go first.
            if (x.IsBase && !y.IsBase)
            {
                return(-1);
            }
            if (!x.IsBase && y.IsBase)
            {
                return(1);
            }

            if (x.Offset == y.Offset)
            {
                return(x.Size == y.Size ? 0 : (x.Size < y.Size) ? -1 : 1);
            }
            else
            {
                return((x.Offset < y.Offset) ? -1 : 1);
            }
        }
        public CruncherReport(string PDBFile, string CSVFile)
        {
            m_CruncherData = new CruncherData(null);
            string result = m_CruncherData.LoadDataFromPdb(PDBFile, null);

            if (result == null)
            {
                System.Console.WriteLine("Something went wrong loading PDB file, see log. Exiting...");
                return;
            }

            List <Tuple <string, ulong, ulong> > SymbolsToValidate = new List <Tuple <string, ulong, ulong> >();
            TextFieldParser parser = new TextFieldParser(CSVFile);

            parser.Delimiters = new String[] { "," };
            while (true)
            {
                string[] elements = parser.ReadFields();
                if (elements == null)
                {
                    break;
                }
                SymbolsToValidate.Add(new Tuple <string, ulong, ulong>(elements[0], Convert.ToUInt64(elements[1]), Convert.ToUInt64(elements[2])));
            }

            foreach (Tuple <string, ulong, ulong> SymbolToValidate in SymbolsToValidate)
            {
                CruncherSymbol Info = m_CruncherData.FindSymbolInfo(SymbolToValidate.Item1);
                if (Info == null)
                {
                    System.Console.WriteLine("ERROR: Unable to find symbol '" + SymbolToValidate.Item1 + "' in PDB");
                }
                else
                {
                    if (Info.Size > SymbolToValidate.Item2)
                    {
                        string Larger = "WARNING: Symbol '"
                                        + SymbolToValidate.Item1
                                        + "'was expected to be "
                                        + SymbolToValidate.Item2
                                        + " bytes with "
                                        + SymbolToValidate.Item3
                                        + " bytes of padding, however it is "
                                        + Info.Size
                                        + " bytes with "
                                        + Info.Padding
                                        + " bytes of padding. Inspect symbol to ensure no unneeded size regressions have occurred and update expected symbol size csv as needed.";
                        System.Console.WriteLine(Larger);
                    }
                    else if (Info.Size < SymbolToValidate.Item2)
                    {
                        string Smaller = "Symbol '"
                                         + SymbolToValidate.Item1
                                         + "'was expected to be "
                                         + SymbolToValidate.Item2
                                         + " bytes with "
                                         + SymbolToValidate.Item3
                                         + " bytes of padding, however it is "
                                         + Info.Size
                                         + " bytes with "
                                         + Info.Padding
                                         + " bytes of padding. Consider updating symbol size csv as to maintain size savings.";
                        System.Console.WriteLine(Smaller);
                    }
                }
            }
        }
        /** Shows the given symbol info on the tables on the right hand side */
        void ShowSymbolInfo(CruncherSymbol info)
        {
            dataGridViewSymbolInfo.Rows.Clear();
            if (!info.HasChildren)
            {
                return;
            }

            if (bUpdateStack && (UndoStack.Count == 0 || info.Name != UndoStack.Peek()))
            {
                RedoStack.Clear();
                UndoStack.Push(info.Name);
            }

            long cacheLineSize           = (long)GetCacheLineSize();
            long prevCacheBoundaryOffset = m_prefetchStartOffset;

            if (prevCacheBoundaryOffset > (long)info.Size)
            {
                prevCacheBoundaryOffset = (long)info.Size;
            }

            long numCacheLines = 0;

            InsertCachelineBoundaryRowsDelegate InsertCachelineBoundaryRows = (nextOffset) =>
            {
                while (nextOffset - prevCacheBoundaryOffset >= cacheLineSize)
                {
                    numCacheLines = numCacheLines + 1;
                    long     cacheLineOffset = numCacheLines * cacheLineSize + m_prefetchStartOffset;
                    string[] boundaryRow     = { "Cacheline boundary", cacheLineOffset.ToString(), "" };
                    dataGridViewSymbolInfo.Rows.Add(boundaryRow);
                    prevCacheBoundaryOffset = cacheLineOffset;
                }
            };

            foreach (CruncherSymbol child in info.m_children)
            {
                if (child.Padding > 0)
                {
                    long paddingOffset = child.Offset - child.Padding;

                    InsertCachelineBoundaryRows(paddingOffset);

                    string[] paddingRow = { "*Padding*", paddingOffset.ToString(), child.Padding.ToString() };
                    dataGridViewSymbolInfo.Rows.Add(paddingRow);
                }

                InsertCachelineBoundaryRows(child.Offset);

                string[] row = { child.Name, child.Offset.ToString(), child.Size.ToString() };
                dataGridViewSymbolInfo.Rows.Add(row);
                dataGridViewSymbolInfo.Rows[dataGridViewSymbolInfo.Rows.Count - 1].Tag = child;
                if (child.TypeName != null && child.TypeName.Length != 0)
                {
                    dataGridViewSymbolInfo.Rows[dataGridViewSymbolInfo.Rows.Count - 1].Cells[0].ToolTipText = child.TypeName;
                }
            }
            // Final structure padding.
            if (info.Padding > 0)
            {
                long     paddingOffset = (long)info.Size - info.Padding;
                string[] paddingRow    = { "*Padding*", paddingOffset.ToString(), info.Padding.ToString() };
                dataGridViewSymbolInfo.Rows.Add(paddingRow);
            }
        }