dwww Home | Manual pages | Find package

LLVM-DEBUGINFO-ANALYZER(1)           LLVM           LLVM-DEBUGINFO-ANALYZER(1)

NAME
       llvm-debuginfo-analyzer  -  Print a logical representation of low-level
       debug information.

       • SYNOPSISDESCRIPTIONOPTIONSGENERALATTRIBUTESPRINTOUTPUTREPORTSELECTIONELEMENTSLINESSCOPESSYMBOLSTYPESCOMPAREWARNINGINTERNALEXAMPLESTEST CASE 1 - GENERAL OPTIONSPRINTING MODEBASIC DETAILSSELECT LOGICAL ELEMENTSCOMPARISON MODELOGICAL VIEWLOGICAL ELEMENTSTEST CASE 2 - ASSEMBLER INSTRUCTIONSCodeView - Clang (Windows)CodeView - MSVC (Windows)DWARF - Clang (Linux)DWARF - GCC (Linux)TEST CASE 3 - INCORRECT LEXICAL SCOPE FOR TYPEDEFCodeView - Clang (Windows)CodeView - MSVC (Windows)DWARF - Clang (Linux)DWARF - GCC (Linux)TEST CASE 4 - MISSING NESTED ENUMERATIONSCodeView - Clang (Windows)CodeView - MSVC (Windows)DWARF - Clang (Linux)DWARF - GCC (Linux)TEST CASE 5 - INCORRECT LEXICAL SCOPE FOR VARIABLECODEVIEW - Clang (Windows)CODEVIEW - MSVC (Windows)DWARF - Clang (Linux)DWARF - GCC (Linux)TEST CASE 6 - FULL LOGICAL VIEWEXIT STATUSSEE ALSO

SYNOPSIS
       llvm-debuginfo-analyzer [options] [filename ]

DESCRIPTION
       llvm-debuginfo-analyzer parses debug and text sections in binary object
       files  and  prints  their  contents in a logical view, which is a human
       readable representation that closely matches the structure of the orig-
       inal  user  source  code.  Supported  object  file formats include ELF,
       Mach-O, PDB and COFF.

       The logical view abstracts the complexity associated with the different
       low-level representations of the debugging information that is embedded
       in the object file. llvm-debuginfo-analyzer produces a  canonical  view
       of  the  debug  information regardless of how it is formatted. The same
       logical view will be seen regardless of object  file  format,  assuming
       the  debug  information  correctly  represents the same original source
       code.

       The logical view includes the following logical elements: type,  scope,
       symbol  and  line,  which  are  the basic software elements used in the
       C/C++ programming language. Each logical  element  has  a  set  of  at-
       tributes,  such  as  types,  classes, functions, variables, parameters,
       etc. The --attribute can be used to specify which attributes to include
       when printing a logical element. A logical element may have a kind that
       describes specific types of elements. For instance, a scope could  have
       a kind value of function, class, namespace.

       llvm-debuginfo-analyzer defaults to print a pre-defined layout of logi-
       cal elements and attributes. The command line options can  be  used  to
       control  the  printed  elements  (--print),  using a specific layout (-
       --report), matching a given pattern (--select, --select-offsets). Also,
       the  output  can  be  limited  to  specified  logical elements using (-
       --select-lines, --select-scopes, --select-symbols, --select-types).

       llvm-debuginfo-analyzer can also compare a  set  of  logical  views  (-
       --compare), to find differences and identify possible debug information
       syntax issues (--warning) in any object file.

