//===-- 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(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 cmdline::InputFilenames(cl::desc(""), 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=[,,...] cl::list 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 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=[,,...] cl::list 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= cl::opt 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= static cl::opt 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= static cl::opt 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=[,,...] cl::list 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 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=[,,...] cl::list 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=[,,...] cl::list 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 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 SelectUseRegex( "select-regex", cl::cat(SelectCategory), cl::desc("Treat any 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= cl::list cmdline::SelectPatterns( "select", cl::cat(SelectCategory), cl::desc("Search elements matching the given pattern."), cl::Hidden, cl::value_desc("pattern"), cl::CommaSeparated); // --select-offsets=[,,...] 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=[,,...] cl::list 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=[,,...] cl::list 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=[,,...] cl::list 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=[,,...] cl::list 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=[,,...] cl::list 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=[,,...] cl::list 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=[,,...] cl::list 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(); }