dwww Home | Show directory contents | Find package

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

.. program:: llvm-debuginfo-analyzer

.. contents::
   :local:

SYNOPSIS
--------
:program:`llvm-debuginfo-analyzer` [*options*] [*filename ...*]

DESCRIPTION
-----------
:program:`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 original 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. :program:`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
**attributes**, such as *types*, *classes*, *functions*, *variables*,
*parameters*, etc. The :option:`--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*.

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

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

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

  * :ref:`general_` - Standard LLVM options to display help, version, etc.
  * :ref:`attributes_` - Describe how to include different details when
    printing an element.
  * :ref:`print_` - Specify which elements will be included when printing
    the view.
  * :ref:`output_` - Describe the supported formats when printing the view.
  * :ref:`report_` - Describe the format layouts for view printing.
  * :ref:`select_` - Allows to use specific criteria or conditions to
    select which elements to print.
  * :ref:`compare_` - Compare logical views and print missing and/or
    added elements.
  * :ref:`warning_` - Print the warnings detected during the creation
    of the view.
  * :ref:`internal_` - Internal analysis of the logical view.

.. _general_:

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

.. option:: -h, --help

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

.. option:: --help-list

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

.. option:: --help-hidden

 Display all available options.

.. option:: --print-all-options

 Print all option values after command line parsing.

.. option:: --print-options

 Print non-default options after command line parsing

.. option:: --version

 Display the version of the tool.

.. option:: @<FILE>

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

If no input file is specified, :program:`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, :program:`llvm-debuginfo-analyzer`
reads the input from its standard input stream.

.. _attributes_:

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

.. option:: --attribute=<value[,value,...]>

 With **value** being one of the options in the following lists.

 .. code-block:: text

   =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.

 .. code-block:: text

   =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 defined; functions
 with public visibility across modules. These options allow to map the
 elements to their user code location, for cross references purposes.

 .. code-block:: text

   =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 instantiation; parent
 name hierarchy; array dimensions information; compiler generated
 elements and the underlying types associated with the types aliases.

 .. code-block:: text

   =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 coverage 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.

 .. code-block:: text

   =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 instances; 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.

 .. code-block:: text

   =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.

 .. code-block:: text

   =system: Display PDB's MS system elements.

 The above attributes are grouped into *standard* and *extended*
 categories that can be enabled.

 The *standard* group, contains those attributes that add sufficient
 information to describe a logical element and that can cover the
 normal situations while dealing with debug information.

 .. code-block:: text

   =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 intended when a
 lower level of detail is required.

 .. code-block:: text

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

.. _print_:

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

.. option:: --print=<value[,value,...]>

 With **value** being one of the options in the following lists.

 .. code-block:: text

   =all: Include all the below attributes.

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

 .. code-block:: text

   =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 (:option:`--select`);
 warnings produced during the view creation.

 .. code-block:: text

   =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_:

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

.. option:: --output-file=<path>

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

:program:`llvm-debuginfo-analyzer` has the concept of **split view**.
When redirecting the output from a complex binary format, it is
**divided** into individual files, each one containing the logical view
output for a single compilation unit.

.. option:: --output-folder=<name>

 The folder to write a file per compilation unit when **--output=split**
 is specified.

.. option:: --output-level=<level>

 Only print elements up to the given **lexical level** value. The input
 file is at lexical level zero and a compilation unit is at lexical level
 one.

.. option:: --output=<value[,value,...]>

 With **value** being one of the options in the following lists.

 .. code-block:: text

   =all: Include all the below outputs.

 .. code-block:: text

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

.. option:: --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 (:option:`--select-lines`,
 :option:`--select-scopes`, :option:`--select-symbols`,
 :option:`--select-types`), as those options describe the different
 logical element kinds.

 .. code-block:: text

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

.. _report_:

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.

.. option:: --report=<value[,value,...]>

 With **value** being one of the options in the following list.

 .. code-block:: text

   =all: Include all the below reports.

 .. code-block:: text

   =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 being 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 (:option:`--select`) or (:option:`--compare`) and its children.

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

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

