Home

Awesome

This is an example application for analyzing the symbols from an executable extracted either from the PDB or from a dump using DumpBin /headers. More documentation is available at http://gameangst.com/?p=320

This code was originally authored and released by Adrian Stone (stone@gameangst.com). It is available for use under the Apache 2.0 license. See LICENCE file for details.

#SYMBOLSORT OVERVIEW:

SymbolSort is a utility for analyzing code bloat in C++ applications. It works by extracting the symbols from a dump generated by the Microsoft DumpBin utility or by reading a PDB file. It processes the symbols it extracts and generates lists sorted by a number of different criteria.

The lists are:

This list is generated from the complete set of symbols. No deduplication is performed so this list is intended to highlight individual large symbols.

This list is generated by calculating the total size of symbols that contribute to a folder path. If the input is a COMDAT dump, the source location for symbols is the .obj or .lib file that DumpBin was run on (see usage for details). It is important to note that for COMDAT dumps individual symbols will appear multiple times coming from different .obj files. If the input is a PDB file, the source location for symbols is the actual source file in which the symbol is defined. The source file for data symbols is not always clearly defined within the PDB so in some cases it is a best guess.

This is a complete, hierarchical list of the size of symbols in all contributing source files.

This shows a breakdown of symbols by section or type, depending on the kind of information that can be extracted from the input source.

This list is generated by merging symbols with identical names. The symbols are not guaranteed to be the same symbol. In the case of PDB input there will be very few duplicate symbols. COMDAT input, however, should contain a large number of duplicate symbols. This list is useful for measuring total compile and link time for a particular symbol. A relatively small symbol that appears in a very large number of .obj files will have a large total size and appear near the top of this list.

This list is generated by stripping template parameters from symbols and then merging duplicates. Symbols std::auto_ptr<int> and std::auto_ptr<float> will be transformed into std::auto_ptr<T> in this list and be counted together.

This list is generated by stripping template parameters and function parameters from symbols and then merging duplicates. Overloaded functions sqrt(float) and sqrt(double) will be transformed into sqrt(...) in this list and be counted together.

This list represents a tag cloud generated from the symbol names. The symbols are tokenized and the total size and count is tallied for each token. I'm not sure what this list is good for, but I'm all about tag clouds so I couldn't resist including it.

USAGE:

SymbolSort [options]

Options:
  -in[:type] filename
      Specify an input file with optional type.  Exe and PDB files are
      identified automatically by extension.  Otherwise type may be:
          comdat - the format produced by DumpBin /headers
          sysv   - the format produced by nm --format=sysv
          bsd    - the format produced by nm --format=bsd --print-size

  -out filename
      Write output to specified file instead of stdout

  -count num_symbols
      Limit the number of symbols displayed to num_symbols

  -exclude substring
      Exclude symbols that contain the specified substring

  -diff:[type] filename
      Use this file as a basis for generating a differences report.
      See -in option for valid types.

  -searchpath path
      Specify the symbol search path when loading an exe

  -path_replace regex_match regex_replace
      Specify a regular expression search/replace for symbol paths.
      Multiple path_replace sequences can be specified for a single
      run.  The match term is escaped but the replace term is not.
      For example: -path_replace d:\\SDK_v1 c:\SDK -path_replace
      d:\\SDK_v2 c:\SDK

  -complete
      Include a complete listing of all symbols sorted by address.
    
Options specific to Exe and PDB inputs:
  -include_public_symbols
      Include 'public symbols' from PDB inputs.  Many symbols in the
      PDB are listed redundantly as 'public symbols.'  These symbols
      provide a slightly different view of the PDB as they are named
      more descriptively and usually include padding for alignment
      in their sizes.
    
  -keep_redundant_symbols
      Normally symbols are processed to remove redundancies.  Partially
      overlapped symbols are adjusted so that their sizes aren't over
      reported and completely overlapped symbols are discarded
      completely.  This option preserves all symbols and their reported
      sizes
    
  -include_sections_as_symbols
      Attempt to extract entire sections and treat them as individual
      symbols.  This can be useful when mapping sections of an
      executable that don't otherwise contain symbols (such as .pdata).
    
  -include_unmapped_addresses
      Insert fake symbols representing any unmapped addresses in the
      PDB.  This option can highlight sections of the executable that
      aren't directly attributable to symbols.  In the complete view
      this will also highlight space lost due to alignment padding.

Supported Input files

SymbolSort supports several types of input files:

COMDAT dump

A COMDAT dump is generated using the DumpBin utility with the /headers option. DumpBin is included with the Microsoft compiler toolchain. SymbolSort can accept the dump from a single .lib or .obj file, but the best way to use it is to create a complete dump of all the .obj files from an entire application. The Windows command line utility FOR can be used for this:

for /R "c:\obj_file_location" %n in (*.obj) do "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\DumpBin.exe" /headers "%n" >> c:\comdat_dump.txt

This will generate a concatenated dump of all the headers in all the .obj files in c:\obj_file_location. Beware, for large applications this could produce a multi-gigabyte file.

PDB or EXE

SymbolSort supports reading debug symbol information from .exe files and .pdb files. The .exe file will only be used to find the location of its matching .pdb file, and then the symbols will be extracted from the PDB. SymbolSort uses msdia140.dll to extract data from the PDB file. Msdia140.dll is included with the Microsoft compiler toolchain. In order to use it you will probably have to register the dll by running this command from an elevated command prompt:

regsvr32 "c:\Program Files (x86)\Microsoft Visual Studio 14.0\DIA SDK\bin\amd64\msdia140.dll"

It is important that you register the 64-bit version of msdia140.dll on 64-bit Windows and the 32-bit version on 32-bit Windows. Note that SymbolSort works with multiple versions of msdia*.dll, from at least msdia90.dll to msdia140.dll.

NM dump

Similar to the COMDAT dump, SymbolSort can accept symbol dumps from the unix utility nm. The symbols can be extracted from .obj files or entire .elfs. SymbolSort supports bsd and sysv format dumps. Sysv is preferred because it contains more information. The recommended nm commands lines are:

nm --format=sysv --demangle --line-numbers input_file.elf
nm --format=bsd --demangle --line-numbers --print-size input_file.elf

BUILDING:

SymbolSort comes with a Solution and Project file for Visual Studio 2015. If you want to build with VS2015 or a compatible future version of Visual Studio, just open SymbolSort.sln and hit build.

If you want to build it with a different version of Visual Studio, you can pretty easily start with just SymbolSort.cs and place it in a default-generated C# command line application. In order to get the msdia140 interop to work you must add msdia140.dll as a reference to the C# project. That is done either by dragging and dropping the dll onto the references folder in the C# project or by right clicking the references folder, selecting "Add Reference" and then browsing for the msdia140 dll.

You may get this error message:

A reference to 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\DIA
SDK\bin\amd64\msdia140.dll' could not be added. Please make sure that the
file is accessible, and that it is a valid assembly or COM component.

This just means that msdia140.dll has not been registered. This is easily fixed by running this command from an administrator command prompt:

regsvr32 "c:\Program Files (x86)\Microsoft Visual Studio 14.0\DIA SDK\bin\amd64\msdia140.dll"

REVISION HISTORY:

###1.2

###1.1

###1.0

FUTURE WORK (to be done by someone else!):