OPTIONS
       llvm-debuginfo-analyzer options are separated into several  categories,
       each tailored to a different purpose:

          • GENERAL - Standard LLVM options to display help, version, etc.

          • ATTRIBUTES - Describe how to include different details when print-
            ing an element.

          • PRINT - Specify which elements will be included when printing  the
            view.

          • OUTPUT - Describe the supported formats when printing the view.

          • REPORT - Describe the format layouts for view printing.

          • SELECTION  -  Allows to use specific criteria or conditions to se-
            lect which elements to print.

          • COMPARE - Compare logical views and print missing and/or added el-
            ements.

          • WARNING  -  Print the warnings detected during the creation of the
            view.

          • INTERNAL - Internal analysis of the logical view.

   GENERAL
       This section describes the standard help options, used to  display  the
       usage, version, response files, etc.

       -h, --help
              Show help and usage for this command. (–help-hidden for more).

       --help-list
              Show  help  and  usage for this command without grouping the op-
              tions into categories (–help-list-hidden for more).

       --help-hidden
              Display all available options.

       --print-all-options
              Print all option values after command line parsing.

       --print-options
              Print non-default options after command line parsing

       --version
              Display the version of the tool.

       @<FILE>
              Read command-line options from <FILE>.

       If no input file is specified, llvm-debuginfo-analyzer defaults to read
       a.out and return an error when no input file is found.

       If - is used as the input file, llvm-debuginfo-analyzer reads the input
       from its standard input stream.

   ATTRIBUTES
       The following options enable attributes given for the printed elements.
       The  attributes are divided in categories based on the type of data be-
       ing added, such as: internal offsets in the binary file,  location  de-
       scriptors,  register  names,  user source filenames, additional element
       transformations, toolchain name, binary file format, etc.

       --attribute=<value[,value,...]>
              With value being one of the options in the following lists.

                 =all: Include all the below attributes.
                 =extended: Add low-level attributes.
                 =standard: Add standard high-level attributes.

              The following attributes describe the  most  common  information
              for  a  logical element. They help to identify the lexical scope
              level; the element visibility across  modules  (global,  local);
              the toolchain name that produced the binary file.

                 =global: Element referenced across Compile Units.
                 =format: Object file format name.
                 =level: Lexical scope level (File=0, Compile Unit=1).
                 =local: Element referenced only in the Compile Unit.
                 =producer: Toolchain identification name.

              The following attributes describe files and directory names from
              the user source code, where the elements  are  declared  or  de-
              fined;  functions  with  public visibility across modules. These
              options allow to map the elements to their user  code  location,
              for cross references purposes.

                 =directories: Directories referenced in the debug information.
                 =filename: Filename where the element is defined.
                 =files: Files referenced in the debug information.
                 =pathname: Pathname where the object is defined.
                 =publics: Function names that are public.

              The  following  attributes  describe  additional logical element
              source transformations, in order to display built-in types (int,
              bool,  etc.);  parameters and arguments used during template in-
              stantiation; parent name hierarchy;  array  dimensions  informa-
              tion; compiler generated elements and the underlying types asso-
              ciated with the types aliases.

                 =argument: Template parameters replaced by its arguments.
                 =base: Base types (int, bool, etc.).
                 =generated: Compiler generated elements.
                 =encoded: Template arguments encoded in the template name.
                 =qualified: The element type include parents in its name.
                 =reference: Element declaration and definition references.
                 =subrange: Subrange encoding information for arrays.
                 =typename: Template parameters.
                 =underlying: Underlying type for type definitions.

              The following attributes describe the debug location information
              for  a symbol or scope. It includes the symbol percentage cover-
              age and any gaps within the location layout; ranges  determining
              the  code  sections attached to a function. When descriptors are
              used, the target processor registers are displayed.

                 =coverage: Symbol location coverage.
                 =gaps: Missing debug location (gaps).
                 =location: Symbol debug location.
                 =range: Debug location ranges.
                 =register: Processor register names.

              The following attributes are associated with low level  details,
              such as: offsets in the binary file; discriminators added to the
              lines of inlined functions in order to distinguish specific  in-
              stances; debug lines state machine registers; elements discarded
              by the  compiler  (inlining)  or  by  the  linker  optimizations
              (dead-stripping);  system  compile  units  generated  by  the MS
              toolchain in PDBs.

                 =discarded: Discarded elements by the linker.
                 =discriminator: Discriminators for inlined function instances.
                 =inserted: Generated inlined abstract references.
                 =linkage: Object file linkage name.
                 =offset: Debug information offset.
                 =qualifier: Line qualifiers (Newstatement, BasicBlock, etc).
                 =zero: Zero line numbers.

              The following attribute described specific information  for  the
              PE/COFF file format. It includes MS runtime types.

                 =system: Display PDB's MS system elements.

              The above attributes are grouped into standard and extended cat-
              egories that can be enabled.

              The standard group, contains those attributes  that  add  suffi-
              cient  information  to  describe  a logical element and that can
              cover the normal situations while dealing  with  debug  informa-
              tion.

                 =base
                 =coverage
                 =directories
                 =discriminator
                 =filename
                 =files
                 =format
                 =level
                 =producer
                 =publics
                 =range
                 =reference
                 =zero

              The  extended  group,  contains  those attributes that require a
              more extended knowledge about debug information.  They  are  in-
              tended when a lower level of detail is required.

                 =argument
                 =discarded
                 =encoded
                 =gaps
                 =generated
                 =global
                 =inserted
                 =linkage
                 =local
                 =location
                 =offset
                 =operation
                 =pathname
                 =qualified
                 =qualifier
                 =register
                 =subrange
                 =system
                 =typename

   PRINT
       The  following  options describe the elements to print. The layout used
       is determined by the --report. In the tree  layout,  all  the  elements
       have  their  enclosing lexical scopes printed, even when not explicitly
       specified.

       --print=<value[,value,...]>
              With value being one of the options in the following lists.

                 =all: Include all the below attributes.

              The following options print the requested elements; in the  case
              of  any  given select conditions (--select), only those elements
              that match them, will be printed. The elements value is a conve-
              nient  way  to  specify instructions, lines, scopes, symbols and
              types all at once.

                 =elements: Instructions, lines, scopes, symbols and types.
                 =instructions: Assembler instructions for code sections.
                 =lines: Source lines referenced in the debug information.
                 =scopes: Lexical blocks (function, class, namespace, etc).
                 =symbols: Symbols (variable, member, parameter, etc).
                 =types: Types (pointer, reference, type alias, etc).

              The following options print information,  collected  during  the
              creation  of  the  elements, such as: scope contributions to the
              debug information;  summary  of  elements  created,  printed  or
              matched (--select); warnings produced during the view creation.

                 =sizes: Debug Information scopes contributions.
                 =summary: Summary of elements allocated, selected or printed.
                 =warnings: Warnings detected.

              Note: The –print=sizes option is ELF specific.

   OUTPUT
       The following options describe how to control the output generated when
       printing the logical elements.

       --output-file=<path>
              Redirect the output to a file specified by <path>,  where  -  is
              the standard output stream.

       llvm-debuginfo-analyzer  has the concept of split view.  When redirect-
       ing the output from a complex binary format, it is divided  into  indi-
       vidual  files, each one containing the logical view output for a single
       compilation unit.

       --output-folder=<name>
              The folder to write a  file  per  compilation  unit  when  –out-
              put=split is specified.

       --output-level=<level>
              Only print elements up to the given lexical level value. The in-
              put file is at lexical level zero and a compilation unit  is  at
              lexical level one.

       --output=<value[,value,...]>
              With value being one of the options in the following lists.

                 =all: Include all the below outputs.

                 =json: Use JSON as the output format (Not implemented).
                 =split: Split the output by Compile Units.
                 =text: Use a free form text output.

       --output-sort=<key>
              Primary  key  when ordering the elements in the output (default:
              line).  Sorting by logical element kind, requires be familiarity
              with   the   element  kind  selection  options  (--select-lines,
              --select-scopes, --select-symbols, --select-types), as those op-
              tions describe the different logical element kinds.

                 =kind: Sort by element kind.
                 =line: Sort by element line number.
                 =name: Sort by element name.
                 =offset: Sort by element offset.

   REPORT
       Depending  on the task being executed (print, compare, select), several
       layouts are supported to display the elements in a more  suitable  way,
       to make the output easier to understand.

       --report=<value[,value,...]>
              With value being one of the options in the following list.

                 =all: Include all the below reports.

                 =children: Elements and children are displayed in a tree format.
                 =list: Elements are displayed in a tabular format.
                 =parents: Elements and parents are displayed in a tree format.
                 =view: Elements, parents and children are displayed in a tree format.

       The list layout presents the logical elements in a tabular form without
       any parent-child relationship. This may be the preferred way to display
       elements  that  match specific conditions when comparing logical views,
       making it easier to find differences.

       The children, parents and view layout displays the elements in  a  tree
       format,  with  the scopes representing their nodes, and types, symbols,
       lines and other scopes representing the children. The layout shows  the
       lexical scoping relationship between elements, with the binary file be-
       ing the tree root (level 0) and each compilation  unit  being  a  child
       (level 1).

       The children layout includes the elements that match any given criteria
       (--select) or (--compare) and its children.

       The parents layout includes the elements that match any given  criteria
       (--select) or (--compare) and its parents.

       The  combined  view  layout  includes the elements that match any given
       criteria (--select) or (--compare), its parents and children.

       Notes:

       1. When a selection criteria (--select) is specified with no report op-
          tion, the list layout is selected.

       2. The comparison mode always uses the view layout.

   SELECTION
       When  printing an element, different data can be included and it varies
       (--attribute) from data directly associated with the binary file  (off-
       set) to high level details such as coverage, lexical scope level, loca-
       tion. As the printed output can reach a considerable size, several  se-
       lection options, enable printing of specific elements.

       The  pattern  matching can ignore the case (--select-nocase) and be ex-
       tended to use regular expressions (--select-regex).

   ELEMENTS
       The following options allow printing of elements that match  the  given
       <pattern>, offset <value> or an element <condition>.

       --select=<pattern>
              Print  all  elements whose name or line number matches the given
              <pattern>.

       --select-offsets=<value[,value,...]>
              Print all elements whose offset matches the  given  values.  See
              --attribute option.

       --select-elements=<condition[,condition,...]>
              Print all elements that satisfy the given <condition>. With con-
              dition being one of the options in the following list.

                 =discarded: Discarded elements by the linker.
                 =global: Element referenced across Compile Units.
                 =optimized: Optimized inlined abstract references.

       --select-nocase
              Pattern matching is case-insensitive when using --select.

       --select-regex
              Treat any <pattern> strings as regular expressions when  select-
              ing  with  --select option. If --select-nocase is specified, the
              regular expression becomes case-insensitive.

       If the <pattern> criteria is too general, a more selective  option  can
       be  specified  to  target  a  particular category of elements: lines (-
       --select-lines), scopes (--select-scopes),  symbols  (--select-symbols)
       and types (--select-types).  These options require knowledge of the de-
       bug information format (DWARF, CodeView, COFF), as the given  kind  de-
       scribes a very specific type of element.

   LINES
       The  following  options  allow  printing  of lines that match the given
       <kind>.  The given criteria describes the debug line state machine reg-
       isters.

       --select-lines=<kind[,kind,...]>
              With kind being one of the options in the following list.

                 =AlwaysStepInto: marks an always step into.
                 =BasicBlock: Marks a new basic block.
                 =Discriminator: Line that has a discriminator.
                 =EndSequence: Marks the end in the sequence of lines.
                 =EpilogueBegin: Marks the start of a function epilogue.
                 =LineDebug: Lines that correspond to debug lines.
                 =LineAssembler: Lines that correspond to disassembly text.
                 =NeverStepInto: marks a never step into.
                 =NewStatement: Marks a new statement.
                 =PrologueEnd: Marks the end of a function prologue.

   SCOPES
       The  following  options  allow  printing of scopes that match the given
       <kind>.

       --select-scopes=<kind[,kind,...]>
              With kind being one of the options in the following list.

                 =Aggregate: A class, structure or union.
                 =Array: An array.
                 =Block: A generic block (lexical block or exception block).
                 =CallSite: A call site.
                 =CatchBlock: An exception block.
                 =Class: A class.
                 =CompileUnit: A compile unit.
                 =EntryPoint: A subroutine entry point.
                 =Enumeration: An enumeration.
                 =Function: A function.
                 =FunctionType: A function pointer.
                 =InlinedFunction: An inlined function.
                 =Label: A label.
                 =LexicalBlock: A lexical block.
                 =Namespace: A namespace.
                 =Root: The element representing the main scope.
                 =Structure: A structure.
                 =Subprogram: A subprogram.
                 =Template: A template definition.
                 =TemplateAlias: A template alias.
                 =TemplatePack: A template pack.
                 =TryBlock: An exception try block.
                 =Union: A union.

   SYMBOLS
       The following options allow printing of symbols that  match  the  given
       <kind>.

       --select-symbols=<kind[,kind,...]>
              With kind being one of the options in the following list.

                 =CallSiteParameter: A call site parameter.
                 =Constant: A constant symbol.
                 =Inheritance: A base class.
                 =Member: A member class.
                 =Parameter: A parameter to function.
                 =Unspecified: Unspecified parameters to function.
                 =Variable: A variable.

   TYPES
       The  following  options  allow  printing  of types that match the given
       <kind>.

       --select-types=<kind[,kind,...]>
              With kind being one of the options in the following list.

                 =Base: Base type (integer, boolean, etc).
                 =Const: Constant specifier.
                 =Enumerator: Enumerator.
                 =Import: Import declaration.
                 =ImportDeclaration: Import declaration.
                 =ImportModule: Import module.
                 =Pointer: Pointer type.
                 =PointerMember: Pointer to member function.
                 =Reference: Reference type.
                 =Restrict: Restrict specifier.
                 =RvalueReference: R-value reference.
                 =Subrange: Array subrange.
                 =TemplateParam: Template parameter.
                 =TemplateTemplateParam: Template template parameter.
                 =TemplateTypeParam: Template type parameter.
                 =TemplateValueParam: Template value parameter.
                 =Typedef: Type definition.
                 =Unspecified: Unspecified type.
                 =Volatile: Volatile specifier.

   COMPARE
       When dealing with debug information,  there  are  situations  when  the
       printing of the elements is not the correct approach. That is the case,
       when we are interested in the effects caused by different  versions  of
       the same toolchain, or the impact of specific compiler optimizations.

       For  those  cases, we are looking to see which elements have been added
       or removed. Due to the complicated debug information format, it is very
       difficult  to  use a regular diff tool to find those elements; even im-
       possible when dealing with different debug formats.

       llvm-debuginfo-analyzer supports a logical element comparison, allowing
       to find semantic differences between logical views, produced by differ-
       ent toolchain versions or even debug information formats.

       When comparing logical views created from different debug formats,  its
       accuracy depends on how close the debug information represents the user
       code. For instance, a logical view created  from  a  binary  file  with
       DWARF  debug  information may include more detailed data than a logical
       view created from a binary file with CodeView/COFF debug information.

       The following options describe the elements to compare.

       --compare=<value[,value,...]>
              With value being one of the options in the following list.

                 =all: Include all the below elements.

                 =lines: Include lines.
                 =scopes: Include scopes.
                 =symbols: Include symbols.
                 =types: Include types.

       llvm-debuginfo-analyzer takes the first binary file on the command line
       as  the  reference and the second one as the target.  To get a more de-
       scriptive report, the comparison is done twice. The reference and  tar-
       get  views are swapped, in order to produce those missing elements from
       the target view and those added elements to the reference view.

       See --report options on how to describe the comparison reports.

   WARNING
       When reading the input object files, llvm-debuginfo-analyzer can detect
       issues  in the raw debug information. These may not be considered fatal
       to the purpose of printing a logical view but they can give an  indica-
       tion about the quality and potentially expose issues with the generated
       debug information.

       The following options describe the warnings to be  recorded  for  later
       printing, if they are requested by --print.

       --warning=<value[,value,...]>
              With value being one of the options in the following list.

                 =all: Include all the below warnings.

              The  following options collect additional information during the
              creation of the logical view, to include invalid coverage values
              and  locations  for symbols; invalid code ranges; lines that are
              zero.

                 =coverages: Invalid symbol coverages values.
                 =lines: Debug lines that are zero.
                 =locations: Invalid symbol locations.
                 =ranges: Invalid code ranges.

   INTERNAL
          For a better understanding of the logical view, access to  more  de-
          tailed internal information could be needed. Such data would help to
          identify debug information processed or  incorrect  logical  element
          management.   Typically  these kind of options are available only in
          debug builds.

          llvm-debuginfo-analyzer supports these advanced options in both  re-
          lease  and debug builds, with the exception of the unique ID that is
          generated only in debug builds.

       --internal=<value[,value,...]>
              With value being one of the options in the following list.

                 =all: Include all the below options.

              The following options allow to check the integrity of the  logi-
              cal  view;  collect the debug tags that are processed or not im-
              plemented; ignore the logical element line number, to facilitate
              the  logical  view  comparison  when  using  external comparison
              tools; print the command line options used to invoke llvm-debug-
              info-analyzer.

                 =id: Print unique element ID.
                 =cmdline: Print command line.
                 =integrity: Check elements integrity.
                 =none: Ignore element line number.
                 =tag: Debug information tags.

              Note:  For  ELF  format,  the collected tags represent the debug
              tags that are not processed. For PE/COFF format, they  represent
              the tags that are processed.