**Notes**:

1. When a selection criteria (:option:`--select`) is specified with no
   report option, the **list** layout is selected.
2. The comparison mode always uses the **view** layout.

.. _select_:

SELECTION
~~~~~~~~~
When printing an element, different data can be included and it varies
(:option:`--attribute`) from data directly associated with the binary
file (offset) to high level details such as coverage, lexical scope
level, location. As the printed output can reach a considerable size,
several selection options, enable printing of specific elements.

The pattern matching can ignore the case (:option:`--select-nocase`)
and be extended to use regular expressions (:option:`--select-regex`).

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

.. option:: --select=<pattern>

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

.. option:: --select-offsets=<value[,value,...]>

 Print all elements whose offset matches the given values. See
 :option:`--attribute` option.

.. option:: --select-elements=<condition[,condition,...]>

 Print all elements that satisfy the given <condition>. With **condition**
 being one of the options in the following list.

 .. code-block:: text

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

.. option:: --select-nocase

 Pattern matching is case-insensitive when using :option:`--select`.

.. option:: --select-regex

 Treat any <pattern> strings as regular expressions when selecting with
 :option:`--select` option. If :option:`--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 (:option:`--select-lines`), scopes (:option:`--select-scopes`),
symbols (:option:`--select-symbols`) and types (:option:`--select-types`).
These options require knowledge of the debug information format (DWARF,
CodeView, COFF), as the given **kind** describes 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 registers.

.. option:: --select-lines=<kind[,kind,...]>

 With **kind** being one of the options in the following list.

 .. code-block:: text

   =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>.

.. option:: --select-scopes=<kind[,kind,...]>

 With **kind** being one of the options in the following list.

 .. code-block:: text

    =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>.

.. option:: --select-symbols=<kind[,kind,...]>

 With **kind** being one of the options in the following list.

 .. code-block:: text

    =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>.

.. option:: --select-types=<kind[,kind,...]>

 With **kind** being one of the options in the following list.

 .. code-block:: text

    =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_:

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
impossible when dealing with different debug formats.

:program:`llvm-debuginfo-analyzer` supports a logical element comparison,
allowing to find semantic differences between logical views, produced by
different 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.

.. option:: --compare=<value[,value,...]>

 With **value** being one of the options in the following list.

 .. code-block:: text

    =all: Include all the below elements.

 .. code-block:: text

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

:program:`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 descriptive report, the comparison is done twice. The
reference and target views are swapped, in order to produce those
**missing** elements from the target view and those **added** elements
to the reference view.

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

.. _warning_:

WARNING
~~~~~~~
When reading the input object files, :program:`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 indication 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 :option:`--print`.

.. option:: --warning=<value[,value,...]>

 With **value** being one of the options in the following list.

 .. code-block:: text

    =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.

 .. code-block:: text

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

.. _internal_:

INTERNAL
~~~~~~~~
 For a better understanding of the logical view, access to more detailed
 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.

 :program:`llvm-debuginfo-analyzer` supports these advanced options in
 both *release* and *debug* builds, with the exception of the unique ID
 that is generated only in *debug* builds.

.. option:: --internal=<value[,value,...]>

 With **value** being one of the options in the following list.

 .. code-block:: text

    =all: Include all the below options.

 The following options allow to check the integrity of the logical view;
 collect the debug tags that are processed or not implemented; 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 :program:`llvm-debuginfo-analyzer`.

 .. code-block:: text

    =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
:program:`llvm-debuginfo-analyzer` to print a logical view and to
diagnose possible debug information issues.

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

.. code-block:: c++

  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 :program:`llvm-debuginfo-analyzer` prints the *logical view*
or portions 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 lexical
level and debug info format.

.. code-block:: none

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

or

.. code-block:: none

  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
information. The first column represents the scope level, followed by
the associated line number (if any), and finally the description of
the element.

.. code-block:: none

  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:

.. code-block:: none

  [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.

.. code-block:: none

  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 :program:`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
