[llvm] fe7a3ce - [llvm-debuginfo-analyzer] (02/09) - Driver and documentation

Carlos Alberto Enciso via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 17 05:49:53 PDT 2022


Author: Carlos Alberto Enciso
Date: 2022-10-17T13:46:55+01:00
New Revision: fe7a3cedf77125a6309150d85cecbc20b1a31775

URL: https://github.com/llvm/llvm-project/commit/fe7a3cedf77125a6309150d85cecbc20b1a31775
DIFF: https://github.com/llvm/llvm-project/commit/fe7a3cedf77125a6309150d85cecbc20b1a31775.diff

LOG: [llvm-debuginfo-analyzer] (02/09) - Driver and documentation

llvm-debuginfo-analyzer is a command line tool that processes debug
info contained in a binary file and produces a debug information
format agnostic “Logical View”, which is a high-level semantic
representation of the debug info, independent of the low-level
format.

The code has been divided into the following patches:

1) Interval tree
2) Driver and documentation
3) Logical elements
4) Locations and ranges
5) Select elements
6) Warning and internal options
7) Compare elements
8) ELF Reader
9) CodeView Reader

Full details:
https://discourse.llvm.org/t/llvm-dev-rfc-llvm-dva-debug-information-visual-analyzer/62570

This patch:

Driver and documentation
- Command line options.
- Full documentation.
- String Pool table.

Reviewed By: psamolysov, probinson

Differential Revision: https://reviews.llvm.org/D125777

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..fcb15fc787523
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h
@@ -0,0 +1,52 @@
+//===-- 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:
+  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..7b3f0002ce35e
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
@@ -0,0 +1,57 @@
+//===-- 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:
+  // 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..478c4b3931c34
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVStringPool.h
@@ -0,0 +1,99 @@
+//===-- 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 {
+    assert(Index < Entries.size() && "Invalid string pool index.");
+    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