EXAMPLES
       This  section  includes  some  real  binary  files  to  show how to use
       llvm-debuginfo-analyzer to print a logical view and to diagnose  possi-
       ble debug information issues.

   TEST CASE 1 - GENERAL OPTIONS
       The  below  example  is  used  to  show  different  output generated by
       llvm-debuginfo-analyzer. We compiled the example for an X86 ELF  target
       with Clang (-O0 -g):

          1  using INTPTR = const int *;
          2  int foo(INTPTR ParamPtr, unsigned ParamUnsigned, bool ParamBool) {
          3    if (ParamBool) {
          4      typedef int INTEGER;
          5      const INTEGER CONSTANT = 7;
          6      return CONSTANT;
          7    }
          8    return ParamUnsigned;
          9  }

   PRINTING MODE
       In  this  mode  llvm-debuginfo-analyzer prints the logical view or por-
       tions of it, based on criteria patterns (including regular expressions)
       to select the kind of logical elements to be included in the output.

   BASIC DETAILS
       The following command prints basic details for all the logical elements
       sorted by the debug information internal offset; it includes its  lexi-
       cal level and debug info format.

          llvm-debuginfo-analyzer --attribute=level,format
                                  --output-sort=offset
                                  --print=scopes,symbols,types,lines,instructions
                                  test-dwarf-clang.o

       or

          llvm-debuginfo-analyzer --attribute=level,format
                                  --output-sort=offset
                                  --print=elements
                                  test-dwarf-clang.o

       Each  row represents an element that is present within the debug infor-
       mation. The first column represents the scope level,  followed  by  the
       associated line number (if any), and finally the description of the el-
       ement.

          Logical View:
          [000]           {File} 'test-dwarf-clang.o' -> elf64-x86-64

          [001]             {CompileUnit} 'test.cpp'
          [002]     2         {Function} extern not_inlined 'foo' -> 'int'
          [003]     2           {Parameter} 'ParamPtr' -> 'INTPTR'
          [003]     2           {Parameter} 'ParamUnsigned' -> 'unsigned int'
          [003]     2           {Parameter} 'ParamBool' -> 'bool'
          [003]                 {Block}
          [004]     5             {Variable} 'CONSTANT' -> 'const INTEGER'
          [004]     5             {Line}
          [004]                   {Code} 'movl  $0x7, -0x1c(%rbp)'
          [004]     6             {Line}
          [004]                   {Code} 'movl  $0x7, -0x4(%rbp)'
          [004]                   {Code} 'jmp   0x6'
          [004]     8             {Line}
          [004]                   {Code} 'movl  -0x14(%rbp), %eax'
          [003]     4           {TypeAlias} 'INTEGER' -> 'int'
          [003]     2           {Line}
          [003]                 {Code} 'pushq   %rbp'
          [003]                 {Code} 'movq    %rsp, %rbp'
          [003]                 {Code} 'movb    %dl, %al'
          [003]                 {Code} 'movq    %rdi, -0x10(%rbp)'
          [003]                 {Code} 'movl    %esi, -0x14(%rbp)'
          [003]                 {Code} 'andb    $0x1, %al'
          [003]                 {Code} 'movb    %al, -0x15(%rbp)'
          [003]     3           {Line}
          [003]                 {Code} 'testb   $0x1, -0x15(%rbp)'
          [003]                 {Code} 'je      0x13'
          [003]     8           {Line}
          [003]                 {Code} 'movl    %eax, -0x4(%rbp)'
          [003]     9           {Line}
          [003]                 {Code} 'movl    -0x4(%rbp), %eax'
          [003]                 {Code} 'popq    %rbp'
          [003]                 {Code} 'retq'
          [003]     9           {Line}
          [002]     1         {TypeAlias} 'INTPTR' -> '* const int'

       On closer inspection, we can see what could be a potential debug issue:

          [003]                 {Block}
          [003]     4           {TypeAlias} 'INTEGER' -> 'int'

       The ‘INTEGER’ definition is at level [003], the same lexical  scope  as
       the anonymous {Block} (‘true’ branch for the ‘if’ statement) whereas in
       the original source code the typedef statement is clearly  inside  that
       block, so the ‘INTEGER’ definition should also be at level [004] inside
       the block.

   SELECT LOGICAL ELEMENTS
       The following prints all instructions, symbols and types  that  contain
       ‘inte’  or ‘movl’ in their names or types, using a tab layout and given
       the number of matches.

          llvm-debuginfo-analyzer --attribute=level
                                  --select-nocase --select-regex
                                  --select=INTe --select=movl
                                  --report=list
                                  --print=symbols,types,instructions,summary
                                  test-dwarf-clang.o

          Logical View:
          [000]           {File} 'test-dwarf-clang.o'

          [001]           {CompileUnit} 'test.cpp'
          [003]           {Code} 'movl  $0x7, -0x1c(%rbp)'
          [003]           {Code} 'movl  $0x7, -0x4(%rbp)'
          [003]           {Code} 'movl  %eax, -0x4(%rbp)'
          [003]           {Code} 'movl  %esi, -0x14(%rbp)'
          [003]           {Code} 'movl  -0x14(%rbp), %eax'
          [003]           {Code} 'movl  -0x4(%rbp), %eax'
          [003]     4     {TypeAlias} 'INTEGER' -> 'int'
          [004]     5     {Variable} 'CONSTANT' -> 'const INTEGER'

          -----------------------------
          Element      Total      Found
          -----------------------------
          Scopes           3          0
          Symbols          4          1
          Types            2          1
          Lines           17          6
          -----------------------------
          Total           26          8

   COMPARISON MODE
       In this mode llvm-debuginfo-analyzer compares logical views to  produce
       a  report  with the logical elements that are missing or added.  This a
       very powerful aid in finding semantic differences in the debug informa-
       tion  produced  by different toolchain versions or even completely dif-
       ferent toolchains altogether (For example a  compiler  producing  DWARF
       can  be  directly compared against a completely different compiler that
       produces CodeView).

       Given the previous example we found the above debug  information  issue
       (related  to  the  previous invalid scope location for the ‘typedef int
       INTEGER’) by comparing against another compiler.

       Using GCC to generate test-dwarf-gcc.o, we can apply a  selection  pat-
       tern  with  the printing mode to obtain the following logical view out-
       put.

          llvm-debuginfo-analyzer --attribute=level
                                  --select-regex --select-nocase --select=INTe
                                  --report=list
                                  --print=symbols,types
                                  test-dwarf-clang.o test-dwarf-gcc.o

          Logical View:
          [000]           {File} 'test-dwarf-clang.o'

          [001]           {CompileUnit} 'test.cpp'
          [003]     4     {TypeAlias} 'INTEGER' -> 'int'
          [004]     5     {Variable} 'CONSTANT' -> 'const INTEGER'

          Logical View:
          [000]           {File} 'test-dwarf-gcc.o'

          [001]           {CompileUnit} 'test.cpp'
          [004]     4     {TypeAlias} 'INTEGER' -> 'int'
          [004]     5     {Variable} 'CONSTANT' -> 'const INTEGER'

       The output shows that both objects contain the same elements.  But  the
       ‘typedef  INTEGER’  is located at different scope level. The GCC gener-
       ated object, shows ‘4’, which is the correct value.

       Note that there is no requirement that GCC must  produce  identical  or
       similar  DWARF  to  Clang to allow the comparison. We’re only comparing
       the semantics. The same case when comparing CodeView debug  information
       generated by MSVC and Clang.

       There are 2 comparison methods: logical view and logical elements.

   LOGICAL VIEW
       It  compares  the  logical view as a whole unit; for a match, each com-
       pared logical element must have the same parents and children.

       Using the llvm-debuginfo-analyzer comparison functionality, that  issue
       can  be  seen  in  a  more global context, that can include the logical
       view.

       The output shows in view form the missing (-), added (+) elements, giv-
       ing more context by swapping the reference and target object files.

          llvm-debuginfo-analyzer --attribute=level
                                  --compare=types
                                  --report=view
                                  --print=symbols,types
                                  test-dwarf-clang.o test-dwarf-gcc.o

          Reference: 'test-dwarf-clang.o'
          Target:    'test-dwarf-gcc.o'

          Logical View:
           [000]           {File} 'test-dwarf-clang.o'

           [001]             {CompileUnit} 'test.cpp'
           [002]     1         {TypeAlias} 'INTPTR' -> '* const int'
           [002]     2         {Function} extern not_inlined 'foo' -> 'int'
           [003]                 {Block}
           [004]     5             {Variable} 'CONSTANT' -> 'const INTEGER'
          +[004]     4             {TypeAlias} 'INTEGER' -> 'int'
           [003]     2           {Parameter} 'ParamBool' -> 'bool'
           [003]     2           {Parameter} 'ParamPtr' -> 'INTPTR'
           [003]     2           {Parameter} 'ParamUnsigned' -> 'unsigned int'
          -[003]     4           {TypeAlias} 'INTEGER' -> 'int'

       The  output shows the merging view path (reference and target) with the
       missing and added elements.

   LOGICAL ELEMENTS
       It compares individual logical elements without  considering  if  their
       parents  are  the same. For both comparison methods, the equal criteria
       includes the name, source code location, type, lexical scope level.

          llvm-debuginfo-analyzer --attribute=level
                                  --compare=types
                                  --report=list
                                  --print=symbols,types,summary
                                  test-dwarf-clang.o test-dwarf-gcc.o

          Reference: 'test-dwarf-clang.o'
          Target:    'test-dwarf-gcc.o'

          (1) Missing Types:
          -[003]     4     {TypeAlias} 'INTEGER' -> 'int'

          (1) Added Types:
          +[004]     4     {TypeAlias} 'INTEGER' -> 'int'

          ----------------------------------------
          Element   Expected    Missing      Added
          ----------------------------------------
          Scopes           4          0          0
          Symbols          0          0          0
          Types            2          1          1
          Lines            0          0          0
          ----------------------------------------
          Total            6          1          1

       Changing the Reference and Target order:

          llvm-debuginfo-analyzer --attribute=level
                                  --compare=types
                                  --report=list
                                  --print=symbols,types,summary
                                  test-dwarf-gcc.o test-dwarf-clang.o

          Reference: 'test-dwarf-gcc.o'
          Target:    'test-dwarf-clang.o'

          (1) Missing Types:
          -[004]     4     {TypeAlias} 'INTEGER' -> 'int'

          (1) Added Types:
          +[003]     4     {TypeAlias} 'INTEGER' -> 'int'

          ----------------------------------------
          Element   Expected    Missing      Added
          ----------------------------------------
          Scopes           4          0          0
          Symbols          0          0          0
          Types            2          1          1
          Lines            0          0          0
          ----------------------------------------
          Total            6          1          1

       As the Reference and Target are switched,  the  Added  Types  from  the
       first case now are listed as Missing Types.

   TEST CASE 2 - ASSEMBLER INSTRUCTIONS
       The  below  example  is  used  to  show  different  output generated by
       llvm-debuginfo-analyzer. We compiled the example for  an  X86  Codeview
       and  ELF  targets  with recent versions of Clang, GCC and MSVC (-O0 -g)
       for Windows and Linux.

          1  extern int printf(const char * format, ... );
          2
          3  int main()
          4  {
          5    printf("Hello, World\n");
          6    return 0;
          7  }

       These are the logical views that llvm-debuginfo-analyzer generates  for
       3  different  compilers (MSVC, Clang and GCC), emitting different debug
       information formats (CodeView, DWARF) on Windows and Linux.

          llvm-debuginfo-analyzer --attribute=level,format,producer
                                  --print=lines,instructions
                                  hello-world-codeview-clang.o
                                  hello-world-codeview-msvc.o
                                  hello-world-dwarf-clang.o
                                  hello-world-dwarf-gcc.o

   CodeView - Clang (Windows)
          Logical View:
          [000]           {File} 'hello-world-codeview-clang.o' -> COFF-x86-64

          [001]             {CompileUnit} 'hello-world.cpp'
          [002]               {Producer} 'clang version 14.0.0'
          [002]               {Function} extern not_inlined 'main' -> 'int'
          [003]     4           {Line}
          [003]                 {Code} 'subq    $0x28, %rsp'
          [003]                 {Code} 'movl    $0x0, 0x24(%rsp)'
          [003]     5           {Line}
          [003]                 {Code} 'leaq    (%rip), %rcx'
          [003]                 {Code} 'callq   0x0'
          [003]     6           {Line}
          [003]                 {Code} 'xorl    %eax, %eax'
          [003]                 {Code} 'addq    $0x28, %rsp'
          [003]                 {Code} 'retq'

   CodeView - MSVC (Windows)
          Logical View:
          [000]           {File} 'hello-world-codeview-msvc.o' -> COFF-i386

          [001]             {CompileUnit} 'hello-world.cpp'
          [002]               {Producer} 'Microsoft (R) Optimizing Compiler'
          [002]               {Function} extern not_inlined 'main' -> 'int'
          [003]     4           {Line}
          [003]                 {Code} 'pushl   %ebp'
          [003]                 {Code} 'movl    %esp, %ebp'
          [003]     5           {Line}
          [003]                 {Code} 'pushl   $0x0'
          [003]                 {Code} 'calll   0x0'
          [003]                 {Code} 'addl    $0x4, %esp'
          [003]     6           {Line}
          [003]                 {Code} 'xorl    %eax, %eax'
          [003]     7           {Line}
          [003]                 {Code} 'popl    %ebp'
          [003]                 {Code} 'retl'

   DWARF - Clang (Linux)
          Logical View:
          [000]           {File} 'hello-world-dwarf-clang.o' -> elf64-x86-64

          [001]             {CompileUnit} 'hello-world.cpp'
          [002]               {Producer} 'clang version 14.0.0'
          [002]     3         {Function} extern not_inlined 'main' -> 'int'
          [003]     4           {Line}
          [003]                 {Code} 'pushq   %rbp'
          [003]                 {Code} 'movq    %rsp, %rbp'
          [003]                 {Code} 'subq    $0x10, %rsp'
          [003]                 {Code} 'movl    $0x0, -0x4(%rbp)'
          [003]     5           {Line}
          [003]                 {Code} 'movabsq $0x0, %rdi'
          [003]                 {Code} 'movb    $0x0, %al'
          [003]                 {Code} 'callq   0x0'
          [003]     6           {Line}
          [003]                 {Code} 'xorl    %eax, %eax'
          [003]                 {Code} 'addq    $0x10, %rsp'
          [003]                 {Code} 'popq    %rbp'
          [003]                 {Code} 'retq'
          [003]     6           {Line}

   DWARF - GCC (Linux)
          Logical View:
          [000]           {File} 'hello-world-dwarf-gcc.o' -> elf64-x86-64

          [001]             {CompileUnit} 'hello-world.cpp'
          [002]               {Producer} 'GNU C++14 9.3.0'
          [002]     3         {Function} extern not_inlined 'main' -> 'int'
          [003]     4           {Line}
          [003]                 {Code} 'endbr64'
          [003]                 {Code} 'pushq   %rbp'
          [003]                 {Code} 'movq    %rsp, %rbp'
          [003]     5           {Line}
          [003]                 {Code} 'leaq    (%rip), %rdi'
          [003]                 {Code} 'movl    $0x0, %eax'
          [003]                 {Code} 'callq   0x0'
          [003]     6           {Line}
          [003]                 {Code} 'movl    $0x0, %eax'
          [003]     7           {Line}
          [003]                 {Code} 'popq    %rbp'
          [003]                 {Code} 'retq'
          [003]     7           {Line}

       The logical views shows the intermixed  lines  and  assembler  instruc-
       tions,  allowing  to  compare  the  code  generated  by  the  different
       toolchains.

   TEST CASE 3 - INCORRECT LEXICAL SCOPE FOR TYPEDEF
       The below example  is  used  to  show  different  output  generated  by
       llvm-debuginfo-analyzer.  We  compiled  the example for an X86 Codeview
       and ELF targets with recent versions of Clang, GCC and MSVC (-O0 -g).

           1  int bar(float Input) { return (int)Input; }
           2
           3  unsigned foo(char Param) {
           4    typedef int INT;                // ** Definition for INT **
           5    INT Value = Param;
           6    {
           7      typedef float FLOAT;          // ** Definition for FLOAT **
           8      {
           9        FLOAT Added = Value + Param;
          10        Value = bar(Added);
          11      }
          12    }
          13    return Value + Param;
          14  }

       The above test is used to illustrate a scope issue found in  the  Clang
       compiler: PR44884 (Bugs LLVM) / PR44229 (GitHub LLVM)

       The  lines  4  and  7 contains 2 typedefs, defined at different lexical
       scopes.

          4    typedef int INT;
          7      typedef float FLOAT;

       These are the logical views that llvm-debuginfo-analyzer generates  for
       3  different  compilers (MSVC, Clang and GCC), emitting different debug
       information formats (CodeView, DWARF) on different platforms.

          llvm-debuginfo-analyzer --attribute=level,format,producer
                                  --print=symbols,types,lines
                                  --output-sort=kind
                                  pr-44884-codeview-clang.o
                                  pr-44884-codeview-msvc.o
                                  pr-44884-dwarf-clang.o
                                  pr-44884-dwarf-gcc.o

   CodeView - Clang (Windows)
          Logical View:
          [000]           {File} 'pr-44884-codeview-clang.o' -> COFF-x86-64

          [001]             {CompileUnit} 'pr-44884.cpp'
          [002]               {Producer} 'clang version 14.0.0'
          [002]               {Function} extern not_inlined 'bar' -> 'int'
          [003]                 {Parameter} 'Input' -> 'float'
          [003]     1           {Line}
          [002]               {Function} extern not_inlined 'foo' -> 'unsigned'
          [003]                 {Block}
          [004]                   {Variable} 'Added' -> 'float'
          [004]     9             {Line}
          [004]    10             {Line}
          [003]                 {Parameter} 'Param' -> 'char'
          [003]                 {TypeAlias} 'FLOAT' -> 'float'
          [003]                 {TypeAlias} 'INT' -> 'int'
          [003]                 {Variable} 'Value' -> 'int'
          [003]     3           {Line}
          [003]     5           {Line}
          [003]    13           {Line}

   CodeView - MSVC (Windows)
          Logical View:
          [000]           {File} 'pr-44884-codeview-msvc.o' -> COFF-i386

          [001]             {CompileUnit} 'pr-44884.cpp'
          [002]               {Producer} 'Microsoft (R) Optimizing Compiler'
          [002]               {Function} extern not_inlined 'bar' -> 'int'
          [003]                 {Variable} 'Input' -> 'float'
          [003]     1           {Line}
          [002]               {Function} extern not_inlined 'foo' -> 'unsigned'
          [003]                 {Block}
          [004]                   {Block}
          [005]                     {Variable} 'Added' -> 'float'
          [004]                   {TypeAlias} 'FLOAT' -> 'float'
          [004]     9             {Line}
          [004]    10             {Line}
          [003]                 {TypeAlias} 'INT' -> 'int'
          [003]                 {Variable} 'Param' -> 'char'
          [003]                 {Variable} 'Value' -> 'int'
          [003]     3           {Line}
          [003]     5           {Line}
          [003]    13           {Line}
          [003]    14           {Line}

   DWARF - Clang (Linux)
          Logical View:
          [000]           {File} 'pr-44884-dwarf-clang.o' -> elf64-x86-64

          [001]             {CompileUnit} 'pr-44884.cpp'
          [002]               {Producer} 'clang version 14.0.0'
          [002]     1         {Function} extern not_inlined 'bar' -> 'int'
          [003]     1           {Parameter} 'Input' -> 'float'
          [003]     1           {Line}
          [003]     1           {Line}
          [003]     1           {Line}
          [002]     3         {Function} extern not_inlined 'foo' -> 'unsigned int'
          [003]                 {Block}
          [004]     9             {Variable} 'Added' -> 'FLOAT'
          [004]     9             {Line}
          [004]     9             {Line}
          [004]     9             {Line}
          [004]     9             {Line}
          [004]     9             {Line}
          [004]    10             {Line}
          [004]    10             {Line}
          [004]    10             {Line}
          [004]    13             {Line}
          [003]     3           {Parameter} 'Param' -> 'char'
          [003]     7           {TypeAlias} 'FLOAT' -> 'float'
          [003]     4           {TypeAlias} 'INT' -> 'int'
          [003]     5           {Variable} 'Value' -> 'INT'
          [003]     3           {Line}
          [003]     5           {Line}
          [003]     5           {Line}
          [003]    13           {Line}
          [003]    13           {Line}
          [003]    13           {Line}
          [003]    13           {Line}

   DWARF - GCC (Linux)
          Logical View:
          [000]           {File} 'pr-44884-dwarf-gcc.o' -> elf32-littlearm

          [001]             {CompileUnit} 'pr-44884.cpp'
          [002]               {Producer} 'GNU C++14 10.2.1 20201103'
          [002]     1         {Function} extern not_inlined 'bar' -> 'int'
          [003]     1           {Parameter} 'Input' -> 'float'
          [003]     1           {Line}
          [003]     1           {Line}
          [003]     1           {Line}
          [002]     3         {Function} extern not_inlined 'foo' -> 'unsigned int'
          [003]                 {Block}
          [004]                   {Block}
          [005]     9               {Variable} 'Added' -> 'FLOAT'
          [005]     9               {Line}
          [005]     9               {Line}
          [005]     9               {Line}
          [005]    10               {Line}
          [005]    13               {Line}
          [004]     7             {TypeAlias} 'FLOAT' -> 'float'
          [003]     3           {Parameter} 'Param' -> 'char'
          [003]     4           {TypeAlias} 'INT' -> 'int'
          [003]     5           {Variable} 'Value' -> 'INT'
          [003]     3           {Line}
          [003]     5           {Line}
          [003]    13           {Line}
          [003]    14           {Line}
          [003]    14           {Line}

       From the previous logical views, we can see  that  the  Clang  compiler
       emits both typedefs at the same lexical scope (3), which is wrong.  GCC
       and MSVC emit correct lexical scope for both typedefs.

       Using the llvm-debuginfo-analyzer selection facilities, we can  produce
       a  simple  tabular output showing just the logical types that are Type-
       def.

          llvm-debuginfo-analyzer --attribute=level,format
                                  --output-sort=name
                                  --select-types=Typedef
                                  --report=list
                                  --print=types
                                  pr-44884-*.o

          Logical View:
          [000]           {File} 'pr-44884-codeview-clang.o' -> COFF-x86-64

          [001]           {CompileUnit} 'pr_44884.cpp'
          [003]           {TypeAlias} 'FLOAT' -> 'float'
          [003]           {TypeAlias} 'INT' -> 'int'

          Logical View:
          [000]           {File} 'pr-44884-codeview-msvc.o' -> COFF-i386

          [001]           {CompileUnit} 'pr_44884.cpp'
          [004]           {TypeAlias} 'FLOAT' -> 'float'
          [003]           {TypeAlias} 'INT' -> 'int'

          Logical View:
          [000]           {File} 'pr-44884-dwarf-clang.o' -> elf64-x86-64

          [001]           {CompileUnit} 'pr_44884.cpp'
          [003]     7     {TypeAlias} 'FLOAT' -> 'float'
          [003]     4     {TypeAlias} 'INT' -> 'int'

          Logical View:
          [000]           {File} 'pr-44884-dwarf-gcc.o' -> elf32-littlearm

          [001]           {CompileUnit} 'pr_44884.cpp'
          [004]     7     {TypeAlias} 'FLOAT' -> 'float'
          [003]     4     {TypeAlias} 'INT' -> 'int'

       It also shows, that the CodeView debug information  does  not  generate
       source  code line numbers for the those logical types. The logical view
       is sorted by the types name.

   TEST CASE 4 - MISSING NESTED ENUMERATIONS
       The below example  is  used  to  show  different  output  generated  by
       llvm-debuginfo-analyzer.  We  compiled  the example for an X86 Codeview
       and ELF targets with recent versions of Clang, GCC and MSVC (-O0 -g).

           1  struct Struct {
           2    union Union {
           3      enum NestedEnum { RED, BLUE };
           4    };
           5    Union U;
           6  };
           7
           8  Struct S;
           9  int test() {
          10    return S.U.BLUE;
          11  }

       The above test is used to illustrate a scope issue found in  the  Clang
       compiler: PR46466 (Bugs LLVM) / PR45811 (GitHub LLVM)

       These  are the logical views that llvm-debuginfo-analyzer generates for
       3 different compilers (MSVC, Clang and GCC), emitting  different  debug
       information formats (CodeView, DWARF) on different platforms.

          llvm-debuginfo-analyzer --attribute=level,format,producer
                                  --output-sort=name
                                  --print=symbols,types
                                  pr-46466-codeview-clang.o
                                  pr-46466-codeview-msvc.o
                                  pr-46466-dwarf-clang.o
                                  pr-46466-dwarf-gcc.o

   CodeView - Clang (Windows)
          Logical View:
          [000]           {File} 'pr-46466-codeview-clang.o' -> COFF-x86-64

          [001]             {CompileUnit} 'pr-46466.cpp'
          [002]               {Producer} 'clang version 14.0.0'
          [002]               {Variable} extern 'S' -> 'Struct'
          [002]     1         {Struct} 'Struct'
          [003]                 {Member} public 'U' -> 'Union'
          [003]     2           {Union} 'Union'
          [004]     3             {Enumeration} 'NestedEnum' -> 'int'
          [005]                     {Enumerator} 'BLUE' = '0x1'
          [005]                     {Enumerator} 'RED' = '0x0'

   CodeView - MSVC (Windows)
          Logical View:
          [000]           {File} 'pr-46466-codeview-msvc.o' -> COFF-i386

          [001]             {CompileUnit} 'pr-46466.cpp'
          [002]               {Producer} 'Microsoft (R) Optimizing Compiler'
          [002]               {Variable} extern 'S' -> 'Struct'
          [002]     1         {Struct} 'Struct'
          [003]                 {Member} public 'U' -> 'Union'
          [003]     2           {Union} 'Union'
          [004]     3             {Enumeration} 'NestedEnum' -> 'int'
          [005]                     {Enumerator} 'BLUE' = '0x1'
          [005]                     {Enumerator} 'RED' = '0x0'

   DWARF - Clang (Linux)
          Logical View:
          [000]           {File} 'pr-46466-dwarf-clang.o' -> elf64-x86-64

          [001]             {CompileUnit} 'pr-46466.cpp'
          [002]               {Producer} 'clang version 14.0.0'
          [002]     8         {Variable} extern 'S' -> 'Struct'
          [002]     1         {Struct} 'Struct'
          [003]     5           {Member} public 'U' -> 'Union'

   DWARF - GCC (Linux)
          Logical View:
          [000]           {File} 'pr-46466-dwarf-gcc.o' -> elf64-x86-64

          [001]             {CompileUnit} 'pr-46466.cpp'
          [002]               {Producer} 'GNU C++14 9.3.0'
          [002]     8         {Variable} extern 'S' -> 'Struct'
          [002]     1         {Struct} 'Struct'
          [003]     5           {Member} public 'U' -> 'Union'
          [003]     2           {Union} 'Union'
          [004]     3             {Enumeration} 'NestedEnum' -> 'unsigned int'
          [005]                     {Enumerator} 'BLUE' = '0x1'
          [005]                     {Enumerator} 'RED' = '0x0'

       From the previous logical views, we can see that the DWARF debug infor-
       mation generated by the Clang compiler does not include any  references
       to  the  enumerators RED and BLUE. The DWARF generated by GCC, CodeView
       generated by Clang and MSVC, they do include such references.

       Using the llvm-debuginfo-analyzer selection facilities, we can  produce
       a  logical  view showing just the logical types that are Enumerator and
       its parents. The logical view is sorted by the types name.

          llvm-debuginfo-analyzer --attribute=format,level
                                  --output-sort=name
                                  --select-types=Enumerator
                                  --report=parents
                                  --print=types
                                  pr-46466-*.o

          Logical View:
          [000]           {File} 'pr-46466-codeview-clang.o' -> COFF-x86-64

          [001]             {CompileUnit} 'pr-46466.cpp'
          [002]     1         {Struct} 'Struct'
          [003]     2           {Union} 'Union'
          [004]     3             {Enumeration} 'NestedEnum' -> 'int'
          [005]                     {Enumerator} 'BLUE' = '0x1'
          [005]                     {Enumerator} 'RED' = '0x0'

          Logical View:
          [000]           {File} 'pr-46466-codeview-msvc.o' -> COFF-i386

          [001]             {CompileUnit} 'pr-46466.cpp'
          [002]     1         {Struct} 'Struct'
          [003]     2           {Union} 'Union'
          [004]     3             {Enumeration} 'NestedEnum' -> 'int'
          [005]                     {Enumerator} 'BLUE' = '0x1'
          [005]                     {Enumerator} 'RED' = '0x0'

          Logical View:
          [000]           {File} 'pr-46466-dwarf-clang.o' -> elf64-x86-64

          [001]             {CompileUnit} 'pr-46466.cpp'

          Logical View:
          [000]           {File} 'pr-46466-dwarf-gcc.o' -> elf64-x86-64

          [001]             {CompileUnit} 'pr-46466.cpp'
          [002]     1         {Struct} 'Struct'
          [003]     2           {Union} 'Union'
          [004]     3             {Enumeration} 'NestedEnum' -> 'unsigned int'
          [005]                     {Enumerator} 'BLUE' = '0x1'
          [005]                     {Enumerator} 'RED' = '0x0'

       Using the llvm-debuginfo-analyzer selection facilities, we can  produce
       a  simple tabular output including a summary for the logical types that
       are Enumerator. The logical view is sorted by the types name.

          llvm-debuginfo-analyzer --attribute=format,level
                                  --output-sort=name
                                  --select-types=Enumerator
                                  --print=types,summary
                                  pr-46466-*.o

          Logical View:
          [000]           {File} 'pr-46466-codeview-clang.o' -> COFF-x86-64

          [001]           {CompileUnit} 'pr-46466.cpp'
          [005]           {Enumerator} 'BLUE' = '0x1'
          [005]           {Enumerator} 'RED' = '0x0'

          -----------------------------
          Element      Total      Found
          -----------------------------
          Scopes           5          0
          Symbols          2          0
          Types            6          2
          Lines            0          0
          -----------------------------
          Total           13          2

          Logical View:
          [000]           {File} 'pr-46466-codeview-msvc.o' -> COFF-i386

          [001]           {CompileUnit} 'pr-46466.cpp'
          [005]           {Enumerator} 'BLUE' = '0x1'
          [005]           {Enumerator} 'RED' = '0x0'

          -----------------------------
          Element      Total      Found
          -----------------------------
          Scopes           5          0
          Symbols          2          0
          Types            7          2
          Lines            0          0
          -----------------------------
          Total           14          2

          Logical View:
          [000]           {File} 'pr-46466-dwarf-clang.o' -> elf64-x86-64

          [001]           {CompileUnit} 'pr-46466.cpp'

          -----------------------------
          Element      Total      Found
          -----------------------------
          Scopes           4          0
          Symbols          0          0
          Types            0          0
          Lines            0          0
          -----------------------------
          Total            4          0

          Logical View:
          [000]           {File} 'pr-46466-dwarf-gcc.o' -> elf64-x86-64

          [001]           {CompileUnit} 'pr-46466.cpp'
          [005]           {Enumerator} 'BLUE' = '0x1'
          [005]           {Enumerator} 'RED' = '0x0'

          -----------------------------
          Element      Total      Found
          -----------------------------
          Scopes           5          0
          Symbols          0          0
          Types            2          2
          Lines            0          0
          -----------------------------
          Total            7          2

       From the values printed under the Found column,  we  can  see  that  no
       Types were found in the DWARF debug information generated by Clang.

   TEST CASE 5 - INCORRECT LEXICAL SCOPE FOR VARIABLE
       The  below  example  is  used  to  show  different  output generated by
       llvm-debuginfo-analyzer. We compiled the example for  an  X86  Codeview
       and ELF targets with recent versions of Clang, GCC and MSVC (-O0 -g).

          // definitions.h
          #ifdef _MSC_VER
            #define forceinline __forceinline
          #elif defined(__clang__)
            #if __has_attribute(__always_inline__)
              #define forceinline inline __attribute__((__always_inline__))
            #else
              #define forceinline inline
            #endif
          #elif defined(__GNUC__)
            #define forceinline inline __attribute__((__always_inline__))
          #else
            #define forceinline inline
            #error
          #endif

       As  the  test is dependent on inline compiler options, the above header
       file defines forceinline.

          #include "definitions.h"

           1  #include "definitions.h"
           2  forceinline int InlineFunction(int Param) {
           3    int Var_1 = Param;
           4    {
           5      int Var_2 = Param + Var_1;
           6      Var_1 = Var_2;
           7    }
           8    return Var_1;
           9  }
          10
          11  int test(int Param_1, int Param_2) {
          12    int A = Param_1;
          13    A += InlineFunction(Param_2);
          14    return A;
          15  }

       The above test is used to illustrate a  variable  issue  found  in  the
       Clang compiler: PR43860 (Bugs LLVM) / PR43205 (GitHub)

       These  are the logical views that llvm-debuginfo-analyzer generates for
       3 different compilers (MSVC, Clang and GCC), emitting  different  debug
       information formats (CodeView, DWARF) on different platforms.

          llvm-debuginfo-analyzer --attribute=level,format,producer
                                  --output-sort=name
                                  --print=symbols
                                  pr-43860-codeview-clang.o
                                  pr-43860-codeview-msvc.o
                                  pr-43860-dwarf-clang.o
                                  pr-43860-dwarf-gcc.o

   CODEVIEW - Clang (Windows)
          Logical View:
          [000]           {File} 'pr-43860-codeview-clang.o' -> COFF-x86-64

          [001]             {CompileUnit} 'pr-43860.cpp'
          [002]               {Producer} 'clang version 14.0.0'
          [002]     2         {Function} inlined 'InlineFunction' -> 'int'
          [003]                 {Parameter} '' -> 'int'
          [002]               {Function} extern not_inlined 'test' -> 'int'
          [003]                 {Variable} 'A' -> 'int'
          [003]                 {InlinedFunction} inlined 'InlineFunction' -> 'int'
          [004]                   {Parameter} 'Param' -> 'int'
          [004]                   {Variable} 'Var_1' -> 'int'
          [004]                   {Variable} 'Var_2' -> 'int'
          [003]                 {Parameter} 'Param_1' -> 'int'
          [003]                 {Parameter} 'Param_2' -> 'int'

   CODEVIEW - MSVC (Windows)
          Logical View:
          [000]           {File} 'pr-43860-codeview-msvc.o' -> COFF-i386

          [001]             {CompileUnit} 'pr-43860.cpp'
          [002]               {Producer} 'Microsoft (R) Optimizing Compiler'
          [002]               {Function} extern not_inlined 'InlineFunction' -> 'int'
          [003]                 {Block}
          [004]                   {Variable} 'Var_2' -> 'int'
          [003]                 {Variable} 'Param' -> 'int'
          [003]                 {Variable} 'Var_1' -> 'int'
          [002]               {Function} extern not_inlined 'test' -> 'int'
          [003]                 {Variable} 'A' -> 'int'
          [003]                 {Variable} 'Param_1' -> 'int'
          [003]                 {Variable} 'Param_2' -> 'int'

   DWARF - Clang (Linux)
          Logical View:
          [000]           {File} 'pr-43860-dwarf-clang.o' -> elf64-x86-64

          [001]             {CompileUnit} 'pr-43860.cpp'
          [002]               {Producer} 'clang version 14.0.0'
          [002]     2         {Function} extern inlined 'InlineFunction' -> 'int'
          [003]                 {Block}
          [004]     5             {Variable} 'Var_2' -> 'int'
          [003]     2           {Parameter} 'Param' -> 'int'
          [003]     3           {Variable} 'Var_1' -> 'int'
          [002]    11         {Function} extern not_inlined 'test' -> 'int'
          [003]    12           {Variable} 'A' -> 'int'
          [003]    14           {InlinedFunction} inlined 'InlineFunction' -> 'int'
          [004]                   {Block}
          [005]                     {Variable} 'Var_2' -> 'int'
          [004]                   {Parameter} 'Param' -> 'int'
          [004]                   {Variable} 'Var_1' -> 'int'
          [003]    11           {Parameter} 'Param_1' -> 'int'
          [003]    11           {Parameter} 'Param_2' -> 'int'

   DWARF - GCC (Linux)
          Logical View:
          [000]           {File} 'pr-43860-dwarf-gcc.o' -> elf64-x86-64

          [001]             {CompileUnit} 'pr-43860.cpp'
          [002]               {Producer} 'GNU C++14 9.3.0'
          [002]     2         {Function} extern declared_inlined 'InlineFunction' -> 'int'
          [003]                 {Block}
          [004]     5             {Variable} 'Var_2' -> 'int'
          [003]     2           {Parameter} 'Param' -> 'int'
          [003]     3           {Variable} 'Var_1' -> 'int'
          [002]    11         {Function} extern not_inlined 'test' -> 'int'
          [003]    12           {Variable} 'A' -> 'int'
          [003]    13           {InlinedFunction} declared_inlined 'InlineFunction' -> 'int'
          [004]                   {Block}
          [005]                     {Variable} 'Var_2' -> 'int'
          [004]                   {Parameter} 'Param' -> 'int'
          [004]                   {Variable} 'Var_1' -> 'int'
          [003]    11           {Parameter} 'Param_1' -> 'int'
          [003]    11           {Parameter} 'Param_2' -> 'int'

       From the previous logical views, we can see that the CodeView debug in-
       formation generated by the Clang compiler shows the variables Var_1 and
       Var_2  are at the same lexical scope (4) in the function InlineFuction.
       The DWARF generated by GCC/Clang and CodeView generated by  MSVC,  show
       those variables at the correct lexical scope: 3 and 4 respectively.

       Using  the llvm-debuginfo-analyzer selection facilities, we can produce
       a simple tabular output showing just the logical elements that have  in
       their name the var pattern. The logical view is sorted by the variables
       name.

          llvm-debuginfo-analyzer --attribute=level,format
                                  --output-sort=name
                                  --select-regex --select-nocase --select=Var
                                  --report=list
                                  --print=symbols
                                  pr-43860-*.o

          Logical View:
          [000]           {File} 'pr-43860-codeview-clang.o' -> COFF-x86-64

          [001]           {CompileUnit} 'pr-43860.cpp'
          [004]           {Variable} 'Var_1' -> 'int'
          [004]           {Variable} 'Var_2' -> 'int'

          Logical View:
          [000]           {File} 'pr-43860-codeview-msvc.o' -> COFF-i386

          [001]           {CompileUnit} 'pr-43860.cpp'
          [003]           {Variable} 'Var_1' -> 'int'
          [004]           {Variable} 'Var_2' -> 'int'

          Logical View:
          [000]           {File} 'pr-43860-dwarf-clang.o' -> elf64-x86-64

          [001]           {CompileUnit} 'pr-43860.cpp'
          [004]           {Variable} 'Var_1' -> 'int'
          [003]     3     {Variable} 'Var_1' -> 'int'
          [005]           {Variable} 'Var_2' -> 'int'
          [004]     5     {Variable} 'Var_2' -> 'int'

          Logical View:
          [000]           {File} 'pr-43860-dwarf-gcc.o' -> elf64-x86-64

          [001]           {CompileUnit} 'pr-43860.cpp'
          [004]           {Variable} 'Var_1' -> 'int'
          [003]     3     {Variable} 'Var_1' -> 'int'
          [005]           {Variable} 'Var_2' -> 'int'
          [004]     5     {Variable} 'Var_2' -> 'int'

       It also shows, that the CodeView debug information  does  not  generate
       source  code  line  numbers  for the those logical symbols. The logical
       view is sorted by the types name.

   TEST CASE 6 - FULL LOGICAL VIEW
       For advanced users, llvm-debuginfo-analyzer can display low  level  in-
       formation  that  includes offsets within the debug information section,
       debug location operands, linkage names, etc.

          llvm-debuginfo-analyzer --attribute=all
                                  --print=all
                                  test-dwarf-clang.o

          Logical View:
          [0x0000000000][000]            {File} 'test-dwarf-clang.o' -> elf64-x86-64

          [0x000000000b][001]              {CompileUnit} 'test.cpp'
          [0x000000000b][002]                {Producer} 'clang version 12.0.0'
                                             {Directory} ''
                                             {File} 'test.cpp'
                                             {Public} 'foo' [0x0000000000:0x000000003a]
          [0x000000000b][002]                {Range} Lines 2:9 [0x0000000000:0x000000003a]
          [0x00000000bc][002]                {BaseType} 'bool'
          [0x0000000099][002]                {BaseType} 'int'
          [0x00000000b5][002]                {BaseType} 'unsigned int'

          [0x00000000a0][002]   {Source} '/test.cpp'
          [0x00000000a0][002]      1         {TypeAlias} 'INTPTR' -> [0x00000000ab]'* const int'
          [0x000000002a][002]      2         {Function} extern not_inlined 'foo' -> [0x0000000099]'int'
          [0x000000002a][003]                  {Range} Lines 2:9 [0x0000000000:0x000000003a]
          [0x000000002a][003]                  {Linkage}  0x2 '_Z3fooPKijb'
          [0x0000000071][003]                  {Block}
          [0x0000000071][004]                    {Range} Lines 5:8 [0x000000001c:0x000000002f]
          [0x000000007e][004]      5             {Variable} 'CONSTANT' -> [0x00000000c3]'const INTEGER'
          [0x000000007e][005]                      {Coverage} 100.00%
          [0x000000007f][005]                      {Location}
          [0x000000007f][006]                        {Entry} Stack Offset: -28 (0xffffffffffffffe4) [DW_OP_fbreg]
          [0x000000001c][004]      5             {Line} {NewStatement} '/test.cpp'
          [0x000000001c][004]                    {Code} 'movl   $0x7, -0x1c(%rbp)'
          [0x0000000023][004]      6             {Line} {NewStatement} '/test.cpp'
          [0x0000000023][004]                    {Code} 'movl   $0x7, -0x4(%rbp)'
          [0x000000002a][004]                    {Code} 'jmp    0x6'
          [0x000000002f][004]      8             {Line} {NewStatement} '/test.cpp'
          [0x000000002f][004]                    {Code} 'movl   -0x14(%rbp), %eax'
          [0x0000000063][003]      2           {Parameter} 'ParamBool' -> [0x00000000bc]'bool'
          [0x0000000063][004]                    {Coverage} 100.00%
          [0x0000000064][004]                    {Location}
          [0x0000000064][005]                      {Entry} Stack Offset: -21 (0xffffffffffffffeb) [DW_OP_fbreg]
          [0x0000000047][003]      2           {Parameter} 'ParamPtr' -> [0x00000000a0]'INTPTR'
          [0x0000000047][004]                    {Coverage} 100.00%
          [0x0000000048][004]                    {Location}
          [0x0000000048][005]                      {Entry} Stack Offset: -16 (0xfffffffffffffff0) [DW_OP_fbreg]
          [0x0000000055][003]      2           {Parameter} 'ParamUnsigned' -> [0x00000000b5]'unsigned int'
          [0x0000000055][004]                    {Coverage} 100.00%
          [0x0000000056][004]                    {Location}
          [0x0000000056][005]                      {Entry} Stack Offset: -20 (0xffffffffffffffec) [DW_OP_fbreg]
          [0x000000008d][003]      4           {TypeAlias} 'INTEGER' -> [0x0000000099]'int'
          [0x0000000000][003]      2           {Line} {NewStatement} '/test.cpp'
          [0x0000000000][003]                  {Code} 'pushq    %rbp'
          [0x0000000001][003]                  {Code} 'movq     %rsp, %rbp'
          [0x0000000004][003]                  {Code} 'movb     %dl, %al'
          [0x0000000006][003]                  {Code} 'movq     %rdi, -0x10(%rbp)'
          [0x000000000a][003]                  {Code} 'movl     %esi, -0x14(%rbp)'
          [0x000000000d][003]                  {Code} 'andb     $0x1, %al'
          [0x000000000f][003]                  {Code} 'movb     %al, -0x15(%rbp)'
          [0x0000000012][003]      3           {Line} {NewStatement} {PrologueEnd} '/test.cpp'
          [0x0000000012][003]                  {Code} 'testb    $0x1, -0x15(%rbp)'
          [0x0000000016][003]                  {Code} 'je       0x13'
          [0x0000000032][003]      8           {Line} '/test.cpp'
          [0x0000000032][003]                  {Code} 'movl     %eax, -0x4(%rbp)'
          [0x0000000035][003]      9           {Line} {NewStatement} '/test.cpp'
          [0x0000000035][003]                  {Code} 'movl     -0x4(%rbp), %eax'
          [0x0000000038][003]                  {Code} 'popq     %rbp'
          [0x0000000039][003]                  {Code} 'retq'
          [0x000000003a][003]      9           {Line} {NewStatement} {EndSequence} '/test.cpp'

          -----------------------------
          Element      Total    Printed
          -----------------------------
          Scopes           3          3
          Symbols          4          4
          Types            5          5
          Lines           25         25
          -----------------------------
          Total           37         37

          Scope Sizes:
                 189 (100.00%) : [0x000000000b][001]              {CompileUnit} 'test.cpp'
                 110 ( 58.20%) : [0x000000002a][002]      2         {Function} extern not_inlined 'foo' -> [0x0000000099]'int'
                  27 ( 14.29%) : [0x0000000071][003]                  {Block}

          Totals by lexical level:
          [001]:        189 (100.00%)
          [002]:        110 ( 58.20%)
          [003]:         27 ( 14.29%)

       The Scope Sizes table shows the contribution in bytes to the debug  in-
       formation by each scope, which can be used to determine unexpected size
       changes in the DWARF sections between different versions  of  the  same
       toolchain.

          [0x000000002a][002]      2         {Function} extern not_inlined 'foo' -> [0x0000000099]'int'
          [0x000000002a][003]                  {Range} Lines 2:9 [0x0000000000:0x000000003a]
          [0x000000002a][003]                  {Linkage}  0x2 '_Z3fooPKijb'
          [0x0000000071][003]                  {Block}
          [0x0000000071][004]                    {Range} Lines 5:8 [0x000000001c:0x000000002f]
          [0x000000007e][004]      5             {Variable} 'CONSTANT' -> [0x00000000c3]'const INTEGER'
          [0x000000007e][005]                      {Coverage} 100.00%
          [0x000000007f][005]                      {Location}
          [0x000000007f][006]                        {Entry} Stack Offset: -28 (0xffffffffffffffe4) [DW_OP_fbreg]

       The  {Range}  attribute  describe  the line ranges for a logical scope.
       For this case, the function foo is within the lines 2 and 9.

       The {Coverage} and {Location} attributes describe  the  debug  location
       and  coverage  for  logical  symbols.  For optimized code, the coverage
       value decreases and it affects the program debuggability.

EXIT STATUS
       llvm-debuginfo-analyzer returns 0 if the input files  were  parsed  and
       printed successfully. Otherwise, it returns 1.

SEE ALSO
       llvm-dwarfdump

AUTHOR
       Maintained by the LLVM Team (https://llvm.org/).

COPYRIGHT
       2003-2023, LLVM Project

15                                2023-10-16        LLVM-DEBUGINFO-ANALYZER(1)

Generated by dwww version 1.15 on Sun Jun 23 09:39:40 CEST 2024.