information produced by different toolchain versions or even completely
different 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 pattern
with the printing mode to obtain the following logical view output.

.. code-block:: none

  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
generated 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 compared
logical element must have the same parents and children.

Using the :program:`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,
giving more context by swapping the reference and target object files.

.. code-block:: none

  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.

.. code-block:: none

  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:

.. code-block:: none

  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
:program:`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.

.. code-block:: c++

   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 :program:`llvm-debuginfo-analyzer`
generates for 3 different compilers (MSVC, Clang and GCC), emitting
different debug information formats (CodeView, DWARF) on Windows and
Linux.

.. code-block:: none

  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)
^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: none

  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)
^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: none

  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)
^^^^^^^^^^^^^^^^^^^^^

.. code-block:: none

  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)
^^^^^^^^^^^^^^^^^^^

.. code-block:: none

  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 instructions,
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
:program:`llvm-debuginfo-analyzer`. We compiled the example for an X86
Codeview and ELF targets with recent versions of Clang, GCC and MSVC
(-O0 -g).

.. code-block:: c++

   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) <https://bugs.llvm.org/show_bug.cgi?id=44884>`_ /
`PR44229 (GitHub LLVM) <https://github.com/llvm/llvm-project/issues/44229>`_

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

.. code-block:: c++

  4    typedef int INT;
  7      typedef float FLOAT;

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

.. code-block:: none

  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)
^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: none

  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)
^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: none

  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)
^^^^^^^^^^^^^^^^^^^^^

.. code-block:: none

  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)
^^^^^^^^^^^^^^^^^^^

.. code-block:: none

  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 :program:`llvm-debuginfo-analyzer` selection facilities, we
can produce a simple tabular output showing just the logical types that
are **Typedef**.

.. code-block:: none

  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
:program:`llvm-debuginfo-analyzer`. We compiled the example for an X86
Codeview and ELF targets with recent versions of Clang, GCC and MSVC
(-O0 -g).

.. code-block:: c++

   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) <https://bugs.llvm.org/show_bug.cgi?id=46466>`_ /
`PR45811 (GitHub LLVM) <https://github.com/llvm/llvm-project/issues/45811>`_

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

.. code-block:: none

  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)
^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: none

  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)
^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: none

  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)
^^^^^^^^^^^^^^^^^^^^^

.. code-block:: none

  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)
^^^^^^^^^^^^^^^^^^^

.. code-block:: none

  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
information 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 :program:`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.

.. code-block:: none

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

.. code-block:: none

  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 :program:`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.

.. code-block:: none

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

.. code-block:: none

  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
:program:`llvm-debuginfo-analyzer`. We compiled the example for an X86
Codeview and ELF targets with recent versions of Clang, GCC and MSVC
(-O0 -g).

.. code-block:: c++

  // 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*.

.. code-block:: c++

   #include "definitions.h"

.. code-block:: c++

   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) <https://bugs.llvm.org/show_bug.cgi?id=43860>`_ /
`PR43205 (GitHub) <https://github.com/llvm/llvm-project/issues/43205>`_

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

.. code-block:: none

  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)
^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: none

  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)
^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: none

  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)
^^^^^^^^^^^^^^^^^^^^^

.. code-block:: none

  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)
^^^^^^^^^^^^^^^^^^^

.. code-block:: none

  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
information 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 :program:`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.

.. code-block:: none

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

.. code-block:: none

  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, :program:`llvm-debuginfo-analyzer` can display low
level information that includes offsets within the debug information
section, debug location operands, linkage names, etc.

.. code-block:: none

  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
information by each scope, which can be used to determine unexpected
size changes in the DWARF sections between different versions of the
same toolchain.

.. code-block:: none

  [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
-----------
:program:`llvm-debuginfo-analyzer` returns 0 if the input files were
parsed and printed successfully. Otherwise, it returns 1.

SEE ALSO
--------
:manpage:`llvm-dwarfdump`

Generated by dwww version 1.15 on Wed May 22 22:36:34 CEST 2024.