[llvm] c28a977 - Recommit [llvm-debuginfo-analyzer] (02/09) - Driver and documentation
Carlos Alberto Enciso via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 18 00:42:55 PDT 2022
Author: Carlos Alberto Enciso
Date: 2022-10-18T08:39:26+01:00
New Revision: c28a977b87defd2f37fd0808d7ba6173133744ce
URL: https://github.com/llvm/llvm-project/commit/c28a977b87defd2f37fd0808d7ba6173133744ce
DIFF: https://github.com/llvm/llvm-project/commit/c28a977b87defd2f37fd0808d7ba6173133744ce.diff
LOG: Recommit [llvm-debuginfo-analyzer] (02/09) - Driver and documentation
Originally committed in fe7a3cedf77125a6309150d85cecbc20b1a31775
Reverted in 26dd64ba9cfabe5474bb207f3b7099965f81fed7
Buildbot failures:
https://lab.llvm.org/buildbot#builders/139/builds/29663
- unittest trigger an invalid assertion.
https://lab.llvm.org/buildbot#builders/196/builds/19665
- 'has virtual functions but non-virtual destructor' warning as error.
Recommitted with fix:
- Removed the assertion.
- Added virtual destructor.
Added:
llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst
llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h
llvm/include/llvm/DebugInfo/LogicalView/Core/LVLine.h
llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
llvm/include/llvm/DebugInfo/LogicalView/Core/LVOptions.h
llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h
llvm/include/llvm/DebugInfo/LogicalView/Core/LVSort.h
llvm/include/llvm/DebugInfo/LogicalView/Core/LVStringPool.h
llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h
llvm/include/llvm/DebugInfo/LogicalView/Core/LVSymbol.h
llvm/include/llvm/DebugInfo/LogicalView/Core/LVType.h
llvm/lib/DebugInfo/LogicalView/CMakeLists.txt
llvm/lib/DebugInfo/LogicalView/Core/LVOptions.cpp
llvm/lib/DebugInfo/LogicalView/LLVMBuild.txt
llvm/test/tools/llvm-debuginfo-analyzer/cmdline.test
llvm/tools/llvm-debuginfo-analyzer/CMakeLists.txt
llvm/tools/llvm-debuginfo-analyzer/LLVMBuild.txt
llvm/tools/llvm-debuginfo-analyzer/Options.cpp
llvm/tools/llvm-debuginfo-analyzer/Options.h
llvm/tools/llvm-debuginfo-analyzer/llvm-debuginfo-analyzer.cpp
llvm/unittests/DebugInfo/LogicalView/CMakeLists.txt
llvm/unittests/DebugInfo/LogicalView/CommandLineOptionsTest.cpp
llvm/unittests/DebugInfo/LogicalView/StringPoolTest.cpp
Modified:
llvm/docs/CommandGuide/index.rst
llvm/lib/DebugInfo/CMakeLists.txt
llvm/test/CMakeLists.txt
llvm/test/lit.cfg.py
llvm/unittests/DebugInfo/CMakeLists.txt
Removed:
################################################################################
diff --git a/llvm/docs/CommandGuide/index.rst b/llvm/docs/CommandGuide/index.rst
index fc87f15c9d588..3b8375cb7e868 100644
--- a/llvm/docs/CommandGuide/index.rst
+++ b/llvm/docs/CommandGuide/index.rst
@@ -21,6 +21,7 @@ Basic Commands
llvm-config
llvm-cov
llvm-cxxmap
+ llvm-debuginfo-analyzer
llvm-
diff
llvm-dis
llvm-dwarfdump
diff --git a/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst b/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst
new file mode 100644
index 0000000000000..a78066a5eea37
--- /dev/null
+++ b/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst
@@ -0,0 +1,1962 @@
+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
+
diff erent 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
diff erences 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
diff erent purpose:
+
+ * :ref:`general_` - Standard LLVM options to display help, version, etc.
+ * :ref:`attributes_` - Describe how to include
diff erent 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
diff erent
+ 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
diff erences.
+
+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,
diff erent 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
diff erent 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
+
diff icult to use a regular
diff tool to find those elements; even
+impossible when dealing with
diff erent debug formats.
+
+:program:`llvm-debuginfo-analyzer` supports a logical element comparison,
+allowing to find semantic
diff erences between logical views, produced by
+
diff erent toolchain versions or even debug information formats.
+
+When comparing logical views created from
diff erent 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
diff erent 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
diff erences in the debug
+information produced by
diff erent toolchain versions or even completely
+
diff erent toolchains altogether (For example a compiler producing DWARF
+can be directly compared against a completely
diff erent 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
diff erent 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
diff erent 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
diff erent compilers (MSVC, Clang and GCC), emitting
+
diff erent 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
diff erent toolchains.
+
+TEST CASE 3 - INCORRECT LEXICAL SCOPE FOR TYPEDEF
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The below example is used to show
diff erent 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
diff erent 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
diff erent compilers (MSVC, Clang and GCC), emitting
+
diff erent debug information formats (CodeView, DWARF) on
diff erent
+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
diff erent 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
diff erent compilers (MSVC, Clang and GCC), emitting
+
diff erent debug information formats (CodeView, DWARF) on
diff erent
+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
diff erent 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
diff erent compilers (MSVC, Clang and GCC), emitting
+
diff erent debug information formats (CodeView, DWARF) on
diff erent
+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
diff erent 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`
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h
new file mode 100644
index 0000000000000..a622c499b48aa
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h
@@ -0,0 +1,55 @@
+//===-- LVElement.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LVElement class, which is used to describe a debug
+// information element.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVELEMENT_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVELEMENT_H
+
+#include "llvm/DebugInfo/LogicalView/Core/LVObject.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVStringPool.h"
+#include <set>
+
+namespace llvm {
+namespace logicalview {
+
+enum class LVElementKind { Discarded, Global, Optimized, LastEntry };
+using LVElementKindSet = std::set<LVElementKind>;
+
+class LVElement : public LVObject {
+ // Indexes in the String Pool.
+ size_t NameIndex = 0;
+ size_t FilenameIndex = 0;
+
+public:
+ LVElement() = default;
+ virtual ~LVElement() = default;
+
+ bool isNamed() const override { return NameIndex != 0; }
+
+ StringRef getName() const override {
+ return getStringPool().getString(NameIndex);
+ }
+
+ // Get pathname associated with the Element.
+ StringRef getPathname() const {
+ return getStringPool().getString(getFilenameIndex());
+ }
+
+ // Element type name.
+ StringRef getTypeName() const;
+ size_t getFilenameIndex() const { return FilenameIndex; }
+};
+
+} // end namespace logicalview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVELEMENT_H
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVLine.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVLine.h
new file mode 100644
index 0000000000000..552e9bb792cbc
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVLine.h
@@ -0,0 +1,40 @@
+//===-- LVLine.h ------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LVLine class, which is used to describe a debug
+// information line.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVLINE_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVLINE_H
+
+#include "llvm/DebugInfo/LogicalView/Core/LVElement.h"
+
+namespace llvm {
+namespace logicalview {
+
+enum class LVLineKind {
+ IsBasicBlock,
+ IsDiscriminator,
+ IsEndSequence,
+ IsEpilogueBegin,
+ IsLineDebug,
+ IsLineAssembler,
+ IsNewStatement, // Shared with CodeView 'IsStatement' flag.
+ IsPrologueEnd,
+ IsAlwaysStepInto, // CodeView
+ IsNeverStepInto, // CodeView
+ LastEntry
+};
+using LVLineKindSet = std::set<LVLineKind>;
+
+} // end namespace logicalview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVLINE_H
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
new file mode 100644
index 0000000000000..462d929bad339
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
@@ -0,0 +1,60 @@
+//===-- LVObject.h ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LVObject class, which is used to describe a debug
+// information object.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVOBJECT_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVOBJECT_H
+
+#include "llvm/DebugInfo/LogicalView/Core/LVSupport.h"
+#include <string>
+
+namespace llvm {
+namespace logicalview {
+
+using LVHalf = uint16_t;
+using LVOffset = uint64_t;
+
+class LVObject {
+ LVOffset Offset = 0;
+
+protected:
+ // Get a string representation for the given number and discriminator.
+ std::string lineAsString(uint32_t LineNumber, LVHalf Discriminator,
+ bool ShowZero) const;
+
+ // Get a string representation for the given number.
+ std::string referenceAsString(uint32_t LineNumber, bool Spaces) const;
+
+ // Print the Filename or Pathname.
+ // Empty implementation for those objects that do not have any user
+ // source file references, such as debug locations.
+ virtual void printFileIndex(raw_ostream &OS, bool Full = true) const {}
+
+public:
+ LVObject() = default;
+ virtual ~LVObject() = default;
+
+ // True if the scope has been named.
+ virtual bool isNamed() const { return false; }
+
+ // DIE offset.
+ LVOffset getOffset() const { return Offset; }
+
+ virtual StringRef getName() const { return StringRef(); }
+
+ std::string lineNumberAsStringStripped(bool ShowZero = false) const;
+};
+
+} // end namespace logicalview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVOBJECT_H
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVOptions.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVOptions.h
new file mode 100644
index 0000000000000..88b027166d054
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVOptions.h
@@ -0,0 +1,451 @@
+//===-- LVOptions.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LVOptions class, which is used to record the command
+// line options.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVOPTIONS_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVOPTIONS_H
+
+#include "llvm/ADT/StringSet.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVType.h"
+#include <set>
+#include <string>
+
+namespace llvm {
+namespace logicalview {
+
+// Generate get and set 'bool' functions.
+#define BOOL_FUNCTION(FAMILY, FIELD) \
+ bool get##FAMILY##FIELD() const { return FAMILY.FIELD; } \
+ void set##FAMILY##FIELD() { FAMILY.FIELD = true; } \
+ void reset##FAMILY##FIELD() { FAMILY.FIELD = false; }
+
+// Generate get and set 'unsigned' functions.
+#define UNSIGNED_FUNCTION(FAMILY, FIELD) \
+ unsigned get##FAMILY##FIELD() const { return FAMILY.FIELD; } \
+ void set##FAMILY##FIELD(unsigned Value) { FAMILY.FIELD = Value; } \
+ void reset##FAMILY##FIELD() { FAMILY.FIELD = -1U; }
+
+// Generate get and set 'std::string' functions.
+#define STD_STRING_FUNCTION(FAMILY, FIELD) \
+ std::string get##FAMILY##FIELD() const { return FAMILY.FIELD; } \
+ void set##FAMILY##FIELD(std::string FIELD) { FAMILY.FIELD = FIELD; } \
+ void reset##FAMILY##FIELD() { FAMILY.FIELD = ""; }
+
+// Generate get and set 'std::set' functions.
+#define STDSET_FUNCTION_4(FAMILY, FIELD, TYPE, SET) \
+ bool get##FAMILY##FIELD() const { \
+ return FAMILY.SET.find(TYPE::FIELD) != FAMILY.SET.end(); \
+ } \
+ void set##FAMILY##FIELD() { FAMILY.SET.insert(TYPE::FIELD); } \
+ void reset##FAMILY##FIELD() { \
+ std::set<TYPE>::iterator Iter = FAMILY.SET.find(TYPE::FIELD); \
+ if (Iter != FAMILY.SET.end()) \
+ FAMILY.SET.erase(Iter); \
+ }
+
+#define STDSET_FUNCTION_5(FAMILY, FIELD, ENTRY, TYPE, SET) \
+ bool get##FAMILY##FIELD##ENTRY() const { \
+ return FAMILY.SET.find(TYPE::ENTRY) != FAMILY.SET.end(); \
+ } \
+ void set##FAMILY##FIELD##ENTRY() { FAMILY.SET.insert(TYPE::ENTRY); }
+
+// Generate get and set functions for '--attribute'
+#define ATTRIBUTE_OPTION(FIELD) \
+ STDSET_FUNCTION_4(Attribute, FIELD, LVAttributeKind, Kinds)
+
+// Generate get and set functions for '--output'
+#define OUTPUT_OPTION(FIELD) \
+ STDSET_FUNCTION_4(Output, FIELD, LVOutputKind, Kinds)
+
+// Generate get and set functions for '--print'
+#define PRINT_OPTION(FIELD) STDSET_FUNCTION_4(Print, FIELD, LVPrintKind, Kinds)
+
+// Generate get and set functions for '--warning'
+#define WARNING_OPTION(FIELD) \
+ STDSET_FUNCTION_4(Warning, FIELD, LVWarningKind, Kinds)
+
+// Generate get and set functions for '--compare'
+#define COMPARE_OPTION(FIELD) \
+ STDSET_FUNCTION_4(Compare, FIELD, LVCompareKind, Elements)
+
+// Generate get and set functions for '--report'
+#define REPORT_OPTION(FIELD) \
+ STDSET_FUNCTION_4(Report, FIELD, LVReportKind, Kinds)
+
+// Generate get and set functions for '--internal'
+#define INTERNAL_OPTION(FIELD) \
+ STDSET_FUNCTION_4(Internal, FIELD, LVInternalKind, Kinds)
+
+using LVOffsetSet = std::set<uint64_t>;
+
+enum class LVAttributeKind {
+ All, // --attribute=all
+ Argument, // --attribute=argument
+ Base, // --attribute=base
+ Coverage, // --attribute=coverage
+ Directories, // --attribute=directories
+ Discarded, // --attribute=discarded
+ Discriminator, // --attribute=discriminator
+ Encoded, // --attribute=encoded
+ Extended, // --attribute=extended
+ Filename, // --attribute=filename
+ Files, // --attribute=files
+ Format, // --attribute=format
+ Gaps, // --attribute=gaps
+ Generated, // --attribute=generated
+ Global, // --attribute=global
+ Inserted, // --attribute=inserted
+ Level, // --attribute=level
+ Linkage, // --attribute=linkage
+ Local, // --attribute=local
+ Location, // --attribute=location
+ Offset, // --attribute=offset
+ Pathname, // --attribute=pathname
+ Producer, // --attribute=producer
+ Publics, // --attribute=publics
+ Qualified, // --attribute=qualified
+ Qualifier, // --attribute=qualifier
+ Range, // --attribute=range
+ Reference, // --attribute=reference
+ Register, // --attribute=register
+ Standard, // --attribute=standard
+ Subrange, // --attribute=subrange
+ System, // --attribute=system
+ Typename, // --attribute=typename
+ Underlying, // --attribute=underlying
+ Zero // --attribute=zero
+};
+using LVAttributeKindSet = std::set<LVAttributeKind>;
+
+enum class LVCompareKind {
+ All, // --compare=all
+ Lines, // --compare=lines
+ Scopes, // --compare=scopes
+ Symbols, // --compare=symbols
+ Types // --compare=types
+};
+using LVCompareKindSet = std::set<LVCompareKind>;
+
+enum class LVOutputKind {
+ All, // --output=all
+ Split, // --output=split
+ Json, // --output=json
+ Text // --output=text
+};
+using LVOutputKindSet = std::set<LVOutputKind>;
+
+enum class LVPrintKind {
+ All, // --print=all
+ Elements, // --print=elements
+ Instructions, // --print=instructions
+ Lines, // --print=lines
+ Scopes, // --print=scopes
+ Sizes, // --print=sizes
+ Symbols, // --print=symbols
+ Summary, // --print=summary
+ Types, // --print=types
+ Warnings // --print=warnings
+};
+using LVPrintKindSet = std::set<LVPrintKind>;
+
+enum class LVReportKind {
+ All, // --report=all
+ Children, // --report=children
+ List, // --report=list
+ Parents, // --report=parents
+ View // --report=view
+};
+using LVReportKindSet = std::set<LVReportKind>;
+
+enum class LVWarningKind {
+ All, // --warning=all
+ Coverages, // --warning=coverages
+ Lines, // --warning=lines
+ Locations, // --warning=locations
+ Ranges // --warning=ranges
+};
+using LVWarningKindSet = std::set<LVWarningKind>;
+
+enum class LVInternalKind {
+ All, // --internal=all
+ Cmdline, // --internal=cmdline
+ ID, // --internal=id
+ Integrity, // --internal=integrity
+ None, // --internal=none
+ Tag // --internal=tag
+};
+using LVInternalKindSet = std::set<LVInternalKind>;
+
+// The 'Kinds' members are a one-to-one mapping to the associated command
+// options that supports comma separated values. There are other 'bool'
+// members that in very few cases point to a command option (see associated
+// comment). Other cases for 'bool' refers to internal values derivated from
+// the command options.
+class LVOptions {
+ class LVAttribute {
+ public:
+ LVAttributeKindSet Kinds; // --attribute=<Kind>
+ bool Added = false; // Added elements found during comparison.
+ bool AnyLocation = false; // Any kind of location information.
+ bool AnySource = false; // Any kind of source information.
+ bool Missing = false; // Missing elements found during comparison.
+ };
+
+ class LVCompare {
+ public:
+ LVCompareKindSet Elements; // --compare=<kind>
+ bool Context = false; // --compare-context
+ bool Execute = false; // Compare requested.
+ bool Print = false; // Enable any printing.
+ };
+
+ class LVPrint {
+ public:
+ LVPrintKindSet Kinds; // --print=<Kind>
+ bool AnyElement = false; // Request to print any element.
+ bool AnyLine = false; // Print 'lines' or 'instructions'.
+ bool Execute = false; // Print requested.
+ bool Formatting = true; // Disable formatting during printing.
+ bool Offset = false; // Print offsets while formatting is disabled.
+ bool SizesSummary = false; // Print 'sizes' or 'summary'.
+ };
+
+ class LVReport {
+ public:
+ LVReportKindSet Kinds; // --report=<kind>
+ bool AnyView = false; // View, Parents or Children.
+ bool Execute = false; // Report requested.
+ };
+
+ class LVSelect {
+ public:
+ bool IgnoreCase = false; // --select-ignore-case
+ bool UseRegex = false; // --select-use-regex
+ bool Execute = false; // Select requested.
+ bool GenericKind = false; // We have collected generic kinds.
+ bool GenericPattern = false; // We have collected generic patterns.
+ bool OffsetPattern = false; // We have collected offset patterns.
+ StringSet<> Generic; // --select=<Pattern>
+ LVOffsetSet Offsets; // --select-offset=<Offset>
+ LVElementKindSet Elements; // --select-elements=<Kind>
+ LVLineKindSet Lines; // --select-lines=<Kind>
+ LVScopeKindSet Scopes; // --select-scopes=<Kind>
+ LVSymbolKindSet Symbols; // --select-symbols=<Kind>
+ LVTypeKindSelection Types; // --select-types=<Kind>
+ };
+
+ class LVOutput {
+ public:
+ LVOutputKindSet Kinds; // --output=<kind>
+ LVSortMode SortMode = LVSortMode::None; // --output-sort=<SortMode>
+ std::string Folder; // --output-folder=<Folder>
+ unsigned Level = -1U; // --output-level=<level>
+ };
+
+ class LVWarning {
+ public:
+ LVWarningKindSet Kinds; // --warning=<Kind>
+ };
+
+ class LVInternal {
+ public:
+ LVInternalKindSet Kinds; // --internal=<Kind>
+ };
+
+ class LVGeneral {
+ public:
+ bool CollectRanges = false; // Collect ranges information.
+ };
+
+ // Filters the output of the filename associated with the element being
+ // printed in order to see clearly which logical elements belongs to
+ // a particular filename. It is value is reset after the element
+ // that represents the Compile Unit is printed.
+ size_t LastFilenameIndex = 0;
+
+ // Controls the amount of additional spaces to insert when printing
+ // object attributes, in order to get a consistent printing layout.
+ size_t IndentationSize = 0;
+
+ // Calculate the indentation size, so we can use that value when printing
+ // additional attributes to objects, such as location.
+ void calculateIndentationSize();
+
+public:
+ void resetFilenameIndex() { LastFilenameIndex = 0; }
+ bool changeFilenameIndex(size_t Index) {
+ bool IndexChanged = (Index != LastFilenameIndex);
+ if (IndexChanged)
+ LastFilenameIndex = Index;
+ return IndexChanged;
+ }
+
+ // Access to command line options, pattern and printing information.
+ static LVOptions *getOptions();
+ static void setOptions(LVOptions *Options);
+
+ LVOptions() = default;
+ LVOptions(const LVOptions &) = default;
+ LVOptions &operator=(const LVOptions &) = default;
+ ~LVOptions() = default;
+
+ // Some command line options support shortcuts. For example:
+ // The command line option '--print=elements' is a shortcut for:
+ // '--print=instructions,lines,scopes,symbols,types'.
+ // In the case of logical view comparison, some options related to
+ // attributes must be set or reset for a proper comparison.
+ // Resolve any dependencies between command line options.
+ void resolveDependencies();
+ size_t indentationSize() const { return IndentationSize; }
+
+ LVAttribute Attribute;
+ LVCompare Compare;
+ LVOutput Output;
+ LVPrint Print;
+ LVReport Report;
+ LVSelect Select;
+ LVWarning Warning;
+ LVInternal Internal;
+ LVGeneral General;
+
+ // --attribute.
+ ATTRIBUTE_OPTION(All);
+ ATTRIBUTE_OPTION(Argument);
+ ATTRIBUTE_OPTION(Base);
+ ATTRIBUTE_OPTION(Coverage);
+ ATTRIBUTE_OPTION(Directories);
+ ATTRIBUTE_OPTION(Discarded);
+ ATTRIBUTE_OPTION(Discriminator);
+ ATTRIBUTE_OPTION(Encoded);
+ ATTRIBUTE_OPTION(Extended);
+ ATTRIBUTE_OPTION(Filename);
+ ATTRIBUTE_OPTION(Files);
+ ATTRIBUTE_OPTION(Format);
+ ATTRIBUTE_OPTION(Gaps);
+ ATTRIBUTE_OPTION(Generated);
+ ATTRIBUTE_OPTION(Global);
+ ATTRIBUTE_OPTION(Inserted);
+ ATTRIBUTE_OPTION(Level);
+ ATTRIBUTE_OPTION(Linkage);
+ ATTRIBUTE_OPTION(Location);
+ ATTRIBUTE_OPTION(Local);
+ ATTRIBUTE_OPTION(Offset);
+ ATTRIBUTE_OPTION(Pathname);
+ ATTRIBUTE_OPTION(Producer);
+ ATTRIBUTE_OPTION(Publics);
+ ATTRIBUTE_OPTION(Qualified);
+ ATTRIBUTE_OPTION(Qualifier);
+ ATTRIBUTE_OPTION(Range);
+ ATTRIBUTE_OPTION(Reference);
+ ATTRIBUTE_OPTION(Register);
+ ATTRIBUTE_OPTION(Standard);
+ ATTRIBUTE_OPTION(Subrange);
+ ATTRIBUTE_OPTION(System);
+ ATTRIBUTE_OPTION(Typename);
+ ATTRIBUTE_OPTION(Underlying);
+ ATTRIBUTE_OPTION(Zero);
+ BOOL_FUNCTION(Attribute, Added);
+ BOOL_FUNCTION(Attribute, AnyLocation);
+ BOOL_FUNCTION(Attribute, AnySource);
+ BOOL_FUNCTION(Attribute, Missing);
+
+ // --compare.
+ COMPARE_OPTION(All);
+ COMPARE_OPTION(Lines);
+ COMPARE_OPTION(Scopes);
+ COMPARE_OPTION(Symbols);
+ COMPARE_OPTION(Types);
+ BOOL_FUNCTION(Compare, Context);
+ BOOL_FUNCTION(Compare, Execute);
+ BOOL_FUNCTION(Compare, Print);
+
+ // --output.
+ OUTPUT_OPTION(All);
+ OUTPUT_OPTION(Split);
+ OUTPUT_OPTION(Text);
+ OUTPUT_OPTION(Json);
+ STD_STRING_FUNCTION(Output, Folder);
+ UNSIGNED_FUNCTION(Output, Level);
+ LVSortMode getSortMode() const { return Output.SortMode; }
+ void setSortMode(LVSortMode SortMode) { Output.SortMode = SortMode; }
+
+ // --print.
+ PRINT_OPTION(All);
+ PRINT_OPTION(Elements);
+ PRINT_OPTION(Instructions);
+ PRINT_OPTION(Lines);
+ PRINT_OPTION(Scopes);
+ PRINT_OPTION(Sizes);
+ PRINT_OPTION(Symbols);
+ PRINT_OPTION(Summary);
+ PRINT_OPTION(Types);
+ PRINT_OPTION(Warnings);
+ BOOL_FUNCTION(Print, AnyElement);
+ BOOL_FUNCTION(Print, AnyLine);
+ BOOL_FUNCTION(Print, Execute);
+ BOOL_FUNCTION(Print, Formatting);
+ BOOL_FUNCTION(Print, Offset);
+ BOOL_FUNCTION(Print, SizesSummary);
+
+ // --report.
+ REPORT_OPTION(All);
+ REPORT_OPTION(Children);
+ REPORT_OPTION(List);
+ REPORT_OPTION(Parents);
+ REPORT_OPTION(View);
+ BOOL_FUNCTION(Report, AnyView);
+ BOOL_FUNCTION(Report, Execute);
+
+ // --select.
+ BOOL_FUNCTION(Select, IgnoreCase);
+ BOOL_FUNCTION(Select, UseRegex);
+ BOOL_FUNCTION(Select, Execute);
+ BOOL_FUNCTION(Select, GenericKind);
+ BOOL_FUNCTION(Select, GenericPattern);
+ BOOL_FUNCTION(Select, OffsetPattern);
+
+ // --warning.
+ WARNING_OPTION(All);
+ WARNING_OPTION(Coverages);
+ WARNING_OPTION(Lines);
+ WARNING_OPTION(Locations);
+ WARNING_OPTION(Ranges);
+
+ // --internal.
+ INTERNAL_OPTION(All);
+ INTERNAL_OPTION(Cmdline);
+ INTERNAL_OPTION(ID);
+ INTERNAL_OPTION(Integrity);
+ INTERNAL_OPTION(None);
+ INTERNAL_OPTION(Tag);
+
+ // General shortcuts to some combinations.
+ BOOL_FUNCTION(General, CollectRanges);
+
+ void print(raw_ostream &OS) const;
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ void dump() const { print(dbgs()); }
+#endif
+};
+
+inline LVOptions &options() { return (*LVOptions::getOptions()); }
+inline void setOptions(LVOptions *Options) { LVOptions::setOptions(Options); }
+
+} // namespace logicalview
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVOPTIONS_H
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h
new file mode 100644
index 0000000000000..0ce2d7e2538e0
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h
@@ -0,0 +1,56 @@
+//===-- LVScope.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LVScope class, which is used to describe a debug
+// information scope.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H
+
+#include "llvm/DebugInfo/LogicalView/Core/LVElement.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVSort.h"
+#include <set>
+
+namespace llvm {
+namespace logicalview {
+
+enum class LVScopeKind {
+ IsAggregate,
+ IsArray,
+ IsBlock,
+ IsCallSite,
+ IsCatchBlock,
+ IsClass,
+ IsCompileUnit,
+ IsEntryPoint,
+ IsEnumeration,
+ IsFunction,
+ IsFunctionType,
+ IsInlinedFunction,
+ IsLabel,
+ IsLexicalBlock,
+ IsMember,
+ IsNamespace,
+ IsRoot,
+ IsStructure,
+ IsSubprogram,
+ IsTemplate,
+ IsTemplateAlias,
+ IsTemplatePack,
+ IsTryBlock,
+ IsUnion,
+ LastEntry
+};
+using LVScopeKindSet = std::set<LVScopeKind>;
+
+} // end namespace logicalview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSort.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSort.h
new file mode 100644
index 0000000000000..d5ed3f965810e
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSort.h
@@ -0,0 +1,31 @@
+//===-- LVSort.h ------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the sort algorithms.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSORT_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSORT_H
+
+namespace llvm {
+namespace logicalview {
+
+// Object Sorting Mode.
+enum class LVSortMode {
+ None = 0, // No given sort.
+ Kind, // Sort by kind.
+ Line, // Sort by line.
+ Name, // Sort by name.
+ Offset // Sort by offset.
+};
+
+} // end namespace logicalview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSORT_H
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVStringPool.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVStringPool.h
new file mode 100644
index 0000000000000..3733c6c51f19d
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVStringPool.h
@@ -0,0 +1,98 @@
+//===-- LVStringPool.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LVStringPool class, which is used to implement a
+// basic string pool table.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSTRINGPOOL_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSTRINGPOOL_H
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <iomanip>
+#include <vector>
+
+namespace llvm {
+namespace logicalview {
+
+class LVStringPool {
+ static constexpr size_t BadIndex = std::numeric_limits<size_t>::max();
+ using TableType = StringMap<size_t, BumpPtrAllocator>;
+ using ValueType = TableType::value_type;
+ BumpPtrAllocator Allocator;
+ TableType StringTable;
+ std::vector<ValueType *> Entries;
+
+public:
+ LVStringPool() { getIndex(""); }
+ LVStringPool(LVStringPool const &other) = delete;
+ LVStringPool(LVStringPool &&other) = delete;
+ ~LVStringPool() = default;
+
+ bool isValidIndex(size_t Index) const { return Index != BadIndex; }
+
+ // Return number of strings in the pool. The empty string is allocated
+ // at the slot zero. We substract 1 to indicate the number of non empty
+ // strings.
+ size_t getSize() const { return Entries.size() - 1; }
+
+ // Return the index for the specified key, otherwise 'BadIndex'.
+ size_t findIndex(StringRef Key) const {
+ TableType::const_iterator Iter = StringTable.find(Key);
+ if (Iter != StringTable.end())
+ return Iter->second;
+ return BadIndex;
+ }
+
+ // Return an index for the specified key.
+ size_t getIndex(StringRef Key) {
+ size_t Index = findIndex(Key);
+ if (isValidIndex(Index))
+ return Index;
+ size_t Value = Entries.size();
+ ValueType *Entry = ValueType::Create(Key, Allocator, std::move(Value));
+ StringTable.insert(Entry);
+ Entries.push_back(Entry);
+ return Value;
+ }
+
+ // Given the index, return its corresponding string.
+ StringRef getString(size_t Index) const {
+ return (Index >= Entries.size()) ? StringRef() : Entries[Index]->getKey();
+ }
+
+ static LVStringPool &getInstance() {
+ static LVStringPool Instance;
+ return Instance;
+ }
+
+ void print(raw_ostream &OS) const {
+ if (!Entries.empty()) {
+ OS << "\nString Pool:\n";
+ for (const ValueType *Entry : Entries)
+ OS << "Index: " << Entry->getValue() << ", "
+ << "Key: '" << Entry->getKey() << "'\n";
+ }
+ }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ void dump() const { print(dbgs()); }
+#endif
+};
+
+inline LVStringPool &getStringPool() { return LVStringPool::getInstance(); }
+
+} // namespace logicalview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSTRINGPOOL_H
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h
new file mode 100644
index 0000000000000..0df64842d9037
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h
@@ -0,0 +1,51 @@
+//===-- LVSupport.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines support functions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSUPPORT_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSUPPORT_H
+
+#include "llvm/ADT/SmallBitVector.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cctype>
+#include <sstream>
+
+namespace llvm {
+namespace logicalview {
+
+const int HEX_WIDTH = 12;
+inline FormattedNumber hexValue(uint64_t N, unsigned Width = HEX_WIDTH,
+ bool Upper = false) {
+ return format_hex(N, Width, Upper);
+}
+
+// Output the hexadecimal representation of 'Value' using '[0x%08x]' format.
+inline std::string hexString(uint64_t Value, size_t Width = HEX_WIDTH) {
+ std::string String;
+ raw_string_ostream Stream(String);
+ Stream << hexValue(Value, Width, false);
+ return Stream.str();
+}
+
+// Get a hexadecimal string representation for the given value.
+inline std::string hexSquareString(uint64_t Value) {
+ return (Twine("[") + Twine(hexString(Value)) + Twine("]")).str();
+}
+
+} // end namespace logicalview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSUPPORT_H
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSymbol.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSymbol.h
new file mode 100644
index 0000000000000..52b46f8a117b8
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSymbol.h
@@ -0,0 +1,37 @@
+//===-- LVSymbol.h ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LVSymbol class, which is used to describe a debug
+// information symbol.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSYMBOL_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSYMBOL_H
+
+#include "llvm/DebugInfo/LogicalView/Core/LVElement.h"
+
+namespace llvm {
+namespace logicalview {
+
+enum class LVSymbolKind {
+ IsCallSiteParameter,
+ IsConstant,
+ IsInheritance,
+ IsMember,
+ IsParameter,
+ IsUnspecified,
+ IsVariable,
+ LastEntry
+};
+using LVSymbolKindSet = std::set<LVSymbolKind>;
+
+} // end namespace logicalview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSYMBOL_H
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVType.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVType.h
new file mode 100644
index 0000000000000..a288a16bd7320
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVType.h
@@ -0,0 +1,51 @@
+//===-- LVType.h ------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LVType class, which is used to describe a debug
+// information type.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVTYPE_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVTYPE_H
+
+#include "llvm/DebugInfo/LogicalView/Core/LVElement.h"
+
+namespace llvm {
+namespace logicalview {
+
+enum class LVTypeKind {
+ IsBase,
+ IsConst,
+ IsEnumerator,
+ IsImport,
+ IsImportDeclaration,
+ IsImportModule,
+ IsPointer,
+ IsPointerMember,
+ IsReference,
+ IsRestrict,
+ IsRvalueReference,
+ IsSubrange,
+ IsTemplateParam,
+ IsTemplateTemplateParam,
+ IsTemplateTypeParam,
+ IsTemplateValueParam,
+ IsTypedef,
+ IsUnaligned,
+ IsUnspecified,
+ IsVolatile,
+ IsModifier, // CodeView - LF_MODIFIER
+ LastEntry
+};
+using LVTypeKindSelection = std::set<LVTypeKind>;
+
+} // end namespace logicalview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVTYPE_H
diff --git a/llvm/lib/DebugInfo/CMakeLists.txt b/llvm/lib/DebugInfo/CMakeLists.txt
index 6355ba08d03c7..d004981fb087a 100644
--- a/llvm/lib/DebugInfo/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/CMakeLists.txt
@@ -1,5 +1,6 @@
add_subdirectory(DWARF)
add_subdirectory(GSYM)
+add_subdirectory(LogicalView)
add_subdirectory(MSF)
add_subdirectory(CodeView)
add_subdirectory(PDB)
diff --git a/llvm/lib/DebugInfo/LogicalView/CMakeLists.txt b/llvm/lib/DebugInfo/LogicalView/CMakeLists.txt
new file mode 100644
index 0000000000000..dbdfa031cbcc9
--- /dev/null
+++ b/llvm/lib/DebugInfo/LogicalView/CMakeLists.txt
@@ -0,0 +1,31 @@
+set(LLVM_LINK_COMPONENTS
+ BinaryFormat
+ DebugInfoDWARF
+ DebugInfoCodeView
+ DebugInfoPDB
+ Demangle
+ MC
+ Object
+ Support
+ )
+
+macro(add_lv_impl_folder group)
+ list(APPEND LV_IMPL_SOURCES ${ARGN})
+ source_group(${group} FILES ${ARGN})
+endmacro()
+
+add_lv_impl_folder(Core
+ Core/LVOptions.cpp
+ )
+
+list(APPEND LIBLV_ADDITIONAL_HEADER_DIRS
+ "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/LogicalView"
+ "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/LogicalView/Core"
+ )
+
+add_llvm_library(LLVMDebugInfoLogicalView
+ ${LV_IMPL_SOURCES}
+
+ ADDITIONAL_HEADER_DIRS
+ ${LIBLV_ADDITIONAL_HEADER_DIRS}
+ )
diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVOptions.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVOptions.cpp
new file mode 100644
index 0000000000000..1afc24403837b
--- /dev/null
+++ b/llvm/lib/DebugInfo/LogicalView/Core/LVOptions.cpp
@@ -0,0 +1,396 @@
+//===-- LVOptions.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This implements the LVOptions class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
+
+using namespace llvm;
+using namespace llvm::logicalview;
+
+#define DEBUG_TYPE "Options"
+
+//===----------------------------------------------------------------------===//
+// Options extracted from the command line.
+//===----------------------------------------------------------------------===//
+static LVOptions Options;
+LVOptions *LVOptions::getOptions() { return &Options; }
+void LVOptions::setOptions(LVOptions *CmdOptions) { Options = *CmdOptions; }
+
+void LVOptions::resolveDependencies() {
+ // Attributes that are classified as standard options.
+ auto StandardAttributes = [&]() {
+ // Set the 'standard' attribute to indicate its associated attributes.
+ setAttributeStandard();
+
+ setAttributeBase();
+ setAttributeCoverage();
+ setAttributeDirectories();
+ setAttributeDiscriminator();
+ setAttributeFilename();
+ setAttributeFiles();
+ setAttributeFormat();
+ setAttributeLevel();
+ setAttributeProducer();
+ setAttributePublics();
+ setAttributeRange();
+ setAttributeReference();
+ setAttributeZero();
+ };
+
+ // Attributes that are classified as extended options.
+ auto ExtendedAttributes = [&]() {
+ // Set the 'extended' attribute to indicate its associated attributes.
+ setAttributeExtended();
+
+ setAttributeArgument();
+ setAttributeDiscarded();
+ setAttributeEncoded();
+ setAttributeGaps();
+ setAttributeGenerated();
+ setAttributeGlobal();
+ setAttributeInserted();
+ setAttributeLinkage();
+ setAttributeLocal();
+ setAttributeLocation();
+ setAttributeOffset();
+ setAttributePathname();
+ setAttributeQualified();
+ setAttributeQualifier();
+ setAttributeRegister();
+ setAttributeSubrange();
+ setAttributeSystem();
+ setAttributeTypename();
+ };
+
+ // '--Attribute=standard' settings.
+ if (getAttributeStandard())
+ StandardAttributes();
+
+ // '--Attribute=extended' settings.
+ if (getAttributeExtended())
+ ExtendedAttributes();
+
+ // '--Attribute=all' settings.
+ if (getAttributeAll()) {
+ StandardAttributes();
+ ExtendedAttributes();
+ }
+
+ // '--attribute=pathname' supersedes '--attribute=filename'.
+ if (getAttributePathname())
+ resetAttributeFilename();
+
+ // Assume '--output=text' as default
+ if (!getOutputText() && !getOutputJson())
+ setOutputText();
+
+ // '--output=all' settings.
+ if (getOutputAll()) {
+ setOutputJson();
+ setOutputSplit();
+ setOutputText();
+ }
+
+ // A view split folder was specified.
+ if (getOutputFolder().length())
+ setOutputSplit();
+
+ // Always use the full pathname with splitted output.
+ if (getOutputSplit())
+ setAttributePathname();
+
+ // '--print=elements' settings.
+ if (getPrintElements()) {
+ setPrintInstructions();
+ setPrintLines();
+ setPrintScopes();
+ setPrintSymbols();
+ setPrintTypes();
+ }
+
+ // '--print=all' settings.
+ if (getPrintAll()) {
+ setPrintInstructions();
+ setPrintLines();
+ setPrintScopes();
+ setPrintSizes();
+ setPrintSymbols();
+ setPrintSummary();
+ setPrintTypes();
+ setPrintWarnings();
+ }
+
+ // '--warning=all' settings.
+ if (getWarningAll()) {
+ setWarningCoverages();
+ setWarningLines();
+ setWarningLocations();
+ setWarningRanges();
+ }
+
+ // '--internal=all' settings.
+ if (getInternalAll()) {
+ setInternalCmdline();
+ setInternalID();
+ setInternalIntegrity();
+ setInternalNone();
+ setInternalTag();
+ }
+
+ // '--compare=all' settings.
+ if (getCompareAll()) {
+ setCompareLines();
+ setCompareScopes();
+ setCompareSymbols();
+ setCompareTypes();
+ }
+
+ // Compare the scopes if a request for compare symbols, types, lines.
+ if (getCompareLines() || getCompareSymbols() || getCompareTypes())
+ setCompareScopes();
+
+ // Generic request for comparison.
+ if (getCompareScopes())
+ setCompareExecute();
+
+ // Print any logical line (debug or instruction).
+ if (getPrintInstructions() || getPrintLines())
+ setPrintAnyLine();
+
+ // Print any logical element (line, scope, symbol or type).
+ if (getPrintAnyLine() || getPrintScopes() || getPrintSymbols() ||
+ getPrintTypes())
+ setPrintAnyElement();
+
+ // Print 'sizes' or 'summary'.
+ if (getPrintSizes() && getPrintSummary())
+ setPrintSizesSummary();
+
+ // Generic request for printing.
+ if (getPrintAll() || getPrintAnyElement() || getPrintSizesSummary() ||
+ getPrintWarnings())
+ setPrintExecute();
+
+ // '--reports=all' settings.
+ if (getReportAll()) {
+ setReportChildren();
+ setReportList();
+ setReportParents();
+ setReportView();
+ }
+
+ // '--report=view' is a shortcut for '--report=parents,children'.
+ if (getReportView()) {
+ setReportChildren();
+ setReportParents();
+ }
+
+ // The report will include: Parents or Children.
+ if (getReportParents() || getReportChildren() || getReportView())
+ setReportAnyView();
+
+ // The report will include: List or Parents or Children.
+ if (getReportList() || getReportAnyView())
+ setReportExecute();
+
+ // If a view or element comparison has been requested, the following options
+ // must be set, in order to get a correct compare:
+ // 1) Sort the CUs, to get a fast compare.
+ // 2) Encode template instantiations, so the names include template
+ // parameter information.
+ // 3) Include qualified types.
+ // 4) Include any inserted abstract references.
+ // 5) For added/missing elements add the '+' or '-' tags.
+ if (getCompareExecute()) {
+ resetPrintExecute();
+ setComparePrint();
+ setSortMode(LVSortMode::Line);
+ setAttributeAdded();
+ setAttributeArgument();
+ setAttributeEncoded();
+ setAttributeInserted();
+ setAttributeMissing();
+ setAttributeQualified();
+ }
+
+ // Enable formatting for printing (indentation, print children).
+ setPrintFormatting();
+
+ // These attributes are dependent on the capture of location information.
+ if (getAttributeCoverage() || getAttributeGaps() || getAttributeRegister())
+ setAttributeLocation();
+
+ // Location information is only relevant when printing symbols.
+ if (!getPrintSymbols()) {
+ resetAttributeCoverage();
+ resetAttributeGaps();
+ resetAttributeLocation();
+ resetAttributeRegister();
+ }
+
+ // Quick check for printing any element source information.
+ if (getAttributeFilename() || getAttributePathname())
+ setAttributeAnySource();
+
+ // Quick check for printing any location information.
+ if (getAttributeLocation() || getAttributeRange())
+ setAttributeAnyLocation();
+
+ if (getAttributeRange() || getPrintAnyLine())
+ setGeneralCollectRanges();
+
+ calculateIndentationSize();
+
+ // Print collected command line options.
+ LLVM_DEBUG({ dump(); });
+}
+
+void LVOptions::calculateIndentationSize() {
+#ifndef NDEBUG
+ if (getInternalID()) {
+ std::string String = hexSquareString(0);
+ IndentationSize += String.length();
+ }
+#endif
+ if (getCompareExecute() && (getAttributeAdded() || getAttributeMissing()))
+ ++IndentationSize;
+ if (getAttributeOffset()) {
+ std::string String = hexSquareString(0);
+ IndentationSize += String.length();
+ }
+ if (getAttributeLevel()) {
+ std::stringstream Stream;
+ Stream.str(std::string());
+ Stream << "[" << std::setfill('0') << std::setw(3) << 0 << "]";
+ IndentationSize += Stream.tellp();
+ }
+ if (getAttributeGlobal())
+ ++IndentationSize;
+}
+
+// Print the current values for all the options, after the dependencies
+// has been resolved.
+void LVOptions::print(raw_ostream &OS) const {
+ // --attribute
+ OS << "** Attributes **\n"
+ << "All: " << getAttributeAll() << ", "
+ << "Argument: " << getAttributeArgument() << ", "
+ << "Base: " << getAttributeBase() << ", "
+ << "Coverage: " << getAttributeCoverage() << "\n"
+ << "Directories: " << getAttributeDirectories() << ", "
+ << "Discarded: " << getAttributeDiscarded() << ", "
+ << "Discriminator: " << getAttributeDiscriminator() << ", "
+ << "Encoded: " << getAttributeEncoded() << "\n"
+ << "Extended: " << getAttributeExtended() << ", "
+ << "Filename: " << getAttributeFilename() << ", "
+ << "Files: " << getAttributeFiles() << ", "
+ << "Format: " << getAttributeFormat() << "\n"
+ << "Gaps: " << getAttributeGaps() << ", "
+ << "Generated: " << getAttributeGenerated() << ", "
+ << "Global: " << getAttributeGlobal() << ", "
+ << "Inserted: " << getAttributeInserted() << "\n"
+ << "Level: " << getAttributeLevel() << ", "
+ << "Linkage: " << getAttributeLinkage() << ", "
+ << "Local: " << getAttributeLocal() << ", "
+ << "Location: " << getAttributeLocation() << "\n"
+ << "Offset: " << getAttributeOffset() << ", "
+ << "Pathname: " << getAttributePathname() << ", "
+ << "Producer: " << getAttributeProducer() << ", "
+ << "Publics: " << getAttributePublics() << "\n"
+ << "Qualified: " << getAttributeQualified() << ", "
+ << "Qualifier: " << getAttributeQualifier() << ", "
+ << "Range: " << getAttributeRange() << ", "
+ << "Reference: " << getAttributeReference() << "\n"
+ << "Register: " << getAttributeRegister() << ", "
+ << "Standard: " << getAttributeStandard() << ", "
+ << "Subrange: " << getAttributeSubrange() << ", "
+ << "System: " << getAttributeSystem() << "\n"
+ << "Typename: " << getAttributeTypename() << ", "
+ << "Underlying: " << getAttributeUnderlying() << ", "
+ << "Zero: " << getAttributeZero() << "\n";
+ OS << "Added: " << getAttributeAdded() << ", "
+ << "AnyLocation: " << getAttributeAnyLocation() << ", "
+ << "AnySource: " << getAttributeAnySource() << ", "
+ << "Missing: " << getAttributeMissing() << "\n"
+ << "\n";
+
+ // --compare
+ OS << "** Compare **\n"
+ << "All: " << getCompareAll() << ", "
+ << "Lines: " << getCompareLines() << ", "
+ << "Scopes: " << getCompareScopes() << ", "
+ << "Symbols: " << getCompareSymbols() << ", "
+ << "Types: " << getCompareTypes() << "\n";
+ OS << "Context: " << getCompareContext() << ", "
+ << "Execute: " << getCompareExecute() << ", "
+ << "Print: " << getComparePrint() << "\n"
+ << "\n";
+
+ // --print
+ OS << "** Print **\n"
+ << "All: " << getPrintAll() << ", "
+ << "Elements: " << getPrintElements() << ", "
+ << "Instructions: " << getPrintInstructions() << ", "
+ << "Lines: " << getPrintLines() << "\n"
+ << "Scopes: " << getPrintScopes() << ", "
+ << "Sizes: " << getPrintSizes() << ", "
+ << "Summary: " << getPrintSummary() << ", "
+ << "Symbols: " << getPrintSymbols() << "\n"
+ << "Types: " << getPrintTypes() << ", "
+ << "Warnings: " << getPrintWarnings() << "\n";
+ OS << "AnyElemeny: " << getPrintAnyElement() << ", "
+ << "AnyLine: " << getPrintAnyLine() << ", "
+ << "Execute: " << getPrintExecute() << ", "
+ << "Formatting: " << getPrintFormatting() << "\n"
+ << "Offset: " << getPrintOffset() << ", "
+ << "SizesSummary: " << getPrintSizesSummary() << "\n"
+ << "\n";
+
+ // --report
+ OS << "** Report **\n"
+ << "All: " << getReportAll() << ", "
+ << "Children: " << getReportChildren() << ", "
+ << "List: " << getReportList() << ", "
+ << "Parents: " << getReportParents() << ", "
+ << "View: " << getReportView() << "\n";
+ OS << "AnyView: " << getReportAnyView() << ", "
+ << "Execute: " << getReportExecute() << "\n"
+ << "\n";
+
+ // --select
+ OS << "** Select **\n"
+ << "IgnoreCase: " << getSelectIgnoreCase() << ", "
+ << "UseRegex: " << getSelectUseRegex() << ", "
+ << "Execute: " << getSelectExecute() << ", "
+ << "GenericKind: " << getSelectGenericKind() << "\n"
+ << "GenericPattern: " << getSelectGenericPattern() << ", "
+ << "OffsetPattern: " << getSelectOffsetPattern() << "\n"
+ << "\n";
+
+ // --warning
+ OS << "** Warning **\n"
+ << "All: " << getWarningAll() << ", "
+ << "Coverage: " << getWarningCoverages() << ", "
+ << "Lines: " << getWarningLines() << ", "
+ << "Locations: " << getWarningLocations() << ", "
+ << "Ranges: " << getWarningRanges() << "\n"
+ << "\n";
+
+ // --internal
+ OS << "** Internal **\n"
+ << "All: " << Options.getInternalAll() << ", "
+ << "Cmdline: " << Options.getInternalCmdline() << ", "
+ << "ID: " << Options.getInternalID() << ", "
+ << "Integrity: " << Options.getInternalIntegrity() << ", "
+ << "None: " << Options.getInternalNone() << "\n"
+ << "Tag: " << Options.getInternalTag() << "\n"
+ << "\n";
+}
diff --git a/llvm/lib/DebugInfo/LogicalView/LLVMBuild.txt b/llvm/lib/DebugInfo/LogicalView/LLVMBuild.txt
new file mode 100644
index 0000000000000..11037f03daef0
--- /dev/null
+++ b/llvm/lib/DebugInfo/LogicalView/LLVMBuild.txt
@@ -0,0 +1,21 @@
+;===- ./lib/DebugInfo/LogicalView/LLVMBuild.txt ----------------*- Conf -*--===;
+;
+; Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+; See https://llvm.org/LICENSE.txt for license information.
+; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = DebugInfoLogicalView
+parent = DebugInfo
+required_libraries = Object Support DebugInfoDWARF DebugInfoCodeView DebugInfoPDB
diff --git a/llvm/test/CMakeLists.txt b/llvm/test/CMakeLists.txt
index a38fb0a2408d4..01e2a6ebf6c72 100644
--- a/llvm/test/CMakeLists.txt
+++ b/llvm/test/CMakeLists.txt
@@ -77,6 +77,7 @@ set(LLVM_TEST_DEPENDS
llvm-cxxdump
llvm-cxxfilt
llvm-cxxmap
+ llvm-debuginfo-analyzer
llvm-debuginfod-find
llvm-
diff
llvm-dis
diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py
index c554b9d902fa9..476424fd75df9 100644
--- a/llvm/test/lit.cfg.py
+++ b/llvm/test/lit.cfg.py
@@ -159,6 +159,7 @@ def get_asan_rtlib():
'dsymutil', 'lli', 'lli-child-target', 'llvm-ar', 'llvm-as',
'llvm-addr2line', 'llvm-bcanalyzer', 'llvm-bitcode-strip', 'llvm-config',
'llvm-cov', 'llvm-cxxdump', 'llvm-cvtres', 'llvm-debuginfod-find', 'llvm-debuginfod',
+ 'llvm-debuginfo-analyzer',
'llvm-
diff ', 'llvm-dis', 'llvm-dwarfdump', 'llvm-dwarfutil', 'llvm-dlltool',
'llvm-exegesis', 'llvm-extract', 'llvm-isel-fuzzer', 'llvm-ifs',
'llvm-install-name-tool', 'llvm-jitlink', 'llvm-opt-fuzzer', 'llvm-lib',
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/cmdline.test b/llvm/test/tools/llvm-debuginfo-analyzer/cmdline.test
new file mode 100644
index 0000000000000..c9c2dbe9fa3ea
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/cmdline.test
@@ -0,0 +1,221 @@
+RUN: llvm-debuginfo-analyzer --version 2>&1 | FileCheck --check-prefix=VERSION %s
+VERSION: {{ version }}
+
+RUN: llvm-debuginfo-analyzer -h > %t 2>&1
+RUN: FileCheck -input-file=%t %s --check-prefix=HELP --implicit-check-not=out-file
+RUN: llvm-debuginfo-analyzer --help > %t 2>&1
+RUN: FileCheck -input-file=%t %s --check-prefix=HELP --implicit-check-not=out-file
+HELP: OVERVIEW: Printing a logical representation of low-level debug information.
+HELP: USAGE: llvm-debuginfo-analyzer{{[^ ]*}} [options] <input object files or .dSYM bundles>
+HELP: OPTIONS:
+HELP: Generic Options:
+HELP: --help - Display available options (--help-hidden for more)
+HELP: --help-list - Display list of available options (--help-list-hidden for more)
+HELP: --version - Display the version of this program
+HELP: Print Options:
+HELP: These control which elements are printed.
+HELP: --print=<value> - Element to print.
+HELP: =all - All elements.
+HELP: =elements - Instructions, lines, scopes, symbols and types.
+HELP: =instructions - Assembler instructions.
+HELP: =lines - Lines referenced in the debug information.
+HELP: =scopes - A lexical block (Function, Class, etc.).
+HELP: =sizes - Scope contributions to the debug information.
+HELP: =summary - Summary of elements missing/added/matched/printed.
+HELP: =symbols - Symbols (Variable, Members, etc.).
+HELP: =types - Types (Pointer, Reference, etc.).
+HELP: =warnings - Warnings detected.
+HELP: Pass @FILE as argument to read options from FILE.
+
+RUN: llvm-debuginfo-analyzer --help-hidden > %t 2>&1
+RUN: FileCheck -input-file=%t %s --check-prefix=HELP-ALL --implicit-check-not=out-file
+HELP-ALL: OVERVIEW: Printing a logical representation of low-level debug information.
+HELP-ALL: USAGE: llvm-debuginfo-analyzer{{[^ ]*}} [options] <input object files or .dSYM bundles>
+HELP-ALL: OPTIONS:
+HELP-ALL: Attribute Options:
+HELP-ALL: These control extra attributes that are added when the element is printed.
+HELP-ALL: --attribute=<value> - Element attributes.
+HELP-ALL: =all - Include all attributes.
+HELP-ALL: =argument - Template parameters replaced by its arguments.
+HELP-ALL: =base - Base types (int, bool, etc.).
+HELP-ALL: =coverage - Symbol location coverage.
+HELP-ALL: =directories - Directories referenced in the debug information.
+HELP-ALL: =discarded - Discarded elements by the linker.
+HELP-ALL: =discriminator - Discriminators for inlined function instances.
+HELP-ALL: =encoded - Template arguments encoded in the template name.
+HELP-ALL: =extended - Advanced attributes alias.
+HELP-ALL: =filename - Filename where the element is defined.
+HELP-ALL: =files - Files referenced in the debug information.
+HELP-ALL: =format - Object file format name.
+HELP-ALL: =gaps - Missing debug location (gaps).
+HELP-ALL: =generated - Compiler generated elements.
+HELP-ALL: =global - Element referenced across Compile Units.
+HELP-ALL: =inserted - Generated inlined abstract references.
+HELP-ALL: =level - Lexical scope level (File=0, Compile Unit=1).
+HELP-ALL: =linkage - Linkage name.
+HELP-ALL: =local - Element referenced only in the Compile Unit.
+HELP-ALL: =location - Element debug location.
+HELP-ALL: =offset - Debug information offset.
+HELP-ALL: =pathname - Pathname where the element is defined.
+HELP-ALL: =producer - Toolchain identification name.
+HELP-ALL: =publics - Function names that are public.
+HELP-ALL: =qualified - The element type include parents in its name.
+HELP-ALL: =qualifier - Line qualifiers (Newstatement, BasicBlock, etc.).
+HELP-ALL: =range - Debug location ranges.
+HELP-ALL: =reference - Element declaration and definition references.
+HELP-ALL: =register - Processor register names.
+HELP-ALL: =standard - Basic attributes alias.
+HELP-ALL: =subrange - Subrange encoding information for arrays.
+HELP-ALL: =system - Display PDB's MS system elements.
+HELP-ALL: =typename - Include Parameters in templates.
+HELP-ALL: =underlying - Underlying type for type definitions.
+HELP-ALL: =zero - Zero line numbers.
+HELP-ALL: Color Options:
+HELP-ALL: This option category has no options.
+HELP-ALL: Compare Options:
+HELP-ALL: These control the view comparison.
+HELP-ALL: --compare=<value> - Elements to compare.
+HELP-ALL: =all - Compare all elements.
+HELP-ALL: =lines - Lines.
+HELP-ALL: =scopes - Scopes.
+HELP-ALL: =symbols - Symbols.
+HELP-ALL: =types - Types.
+HELP-ALL: --compare-context - Add the view as compare context.
+HELP-ALL: General options:
+HELP-ALL: This option category has no options.
+HELP-ALL: Generic Options:
+HELP-ALL: -h - Alias for --help
+HELP-ALL: --help - Display available options (--help-hidden for more)
+HELP-ALL: --help-hidden - Display all available options
+HELP-ALL: --help-list - Display list of available options (--help-list-hidden for more)
+HELP-ALL: --help-list-hidden - Display list of all available options
+HELP-ALL: --print-all-options - Print all option values after command line parsing
+HELP-ALL: --print-options - Print non-default options after command line parsing
+HELP-ALL: --version - Display the version of this program
+HELP-ALL: Internal Options:
+HELP-ALL: Internal traces and extra debugging code.
+HELP-ALL: --internal=<value> - Traces to enable.
+HELP-ALL: =all - Enable all traces.
+HELP-ALL: =cmdline - Print command line.
+HELP-ALL: =id - Print unique element ID
+HELP-ALL: =integrity - Check elements integrity.
+HELP-ALL: =none - Ignore element line number.
+HELP-ALL: =tag - Debug information tags.
+HELP-ALL: Output Options:
+HELP-ALL: These control the output generated.
+HELP-ALL: --output=<value> - Outputs for view.
+HELP-ALL: =all - All outputs.
+HELP-ALL: =split - Split the output by Compile Units.
+HELP-ALL: =text - Use a free form text output.
+HELP-ALL: =json - Use JSON as the output format.
+HELP-ALL: --output-file=<filename> - Redirect output to the specified file.
+HELP-ALL: --output-folder=<pathname> - Folder name for view splitting.
+HELP-ALL: --output-level=<N> - Only print to a depth of N elements.
+HELP-ALL: --output-sort=<value> - Primary key when ordering logical view (default: line).
+HELP-ALL: =kind - Sort by element kind.
+HELP-ALL: =line - Sort by element line number.
+HELP-ALL: =name - Sort by element name.
+HELP-ALL: =offset - Sort by element offset.
+HELP-ALL: Print Options:
+HELP-ALL: These control which elements are printed.
+HELP-ALL: --print=<value> - Element to print.
+HELP-ALL: =all - All elements.
+HELP-ALL: =elements - Instructions, lines, scopes, symbols and types.
+HELP-ALL: =instructions - Assembler instructions.
+HELP-ALL: =lines - Lines referenced in the debug information.
+HELP-ALL: =scopes - A lexical block (Function, Class, etc.).
+HELP-ALL: =sizes - Scope contributions to the debug information.
+HELP-ALL: =summary - Summary of elements missing/added/matched/printed.
+HELP-ALL: =symbols - Symbols (Variable, Members, etc.).
+HELP-ALL: =types - Types (Pointer, Reference, etc.).
+HELP-ALL: =warnings - Warnings detected.
+HELP-ALL: Report Options:
+HELP-ALL: These control how the elements are printed.
+HELP-ALL: --report=<value> - Reports layout used for print, compare and select.
+HELP-ALL: =all - Generate all reports.
+HELP-ALL: =children - Selected elements are displayed in a tree view (Include children)
+HELP-ALL: =list - Selected elements are displayed in a tabular format.
+HELP-ALL: =parents - Selected elements are displayed in a tree view. (Include parents)
+HELP-ALL: =view - Selected elements are displayed in a tree view (Include parents and children.
+HELP-ALL: Select Options:
+HELP-ALL: These control which elements are selected.
+HELP-ALL: --select=<pattern> - Search elements matching the given pattern.
+HELP-ALL: --select-elements=<value> - Conditions to use when printing elements.
+HELP-ALL: =Discarded - Discarded elements by the linker.
+HELP-ALL: =Global - Element referenced across Compile Units.
+HELP-ALL: =Optimized - Generated inlined abstract references.
+HELP-ALL: --select-lines=<value> - Line kind to use when printing lines.
+HELP-ALL: =AlwaysStepInto - Always Step Into.
+HELP-ALL: =BasicBlock - Basic block.
+HELP-ALL: =Discriminator - Discriminator.
+HELP-ALL: =EndSequence - End sequence.
+HELP-ALL: =EpilogueBegin. - Epilogue begin.
+HELP-ALL: =LineDebug - Debug line.
+HELP-ALL: =LineAssembler - Assembler line.
+HELP-ALL: =NeverStepInto - Never Step Into.
+HELP-ALL: =NewStatement - New statement.
+HELP-ALL: =PrologueEnd - Prologue end.
+HELP-ALL: --select-nocase - Ignore case distinctions when searching.
+HELP-ALL: --select-offsets=<offset> - Offset element to print.
+HELP-ALL: --select-regex - Treat any <pattern> strings as regular expressions when selecting instead of just as an exact string match.
+HELP-ALL: --select-scopes=<value> - Scope kind to use when printing scopes.
+HELP-ALL: =Aggregate - Class, Structure or Union.
+HELP-ALL: =Array - Array.
+HELP-ALL: =Block - Lexical block.
+HELP-ALL: =CallSite - Call site block.
+HELP-ALL: =CatchBlock - Exception catch block.
+HELP-ALL: =Class - Class.
+HELP-ALL: =CompileUnit - Compile unit.
+HELP-ALL: =EntryPoint - Function entry point.
+HELP-ALL: =Enumeration - Enumeration.
+HELP-ALL: =Function - Function.
+HELP-ALL: =FunctionType - Function type.
+HELP-ALL: =InlinedFunction - Inlined function.
+HELP-ALL: =Label - Label.
+HELP-ALL: =LexicalBlock - Lexical block.
+HELP-ALL: =Namespace - Namespace.
+HELP-ALL: =Root - Root.
+HELP-ALL: =Structure - Structure.
+HELP-ALL: =Subprogram - Subprogram.
+HELP-ALL: =Template - Template.
+HELP-ALL: =TemplateAlias - Template alias.
+HELP-ALL: =TemplatePack - Template pack.
+HELP-ALL: =TryBlock - Exception try block.
+HELP-ALL: =Union - Union.
+HELP-ALL: --select-symbols=<value> - Symbol kind to use when printing symbols.
+HELP-ALL: =CallSiteParameter - Call site parameter.
+HELP-ALL: =Constant - Constant.
+HELP-ALL: =Inheritance - Inheritance.
+HELP-ALL: =Member - Member.
+HELP-ALL: =Parameter - Parameter.
+HELP-ALL: =Unspecified - Unspecified parameter.
+HELP-ALL: =Variable - Variable.
+HELP-ALL: --select-types=<value> - Type kind to use when printing types.
+HELP-ALL: =Base - Base Type (int, bool, etc.).
+HELP-ALL: =Const - Constant specifier.
+HELP-ALL: =Enumerator - Enumerator.
+HELP-ALL: =Import - Import.
+HELP-ALL: =ImportDeclaration - Import declaration.
+HELP-ALL: =ImportModule - Import module.
+HELP-ALL: =Pointer - Pointer.
+HELP-ALL: =PointerMember - Pointer to member.
+HELP-ALL: =Reference - Reference type.
+HELP-ALL: =Restrict - Restrict specifier.
+HELP-ALL: =RvalueReference - Rvalue reference.
+HELP-ALL: =Subrange - Array subrange.
+HELP-ALL: =TemplateParam - Template Parameter.
+HELP-ALL: =TemplateTemplateParam - Template template parameter.
+HELP-ALL: =TemplateTypeParam - Template type parameter.
+HELP-ALL: =TemplateValueParam - Template value parameter.
+HELP-ALL: =Typedef - Type definition.
+HELP-ALL: =Unspecified - Unspecified type.
+HELP-ALL: =Volatile - Volatile specifier.
+HELP-ALL: Warning Options:
+HELP-ALL: These control the generated warnings.
+HELP-ALL: --warning=<value> - Warnings to generate.
+HELP-ALL: =all - All warnings.
+HELP-ALL: =coverages - Invalid symbol coverages values.
+HELP-ALL: =lines - Debug lines that are zero.
+HELP-ALL: =locations - Invalid symbol locations.
+HELP-ALL: =ranges - Invalid code ranges.
+HELP-ALL: Pass @FILE as argument to read options from FILE.
diff --git a/llvm/tools/llvm-debuginfo-analyzer/CMakeLists.txt b/llvm/tools/llvm-debuginfo-analyzer/CMakeLists.txt
new file mode 100644
index 0000000000000..b36f5d7aa2f37
--- /dev/null
+++ b/llvm/tools/llvm-debuginfo-analyzer/CMakeLists.txt
@@ -0,0 +1,19 @@
+set(LLVM_LINK_COMPONENTS
+ AllTargetsDescs
+ AllTargetsInfos
+ AllTargetsDisassemblers
+ BinaryFormat
+ DebugInfoLogicalView
+ DebugInfoCodeView
+ DebugInfoDWARF
+ DebugInfoPDB
+ MC
+ MCDisassembler
+ Object
+ Support
+ )
+
+add_llvm_tool(llvm-debuginfo-analyzer
+ llvm-debuginfo-analyzer.cpp
+ Options.cpp
+ )
diff --git a/llvm/tools/llvm-debuginfo-analyzer/LLVMBuild.txt b/llvm/tools/llvm-debuginfo-analyzer/LLVMBuild.txt
new file mode 100644
index 0000000000000..2fcd27062688f
--- /dev/null
+++ b/llvm/tools/llvm-debuginfo-analyzer/LLVMBuild.txt
@@ -0,0 +1,21 @@
+;===- ./tools/llvm-debuginfo-analyzer/LLVMBuild.txt ------------*- Conf -*--===;
+;
+; Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+; See https://llvm.org/LICENSE.txt for license information.
+; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Tool
+name = llvm-debuginfo-analyzer
+parent = Tools
+required_libraries = DebugInfoLogicalView DebugInfoDWARF DebugInfoCodeView DebugInfoPDB Object
diff --git a/llvm/tools/llvm-debuginfo-analyzer/Options.cpp b/llvm/tools/llvm-debuginfo-analyzer/Options.cpp
new file mode 100644
index 0000000000000..e5566b3390fd2
--- /dev/null
+++ b/llvm/tools/llvm-debuginfo-analyzer/Options.cpp
@@ -0,0 +1,501 @@
+//===-- options.cpp - Command line options for llvm-debuginfo-analyzer----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This handles the command line options for llvm-debuginfo-analyzer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Options.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVSort.h"
+#include "llvm/Support/CommandLine.h"
+
+using namespace llvm;
+using namespace llvm::logicalview;
+using namespace llvm::logicalview::cmdline;
+
+/// @}
+/// Command line options.
+/// @{
+
+OffsetParser::OffsetParser(cl::Option &O) : parser<unsigned long long>(O) {}
+OffsetParser::~OffsetParser() = default;
+
+bool OffsetParser::parse(cl::Option &O, StringRef ArgName, StringRef Arg,
+ unsigned long long &Val) {
+ char *End;
+ std::string Argument(Arg);
+ Val = strtoull(Argument.c_str(), &End, 0);
+ if (*End)
+ // Print an error message if unrecognized character.
+ return O.error("'" + Arg + "' unrecognized character.");
+ return false;
+}
+
+LVOptions cmdline::ReaderOptions;
+
+//===----------------------------------------------------------------------===//
+// Specific options
+//===----------------------------------------------------------------------===//
+cl::list<std::string>
+ cmdline::InputFilenames(cl::desc("<input object files or .dSYM bundles>"),
+ cl::Positional, cl::ZeroOrMore);
+
+//===----------------------------------------------------------------------===//
+// '--attribute' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+ cmdline::AttributeCategory("Attribute Options",
+ "These control extra attributes that are "
+ "added when the element is printed.");
+
+// --attribute=<value>[,<value>,...]
+cl::list<LVAttributeKind> cmdline::AttributeOptions(
+ "attribute", cl::cat(AttributeCategory), cl::desc("Element attributes."),
+ cl::Hidden, cl::CommaSeparated,
+ values(clEnumValN(LVAttributeKind::All, "all", "Include all attributes."),
+ clEnumValN(LVAttributeKind::Argument, "argument",
+ "Template parameters replaced by its arguments."),
+ clEnumValN(LVAttributeKind::Base, "base",
+ "Base types (int, bool, etc.)."),
+ clEnumValN(LVAttributeKind::Coverage, "coverage",
+ "Symbol location coverage."),
+ clEnumValN(LVAttributeKind::Directories, "directories",
+ "Directories referenced in the debug information."),
+ clEnumValN(LVAttributeKind::Discarded, "discarded",
+ "Discarded elements by the linker."),
+ clEnumValN(LVAttributeKind::Discriminator, "discriminator",
+ "Discriminators for inlined function instances."),
+ clEnumValN(LVAttributeKind::Encoded, "encoded",
+ "Template arguments encoded in the template name."),
+ clEnumValN(LVAttributeKind::Extended, "extended",
+ "Advanced attributes alias."),
+ clEnumValN(LVAttributeKind::Filename, "filename",
+ "Filename where the element is defined."),
+ clEnumValN(LVAttributeKind::Files, "files",
+ "Files referenced in the debug information."),
+ clEnumValN(LVAttributeKind::Format, "format",
+ "Object file format name."),
+ clEnumValN(LVAttributeKind::Gaps, "gaps",
+ "Missing debug location (gaps)."),
+ clEnumValN(LVAttributeKind::Generated, "generated",
+ "Compiler generated elements."),
+ clEnumValN(LVAttributeKind::Global, "global",
+ "Element referenced across Compile Units."),
+ clEnumValN(LVAttributeKind::Inserted, "inserted",
+ "Generated inlined abstract references."),
+ clEnumValN(LVAttributeKind::Level, "level",
+ "Lexical scope level (File=0, Compile Unit=1)."),
+ clEnumValN(LVAttributeKind::Linkage, "linkage", "Linkage name."),
+ clEnumValN(LVAttributeKind::Local, "local",
+ "Element referenced only in the Compile Unit."),
+ clEnumValN(LVAttributeKind::Location, "location",
+ "Element debug location."),
+ clEnumValN(LVAttributeKind::Offset, "offset",
+ "Debug information offset."),
+ clEnumValN(LVAttributeKind::Pathname, "pathname",
+ "Pathname where the element is defined."),
+ clEnumValN(LVAttributeKind::Producer, "producer",
+ "Toolchain identification name."),
+ clEnumValN(LVAttributeKind::Publics, "publics",
+ "Function names that are public."),
+ clEnumValN(LVAttributeKind::Qualified, "qualified",
+ "The element type include parents in its name."),
+ clEnumValN(LVAttributeKind::Qualifier, "qualifier",
+ "Line qualifiers (Newstatement, BasicBlock, etc.)."),
+ clEnumValN(LVAttributeKind::Range, "range",
+ "Debug location ranges."),
+ clEnumValN(LVAttributeKind::Reference, "reference",
+ "Element declaration and definition references."),
+ clEnumValN(LVAttributeKind::Register, "register",
+ "Processor register names."),
+ clEnumValN(LVAttributeKind::Standard, "standard",
+ "Basic attributes alias."),
+ clEnumValN(LVAttributeKind::Subrange, "subrange",
+ "Subrange encoding information for arrays."),
+ clEnumValN(LVAttributeKind::System, "system",
+ "Display PDB's MS system elements."),
+ clEnumValN(LVAttributeKind::Typename, "typename",
+ "Include Parameters in templates."),
+ clEnumValN(LVAttributeKind::Underlying, "underlying",
+ "Underlying type for type definitions."),
+ clEnumValN(LVAttributeKind::Zero, "zero", "Zero line numbers.")));
+
+//===----------------------------------------------------------------------===//
+// '--compare' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+ cmdline::CompareCategory("Compare Options",
+ "These control the view comparison.");
+
+// --compare-context
+static cl::opt<bool, true>
+ CompareContext("compare-context", cl::cat(CompareCategory),
+ cl::desc("Add the view as compare context."), cl::Hidden,
+ cl::ZeroOrMore, cl::location(ReaderOptions.Compare.Context),
+ cl::init(false));
+
+// --compare=<value>[,<value>,...]
+cl::list<LVCompareKind> cmdline::CompareElements(
+ "compare", cl::cat(CompareCategory), cl::desc("Elements to compare."),
+ cl::Hidden, cl::CommaSeparated,
+ values(clEnumValN(LVCompareKind::All, "all", "Compare all elements."),
+ clEnumValN(LVCompareKind::Lines, "lines", "Lines."),
+ clEnumValN(LVCompareKind::Scopes, "scopes", "Scopes."),
+ clEnumValN(LVCompareKind::Symbols, "symbols", "Symbols."),
+ clEnumValN(LVCompareKind::Types, "types", "Types.")));
+
+//===----------------------------------------------------------------------===//
+// '--output' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+ cmdline::OutputCategory("Output Options",
+ "These control the output generated.");
+
+// --output-file=<filename>
+cl::opt<std::string>
+ cmdline::OutputFilename("output-file", cl::cat(OutputCategory),
+ cl::desc("Redirect output to the specified file."),
+ cl::Hidden, cl::value_desc("filename"),
+ cl::init("-"));
+
+// --output-folder=<path>
+static cl::opt<std::string, true>
+ OutputFolder("output-folder", cl::cat(OutputCategory),
+ cl::desc("Folder name for view splitting."),
+ cl::value_desc("pathname"), cl::Hidden, cl::ZeroOrMore,
+ cl::location(ReaderOptions.Output.Folder));
+
+// --output-level=<level>
+static cl::opt<unsigned, true>
+ OutputLevel("output-level", cl::cat(OutputCategory),
+ cl::desc("Only print to a depth of N elements."),
+ cl::value_desc("N"), cl::Hidden, cl::ZeroOrMore,
+ cl::location(ReaderOptions.Output.Level), cl::init(-1U));
+
+// --ouput=<value>[,<value>,...]
+cl::list<LVOutputKind> cmdline::OutputOptions(
+ "output", cl::cat(OutputCategory), cl::desc("Outputs for view."),
+ cl::Hidden, cl::CommaSeparated,
+ values(clEnumValN(LVOutputKind::All, "all", "All outputs."),
+ clEnumValN(LVOutputKind::Split, "split",
+ "Split the output by Compile Units."),
+ clEnumValN(LVOutputKind::Text, "text",
+ "Use a free form text output."),
+ clEnumValN(LVOutputKind::Json, "json",
+ "Use JSON as the output format.")));
+
+// --output-sort
+static cl::opt<LVSortMode, true> OutputSort(
+ "output-sort", cl::cat(OutputCategory),
+ cl::desc("Primary key when ordering logical view (default: line)."),
+ cl::Hidden, cl::ZeroOrMore,
+ values(clEnumValN(LVSortMode::Kind, "kind", "Sort by element kind."),
+ clEnumValN(LVSortMode::Line, "line", "Sort by element line number."),
+ clEnumValN(LVSortMode::Name, "name", "Sort by element name."),
+ clEnumValN(LVSortMode::Offset, "offset", "Sort by element offset.")),
+ cl::location(ReaderOptions.Output.SortMode), cl::init(LVSortMode::Line));
+
+//===----------------------------------------------------------------------===//
+// '--print' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+ cmdline::PrintCategory("Print Options",
+ "These control which elements are printed.");
+
+// --print=<value>[,<value>,...]
+cl::list<LVPrintKind> cmdline::PrintOptions(
+ "print", cl::cat(PrintCategory), cl::desc("Element to print."),
+ cl::CommaSeparated,
+ values(clEnumValN(LVPrintKind::All, "all", "All elements."),
+ clEnumValN(LVPrintKind::Elements, "elements",
+ "Instructions, lines, scopes, symbols and types."),
+ clEnumValN(LVPrintKind::Instructions, "instructions",
+ "Assembler instructions."),
+ clEnumValN(LVPrintKind::Lines, "lines",
+ "Lines referenced in the debug information."),
+ clEnumValN(LVPrintKind::Scopes, "scopes",
+ "A lexical block (Function, Class, etc.)."),
+ clEnumValN(LVPrintKind::Sizes, "sizes",
+ "Scope contributions to the debug information."),
+ clEnumValN(LVPrintKind::Summary, "summary",
+ "Summary of elements missing/added/matched/printed."),
+ clEnumValN(LVPrintKind::Symbols, "symbols",
+ "Symbols (Variable, Members, etc.)."),
+ clEnumValN(LVPrintKind::Types, "types",
+ "Types (Pointer, Reference, etc.)."),
+ clEnumValN(LVPrintKind::Warnings, "warnings",
+ "Warnings detected.")));
+
+//===----------------------------------------------------------------------===//
+// '--report' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+ cmdline::ReportCategory("Report Options",
+ "These control how the elements are printed.");
+
+// --report=<value>[,<value>,...]
+cl::list<LVReportKind> cmdline::ReportOptions(
+ "report", cl::cat(ReportCategory),
+ cl::desc("Reports layout used for print, compare and select."), cl::Hidden,
+ cl::CommaSeparated,
+ values(clEnumValN(LVReportKind::All, "all", "Generate all reports."),
+ clEnumValN(LVReportKind::Children, "children",
+ "Selected elements are displayed in a tree view "
+ "(Include children)"),
+ clEnumValN(LVReportKind::List, "list",
+ "Selected elements are displayed in a tabular format."),
+ clEnumValN(LVReportKind::Parents, "parents",
+ "Selected elements are displayed in a tree view. "
+ "(Include parents)"),
+ clEnumValN(LVReportKind::View, "view",
+ "Selected elements are displayed in a tree view "
+ "(Include parents and children.")));
+
+//===----------------------------------------------------------------------===//
+// '--select' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+ cmdline::SelectCategory("Select Options",
+ "These control which elements are selected.");
+
+// --select-nocase
+static cl::opt<bool, true>
+ SelectIgnoreCase("select-nocase", cl::cat(SelectCategory),
+ cl::desc("Ignore case distinctions when searching."),
+ cl::Hidden, cl::ZeroOrMore,
+ cl::location(ReaderOptions.Select.IgnoreCase),
+ cl::init(false));
+
+// --select-regex
+static cl::opt<bool, true> SelectUseRegex(
+ "select-regex", cl::cat(SelectCategory),
+ cl::desc("Treat any <pattern> strings as regular expressions when "
+ "selecting instead of just as an exact string match."),
+ cl::Hidden, cl::ZeroOrMore, cl::location(ReaderOptions.Select.UseRegex),
+ cl::init(false));
+
+// --select=<pattern>
+cl::list<std::string> cmdline::SelectPatterns(
+ "select", cl::cat(SelectCategory),
+ cl::desc("Search elements matching the given pattern."), cl::Hidden,
+ cl::value_desc("pattern"), cl::CommaSeparated);
+
+// --select-offsets=<value>[,<value>,...]
+OffsetOptionList cmdline::SelectOffsets("select-offsets",
+ cl::cat(SelectCategory),
+ cl::desc("Offset element to print."),
+ cl::Hidden, cl::value_desc("offset"),
+ cl::CommaSeparated, cl::ZeroOrMore);
+
+// --select-elements=<value>[,<value>,...]
+cl::list<LVElementKind> cmdline::SelectElements(
+ "select-elements", cl::cat(SelectCategory),
+ cl::desc("Conditions to use when printing elements."), cl::Hidden,
+ cl::CommaSeparated,
+ values(clEnumValN(LVElementKind::Discarded, "Discarded",
+ "Discarded elements by the linker."),
+ clEnumValN(LVElementKind::Global, "Global",
+ "Element referenced across Compile Units."),
+ clEnumValN(LVElementKind::Optimized, "Optimized",
+ "Generated inlined abstract references.")));
+
+// --select-lines=<value>[,<value>,...]
+cl::list<LVLineKind> cmdline::SelectLines(
+ "select-lines", cl::cat(SelectCategory),
+ cl::desc("Line kind to use when printing lines."), cl::Hidden,
+ cl::CommaSeparated,
+ values(
+ clEnumValN(LVLineKind::IsAlwaysStepInto, "AlwaysStepInto",
+ "Always Step Into."),
+ clEnumValN(LVLineKind::IsBasicBlock, "BasicBlock", "Basic block."),
+ clEnumValN(LVLineKind::IsDiscriminator, "Discriminator",
+ "Discriminator."),
+ clEnumValN(LVLineKind::IsEndSequence, "EndSequence", "End sequence."),
+ clEnumValN(LVLineKind::IsEpilogueBegin, "EpilogueBegin.",
+ "Epilogue begin."),
+ clEnumValN(LVLineKind::IsLineDebug, "LineDebug", "Debug line."),
+ clEnumValN(LVLineKind::IsLineAssembler, "LineAssembler",
+ "Assembler line."),
+ clEnumValN(LVLineKind::IsNeverStepInto, "NeverStepInto",
+ "Never Step Into."),
+ clEnumValN(LVLineKind::IsNewStatement, "NewStatement",
+ "New statement."),
+ clEnumValN(LVLineKind::IsPrologueEnd, "PrologueEnd", "Prologue end.")));
+
+// --select-scopes=<value>[,<value>,...]
+cl::list<LVScopeKind> cmdline::SelectScopes(
+ "select-scopes", cl::cat(SelectCategory),
+ cl::desc("Scope kind to use when printing scopes."), cl::Hidden,
+ cl::CommaSeparated,
+ values(
+ clEnumValN(LVScopeKind::IsAggregate, "Aggregate",
+ "Class, Structure or Union."),
+ clEnumValN(LVScopeKind::IsArray, "Array", "Array."),
+ clEnumValN(LVScopeKind::IsBlock, "Block", "Lexical block."),
+ clEnumValN(LVScopeKind::IsCallSite, "CallSite", "Call site block."),
+ clEnumValN(LVScopeKind::IsCatchBlock, "CatchBlock",
+ "Exception catch block."),
+ clEnumValN(LVScopeKind::IsClass, "Class", "Class."),
+ clEnumValN(LVScopeKind::IsCompileUnit, "CompileUnit", "Compile unit."),
+ clEnumValN(LVScopeKind::IsEntryPoint, "EntryPoint",
+ "Function entry point."),
+ clEnumValN(LVScopeKind::IsEnumeration, "Enumeration", "Enumeration."),
+ clEnumValN(LVScopeKind::IsFunction, "Function", "Function."),
+ clEnumValN(LVScopeKind::IsFunctionType, "FunctionType",
+ "Function type."),
+ clEnumValN(LVScopeKind::IsInlinedFunction, "InlinedFunction",
+ "Inlined function."),
+ clEnumValN(LVScopeKind::IsLabel, "Label", "Label."),
+ clEnumValN(LVScopeKind::IsLexicalBlock, "LexicalBlock",
+ "Lexical block."),
+ clEnumValN(LVScopeKind::IsNamespace, "Namespace", "Namespace."),
+ clEnumValN(LVScopeKind::IsRoot, "Root", "Root."),
+ clEnumValN(LVScopeKind::IsStructure, "Structure", "Structure."),
+ clEnumValN(LVScopeKind::IsSubprogram, "Subprogram", "Subprogram."),
+ clEnumValN(LVScopeKind::IsTemplate, "Template", "Template."),
+ clEnumValN(LVScopeKind::IsTemplateAlias, "TemplateAlias",
+ "Template alias."),
+ clEnumValN(LVScopeKind::IsTemplatePack, "TemplatePack",
+ "Template pack."),
+ clEnumValN(LVScopeKind::IsTryBlock, "TryBlock", "Exception try block."),
+ clEnumValN(LVScopeKind::IsUnion, "Union", "Union.")));
+
+// --select-symbols=<value>[,<value>,...]
+cl::list<LVSymbolKind> cmdline::SelectSymbols(
+ "select-symbols", cl::cat(SelectCategory),
+ cl::desc("Symbol kind to use when printing symbols."), cl::Hidden,
+ cl::CommaSeparated,
+ values(clEnumValN(LVSymbolKind::IsCallSiteParameter, "CallSiteParameter",
+ "Call site parameter."),
+ clEnumValN(LVSymbolKind::IsConstant, "Constant", "Constant."),
+ clEnumValN(LVSymbolKind::IsInheritance, "Inheritance",
+ "Inheritance."),
+ clEnumValN(LVSymbolKind::IsMember, "Member", "Member."),
+ clEnumValN(LVSymbolKind::IsParameter, "Parameter", "Parameter."),
+ clEnumValN(LVSymbolKind::IsUnspecified, "Unspecified",
+ "Unspecified parameter."),
+ clEnumValN(LVSymbolKind::IsVariable, "Variable", "Variable.")));
+
+// --select-types=<value>[,<value>,...]
+cl::list<LVTypeKind> cmdline::SelectTypes(
+ "select-types", cl::cat(SelectCategory),
+ cl::desc("Type kind to use when printing types."), cl::Hidden,
+ cl::CommaSeparated,
+ values(
+ clEnumValN(LVTypeKind::IsBase, "Base", "Base Type (int, bool, etc.)."),
+ clEnumValN(LVTypeKind::IsConst, "Const", "Constant specifier."),
+ clEnumValN(LVTypeKind::IsEnumerator, "Enumerator", "Enumerator."),
+ clEnumValN(LVTypeKind::IsImport, "Import", "Import."),
+ clEnumValN(LVTypeKind::IsImportDeclaration, "ImportDeclaration",
+ "Import declaration."),
+ clEnumValN(LVTypeKind::IsImportModule, "ImportModule",
+ "Import module."),
+ clEnumValN(LVTypeKind::IsPointer, "Pointer", "Pointer."),
+ clEnumValN(LVTypeKind::IsPointerMember, "PointerMember",
+ "Pointer to member."),
+ clEnumValN(LVTypeKind::IsReference, "Reference", "Reference type."),
+ clEnumValN(LVTypeKind::IsRestrict, "Restrict", "Restrict specifier."),
+ clEnumValN(LVTypeKind::IsRvalueReference, "RvalueReference",
+ "Rvalue reference."),
+ clEnumValN(LVTypeKind::IsSubrange, "Subrange", "Array subrange."),
+ clEnumValN(LVTypeKind::IsTemplateParam, "TemplateParam",
+ "Template Parameter."),
+ clEnumValN(LVTypeKind::IsTemplateTemplateParam, "TemplateTemplateParam",
+ "Template template parameter."),
+ clEnumValN(LVTypeKind::IsTemplateTypeParam, "TemplateTypeParam",
+ "Template type parameter."),
+ clEnumValN(LVTypeKind::IsTemplateValueParam, "TemplateValueParam",
+ "Template value parameter."),
+ clEnumValN(LVTypeKind::IsTypedef, "Typedef", "Type definition."),
+ clEnumValN(LVTypeKind::IsUnspecified, "Unspecified",
+ "Unspecified type."),
+ clEnumValN(LVTypeKind::IsVolatile, "Volatile", "Volatile specifier.")));
+
+//===----------------------------------------------------------------------===//
+// '--warning' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+ cmdline::WarningCategory("Warning Options",
+ "These control the generated warnings.");
+
+// --warning=<value>[,<value>,...]
+cl::list<LVWarningKind> cmdline::WarningOptions(
+ "warning", cl::cat(WarningCategory), cl::desc("Warnings to generate."),
+ cl::Hidden, cl::CommaSeparated,
+ values(
+ clEnumValN(LVWarningKind::All, "all", "All warnings."),
+ clEnumValN(LVWarningKind::Coverages, "coverages",
+ "Invalid symbol coverages values."),
+ clEnumValN(LVWarningKind::Lines, "lines", "Debug lines that are zero."),
+ clEnumValN(LVWarningKind::Locations, "locations",
+ "Invalid symbol locations."),
+ clEnumValN(LVWarningKind::Ranges, "ranges", "Invalid code ranges.")));
+
+//===----------------------------------------------------------------------===//
+// '--internal' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+ cmdline::InternalCategory("Internal Options",
+ "Internal traces and extra debugging code.");
+
+// --internal=<value>[,<value>,...]
+cl::list<LVInternalKind> cmdline::InternalOptions(
+ "internal", cl::cat(InternalCategory), cl::desc("Traces to enable."),
+ cl::Hidden, cl::CommaSeparated,
+ values(
+ clEnumValN(LVInternalKind::All, "all", "Enable all traces."),
+ clEnumValN(LVInternalKind::Cmdline, "cmdline", "Print command line."),
+ clEnumValN(LVInternalKind::ID, "id", "Print unique element ID"),
+ clEnumValN(LVInternalKind::Integrity, "integrity",
+ "Check elements integrity."),
+ clEnumValN(LVInternalKind::None, "none", "Ignore element line number."),
+ clEnumValN(LVInternalKind::Tag, "tag", "Debug information tags.")));
+
+/// @}
+
+// Copy local options into a globally accessible data structure.
+void llvm::logicalview::cmdline::propagateOptions() {
+ // Traverse list of options and update the given set (Using case and Regex).
+ auto UpdatePattern = [&](auto &List, auto &Set, bool IgnoreCase,
+ bool UseRegex) {
+ if (!List.empty())
+ for (std::string &Pattern : List)
+ Set.insert((IgnoreCase && !UseRegex) ? StringRef(Pattern).lower()
+ : Pattern);
+ };
+
+ // Handle --select.
+ UpdatePattern(SelectPatterns, ReaderOptions.Select.Generic,
+ ReaderOptions.Select.IgnoreCase, ReaderOptions.Select.UseRegex);
+
+ // Traverse list of options and update the given set.
+ auto UpdateSet = [&](auto &List, auto &Set) {
+ std::copy(List.begin(), List.end(), std::inserter(Set, Set.begin()));
+ };
+
+ // Handle options sets.
+ UpdateSet(AttributeOptions, ReaderOptions.Attribute.Kinds);
+ UpdateSet(PrintOptions, ReaderOptions.Print.Kinds);
+ UpdateSet(OutputOptions, ReaderOptions.Output.Kinds);
+ UpdateSet(ReportOptions, ReaderOptions.Report.Kinds);
+ UpdateSet(WarningOptions, ReaderOptions.Warning.Kinds);
+ UpdateSet(InternalOptions, ReaderOptions.Internal.Kinds);
+
+ UpdateSet(SelectElements, ReaderOptions.Select.Elements);
+ UpdateSet(SelectLines, ReaderOptions.Select.Lines);
+ UpdateSet(SelectScopes, ReaderOptions.Select.Scopes);
+ UpdateSet(SelectSymbols, ReaderOptions.Select.Symbols);
+ UpdateSet(SelectTypes, ReaderOptions.Select.Types);
+ UpdateSet(SelectOffsets, ReaderOptions.Select.Offsets);
+ UpdateSet(CompareElements, ReaderOptions.Compare.Elements);
+
+ // Resolve any options dependencies (ie. --print=all should set other
+ // print options, etc.).
+ ReaderOptions.resolveDependencies();
+}
diff --git a/llvm/tools/llvm-debuginfo-analyzer/Options.h b/llvm/tools/llvm-debuginfo-analyzer/Options.h
new file mode 100644
index 0000000000000..7f30141f9c7b8
--- /dev/null
+++ b/llvm/tools/llvm-debuginfo-analyzer/Options.h
@@ -0,0 +1,81 @@
+//===-- Options.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines command line options used by llvm-debuginfo-analyzer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef OPTIONS_H
+#define OPTIONS_H
+
+#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVType.h"
+#include "llvm/Support/CommandLine.h"
+
+namespace llvm {
+namespace logicalview {
+namespace cmdline {
+
+class OffsetParser final : public llvm::cl::parser<unsigned long long> {
+public:
+ OffsetParser(llvm::cl::Option &O);
+ ~OffsetParser() override;
+
+ // Parse an argument representing an offset. Return true on error.
+ // If the prefix is 0, the base is octal, if the prefix is 0x or 0X, the
+ // base is hexadecimal, otherwise the base is decimal.
+ bool parse(llvm::cl::Option &O, StringRef ArgName, StringRef ArgValue,
+ unsigned long long &Val);
+};
+
+typedef llvm::cl::list<unsigned long long, bool, OffsetParser> OffsetOptionList;
+
+extern llvm::cl::OptionCategory AttributeCategory;
+extern llvm::cl::OptionCategory CompareCategory;
+extern llvm::cl::OptionCategory OutputCategory;
+extern llvm::cl::OptionCategory PrintCategory;
+extern llvm::cl::OptionCategory ReportCategory;
+extern llvm::cl::OptionCategory SelectCategory;
+extern llvm::cl::OptionCategory WarningCategory;
+extern llvm::cl::OptionCategory InternalCategory;
+
+extern llvm::cl::list<std::string> InputFilenames;
+extern llvm::cl::opt<std::string> OutputFilename;
+
+extern llvm::cl::list<std::string> SelectPatterns;
+
+extern llvm::cl::list<LVElementKind> SelectElements;
+extern llvm::cl::list<LVLineKind> SelectLines;
+extern llvm::cl::list<LVScopeKind> SelectScopes;
+extern llvm::cl::list<LVSymbolKind> SelectSymbols;
+extern llvm::cl::list<LVTypeKind> SelectTypes;
+extern OffsetOptionList SelectOffsets;
+
+extern llvm::cl::list<LVAttributeKind> AttributeOptions;
+extern llvm::cl::list<LVOutputKind> OutputOptions;
+extern llvm::cl::list<LVPrintKind> PrintOptions;
+extern llvm::cl::list<LVWarningKind> WarningOptions;
+extern llvm::cl::list<LVInternalKind> InternalOptions;
+
+extern llvm::cl::list<LVCompareKind> CompareElements;
+extern llvm::cl::list<LVReportKind> ReportOptions;
+
+extern LVOptions ReaderOptions;
+
+// Perform any additional post parse command line actions. Propagate the
+// values captured by the command line parser, into the generic reader.
+void propagateOptions();
+
+} // namespace cmdline
+} // namespace logicalview
+} // namespace llvm
+
+#endif // OPTIONS_H
diff --git a/llvm/tools/llvm-debuginfo-analyzer/llvm-debuginfo-analyzer.cpp b/llvm/tools/llvm-debuginfo-analyzer/llvm-debuginfo-analyzer.cpp
new file mode 100644
index 0000000000000..a651b97f3d7de
--- /dev/null
+++ b/llvm/tools/llvm-debuginfo-analyzer/llvm-debuginfo-analyzer.cpp
@@ -0,0 +1,127 @@
+//===-- llvm-debuginfo-analyzer.cpp - LLVM Debug info analysis utility ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This program is a utility that displays the logical view for the debug
+// information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Options.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Support/COM.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/WithColor.h"
+
+using namespace llvm;
+using namespace logicalview;
+using namespace cmdline;
+
+/// Create formatted StringError object.
+static StringRef ToolName = "llvm-debuginfo-analyzer";
+template <typename... Ts>
+static void error(std::error_code EC, char const *Fmt, const Ts &...Vals) {
+ if (!EC)
+ return;
+ std::string Buffer;
+ raw_string_ostream Stream(Buffer);
+ Stream << format(Fmt, Vals...);
+ WithColor::error(errs(), ToolName) << Stream.str() << "\n";
+ exit(1);
+}
+
+/// If the input path is a .dSYM bundle (as created by the dsymutil tool),
+/// replace it with individual entries for each of the object files inside the
+/// bundle otherwise return the input path.
+static std::vector<std::string> expandBundle(const std::string &InputPath) {
+ std::vector<std::string> BundlePaths;
+ SmallString<256> BundlePath(InputPath);
+ // Normalize input path. This is necessary to accept `bundle.dSYM/`.
+ sys::path::remove_dots(BundlePath);
+ // Manually open up the bundle to avoid introducing additional dependencies.
+ if (sys::fs::is_directory(BundlePath) &&
+ sys::path::extension(BundlePath) == ".dSYM") {
+ std::error_code EC;
+ sys::path::append(BundlePath, "Contents", "Resources", "DWARF");
+ for (sys::fs::directory_iterator Dir(BundlePath, EC), DirEnd;
+ Dir != DirEnd && !EC; Dir.increment(EC)) {
+ const std::string &Path = Dir->path();
+ sys::fs::file_status Status;
+ EC = sys::fs::status(Path, Status);
+ error(EC, "%s", Path.c_str());
+ switch (Status.type()) {
+ case sys::fs::file_type::regular_file:
+ case sys::fs::file_type::symlink_file:
+ case sys::fs::file_type::type_unknown:
+ BundlePaths.push_back(Path);
+ break;
+ default: /*ignore*/;
+ }
+ }
+ }
+ if (BundlePaths.empty())
+ BundlePaths.push_back(InputPath);
+ return BundlePaths;
+}
+
+int main(int argc, char **argv) {
+ InitLLVM X(argc, argv);
+
+ // Initialize targets and assembly printers/parsers.
+ llvm::InitializeAllTargetInfos();
+ llvm::InitializeAllTargetMCs();
+ InitializeAllDisassemblers();
+
+ llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
+
+ cl::extrahelp HelpResponse(
+ "\nPass @FILE as argument to read options from FILE.\n");
+
+ cl::HideUnrelatedOptions(
+ {&AttributeCategory, &CompareCategory, &InternalCategory, &OutputCategory,
+ &PrintCategory, &ReportCategory, &SelectCategory, &WarningCategory});
+ cl::ParseCommandLineOptions(argc, argv,
+ "Printing a logical representation of low-level "
+ "debug information.\n");
+ cl::PrintOptionValues();
+
+ std::error_code EC;
+ ToolOutputFile OutputFile(OutputFilename, EC, sys::fs::OF_None);
+ error(EC, "Unable to open output file %s", OutputFilename.c_str());
+ // Don't remove output file if we exit with an error.
+ OutputFile.keep();
+
+ // Defaults to a.out if no filenames specified.
+ if (InputFilenames.empty())
+ InputFilenames.push_back("a.out");
+
+ // Expand any .dSYM bundles to the individual object files contained therein.
+ std::vector<std::string> Objects;
+ for (const std::string &Filename : InputFilenames) {
+ std::vector<std::string> Objs = expandBundle(Filename);
+ Objects.insert(Objects.end(), Objs.begin(), Objs.end());
+ }
+
+ propagateOptions();
+ ScopedPrinter W(OutputFile.os());
+
+ // Print the command line.
+ if (options().getInternalCmdline()) {
+ raw_ostream &Stream = W.getOStream();
+ Stream << "\nCommand line:\n";
+ for (int Index = 0; Index < argc; ++Index)
+ Stream << " " << argv[Index] << "\n";
+ Stream << "\n";
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/llvm/unittests/DebugInfo/CMakeLists.txt b/llvm/unittests/DebugInfo/CMakeLists.txt
index 4be8d76473c2e..8e28a90b45beb 100644
--- a/llvm/unittests/DebugInfo/CMakeLists.txt
+++ b/llvm/unittests/DebugInfo/CMakeLists.txt
@@ -1,6 +1,7 @@
add_subdirectory(CodeView)
add_subdirectory(DWARF)
add_subdirectory(GSYM)
+add_subdirectory(LogicalView)
add_subdirectory(MSF)
add_subdirectory(PDB)
add_subdirectory(Symbolizer)
diff --git a/llvm/unittests/DebugInfo/LogicalView/CMakeLists.txt b/llvm/unittests/DebugInfo/LogicalView/CMakeLists.txt
new file mode 100644
index 0000000000000..f376c4a397750
--- /dev/null
+++ b/llvm/unittests/DebugInfo/LogicalView/CMakeLists.txt
@@ -0,0 +1,10 @@
+set(LLVM_LINK_COMPONENTS
+ DebugInfoLogicalView
+ )
+
+add_llvm_unittest(DebugInfoLogicalViewTests
+ CommandLineOptionsTest.cpp
+ StringPoolTest.cpp
+ )
+
+target_link_libraries(DebugInfoLogicalViewTests PRIVATE LLVMTestingSupport)
diff --git a/llvm/unittests/DebugInfo/LogicalView/CommandLineOptionsTest.cpp b/llvm/unittests/DebugInfo/LogicalView/CommandLineOptionsTest.cpp
new file mode 100644
index 0000000000000..1d4b48d215cdf
--- /dev/null
+++ b/llvm/unittests/DebugInfo/LogicalView/CommandLineOptionsTest.cpp
@@ -0,0 +1,276 @@
+//===- llvm/unittest/DebugInfo/LogicalView/CommandLineOptionsTest.cpp -----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::logicalview;
+
+namespace {
+
+// '--attribute' options.
+TEST(CommandLineOptionsTest, attributeOptions) {
+ auto CheckStandardAttributes = [&](LVOptions &Options, bool Value) {
+ EXPECT_EQ(Options.getAttributeBase(), 1);
+ EXPECT_EQ(Options.getAttributeCoverage(), Value);
+ EXPECT_EQ(Options.getAttributeDirectories(), 1);
+ EXPECT_EQ(Options.getAttributeDiscriminator(), 1);
+ EXPECT_EQ(Options.getAttributeFilename(), 0);
+ EXPECT_EQ(Options.getAttributeFiles(), 1);
+ EXPECT_EQ(Options.getAttributeFormat(), 1);
+ EXPECT_EQ(Options.getAttributeLevel(), 1);
+ EXPECT_EQ(Options.getAttributeProducer(), 1);
+ EXPECT_EQ(Options.getAttributePublics(), 1);
+ EXPECT_EQ(Options.getAttributeRange(), 1);
+ EXPECT_EQ(Options.getAttributeReference(), 1);
+ EXPECT_EQ(Options.getAttributeZero(), 1);
+ };
+
+ auto CheckExtendedAttributes = [&](LVOptions &Options, bool Value) {
+ EXPECT_EQ(Options.getAttributeArgument(), 1);
+ EXPECT_EQ(Options.getAttributeDiscarded(), 1);
+ EXPECT_EQ(Options.getAttributeEncoded(), 1);
+ EXPECT_EQ(Options.getAttributeGaps(), Value);
+ EXPECT_EQ(Options.getAttributeGenerated(), 1);
+ EXPECT_EQ(Options.getAttributeGlobal(), 1);
+ EXPECT_EQ(Options.getAttributeInserted(), 1);
+ EXPECT_EQ(Options.getAttributeLinkage(), 1);
+ EXPECT_EQ(Options.getAttributeLocal(), 1);
+ EXPECT_EQ(Options.getAttributeLocation(), Value);
+ EXPECT_EQ(Options.getAttributeOffset(), 1);
+ EXPECT_EQ(Options.getAttributePathname(), 1);
+ EXPECT_EQ(Options.getAttributeQualified(), 1);
+ EXPECT_EQ(Options.getAttributeQualifier(), 1);
+ EXPECT_EQ(Options.getAttributeRegister(), Value);
+ EXPECT_EQ(Options.getAttributeSubrange(), 1);
+ EXPECT_EQ(Options.getAttributeSystem(), 1);
+ EXPECT_EQ(Options.getAttributeTypename(), 1);
+ };
+
+ // Location information is only relevant when printing symbols.
+ // It means the following attributes are dependent on --print=symbols:
+ // Coverage, gaps, location and register attributes.
+ // '--attribute=pathname' supersedes '--attribute=filename'.
+
+ // Set standard and extended attributes.
+ LVOptions OptionsOne;
+ OptionsOne.setAttributeStandard();
+ OptionsOne.setAttributeExtended();
+ OptionsOne.resolveDependencies();
+ CheckStandardAttributes(OptionsOne, false);
+ CheckExtendedAttributes(OptionsOne, false);
+
+ // Set standard and extended attributes; enable location attributes.
+ LVOptions OptionsTwo;
+ OptionsTwo.setAttributeStandard();
+ OptionsTwo.setAttributeExtended();
+ OptionsTwo.setPrintSymbols();
+ OptionsTwo.resolveDependencies();
+ CheckStandardAttributes(OptionsTwo, true);
+ CheckExtendedAttributes(OptionsTwo, true);
+
+ // Set all attributes.
+ LVOptions OptionsThree;
+ OptionsThree.setAttributeAll();
+ OptionsThree.resolveDependencies();
+ EXPECT_EQ(OptionsThree.getAttributeExtended(), 1);
+ EXPECT_EQ(OptionsThree.getAttributeStandard(), 1);
+
+ // Set filename attribute.
+ LVOptions OptionsFour;
+ OptionsFour.setAttributeFilename();
+ OptionsFour.resolveDependencies();
+ EXPECT_EQ(OptionsFour.getAttributeFilename(), 1);
+ EXPECT_EQ(OptionsFour.getAttributePathname(), 0);
+
+ // Set pathname attribute.
+ OptionsFour.setAttributePathname();
+ OptionsFour.resolveDependencies();
+ EXPECT_EQ(OptionsFour.getAttributeFilename(), 0);
+ EXPECT_EQ(OptionsFour.getAttributePathname(), 1);
+
+ // The location attribute depends on: coverage, gaps or register.
+ LVOptions OptionsFive;
+ OptionsFive.setPrintSymbols();
+ OptionsFive.resetAttributeLocation();
+ OptionsFive.resolveDependencies();
+ EXPECT_EQ(OptionsFive.getAttributeLocation(), 0);
+
+ OptionsFive.resetAttributeLocation();
+ OptionsFive.setAttributeCoverage();
+ OptionsFive.resolveDependencies();
+ EXPECT_EQ(OptionsFive.getAttributeLocation(), 1);
+
+ OptionsFive.resetAttributeLocation();
+ OptionsFive.setAttributeGaps();
+ OptionsFive.resolveDependencies();
+ EXPECT_EQ(OptionsFive.getAttributeLocation(), 1);
+
+ OptionsFive.resetAttributeLocation();
+ OptionsFive.setAttributeRegister();
+ OptionsFive.resolveDependencies();
+ EXPECT_EQ(OptionsFive.getAttributeLocation(), 1);
+}
+
+// '--compare' options.
+TEST(CommandLineOptionsTest, compareOptions) {
+ LVOptions OptionsOne;
+ OptionsOne.setCompareAll();
+ OptionsOne.resolveDependencies();
+ EXPECT_EQ(OptionsOne.getCompareLines(), 1);
+ EXPECT_EQ(OptionsOne.getCompareScopes(), 1);
+ EXPECT_EQ(OptionsOne.getCompareSymbols(), 1);
+ EXPECT_EQ(OptionsOne.getCompareTypes(), 1);
+
+ // The compare scopes attribute depends on: symbols, types or lines.
+ LVOptions OptionsTwo;
+ OptionsTwo.resetCompareScopes();
+ OptionsTwo.resolveDependencies();
+ EXPECT_EQ(OptionsTwo.getCompareScopes(), 0);
+
+ OptionsTwo.resetCompareScopes();
+ OptionsTwo.setCompareLines();
+ OptionsTwo.resolveDependencies();
+ EXPECT_EQ(OptionsTwo.getCompareScopes(), 1);
+
+ OptionsTwo.resetCompareScopes();
+ OptionsTwo.setCompareSymbols();
+ OptionsTwo.resolveDependencies();
+ EXPECT_EQ(OptionsTwo.getCompareScopes(), 1);
+
+ OptionsTwo.resetCompareScopes();
+ OptionsTwo.setCompareTypes();
+ OptionsTwo.resolveDependencies();
+ EXPECT_EQ(OptionsTwo.getCompareScopes(), 1);
+
+ // The compare option, set/reset other attributes.
+ LVOptions OptionsThree;
+ OptionsThree.setCompareAll();
+ OptionsThree.resolveDependencies();
+ EXPECT_EQ(OptionsThree.getAttributeArgument(), 1);
+ EXPECT_EQ(OptionsThree.getAttributeEncoded(), 1);
+ EXPECT_EQ(OptionsThree.getAttributeInserted(), 1);
+ EXPECT_EQ(OptionsThree.getAttributeMissing(), 1);
+ EXPECT_EQ(OptionsThree.getAttributeQualified(), 1);
+}
+
+// '--internal' options.
+TEST(CommandLineOptionsTest, internalOptions) {
+ LVOptions OptionsOne;
+ OptionsOne.setInternalAll();
+ OptionsOne.resolveDependencies();
+ EXPECT_EQ(OptionsOne.getInternalCmdline(), 1);
+ EXPECT_EQ(OptionsOne.getInternalID(), 1);
+ EXPECT_EQ(OptionsOne.getInternalIntegrity(), 1);
+ EXPECT_EQ(OptionsOne.getInternalNone(), 1);
+ EXPECT_EQ(OptionsOne.getInternalTag(), 1);
+}
+
+// '--output' options.
+TEST(CommandLineOptionsTest, outputOptions) {
+ LVOptions OptionsOne;
+ OptionsOne.setOutputAll();
+ OptionsOne.resolveDependencies();
+ EXPECT_EQ(OptionsOne.getOutputJson(), 1);
+ EXPECT_EQ(OptionsOne.getOutputSplit(), 1);
+ EXPECT_EQ(OptionsOne.getOutputText(), 1);
+
+ // The pathname attribute is set with split output.
+ LVOptions OptionsTwo;
+ OptionsTwo.resetAttributePathname();
+ OptionsTwo.setOutputSplit();
+ OptionsTwo.resolveDependencies();
+ EXPECT_EQ(OptionsTwo.getAttributePathname(), 1);
+
+ // Setting an output folder, it sets split option.
+ LVOptions OptionsThree;
+ OptionsThree.resolveDependencies();
+ EXPECT_EQ(OptionsThree.getOutputSplit(), 0);
+
+ OptionsThree.setOutputFolder("folder-name");
+ OptionsThree.resolveDependencies();
+ EXPECT_EQ(OptionsThree.getOutputSplit(), 1);
+ EXPECT_STREQ(OptionsThree.getOutputFolder().c_str(), "folder-name");
+
+ // Assume '--output=text' as default.
+ LVOptions OptionsFour;
+ OptionsFour.resolveDependencies();
+ EXPECT_EQ(OptionsFour.getOutputText(), 1);
+}
+
+// '--print' options.
+TEST(CommandLineOptionsTest, printOptions) {
+ LVOptions OptionsOne;
+ OptionsOne.setPrintAll();
+ OptionsOne.resolveDependencies();
+ EXPECT_EQ(OptionsOne.getPrintInstructions(), 1);
+ EXPECT_EQ(OptionsOne.getPrintLines(), 1);
+ EXPECT_EQ(OptionsOne.getPrintScopes(), 1);
+ EXPECT_EQ(OptionsOne.getPrintSizes(), 1);
+ EXPECT_EQ(OptionsOne.getPrintSymbols(), 1);
+ EXPECT_EQ(OptionsOne.getPrintSummary(), 1);
+ EXPECT_EQ(OptionsOne.getPrintTypes(), 1);
+ EXPECT_EQ(OptionsOne.getPrintWarnings(), 1);
+
+ // '--print=elements' is a shortcut for:
+ // '--print=instructions,lines,scopes,symbols,types'.
+ LVOptions OptionsTwo;
+ OptionsTwo.setPrintElements();
+ OptionsTwo.resolveDependencies();
+ EXPECT_EQ(OptionsTwo.getPrintInstructions(), 1);
+ EXPECT_EQ(OptionsTwo.getPrintLines(), 1);
+ EXPECT_EQ(OptionsTwo.getPrintScopes(), 1);
+ EXPECT_EQ(OptionsTwo.getPrintSizes(), 0);
+ EXPECT_EQ(OptionsTwo.getPrintSymbols(), 1);
+ EXPECT_EQ(OptionsTwo.getPrintSummary(), 0);
+ EXPECT_EQ(OptionsTwo.getPrintTypes(), 1);
+ EXPECT_EQ(OptionsTwo.getPrintWarnings(), 0);
+}
+
+// '--report' options.
+TEST(CommandLineOptionsTest, reportOptions) {
+ LVOptions OptionsOne;
+ OptionsOne.setReportAll();
+ OptionsOne.resolveDependencies();
+ EXPECT_EQ(OptionsOne.getReportChildren(), 1);
+ EXPECT_EQ(OptionsOne.getReportList(), 1);
+ EXPECT_EQ(OptionsOne.getReportParents(), 1);
+ EXPECT_EQ(OptionsOne.getReportView(), 1);
+
+ // '--report=view' is a shortcut for '--report=parents,children'.
+ LVOptions OptionsTwo;
+ OptionsTwo.setReportView();
+ OptionsTwo.resolveDependencies();
+ EXPECT_EQ(OptionsTwo.getReportChildren(), 1);
+ EXPECT_EQ(OptionsTwo.getReportParents(), 1);
+}
+
+// '--select' options.
+TEST(CommandLineOptionsTest, selectOptions) {
+ LVOptions OptionsOne;
+ OptionsOne.setSelectIgnoreCase();
+ OptionsOne.setSelectUseRegex();
+ OptionsOne.resolveDependencies();
+ EXPECT_EQ(OptionsOne.getSelectIgnoreCase(), 1);
+ EXPECT_EQ(OptionsOne.getSelectUseRegex(), 1);
+}
+
+// '--warning' options.
+TEST(CommandLineOptionsTest, warningOptions) {
+ LVOptions OptionsOne;
+ OptionsOne.setWarningAll();
+ OptionsOne.resolveDependencies();
+ EXPECT_EQ(OptionsOne.getWarningCoverages(), 1);
+ EXPECT_EQ(OptionsOne.getWarningLines(), 1);
+ EXPECT_EQ(OptionsOne.getWarningLocations(), 1);
+ EXPECT_EQ(OptionsOne.getWarningRanges(), 1);
+}
+
+} // namespace
diff --git a/llvm/unittests/DebugInfo/LogicalView/StringPoolTest.cpp b/llvm/unittests/DebugInfo/LogicalView/StringPoolTest.cpp
new file mode 100644
index 0000000000000..27ff449c98e64
--- /dev/null
+++ b/llvm/unittests/DebugInfo/LogicalView/StringPoolTest.cpp
@@ -0,0 +1,60 @@
+//===- llvm/unittest/DebugInfo/LogicalView/StringPoolTest.cpp -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/LogicalView/Core/LVStringPool.h"
+#include <vector>
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::logicalview;
+
+namespace {
+
+TEST(StringPoolTest, AddStrings) {
+ LVStringPool PoolInstance;
+ EXPECT_EQ(0u, PoolInstance.getSize());
+
+ // Get indexes for the initial strings.
+ EXPECT_EQ(1u, PoolInstance.getIndex("one"));
+ EXPECT_EQ(2u, PoolInstance.getIndex("two"));
+ EXPECT_EQ(3u, PoolInstance.getIndex("three"));
+ EXPECT_EQ(4u, PoolInstance.getIndex("four"));
+ EXPECT_EQ(5u, PoolInstance.getIndex("five"));
+ EXPECT_EQ(5u, PoolInstance.getSize());
+
+ // Verify the string returned by the given index.
+ EXPECT_EQ("one", PoolInstance.getString(1));
+ EXPECT_EQ("two", PoolInstance.getString(2));
+ EXPECT_EQ("three", PoolInstance.getString(3));
+ EXPECT_EQ("four", PoolInstance.getString(4));
+ EXPECT_EQ("five", PoolInstance.getString(5));
+ EXPECT_EQ(5u, PoolInstance.getSize());
+
+ // Get indexes for the same initial strings.
+ EXPECT_EQ(5u, PoolInstance.getIndex("five"));
+ EXPECT_EQ(4u, PoolInstance.getIndex("four"));
+ EXPECT_EQ(3u, PoolInstance.getIndex("three"));
+ EXPECT_EQ(2u, PoolInstance.getIndex("two"));
+ EXPECT_EQ(1u, PoolInstance.getIndex("one"));
+ EXPECT_EQ(5u, PoolInstance.getSize());
+
+ // Empty string gets the index zero.
+ EXPECT_EQ(0u, PoolInstance.getIndex(""));
+ EXPECT_EQ(5u, PoolInstance.getSize());
+
+ // Empty string for invalid index.
+ EXPECT_EQ("", PoolInstance.getString(620));
+
+ // Lookup for strings
+ EXPECT_EQ(5u, PoolInstance.findIndex("five"));
+ EXPECT_TRUE(PoolInstance.isValidIndex(PoolInstance.findIndex("five")));
+ EXPECT_FALSE(PoolInstance.isValidIndex(PoolInstance.findIndex("FIVE")));
+}
+
+} // namespace
More information about the llvm-commits
mailing list