aboutsummaryrefslogtreecommitdiff
path: root/lldb
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-01-17 20:45:01 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-01-17 20:45:01 +0000
commit706b4fc47bbc608932d3b491ae19a3b9cde9497b (patch)
tree4adf86a776049cbf7f69a1929c4babcbbef925eb /lldb
parent7cc9cf2bf09f069cb2dd947ead05d0b54301fb71 (diff)
downloadsrc-706b4fc47bbc608932d3b491ae19a3b9cde9497b.tar.gz
src-706b4fc47bbc608932d3b491ae19a3b9cde9497b.zip
Vendor import of llvm-project master e26a78e70, the last commit beforevendor/llvm-project/llvmorg-10-init-17466-ge26a78e7085
the llvmorg-11-init tag, from which release/10.x was branched.
Notes
Notes: svn path=/vendor/llvm-project/master/; revision=356843 svn path=/vendor/llvm-project/llvmorg-10-init-17466-ge26a78e7085/; revision=356844; tag=vendor/llvm-project/llvmorg-10-init-17466-ge26a78e7085
Diffstat (limited to 'lldb')
-rw-r--r--lldb/docs/lldb.1154
-rw-r--r--lldb/docs/man/lldb.rst323
-rw-r--r--lldb/include/lldb/API/SBBreakpoint.h3
-rw-r--r--lldb/include/lldb/API/SBBreakpointLocation.h7
-rw-r--r--lldb/include/lldb/API/SBBreakpointName.h7
-rw-r--r--lldb/include/lldb/API/SBReproducer.h3
-rw-r--r--lldb/include/lldb/API/SBStructuredData.h3
-rw-r--r--lldb/include/lldb/API/SBValue.h2
-rw-r--r--lldb/include/lldb/Breakpoint/Breakpoint.h20
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointID.h2
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointList.h8
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointLocation.h5
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h12
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointLocationList.h12
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointOptions.h30
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointResolver.h5
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointSite.h11
-rw-r--r--lldb/include/lldb/Breakpoint/Watchpoint.h5
-rw-r--r--lldb/include/lldb/Breakpoint/WatchpointList.h2
-rw-r--r--lldb/include/lldb/Breakpoint/WatchpointOptions.h3
-rw-r--r--lldb/include/lldb/Core/Address.h84
-rw-r--r--lldb/include/lldb/Core/AddressRange.h5
-rw-r--r--lldb/include/lldb/Core/ClangForward.h1
-rw-r--r--lldb/include/lldb/Core/Debugger.h7
-rw-r--r--lldb/include/lldb/Core/Disassembler.h7
-rw-r--r--lldb/include/lldb/Core/FormatEntity.h1
-rw-r--r--lldb/include/lldb/Core/Highlighter.h3
-rw-r--r--lldb/include/lldb/Core/IOHandler.h49
-rw-r--r--lldb/include/lldb/Core/IOHandlerCursesGUI.h40
-rw-r--r--lldb/include/lldb/Core/Mangled.h15
-rw-r--r--lldb/include/lldb/Core/Module.h19
-rw-r--r--lldb/include/lldb/Core/ModuleChild.h11
-rw-r--r--lldb/include/lldb/Core/ModuleList.h59
-rw-r--r--lldb/include/lldb/Core/ModuleSpec.h28
-rw-r--r--lldb/include/lldb/Core/PropertiesBase.td2
-rw-r--r--lldb/include/lldb/Core/STLUtils.h74
-rw-r--r--lldb/include/lldb/Core/SearchFilter.h23
-rw-r--r--lldb/include/lldb/Core/SourceManager.h2
-rw-r--r--lldb/include/lldb/Core/StreamFile.h6
-rw-r--r--lldb/include/lldb/Core/ThreadSafeDenseMap.h2
-rw-r--r--lldb/include/lldb/Core/ThreadSafeSTLMap.h128
-rw-r--r--lldb/include/lldb/Core/ThreadSafeSTLVector.h72
-rw-r--r--lldb/include/lldb/Core/ValueObject.h18
-rw-r--r--lldb/include/lldb/Core/ValueObjectSyntheticFilter.h15
-rw-r--r--lldb/include/lldb/DataFormatters/DataVisualization.h6
-rw-r--r--lldb/include/lldb/DataFormatters/FormatCache.h57
-rw-r--r--lldb/include/lldb/DataFormatters/FormatClasses.h2
-rw-r--r--lldb/include/lldb/DataFormatters/FormatManager.h34
-rw-r--r--lldb/include/lldb/DataFormatters/FormattersContainer.h1
-rw-r--r--lldb/include/lldb/DataFormatters/LanguageCategory.h28
-rw-r--r--lldb/include/lldb/DataFormatters/TypeCategory.h68
-rw-r--r--lldb/include/lldb/DataFormatters/TypeCategoryMap.h9
-rw-r--r--lldb/include/lldb/DataFormatters/TypeValidator.h201
-rw-r--r--lldb/include/lldb/DataFormatters/ValueObjectPrinter.h7
-rw-r--r--lldb/include/lldb/Expression/DWARFExpression.h76
-rw-r--r--lldb/include/lldb/Expression/Expression.h28
-rw-r--r--lldb/include/lldb/Expression/ExpressionParser.h13
-rw-r--r--lldb/include/lldb/Expression/ExpressionSourceCode.h1
-rw-r--r--lldb/include/lldb/Expression/ExpressionVariable.h4
-rw-r--r--lldb/include/lldb/Expression/FunctionCaller.h25
-rw-r--r--lldb/include/lldb/Expression/IRExecutionUnit.h25
-rw-r--r--lldb/include/lldb/Expression/LLVMUserExpression.h14
-rw-r--r--lldb/include/lldb/Expression/REPL.h2
-rw-r--r--lldb/include/lldb/Expression/UserExpression.h28
-rw-r--r--lldb/include/lldb/Expression/UtilityFunction.h21
-rw-r--r--lldb/include/lldb/Host/Config.h.cmake23
-rw-r--r--lldb/include/lldb/Host/Editline.h17
-rw-r--r--lldb/include/lldb/Host/File.h6
-rw-r--r--lldb/include/lldb/Host/HostInfoBase.h11
-rw-r--r--lldb/include/lldb/Host/HostProcess.h1
-rw-r--r--lldb/include/lldb/Host/PseudoTerminal.h20
-rw-r--r--lldb/include/lldb/Host/SocketAddress.h2
-rw-r--r--lldb/include/lldb/Host/Terminal.h2
-rw-r--r--lldb/include/lldb/Host/XML.h6
-rw-r--r--lldb/include/lldb/Interpreter/CommandInterpreter.h13
-rw-r--r--lldb/include/lldb/Interpreter/CommandObject.h8
-rw-r--r--lldb/include/lldb/Interpreter/CommandReturnObject.h1
-rw-r--r--lldb/include/lldb/Interpreter/OptionGroupPythonClassWithDict.h20
-rw-r--r--lldb/include/lldb/Interpreter/OptionValue.h20
-rw-r--r--lldb/include/lldb/Interpreter/OptionValueProperties.h3
-rw-r--r--lldb/include/lldb/Interpreter/Options.h4
-rw-r--r--lldb/include/lldb/Interpreter/Property.h3
-rw-r--r--lldb/include/lldb/Interpreter/ScriptInterpreter.h37
-rw-r--r--lldb/include/lldb/Symbol/Block.h26
-rw-r--r--lldb/include/lldb/Symbol/ClangASTContext.h303
-rw-r--r--lldb/include/lldb/Symbol/ClangASTImporter.h109
-rw-r--r--lldb/include/lldb/Symbol/ClangASTMetadata.h (renamed from lldb/include/lldb/Symbol/ClangExternalASTSourceCommon.h)51
-rw-r--r--lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h108
-rw-r--r--lldb/include/lldb/Symbol/ClangUtil.h10
-rw-r--r--lldb/include/lldb/Symbol/CompileUnit.h53
-rw-r--r--lldb/include/lldb/Symbol/CompilerDecl.h24
-rw-r--r--lldb/include/lldb/Symbol/CompilerDeclContext.h32
-rw-r--r--lldb/include/lldb/Symbol/CompilerType.h53
-rw-r--r--lldb/include/lldb/Symbol/DebugMacros.h8
-rw-r--r--lldb/include/lldb/Symbol/Declaration.h16
-rw-r--r--lldb/include/lldb/Symbol/Function.h106
-rw-r--r--lldb/include/lldb/Symbol/LineEntry.h17
-rw-r--r--lldb/include/lldb/Symbol/LineTable.h14
-rw-r--r--lldb/include/lldb/Symbol/ObjectFile.h17
-rw-r--r--lldb/include/lldb/Symbol/Symbol.h4
-rw-r--r--lldb/include/lldb/Symbol/SymbolContext.h31
-rw-r--r--lldb/include/lldb/Symbol/SymbolFile.h55
-rw-r--r--lldb/include/lldb/Symbol/Symtab.h32
-rw-r--r--lldb/include/lldb/Symbol/Type.h42
-rw-r--r--lldb/include/lldb/Symbol/TypeSystem.h68
-rw-r--r--lldb/include/lldb/Symbol/VariableList.h10
-rw-r--r--lldb/include/lldb/Target/ABI.h11
-rw-r--r--lldb/include/lldb/Target/Language.h3
-rw-r--r--lldb/include/lldb/Target/MemoryRegionInfo.h48
-rw-r--r--lldb/include/lldb/Target/Platform.h7
-rw-r--r--lldb/include/lldb/Target/Process.h35
-rw-r--r--lldb/include/lldb/Target/Queue.h5
-rw-r--r--lldb/include/lldb/Target/StackFrame.h14
-rw-r--r--lldb/include/lldb/Target/Target.h37
-rw-r--r--lldb/include/lldb/Target/TargetList.h6
-rw-r--r--lldb/include/lldb/Target/Thread.h16
-rw-r--r--lldb/include/lldb/Target/ThreadPlanStepOut.h1
-rw-r--r--lldb/include/lldb/Target/ThreadPlanStepRange.h6
-rw-r--r--lldb/include/lldb/Utility/ArchSpec.h11
-rw-r--r--lldb/include/lldb/Utility/Args.h29
-rw-r--r--lldb/include/lldb/Utility/Baton.h13
-rw-r--r--lldb/include/lldb/Utility/Broadcaster.h1
-rw-r--r--lldb/include/lldb/Utility/Connection.h2
-rw-r--r--lldb/include/lldb/Utility/ConstString.h20
-rw-r--r--lldb/include/lldb/Utility/DataEncoder.h169
-rw-r--r--lldb/include/lldb/Utility/DataExtractor.h7
-rw-r--r--lldb/include/lldb/Utility/FileSpec.h31
-rw-r--r--lldb/include/lldb/Utility/Flags.h11
-rw-r--r--lldb/include/lldb/Utility/GDBRemote.h43
-rw-r--r--lldb/include/lldb/Utility/Log.h2
-rw-r--r--lldb/include/lldb/Utility/RangeMap.h35
-rw-r--r--lldb/include/lldb/Utility/Reproducer.h107
-rw-r--r--lldb/include/lldb/Utility/Scalar.h1
-rw-r--r--lldb/include/lldb/Utility/Status.h2
-rw-r--r--lldb/include/lldb/Utility/Stream.h188
-rw-r--r--lldb/include/lldb/Utility/StringExtractorGDBRemote.h5
-rw-r--r--lldb/include/lldb/Utility/VMRange.h7
-rw-r--r--lldb/include/lldb/lldb-enumerations.h10
-rw-r--r--lldb/include/lldb/lldb-forward.h2
-rw-r--r--lldb/include/lldb/lldb-private-interfaces.h2
-rw-r--r--lldb/source/API/SBBreakpoint.cpp34
-rw-r--r--lldb/source/API/SBBreakpointLocation.cpp31
-rw-r--r--lldb/source/API/SBBreakpointName.cpp37
-rw-r--r--lldb/source/API/SBCompileUnit.cpp4
-rw-r--r--lldb/source/API/SBDebugger.cpp54
-rw-r--r--lldb/source/API/SBEvent.cpp2
-rw-r--r--lldb/source/API/SBFile.cpp11
-rw-r--r--lldb/source/API/SBFileSpec.cpp2
-rw-r--r--lldb/source/API/SBFrame.cpp4
-rw-r--r--lldb/source/API/SBHostOS.cpp7
-rw-r--r--lldb/source/API/SBModule.cpp18
-rw-r--r--lldb/source/API/SBReproducer.cpp40
-rw-r--r--lldb/source/API/SBTarget.cpp35
-rw-r--r--lldb/source/API/SBThread.cpp9
-rw-r--r--lldb/source/API/SBType.cpp6
-rw-r--r--lldb/source/API/SBValue.cpp20
-rw-r--r--lldb/source/API/SystemInitializerFull.cpp18
-rw-r--r--lldb/source/Breakpoint/Breakpoint.cpp3
-rw-r--r--lldb/source/Breakpoint/BreakpointList.cpp18
-rw-r--r--lldb/source/Breakpoint/BreakpointLocation.cpp4
-rw-r--r--lldb/source/Breakpoint/BreakpointOptions.cpp37
-rw-r--r--lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp2
-rw-r--r--lldb/source/Breakpoint/WatchpointOptions.cpp28
-rw-r--r--lldb/source/Commands/CommandCompletions.cpp21
-rw-r--r--lldb/source/Commands/CommandObjectApropos.cpp1
-rw-r--r--lldb/source/Commands/CommandObjectBreakpoint.cpp307
-rw-r--r--lldb/source/Commands/CommandObjectBreakpoint.h29
-rw-r--r--lldb/source/Commands/CommandObjectBreakpointCommand.cpp105
-rw-r--r--lldb/source/Commands/CommandObjectBreakpointCommand.h6
-rw-r--r--lldb/source/Commands/CommandObjectCommands.cpp53
-rw-r--r--lldb/source/Commands/CommandObjectCommands.h2
-rw-r--r--lldb/source/Commands/CommandObjectDisassemble.cpp8
-rw-r--r--lldb/source/Commands/CommandObjectExpression.cpp116
-rw-r--r--lldb/source/Commands/CommandObjectExpression.h1
-rw-r--r--lldb/source/Commands/CommandObjectFrame.cpp114
-rw-r--r--lldb/source/Commands/CommandObjectFrame.h1
-rw-r--r--lldb/source/Commands/CommandObjectGUI.cpp5
-rw-r--r--lldb/source/Commands/CommandObjectHelp.cpp16
-rw-r--r--lldb/source/Commands/CommandObjectLanguage.cpp4
-rw-r--r--lldb/source/Commands/CommandObjectLanguage.h3
-rw-r--r--lldb/source/Commands/CommandObjectLog.cpp10
-rw-r--r--lldb/source/Commands/CommandObjectLog.h2
-rw-r--r--lldb/source/Commands/CommandObjectMemory.cpp36
-rw-r--r--lldb/source/Commands/CommandObjectMultiword.cpp1
-rw-r--r--lldb/source/Commands/CommandObjectPlatform.cpp7
-rw-r--r--lldb/source/Commands/CommandObjectPlatform.h1
-rw-r--r--lldb/source/Commands/CommandObjectPlugin.cpp1
-rw-r--r--lldb/source/Commands/CommandObjectPlugin.h3
-rw-r--r--lldb/source/Commands/CommandObjectProcess.cpp11
-rw-r--r--lldb/source/Commands/CommandObjectRegister.cpp2
-rw-r--r--lldb/source/Commands/CommandObjectReproducer.cpp178
-rw-r--r--lldb/source/Commands/CommandObjectReproducer.h1
-rw-r--r--lldb/source/Commands/CommandObjectSettings.cpp31
-rw-r--r--lldb/source/Commands/CommandObjectSettings.h2
-rw-r--r--lldb/source/Commands/CommandObjectSource.cpp82
-rw-r--r--lldb/source/Commands/CommandObjectSource.h2
-rw-r--r--lldb/source/Commands/CommandObjectStats.cpp5
-rw-r--r--lldb/source/Commands/CommandObjectStats.h1
-rw-r--r--lldb/source/Commands/CommandObjectTarget.cpp465
-rw-r--r--lldb/source/Commands/CommandObjectTarget.h1
-rw-r--r--lldb/source/Commands/CommandObjectThread.cpp81
-rw-r--r--lldb/source/Commands/CommandObjectType.cpp69
-rw-r--r--lldb/source/Commands/CommandObjectType.h4
-rw-r--r--lldb/source/Commands/CommandObjectVersion.cpp1
-rw-r--r--lldb/source/Commands/CommandObjectWatchpoint.cpp85
-rw-r--r--lldb/source/Commands/CommandObjectWatchpoint.h2
-rw-r--r--lldb/source/Commands/CommandObjectWatchpointCommand.cpp51
-rw-r--r--lldb/source/Commands/CommandObjectWatchpointCommand.h4
-rw-r--r--lldb/source/Commands/Options.td22
-rw-r--r--lldb/source/Core/Address.cpp25
-rw-r--r--lldb/source/Core/AddressRange.cpp6
-rw-r--r--lldb/source/Core/AddressResolverFileLine.cpp7
-rw-r--r--lldb/source/Core/Debugger.cpp22
-rw-r--r--lldb/source/Core/Disassembler.cpp11
-rw-r--r--lldb/source/Core/DumpDataExtractor.cpp7
-rw-r--r--lldb/source/Core/FileLineResolver.cpp4
-rw-r--r--lldb/source/Core/FileSpecList.cpp2
-rw-r--r--lldb/source/Core/FormatEntity.cpp50
-rw-r--r--lldb/source/Core/IOHandler.cpp4051
-rw-r--r--lldb/source/Core/IOHandlerCursesGUI.cpp4067
-rw-r--r--lldb/source/Core/Mangled.cpp38
-rw-r--r--lldb/source/Core/Module.cpp54
-rw-r--r--lldb/source/Core/ModuleList.cpp7
-rw-r--r--lldb/source/Core/PluginManager.cpp2
-rw-r--r--lldb/source/Core/SearchFilter.cpp374
-rw-r--r--lldb/source/Core/Section.cpp31
-rw-r--r--lldb/source/Core/SourceManager.cpp18
-rw-r--r--lldb/source/Core/StreamFile.cpp17
-rw-r--r--lldb/source/Core/Value.cpp15
-rw-r--r--lldb/source/Core/ValueObject.cpp121
-rw-r--r--lldb/source/Core/ValueObjectSyntheticFilter.cpp49
-rw-r--r--lldb/source/Core/ValueObjectVariable.cpp45
-rw-r--r--lldb/source/DataFormatters/DataVisualization.cpp14
-rw-r--r--lldb/source/DataFormatters/FormatCache.cpp166
-rw-r--r--lldb/source/DataFormatters/FormatClasses.cpp3
-rw-r--r--lldb/source/DataFormatters/FormatManager.cpp357
-rw-r--r--lldb/source/DataFormatters/LanguageCategory.cpp188
-rw-r--r--lldb/source/DataFormatters/TypeCategory.cpp123
-rw-r--r--lldb/source/DataFormatters/TypeCategoryMap.cpp155
-rw-r--r--lldb/source/DataFormatters/TypeValidator.cpp53
-rw-r--r--lldb/source/DataFormatters/ValueObjectPrinter.cpp38
-rw-r--r--lldb/source/Expression/DWARFExpression.cpp423
-rw-r--r--lldb/source/Expression/Expression.cpp10
-rw-r--r--lldb/source/Expression/FunctionCaller.cpp6
-rw-r--r--lldb/source/Expression/IRExecutionUnit.cpp69
-rw-r--r--lldb/source/Expression/IRInterpreter.cpp166
-rw-r--r--lldb/source/Expression/IRMemoryMap.cpp12
-rw-r--r--lldb/source/Expression/LLVMUserExpression.cpp298
-rw-r--r--lldb/source/Expression/REPL.cpp2
-rw-r--r--lldb/source/Expression/UserExpression.cpp19
-rw-r--r--lldb/source/Expression/UtilityFunction.cpp11
-rw-r--r--lldb/source/Host/common/Editline.cpp109
-rw-r--r--lldb/source/Host/common/File.cpp2
-rw-r--r--lldb/source/Host/common/Host.cpp19
-rw-r--r--lldb/source/Host/common/HostInfoBase.cpp95
-rw-r--r--lldb/source/Host/common/MainLoop.cpp1
-rw-r--r--lldb/source/Host/common/NativeProcessProtocol.cpp4
-rw-r--r--lldb/source/Host/common/PseudoTerminal.cpp4
-rw-r--r--lldb/source/Host/common/Socket.cpp4
-rw-r--r--lldb/source/Host/common/SocketAddress.cpp6
-rw-r--r--lldb/source/Host/common/TCPSocket.cpp12
-rw-r--r--lldb/source/Host/common/Terminal.cpp32
-rw-r--r--lldb/source/Host/common/UDPSocket.cpp2
-rw-r--r--lldb/source/Host/common/XML.cpp59
-rw-r--r--lldb/source/Host/netbsd/Host.cpp1
-rw-r--r--lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp4
-rw-r--r--lldb/source/Host/posix/FileSystemPosix.cpp (renamed from lldb/source/Host/posix/FileSystem.cpp)0
-rw-r--r--lldb/source/Host/posix/PipePosix.cpp9
-rw-r--r--lldb/source/Interpreter/CommandInterpreter.cpp52
-rw-r--r--lldb/source/Interpreter/CommandObjectScript.cpp19
-rw-r--r--lldb/source/Interpreter/OptionArgParser.cpp2
-rw-r--r--lldb/source/Interpreter/OptionGroupPythonClassWithDict.cpp62
-rw-r--r--lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp2
-rw-r--r--lldb/source/Interpreter/OptionValueFileSpecList.cpp2
-rw-r--r--lldb/source/Interpreter/OptionValueProperties.cpp4
-rw-r--r--lldb/source/Interpreter/Property.cpp5
-rw-r--r--lldb/source/Interpreter/ScriptInterpreter.cpp43
-rw-r--r--lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp2
-rw-r--r--lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp12
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp104
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h40
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp20
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h9
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp6
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h2
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp403
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h118
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp14
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h15
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp1494
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h188
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp41
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h13
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp10
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h3
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp10
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h20
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp20
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp38
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h12
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp57
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h11
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp10
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h9
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h4
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp2
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h74
-rw-r--r--lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp8
-rw-r--r--lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp23
-rw-r--r--lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp13
-rw-r--r--lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp14
-rw-r--r--lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp2
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp152
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h2
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp11
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp2
-rw-r--r--lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp19
-rw-r--r--lldb/source/Plugins/Language/ObjC/Cocoa.cpp54
-rw-r--r--lldb/source/Plugins/Language/ObjC/NSArray.cpp58
-rw-r--r--lldb/source/Plugins/Language/ObjC/NSDictionary.cpp2
-rw-r--r--lldb/source/Plugins/Language/ObjC/NSError.cpp12
-rw-r--r--lldb/source/Plugins/Language/ObjC/NSException.cpp26
-rw-r--r--lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp5
-rw-r--r--lldb/source/Plugins/Language/ObjC/NSString.cpp2
-rw-r--r--lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp3
-rw-r--r--lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp203
-rw-r--r--lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h8
-rw-r--r--lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp8
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp12
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp155
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h4
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp16
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp56
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h2
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp15
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp69
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h20
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp16
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h7
-rw-r--r--lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp5
-rw-r--r--lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp2
-rw-r--r--lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp2
-rw-r--r--lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp9
-rw-r--r--lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp17
-rw-r--r--lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h6
-rw-r--r--lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp4
-rw-r--r--lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp4
-rw-r--r--lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp4
-rw-r--r--lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp24
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp333
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h3
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp2
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h7
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp138
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h7
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp108
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h13
-rw-r--r--lldb/source/Plugins/Process/POSIX/CrashReason.cpp8
-rw-r--r--lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp11
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp6
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp6
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp6
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h7
-rw-r--r--lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h5
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp10
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h6
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp31
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h6
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp8
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h8
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp15
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp4
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp14
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp23
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h3
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp106
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h1
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td4
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp9
-rw-r--r--lldb/source/Plugins/Process/minidump/MinidumpParser.cpp73
-rw-r--r--lldb/source/Plugins/Process/minidump/MinidumpParser.h10
-rw-r--r--lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp79
-rw-r--r--lldb/source/Plugins/Process/minidump/ProcessMinidump.h3
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp59
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h48
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp157
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h61
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp110
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h44
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp88
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.h28
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp190
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h16
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h28
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h8
-rw-r--r--lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp9
-rw-r--r--lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h12
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp3082
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h69
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h4
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp14
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h8
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp33
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h4
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h6
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp42
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h10
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp167
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h38
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h2
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp107
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h4
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp204
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h49
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp2
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp491
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h39
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp33
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h28
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp7
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h20
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp2
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h10
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp25
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp42
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h12
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp2
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp77
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp25
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h12
-rw-r--r--lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp2
-rw-r--r--lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h11
-rw-r--r--lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp19
-rw-r--r--lldb/source/Symbol/Block.cpp19
-rw-r--r--lldb/source/Symbol/ClangASTContext.cpp3300
-rw-r--r--lldb/source/Symbol/ClangASTImporter.cpp240
-rw-r--r--lldb/source/Symbol/ClangASTMetadata.cpp35
-rw-r--r--lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp70
-rw-r--r--lldb/source/Symbol/ClangExternalASTSourceCommon.cpp99
-rw-r--r--lldb/source/Symbol/ClangUtil.cpp25
-rw-r--r--lldb/source/Symbol/CompileUnit.cpp231
-rw-r--r--lldb/source/Symbol/CompilerDecl.cpp4
-rw-r--r--lldb/source/Symbol/CompilerDeclContext.cpp23
-rw-r--r--lldb/source/Symbol/CompilerType.cpp179
-rw-r--r--lldb/source/Symbol/Declaration.cpp9
-rw-r--r--lldb/source/Symbol/FuncUnwinders.cpp2
-rw-r--r--lldb/source/Symbol/Function.cpp104
-rw-r--r--lldb/source/Symbol/LineEntry.cpp2
-rw-r--r--lldb/source/Symbol/LineTable.cpp8
-rw-r--r--lldb/source/Symbol/LocateSymbolFile.cpp6
-rw-r--r--lldb/source/Symbol/LocateSymbolFileMacOSX.cpp2
-rw-r--r--lldb/source/Symbol/ObjectFile.cpp3
-rw-r--r--lldb/source/Symbol/Symbol.cpp5
-rw-r--r--lldb/source/Symbol/SymbolContext.cpp43
-rw-r--r--lldb/source/Symbol/SymbolFile.cpp6
-rw-r--r--lldb/source/Symbol/Symtab.cpp39
-rw-r--r--lldb/source/Symbol/Type.cpp80
-rw-r--r--lldb/source/Symbol/TypeSystem.cpp6
-rw-r--r--lldb/source/Symbol/Variable.cpp32
-rw-r--r--lldb/source/Target/ABI.cpp37
-rw-r--r--lldb/source/Target/Language.cpp5
-rw-r--r--lldb/source/Target/LanguageRuntime.cpp4
-rw-r--r--lldb/source/Target/MemoryRegionInfo.cpp40
-rw-r--r--lldb/source/Target/Platform.cpp2
-rw-r--r--lldb/source/Target/Process.cpp22
-rw-r--r--lldb/source/Target/StackFrame.cpp9
-rw-r--r--lldb/source/Target/StackFrameList.cpp25
-rw-r--r--lldb/source/Target/StackFrameRecognizer.cpp2
-rw-r--r--lldb/source/Target/Target.cpp179
-rw-r--r--lldb/source/Target/TargetList.cpp9
-rw-r--r--lldb/source/Target/TargetProperties.td3
-rw-r--r--lldb/source/Target/ThreadPlanRunToAddress.cpp6
-rw-r--r--lldb/source/Target/ThreadPlanStepInRange.cpp8
-rw-r--r--lldb/source/Target/ThreadPlanStepInstruction.cpp16
-rw-r--r--lldb/source/Target/ThreadPlanStepOut.cpp26
-rw-r--r--lldb/source/Target/ThreadPlanStepOverRange.cpp4
-rw-r--r--lldb/source/Target/ThreadPlanStepRange.cpp22
-rw-r--r--lldb/source/Target/ThreadPlanStepThrough.cpp4
-rw-r--r--lldb/source/Target/ThreadPlanTracer.cpp9
-rw-r--r--lldb/source/Utility/ArchSpec.cpp41
-rw-r--r--lldb/source/Utility/Baton.cpp5
-rw-r--r--lldb/source/Utility/Broadcaster.cpp4
-rw-r--r--lldb/source/Utility/ConstString.cpp1
-rw-r--r--lldb/source/Utility/DataBufferLLVM.cpp3
-rw-r--r--lldb/source/Utility/DataEncoder.cpp52
-rw-r--r--lldb/source/Utility/DataExtractor.cpp58
-rw-r--r--lldb/source/Utility/Environment.cpp4
-rw-r--r--lldb/source/Utility/FileSpec.cpp57
-rw-r--r--lldb/source/Utility/GDBRemote.cpp73
-rw-r--r--lldb/source/Utility/LLDBAssert.cpp6
-rw-r--r--lldb/source/Utility/PPC64LE_ehframe_Registers.h193
-rw-r--r--lldb/source/Utility/ProcessInfo.cpp8
-rw-r--r--lldb/source/Utility/RegisterValue.cpp34
-rw-r--r--lldb/source/Utility/Reproducer.cpp66
-rw-r--r--lldb/source/Utility/Scalar.cpp23
-rw-r--r--lldb/source/Utility/Status.cpp21
-rw-r--r--lldb/source/Utility/Stream.cpp82
-rw-r--r--lldb/source/Utility/StreamString.cpp2
-rw-r--r--lldb/source/Utility/StructuredData.cpp8
-rw-r--r--lldb/source/Utility/VMRange.cpp7
-rw-r--r--lldb/tools/driver/Driver.cpp61
-rw-r--r--lldb/tools/driver/Options.td6
-rw-r--r--lldb/tools/lldb-server/lldb-gdbserver.cpp5
-rw-r--r--lldb/tools/lldb-server/lldb-server.cpp2
-rw-r--r--lldb/utils/TableGen/LLDBPropertyDefEmitter.cpp15
506 files changed, 15920 insertions, 18671 deletions
diff --git a/lldb/docs/lldb.1 b/lldb/docs/lldb.1
deleted file mode 100644
index a48b6d1b918f..000000000000
--- a/lldb/docs/lldb.1
+++ /dev/null
@@ -1,154 +0,0 @@
-.Dd December 16, 2015 \" DATE
-.Dt LLDB 1 \" Program name and manual section number
-.Os
-.Sh NAME \" Section Header - required - do not modify
-.Nm lldb
-.Nd The debugger
-.Sh SYNOPSIS \" Section Header - required - do not modify
-.Nm lldb
-.Op Fl hvdexw
-.Op Fl a Ar arch
-.Op Fl c Ar core-file
-.Op Fl l Ar script-language
-.Op Fl s Ar lldb-commands
-.Op Fl n Ar process-name
-.Op Fl p Ar pid
-.Ar [[--] <PROGRAM-ARG1> <PROGRAM-ARG2> ...]
-.Sh DESCRIPTION \" Section Header - required - do not modify
-.Nm
-is the command line interface for the LLDB debugger library.
-.Nm
-can debug C, C++, Objective-C, and Objective-C++ programs.
-.Pp
-The following options are available:
-.Bl -tag -width indent
-.It Fl h, -help
-Prints out the usage information for the
-.Nm
-debugger.
-The
-.Fl -help
-text may be more up-to-date and
-authoritative than the command line options described in this man
-page.
-.It Fl v, -version
-Prints out the version number of the
-.Nm
-debugger.
-.It Fl a, -arch Ar arch
-Specifies which architecture
-.Nm
-will use when launching the specified program (assuming the provided
-executable is built for multiple architectures.)
-.It Fl f, -file Ar filename
-Specifies the executable file that
-.Nm
-will be launching / attaching to.
-.It Fl n, -attach-name Ar process-name
-Specifies the name of a currently-running process to attach to.
-(or the name of a process to wait for if
-.Fl w
-is used.)
-.It Fl w, -wait-for
-When used in concert with
-.Fl n Ar process-name ,
-indicates that
-.Nm
-should wait for a new process of that name to be started -- and attach
-to it as early in the process-launch as possible.
-.It Fl p, -attach-pid Ar pid
-Specifies a currently running process that
-.Nm
-should attach to.
-.It Fl c, -core Ar core-file
-Specifies the core file to examine.
-.It Fl l, -script-language Ar language
-Tells the debugger to use the specified scripting language for
-user-defined scripts, rather than the default.
-Valid scripting
-languages that can be specified include Python, Perl, Ruby and Tcl.
-Currently only the Python extensions have been implemented.
-.It Fl d, -debug
-Tells the debugger to print out extra information for debugging itself.
-.It Fl s, -source Ar filename
-Tells
-.Nm
-to read in and execute the file
-.Qq Ar filename ,
-which should contain
-.Nm
-commands.
-.It Fl e, -editor
-Instructs
-.Nm
-to open source files using the host's "external editor" mechanism.
-.It Fl x, -no-lldbinit
-Do not automatically parse any '.lldbinit' files.
-.Pp
-(If you do not provide -f then the first argument will be the file to
-be debugged
-so 'lldb -- <filename> [<ARG1> [<ARG2>]]' also works.
-Remember to end the options with "--" if any of your arguments have
-a "-" in them.)
-.El
-.Sh USING LLDB
-In
-.Nm
-there is a
-.Cm help
-command which can be used to find descriptions and examples of all
-.Nm
-commands.
-To get help on
-.Qq Cm breakpoint set
-you would type
-.Qq Cm help breakpoint set .
-.Pp
-There is also an
-.Cm apropos
-command which will search the help text of all commands
-for a given term -- this is useful for locating a command by topic.
-For instance,
-.Qq Cm apropos breakpoint
-will list any command that has the word
-.Qq Cm breakpoint
-in its help text.
-.Sh FILES
-.Nm
-will read settings/aliases/commands from three files at startup, if they exist.
-.Pp
-First, it will read a
-.Pa ~/.lldbinit-debugger
-command file.
-If you are using the
-.Nm
-command line interface, this is
-.Pa ~/.lldbinit-lldb .
-If you are using
-.Nm
-inside a GUI debugger like
-.Nm Xcode
-this will be
-.Pa ~/.lldbinit-Xcode .
-This is a useful place to put settings that you want to apply only when a given
-.Nm
-command interpreter is used.
-.Pp
-Second,
-.Pa ~/.lldbinit
-is read.
-.Pp
-Third, an
-.Pa .lldbinit
-file in the current working directory (where
-.Nm
-is started) will be read.
-.Sh SEE ALSO
-The LLDB project page http://lldb.llvm.org/ has many different resources for
-.Nm
-users -- the gdb/lldb command equivalence page http://lldb.llvm.org/lldb-gdb.html can
-be especially helpful for users coming from gdb.
-.Sh BUGS
-To report bugs, please visit https://bugs.llvm.org/
-.Sh AUTHOR
-Maintained by the LLDB Team, http://lldb.llvm.org/
diff --git a/lldb/docs/man/lldb.rst b/lldb/docs/man/lldb.rst
new file mode 100644
index 000000000000..b4972df1b601
--- /dev/null
+++ b/lldb/docs/man/lldb.rst
@@ -0,0 +1,323 @@
+:orphan:
+
+lldb -- The Debugger
+====================
+
+.. program:: lldb
+
+SYNOPSIS
+--------
+
+| :program:`lldb` [*options*] *executable*
+
+DESCRIPTION
+-----------
+
+:program:`lldb` is a next generation, high-performance debugger. It is built as
+a set of reusable components which highly leverage existing libraries in the
+larger LLVM Project, such as the Clang expression parser and LLVM disassembler.
+
+:program:`lldb` is the default debugger in Xcode on macOS and supports
+debugging C, Objective-C and C++ on the desktop and iOS devices and simulator.
+
+All of the code in the LLDB project is available under the Apache 2.0 License
+with LLVM exceptions.
+
+ATTACHING
+---------
+
+.. option:: --attach-name <name>
+
+ Tells the debugger to attach to a process with the given name.
+
+.. option:: --attach-pid <pid>
+
+ Tells the debugger to attach to a process with the given pid.
+
+.. option:: -n <value>
+
+ Alias for --attach-name
+
+.. option:: -p <value>
+
+ Alias for --attach-pid
+
+.. option:: --wait-for
+
+ Tells the debugger to wait for a process with the given pid or name to launch before attaching.
+
+.. option:: -w
+
+ Alias for --wait-for
+
+COMMANDS
+--------
+
+.. option:: --batch
+
+ Tells the debugger to run the commands from -s, -S, -o & -O, and then quit.
+
+.. option:: -b
+
+ Alias for --batch
+
+.. option:: -K <value>
+
+ Alias for --source-on-crash
+
+.. option:: -k <value>
+
+ Alias for --one-line-on-crash
+
+.. option:: --local-lldbinit
+
+ Allow the debugger to parse the .lldbinit files in the current working directory, unless --no-lldbinit is passed.
+
+.. option:: --no-lldbinit
+
+ Do not automatically parse any '.lldbinit' files.
+
+.. option:: --one-line-before-file <command>
+
+ Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded.
+
+.. option:: --one-line-on-crash <command>
+
+ When in batch mode, tells the debugger to run this one-line lldb command if the target crashes.
+
+.. option:: --one-line <command>
+
+ Tells the debugger to execute this one-line lldb command after any file provided on the command line has been loaded.
+
+.. option:: -O <value>
+
+ Alias for --one-line-before-file
+
+.. option:: -o <value>
+
+ Alias for --one-line
+
+.. option:: -Q
+
+ Alias for --source-quietly
+
+.. option:: --source-before-file <file>
+
+ Tells the debugger to read in and execute the lldb commands in the given file, before any file has been loaded.
+
+.. option:: --source-on-crash <file>
+
+ When in batch mode, tells the debugger to source this file of lldb commands if the target crashes.
+
+.. option:: --source-quietly
+
+ Tells the debugger to execute this one-line lldb command before any file has been loaded.
+
+.. option:: --source <file>
+
+ Tells the debugger to read in and execute the lldb commands in the given file, after any file has been loaded.
+
+.. option:: -S <value>
+
+ Alias for --source-before-file
+
+.. option:: -s <value>
+
+ Alias for --source
+
+.. option:: -x
+
+ Alias for --no-lldbinit
+
+OPTIONS
+-------
+
+.. option:: --arch <architecture>
+
+ Tells the debugger to use the specified architecture when starting and running the program.
+
+.. option:: -a <value>
+
+ Alias for --arch
+
+.. option:: --capture-path <filename>
+
+ Tells the debugger to use the given filename for the reproducer.
+
+.. option:: --capture
+
+ Tells the debugger to capture a reproducer.
+
+.. option:: --core <filename>
+
+ Tells the debugger to use the full path to <filename> as the core file.
+
+.. option:: -c <value>
+
+ Alias for --core
+
+.. option:: --debug
+
+ Tells the debugger to print out extra information for debugging itself.
+
+.. option:: -d
+
+ Alias for --debug
+
+.. option:: --editor
+
+ Tells the debugger to open source files using the host's "external editor" mechanism.
+
+.. option:: -e
+
+ Alias for --editor
+
+.. option:: --file <filename>
+
+ Tells the debugger to use the file <filename> as the program to be debugged.
+
+.. option:: -f <value>
+
+ Alias for --file
+
+.. option:: --help
+
+ Prints out the usage information for the LLDB debugger.
+
+.. option:: -h
+
+ Alias for --help
+
+.. option:: --no-use-colors
+
+ Do not use colors.
+
+.. option:: --replay <filename>
+
+ Tells the debugger to replay a reproducer from <filename>.
+
+.. option:: --version
+
+ Prints out the current version number of the LLDB debugger.
+
+.. option:: -v
+
+ Alias for --version
+
+.. option:: -X
+
+ Alias for --no-use-color
+
+REPL
+----
+
+.. option:: -r=<flags>
+
+ Alias for --repl=<flags>
+
+.. option:: --repl-language <language>
+
+ Chooses the language for the REPL.
+
+.. option:: --repl=<flags>
+
+ Runs lldb in REPL mode with a stub process with the given flags.
+
+.. option:: -R <value>
+
+ Alias for --repl-language
+
+SCRIPTING
+---------
+
+.. option:: -l <value>
+
+ Alias for --script-language
+
+.. option:: --python-path
+
+ Prints out the path to the lldb.py file for this version of lldb.
+
+.. option:: -P
+
+ Alias for --python-path
+
+.. option:: --script-language <language>
+
+ Tells the debugger to use the specified scripting language for user-defined scripts.
+
+EXAMPLES
+--------
+
+The debugger can be started in several modes.
+
+Passing an executable as a positional argument prepares :program:`lldb` to
+debug the given executable. Arguments passed after -- are considered arguments
+to the debugged executable.
+
+ lldb --arch x86_64 /path/to/program -- --arch arvm7
+
+Passing one of the attach options causes :program:`lldb` to immediately attach
+to the given process.
+
+ lldb -p <pid>
+ lldb -n <process-name>
+
+Passing --repl starts :program:`lldb` in REPL mode.
+
+ lldb -r
+
+Passing --core causes :program:`lldb` to debug the core file.
+
+ lldb -c /path/to/core
+
+Command options can be combined with these modes and cause :program:`lldb` to
+run the specified commands before or after events, like loading the file or
+crashing, in the order provided on the command line.
+
+ lldb -O 'settings set stop-disassembly-count 20' -o 'run' -o 'bt'
+ lldb -S /source/before/file -s /source/after/file
+ lldb -K /source/before/crash -k /source/after/crash
+
+Note: In REPL mode no file is loaded, so commands specified to run after
+loading the file (via -o or -s) will be ignored.
+
+USING LLDB
+----------
+
+In :program:`lldb` there is a help command which can be used to find
+descriptions and examples of all :program:`lldb` commands. To get help on
+"breakpoint set" you would type "help breakpoint set".
+
+There is also an apropos command which will search the help text of all
+commands for a given term ‐‐ this is useful for locating a command by topic.
+For instance, "apropos breakpoint" will list any command that has the word
+"breakpoint" in its help text.
+
+CONFIGURATION FILES
+-------------------
+
+:program:`lldb` reads things like settings, aliases and commands from the
+.lldbinit file. It will first look for ~/.lldbinit and load that first.
+Secondly, it will look for an .lldbinit file in the current working directory.
+For security reasons, :program:`lldb` will print a warning and not source this
+file by default. This behavior can be changed by changing the
+target.load-cwd-lldbinit setting.
+
+To always load the .lldbinit file in the current working directory, add the
+following command to ~/.lldbinit:
+
+ settings set target.load-cwd-lldbinit true
+
+To never load the .lldbinit file in the current working directory and silence
+the warning, add the following command to ~/.lldbinit:
+
+ settings set target.load-cwd-lldbinit false
+
+SEE ALSO
+--------
+
+The LLDB project page https://lldb.llvm.org has many different resources
+for :program:`lldb` users ‐‐ the gdb/lldb command equivalence page
+https://lldb.llvm.org/use/map.html can be especially helpful for users
+coming from gdb.
diff --git a/lldb/include/lldb/API/SBBreakpoint.h b/lldb/include/lldb/API/SBBreakpoint.h
index 75c0e69a4821..a5ce91d95089 100644
--- a/lldb/include/lldb/API/SBBreakpoint.h
+++ b/lldb/include/lldb/API/SBBreakpoint.h
@@ -94,6 +94,9 @@ public:
void SetScriptCallbackFunction(const char *callback_function_name);
+ SBError SetScriptCallbackFunction(const char *callback_function_name,
+ SBStructuredData &extra_args);
+
void SetCommandLineCommands(SBStringList &commands);
bool GetCommandLineCommands(SBStringList &commands);
diff --git a/lldb/include/lldb/API/SBBreakpointLocation.h b/lldb/include/lldb/API/SBBreakpointLocation.h
index 085bed9399b9..a9e2ef1dd1b8 100644
--- a/lldb/include/lldb/API/SBBreakpointLocation.h
+++ b/lldb/include/lldb/API/SBBreakpointLocation.h
@@ -55,11 +55,14 @@ public:
void SetScriptCallbackFunction(const char *callback_function_name);
+ SBError SetScriptCallbackFunction(const char *callback_function_name,
+ lldb::SBStructuredData &extra_args);
+
SBError SetScriptCallbackBody(const char *script_body_text);
- void SetCommandLineCommands(SBStringList &commands);
+ void SetCommandLineCommands(lldb::SBStringList &commands);
- bool GetCommandLineCommands(SBStringList &commands);
+ bool GetCommandLineCommands(lldb::SBStringList &commands);
void SetThreadID(lldb::tid_t sb_thread_id);
diff --git a/lldb/include/lldb/API/SBBreakpointName.h b/lldb/include/lldb/API/SBBreakpointName.h
index 018238bcd074..3a5f1acf3e4a 100644
--- a/lldb/include/lldb/API/SBBreakpointName.h
+++ b/lldb/include/lldb/API/SBBreakpointName.h
@@ -85,9 +85,12 @@ public:
void SetScriptCallbackFunction(const char *callback_function_name);
- void SetCommandLineCommands(SBStringList &commands);
+ SBError SetScriptCallbackFunction(const char *callback_function_name,
+ SBStructuredData &extra_args);
- bool GetCommandLineCommands(SBStringList &commands);
+ void SetCommandLineCommands(lldb::SBStringList &commands);
+
+ bool GetCommandLineCommands(lldb::SBStringList &commands);
SBError SetScriptCallbackBody(const char *script_body_text);
diff --git a/lldb/include/lldb/API/SBReproducer.h b/lldb/include/lldb/API/SBReproducer.h
index 0f1739d0c5bd..93d78f55fd76 100644
--- a/lldb/include/lldb/API/SBReproducer.h
+++ b/lldb/include/lldb/API/SBReproducer.h
@@ -21,6 +21,9 @@ public:
static const char *Capture();
static const char *Capture(const char *path);
static const char *Replay(const char *path);
+ static const char *Replay(const char *path, bool skip_version_check);
+ static const char *GetPath();
+ static bool Generate();
};
} // namespace lldb
diff --git a/lldb/include/lldb/API/SBStructuredData.h b/lldb/include/lldb/API/SBStructuredData.h
index a090272e45ac..785e91047fdf 100644
--- a/lldb/include/lldb/API/SBStructuredData.h
+++ b/lldb/include/lldb/API/SBStructuredData.h
@@ -93,6 +93,9 @@ protected:
friend class SBTarget;
friend class SBThread;
friend class SBThreadPlan;
+ friend class SBBreakpoint;
+ friend class SBBreakpointLocation;
+ friend class SBBreakpointName;
StructuredDataImplUP m_impl_up;
};
diff --git a/lldb/include/lldb/API/SBValue.h b/lldb/include/lldb/API/SBValue.h
index c36ba20297f0..5f8d17f8642f 100644
--- a/lldb/include/lldb/API/SBValue.h
+++ b/lldb/include/lldb/API/SBValue.h
@@ -75,8 +75,6 @@ public:
const char *GetObjectDescription();
- const char *GetTypeValidatorResult();
-
lldb::SBValue GetDynamicValue(lldb::DynamicValueType use_dynamic);
lldb::SBValue GetStaticValue();
diff --git a/lldb/include/lldb/Breakpoint/Breakpoint.h b/lldb/include/lldb/Breakpoint/Breakpoint.h
index f561b6d900a1..94411bd57a67 100644
--- a/lldb/include/lldb/Breakpoint/Breakpoint.h
+++ b/lldb/include/lldb/Breakpoint/Breakpoint.h
@@ -193,7 +193,7 @@ public:
/// Tell this breakpoint to scan a given module list and resolve any new
/// locations that match the breakpoint's specifications.
///
- /// \param[in] changed_modules
+ /// \param[in] module_list
/// The list of modules to look in for new locations.
///
/// \param[in] new_locations
@@ -205,7 +205,7 @@ public:
/// which case we will remove any locations that are in modules that got
/// unloaded.
///
- /// \param[in] changedModules
+ /// \param[in] changed_modules
/// The list of modules to look in for new locations.
/// \param[in] load_event
/// If \b true then the modules were loaded, if \b false, unloaded.
@@ -372,10 +372,6 @@ public:
/// If \b true the callback will be run on the private event thread
/// before the stop event gets reported. If false, the callback will get
/// handled on the public event thread after the stop has been posted.
- ///
- /// \return
- /// \b true if the process should stop when you hit the breakpoint.
- /// \b false if it should continue.
void SetCallback(BreakpointHitCallback callback, void *baton,
bool is_synchronous = false);
@@ -522,7 +518,7 @@ private: // The target needs to manage adding & removing names. It will do the
if (name_to_remove)
m_name_list.erase(name_to_remove);
}
-
+
public:
bool MatchesName(const char *name) {
return m_name_list.find(name) != m_name_list.end();
@@ -554,14 +550,14 @@ public:
lldb::BreakpointPreconditionSP GetPrecondition() { return m_precondition_sp; }
// Produces the OR'ed values for all the names assigned to this breakpoint.
- const BreakpointName::Permissions &GetPermissions() const {
- return m_permissions;
+ const BreakpointName::Permissions &GetPermissions() const {
+ return m_permissions;
}
- BreakpointName::Permissions &GetPermissions() {
- return m_permissions;
+ BreakpointName::Permissions &GetPermissions() {
+ return m_permissions;
}
-
+
bool AllowList() const {
return GetPermissions().GetAllowList();
}
diff --git a/lldb/include/lldb/Breakpoint/BreakpointID.h b/lldb/include/lldb/Breakpoint/BreakpointID.h
index 095132988eb2..9daa5b6c5e8d 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointID.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointID.h
@@ -65,7 +65,7 @@ public:
/// If it is a mal-formed breakpoint name, error will be set to an appropriate
/// error string.
///
- /// \param[in] input
+ /// \param[in] str
/// A string containing JUST the breakpoint description.
/// \param[out] error
/// If the name is a well-formed breakpoint name, set to success,
diff --git a/lldb/include/lldb/Breakpoint/BreakpointList.h b/lldb/include/lldb/Breakpoint/BreakpointList.h
index fe10adbda8a6..ad68151fefc7 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointList.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointList.h
@@ -67,8 +67,10 @@ public:
/// The breakpoint name for which to search.
///
/// \result
- /// \bfalse if the input name was not a legal breakpoint name.
- bool FindBreakpointsByName(const char *name, BreakpointList &matching_bps);
+ /// error if the input name was not a legal breakpoint name, vector
+ /// of breakpoints otherwise.
+ llvm::Expected<std::vector<lldb::BreakpointSP>>
+ FindBreakpointsByName(const char *name);
/// Returns the number of elements in this breakpoint list.
///
@@ -138,7 +140,7 @@ public:
/// Sets the passed in Locker to hold the Breakpoint List mutex.
///
- /// \param[in] locker
+ /// \param[in] lock
/// The locker object that is set.
void GetListMutex(std::unique_lock<std::recursive_mutex> &lock);
diff --git a/lldb/include/lldb/Breakpoint/BreakpointLocation.h b/lldb/include/lldb/Breakpoint/BreakpointLocation.h
index aadd52288485..86bb164162c1 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointLocation.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointLocation.h
@@ -93,7 +93,7 @@ public:
/// Set the breakpoint to ignore the next \a count breakpoint hits.
///
- /// \param[in] count
+ /// \param[in] n
/// The number of breakpoint hits to ignore.
void SetIgnoreCount(uint32_t n);
@@ -224,9 +224,6 @@ public:
/// \param[in] context
/// Described the breakpoint event.
///
- /// \param[in] bp_loc_id
- /// Which breakpoint location hit this breakpoint.
- ///
/// \return
/// \b true if the target should stop at this breakpoint and \b
/// false not.
diff --git a/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h b/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h
index 3da52eb7962a..be400636877e 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h
@@ -22,17 +22,14 @@ public:
BreakpointLocationCollection();
~BreakpointLocationCollection();
-
+
BreakpointLocationCollection &operator=(const BreakpointLocationCollection &rhs);
/// Add the breakpoint \a bp_loc_sp to the list.
///
- /// \param[in] bp_sp
+ /// \param[in] bp_loc_sp
/// Shared pointer to the breakpoint location that will get added
/// to the list.
- ///
- /// \result
- /// Returns breakpoint location id.
void Add(const lldb::BreakpointLocationSP &bp_loc_sp);
/// Removes the breakpoint location given by \b breakID from this
@@ -66,7 +63,7 @@ public:
/// Returns a shared pointer to the breakpoint location with id \a
/// breakID, const version.
///
- /// \param[in] breakID
+ /// \param[in] break_id
/// The breakpoint location ID to seek for.
///
/// \param[in] break_loc_id
@@ -112,9 +109,6 @@ public:
/// \param[in] context
/// This contains the information about this stop.
///
- /// \param[in] breakID
- /// This break ID that we hit.
- ///
/// \return
/// \b true if we should stop, \b false otherwise.
bool ShouldStop(StoppointCallbackContext *context);
diff --git a/lldb/include/lldb/Breakpoint/BreakpointLocationList.h b/lldb/include/lldb/Breakpoint/BreakpointLocationList.h
index b7e0e49cff83..89ad2f54c923 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointLocationList.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointLocationList.h
@@ -75,7 +75,7 @@ public:
/// \param[in] module
/// The module to seek in.
///
- /// \param[in]
+ /// \param[in] bp_loc_list
/// A breakpoint collection that gets any breakpoint locations
/// that match \a module appended to.
///
@@ -166,14 +166,6 @@ protected:
/// list.
BreakpointLocationList(Breakpoint &owner);
- /// Add the breakpoint \a bp_loc_sp to the list.
- ///
- /// \param[in] bp_sp
- /// Shared pointer to the breakpoint location that will get
- /// added to the list.
- ///
- /// \result
- /// Returns breakpoint location id.
lldb::BreakpointLocationSP Create(const Address &addr,
bool resolve_indirect_symbols);
@@ -189,7 +181,7 @@ protected:
lldb::BreakpointLocationSP from_location_sp);
bool RemoveLocation(const lldb::BreakpointLocationSP &bp_loc_sp);
-
+
void RemoveLocationByIndex(size_t idx);
void RemoveInvalidLocations(const ArchSpec &arch);
diff --git a/lldb/include/lldb/Breakpoint/BreakpointOptions.h b/lldb/include/lldb/Breakpoint/BreakpointOptions.h
index 55a4be2d19c1..2c52170eb9f6 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointOptions.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointOptions.h
@@ -88,7 +88,8 @@ public:
explicit CommandBaton(std::unique_ptr<CommandData> Data)
: TypedBaton(std::move(Data)) {}
- void GetDescription(Stream *s, lldb::DescriptionLevel level) const override;
+ void GetDescription(llvm::raw_ostream &s, lldb::DescriptionLevel level,
+ unsigned indentation) const override;
};
typedef std::shared_ptr<CommandBaton> CommandBatonSP;
@@ -135,7 +136,7 @@ public:
// Operators
const BreakpointOptions &operator=(const BreakpointOptions &rhs);
-
+
/// Copy over only the options set in the incoming BreakpointOptions.
void CopyOverSetOptions(const BreakpointOptions &rhs);
@@ -267,7 +268,7 @@ public:
bool IsEnabled() const { return m_enabled; }
/// If \a enable is \b true, enable the breakpoint, if \b false disable it.
- void SetEnabled(bool enabled) {
+ void SetEnabled(bool enabled) {
m_enabled = enabled;
m_set_flags.Set(eEnabled);
}
@@ -278,7 +279,7 @@ public:
bool IsAutoContinue() const { return m_auto_continue; }
/// Set the auto-continue state.
- void SetAutoContinue(bool auto_continue) {
+ void SetAutoContinue(bool auto_continue) {
m_auto_continue = auto_continue;
m_set_flags.Set(eAutoContinue);
}
@@ -289,17 +290,16 @@ public:
bool IsOneShot() const { return m_one_shot; }
/// If \a enable is \b true, enable the breakpoint, if \b false disable it.
- void SetOneShot(bool one_shot) {
- m_one_shot = one_shot;
- m_set_flags.Set(eOneShot);
+ void SetOneShot(bool one_shot) {
+ m_one_shot = one_shot;
+ m_set_flags.Set(eOneShot);
}
/// Set the breakpoint to ignore the next \a count breakpoint hits.
- /// \param[in] count
+ /// \param[in] n
/// The number of breakpoint hits to ignore.
-
- void SetIgnoreCount(uint32_t n) {
- m_ignore_count = n;
+ void SetIgnoreCount(uint32_t n) {
+ m_ignore_count = n;
m_set_flags.Set(eIgnoreCount);
}
@@ -341,13 +341,13 @@ public:
/// A UP holding the new'ed CommandData object.
/// The breakpoint will take ownership of pointer held by this object.
void SetCommandDataCallback(std::unique_ptr<CommandData> &cmd_data);
-
+
void Clear();
-
+
bool AnySet() const {
return m_set_flags.AnySet(eAllOptions);
}
-
+
protected:
// Classes that inherit from BreakpointOptions can see and modify these
bool IsOptionSet(OptionKind kind)
@@ -377,7 +377,7 @@ protected:
private:
/// For BreakpointOptions only
-
+
/// This is the callback function pointer
BreakpointHitCallback m_callback;
/// This is the client data for the callback
diff --git a/lldb/include/lldb/Breakpoint/BreakpointResolver.h b/lldb/include/lldb/Breakpoint/BreakpointResolver.h
index 11e183b33482..c1dbf9ac0aee 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointResolver.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointResolver.h
@@ -44,9 +44,6 @@ public:
/// The breakpoint that owns this resolver.
/// \param[in] resolverType
/// The concrete breakpoint resolver type for this breakpoint.
- ///
- /// \result
- /// Returns breakpoint location id.
BreakpointResolver(Breakpoint *bkpt, unsigned char resolverType,
lldb::addr_t offset = 0);
@@ -186,7 +183,7 @@ protected:
};
static const char
*g_option_names[static_cast<uint32_t>(OptionNames::LastOptionName)];
-
+
virtual void NotifyBreakpointSet() {};
public:
diff --git a/lldb/include/lldb/Breakpoint/BreakpointSite.h b/lldb/include/lldb/Breakpoint/BreakpointSite.h
index 51ed84f7bf2d..5c9f79a9ab1c 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointSite.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointSite.h
@@ -99,15 +99,12 @@ public:
bool ShouldStop(StoppointCallbackContext *context) override;
/// Standard Dump method
- ///
- /// \param[in] context
- /// The stream to dump this output.
void Dump(Stream *s) const override;
/// The "Owners" are the breakpoint locations that share this breakpoint
/// site. The method adds the \a owner to this breakpoint site's owner list.
///
- /// \param[in] context
+ /// \param[in] owner
/// \a owner is the Breakpoint Location to add.
void AddOwner(const lldb::BreakpointLocationSP &owner);
@@ -123,8 +120,9 @@ public:
/// GetNumberOfOwners() - 1 so you can use this method to iterate over the
/// owners
///
- /// \param[in] index
+ /// \param[in] idx
/// The index in the list of owners for which you wish the owner location.
+ ///
/// \return
/// A shared pointer to the breakpoint location at that index.
lldb::BreakpointLocationSP GetOwnerAtIndex(size_t idx);
@@ -201,9 +199,6 @@ private:
/// The method removes the owner at \a break_loc_id from this breakpoint
/// list.
- ///
- /// \param[in] context
- /// \a break_loc_id is the Breakpoint Location to remove.
size_t RemoveOwner(lldb::break_id_t break_id, lldb::break_id_t break_loc_id);
BreakpointSite::Type m_type; ///< The type of this breakpoint site.
diff --git a/lldb/include/lldb/Breakpoint/Watchpoint.h b/lldb/include/lldb/Breakpoint/Watchpoint.h
index e71f89b3e384..2cc74bb4c632 100644
--- a/lldb/include/lldb/Breakpoint/Watchpoint.h
+++ b/lldb/include/lldb/Breakpoint/Watchpoint.h
@@ -69,7 +69,6 @@ public:
// This doesn't really enable/disable the watchpoint. It is currently just
// for use in the Process plugin's {Enable,Disable}Watchpoint, which should
// be used instead.
-
void SetEnabled(bool enabled, bool notify = true);
bool IsHardware() const override;
@@ -113,10 +112,6 @@ public:
/// If \b true the callback will be run on the private event thread
/// before the stop event gets reported. If false, the callback will get
/// handled on the public event thread after the stop has been posted.
- ///
- /// \return
- /// \b true if the process should stop when you hit the watchpoint.
- /// \b false if it should continue.
void SetCallback(WatchpointHitCallback callback, void *callback_baton,
bool is_synchronous = false);
diff --git a/lldb/include/lldb/Breakpoint/WatchpointList.h b/lldb/include/lldb/Breakpoint/WatchpointList.h
index 98c64832d46d..bb73d4ab75da 100644
--- a/lldb/include/lldb/Breakpoint/WatchpointList.h
+++ b/lldb/include/lldb/Breakpoint/WatchpointList.h
@@ -180,7 +180,7 @@ public:
/// Sets the passed in Locker to hold the Watchpoint List mutex.
///
- /// \param[in] locker
+ /// \param[in] lock
/// The locker object that is set.
void GetListMutex(std::unique_lock<std::recursive_mutex> &lock);
diff --git a/lldb/include/lldb/Breakpoint/WatchpointOptions.h b/lldb/include/lldb/Breakpoint/WatchpointOptions.h
index b395dde21901..0dc34d4ebef7 100644
--- a/lldb/include/lldb/Breakpoint/WatchpointOptions.h
+++ b/lldb/include/lldb/Breakpoint/WatchpointOptions.h
@@ -180,7 +180,8 @@ public:
CommandBaton(std::unique_ptr<CommandData> Data)
: TypedBaton(std::move(Data)) {}
- void GetDescription(Stream *s, lldb::DescriptionLevel level) const override;
+ void GetDescription(llvm::raw_ostream &s, lldb::DescriptionLevel level,
+ unsigned indentation) const override;
};
protected:
diff --git a/lldb/include/lldb/Core/Address.h b/lldb/include/lldb/Core/Address.h
index 07bb450d6092..70a7f790e40d 100644
--- a/lldb/include/lldb/Core/Address.h
+++ b/lldb/include/lldb/Core/Address.h
@@ -61,45 +61,55 @@ public:
/// Dump styles allow the Address::Dump(Stream *,DumpStyle) const function
/// to display Address contents in a variety of ways.
enum DumpStyle {
- DumpStyleInvalid, ///< Invalid dump style
- DumpStyleSectionNameOffset, ///< Display as the section name + offset.
- ///< \code
+ /// Invalid dump style.
+ DumpStyleInvalid,
+ /// Display as the section name + offset.
+ /// \code
/// // address for printf in libSystem.B.dylib as a section name + offset
- /// libSystem.B.dylib.__TEXT.__text + 0x0005cfdf \endcode
- DumpStyleSectionPointerOffset, ///< Display as the section pointer + offset
- ///(debug output).
- ///< \code
+ /// libSystem.B.dylib.__TEXT.__text + 0x0005cfdf
+ /// \endcode
+ DumpStyleSectionNameOffset,
+ /// Display as the section pointer + offset (debug output).
+ /// \code
/// // address for printf in libSystem.B.dylib as a section pointer +
- /// offset (lldb::Section *)0x35cc50 + 0x000000000005cfdf \endcode
- DumpStyleFileAddress, ///< Display as the file address (if any).
- ///< \code
+ /// offset (lldb::Section *)0x35cc50 + 0x000000000005cfdf
+ /// \endcode
+ DumpStyleSectionPointerOffset,
+ /// Display as the file address (if any).
+ /// \code
/// // address for printf in libSystem.B.dylib as a file address
- /// 0x000000000005dcff \endcode
- DumpStyleModuleWithFileAddress, ///< Display as the file address with the
- /// module name prepended (if any).
- ///< \code
+ /// 0x000000000005dcff
+ /// \endcode
+ ///
+ DumpStyleFileAddress,
+ /// Display as the file address with the module name prepended (if any).
+ /// \code
/// // address for printf in libSystem.B.dylib as a file address
- /// libSystem.B.dylib[0x000000000005dcff] \endcode
- DumpStyleLoadAddress, ///< Display as the load address (if resolved).
- ///< \code
+ /// libSystem.B.dylib[0x000000000005dcff]
+ /// \endcode
+ DumpStyleModuleWithFileAddress,
+ /// Display as the load address (if resolved).
+ /// \code
/// // address for printf in libSystem.B.dylib as a load address
- /// 0x00007fff8306bcff \endcode
- DumpStyleResolvedDescription, ///< Display the details about what an address
- /// resolves to. This can
- ///< be anything from a symbol context summary (module, function/symbol,
- ///< and file and line), to information about what the pointer points to
- ///< if the address is in a section (section of pointers, c strings, etc).
+ /// 0x00007fff8306bcff
+ /// \endcode
+ DumpStyleLoadAddress,
+ /// Display the details about what an address resolves to. This can be
+ /// anything from a symbol context summary (module, function/symbol, and
+ /// file and line), to information about what the pointer points to if the
+ /// address is in a section (section of pointers, c strings, etc).
+ DumpStyleResolvedDescription,
DumpStyleResolvedDescriptionNoModule,
DumpStyleResolvedDescriptionNoFunctionArguments,
- DumpStyleNoFunctionName, ///< Elide the function name; display an offset
- /// into the current function.
- ///< Used primarily in disassembly symbolication
- DumpStyleDetailedSymbolContext, ///< Detailed symbol context information for
- /// an address for all symbol
- ///< context members.
- DumpStyleResolvedPointerDescription ///< Dereference a pointer at the
- /// current address and then lookup the
- ///< dereferenced address using DumpStyleResolvedDescription
+ /// Elide the function name; display an offset into the current function.
+ /// Used primarily in disassembly symbolication
+ DumpStyleNoFunctionName,
+ /// Detailed symbol context information for an address for all symbol
+ /// context members.
+ DumpStyleDetailedSymbolContext,
+ /// Dereference a pointer at the current address and then lookup the
+ /// dereferenced address using DumpStyleResolvedDescription
+ DumpStyleResolvedPointerDescription
};
/// Default constructor.
@@ -121,7 +131,7 @@ public:
///
/// Initialize the address with the supplied \a section and \a offset.
///
- /// \param[in] section
+ /// \param[in] section_sp
/// A section pointer to a valid lldb::Section, or NULL if the
/// address doesn't have a section or will get resolved later.
///
@@ -179,9 +189,9 @@ public:
/// The Right Hand Side const Address object reference.
///
/// \return
- /// \li -1 if lhs < rhs
- /// \li 0 if lhs == rhs
- /// \li 1 if lhs > rhs
+ /// -1 if lhs < rhs
+ /// 0 if lhs == rhs
+ /// 1 if lhs > rhs
static int CompareFileAddress(const Address &lhs, const Address &rhs);
static int CompareLoadAddress(const Address &lhs, const Address &rhs,
@@ -433,7 +443,7 @@ public:
/// Set accessor for the section.
///
- /// \param[in] section
+ /// \param[in] section_sp
/// A new lldb::Section pointer to use as the section base. Can
/// be NULL for absolute addresses that are not relative to
/// any section.
diff --git a/lldb/include/lldb/Core/AddressRange.h b/lldb/include/lldb/Core/AddressRange.h
index 4a019bfcfc3f..ac748713a182 100644
--- a/lldb/include/lldb/Core/AddressRange.h
+++ b/lldb/include/lldb/Core/AddressRange.h
@@ -123,7 +123,7 @@ public:
/// Check if the resolved file address \a file_addr is contained within this
/// object's file address range.
///
- /// \param[in] so_addr
+ /// \param[in] file_addr
/// A section offset address object reference.
///
/// \return
@@ -147,9 +147,6 @@ public:
/// Check if the resolved load address \a load_addr is contained within this
/// object's load address range.
///
- /// \param[in] so_addr
- /// A section offset address object reference.
- ///
/// \return
/// Returns \b true if both \a this has a resolvable load
/// address value and \a so_addr is contained in the address
diff --git a/lldb/include/lldb/Core/ClangForward.h b/lldb/include/lldb/Core/ClangForward.h
index 6b24b47c8a96..0bc331438e5c 100644
--- a/lldb/include/lldb/Core/ClangForward.h
+++ b/lldb/include/lldb/Core/ClangForward.h
@@ -17,7 +17,6 @@ namespace Builtin {
class Context;
}
-class Action;
class ASTConsumer;
class ASTContext;
class ASTRecordLayout;
diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h
index b2f696c22834..a8048427c8f1 100644
--- a/lldb/include/lldb/Core/Debugger.h
+++ b/lldb/include/lldb/Core/Debugger.h
@@ -151,7 +151,9 @@ public:
return *m_command_interpreter_up;
}
- ScriptInterpreter *GetScriptInterpreter(bool can_create = true);
+ ScriptInterpreter *
+ GetScriptInterpreter(bool can_create = true,
+ llvm::Optional<lldb::ScriptLanguage> language = {});
lldb::ListenerSP GetListener() { return m_listener_sp; }
@@ -396,8 +398,9 @@ protected:
// source file cache.
std::unique_ptr<CommandInterpreter> m_command_interpreter_up;
- lldb::ScriptInterpreterSP m_script_interpreter_sp;
std::recursive_mutex m_script_interpreter_mutex;
+ std::array<lldb::ScriptInterpreterSP, lldb::eScriptLanguageUnknown>
+ m_script_interpreters;
IOHandlerStack m_input_reader_stack;
llvm::StringMap<std::weak_ptr<llvm::raw_ostream>> m_log_streams;
diff --git a/lldb/include/lldb/Core/Disassembler.h b/lldb/include/lldb/Core/Disassembler.h
index ba9ca87832f6..7ece0eeb708c 100644
--- a/lldb/include/lldb/Core/Disassembler.h
+++ b/lldb/include/lldb/Core/Disassembler.h
@@ -287,6 +287,10 @@ public:
/// a function call (a branch that calls and returns to the next
/// instruction). If false, find the instruction index of any
/// branch in the list.
+ ///
+ /// @param[out] found_calls
+ /// If non-null, this will be set to true if any calls were found in
+ /// extending the range.
///
/// @return
/// The instruction index of the first branch that is at or past
@@ -295,7 +299,8 @@ public:
//------------------------------------------------------------------
uint32_t GetIndexOfNextBranchInstruction(uint32_t start,
Target &target,
- bool ignore_calls) const;
+ bool ignore_calls,
+ bool *found_calls) const;
uint32_t GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr,
Target &target);
diff --git a/lldb/include/lldb/Core/FormatEntity.h b/lldb/include/lldb/Core/FormatEntity.h
index ae6c402a45be..8ee320b0ebb1 100644
--- a/lldb/include/lldb/Core/FormatEntity.h
+++ b/lldb/include/lldb/Core/FormatEntity.h
@@ -85,6 +85,7 @@ public:
FunctionName,
FunctionNameWithArgs,
FunctionNameNoArgs,
+ FunctionMangledName,
FunctionAddrOffset,
FunctionAddrOffsetConcrete,
FunctionLineOffset,
diff --git a/lldb/include/lldb/Core/Highlighter.h b/lldb/include/lldb/Core/Highlighter.h
index 88d3bb3a3cd1..8a268ec1d6b1 100644
--- a/lldb/include/lldb/Core/Highlighter.h
+++ b/lldb/include/lldb/Core/Highlighter.h
@@ -43,8 +43,6 @@ struct HighlightStyle {
void Apply(Stream &s, llvm::StringRef value) const;
/// Sets the prefix and suffix strings.
- /// \param prefix
- /// \param suffix
void Set(llvm::StringRef prefix, llvm::StringRef suffix);
};
@@ -100,6 +98,7 @@ public:
/// Highlights the given line
/// \param options
+ /// The highlight options.
/// \param line
/// The user supplied line that needs to be highlighted.
/// \param cursor_pos
diff --git a/lldb/include/lldb/Core/IOHandler.h b/lldb/include/lldb/Core/IOHandler.h
index 37142a5a8396..9ab5eaaecb66 100644
--- a/lldb/include/lldb/Core/IOHandler.h
+++ b/lldb/include/lldb/Core/IOHandler.h
@@ -10,6 +10,7 @@
#define liblldb_IOHandler_h_
#include "lldb/Core/ValueObjectList.h"
+#include "lldb/Host/Config.h"
#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Flags.h"
@@ -51,6 +52,7 @@ public:
REPL,
ProcessIO,
PythonInterpreter,
+ LuaInterpreter,
PythonCode,
Other
};
@@ -406,7 +408,7 @@ public:
void PrintAsync(Stream *stream, const char *s, size_t len) override;
private:
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
static bool IsInputCompleteCallback(Editline *editline, StringList &lines,
void *baton);
@@ -417,7 +419,7 @@ private:
#endif
protected:
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
std::unique_ptr<Editline> m_editline_up;
#endif
IOHandlerDelegate &m_delegate;
@@ -456,48 +458,9 @@ protected:
bool m_user_response;
};
-class IOHandlerCursesGUI : public IOHandler {
-public:
- IOHandlerCursesGUI(Debugger &debugger);
-
- ~IOHandlerCursesGUI() override;
-
- void Run() override;
-
- void Cancel() override;
-
- bool Interrupt() override;
-
- void GotEOF() override;
-
- void Activate() override;
-
- void Deactivate() override;
-
-protected:
- curses::ApplicationAP m_app_ap;
-};
-
-class IOHandlerCursesValueObjectList : public IOHandler {
-public:
- IOHandlerCursesValueObjectList(Debugger &debugger,
- ValueObjectList &valobj_list);
-
- ~IOHandlerCursesValueObjectList() override;
-
- void Run() override;
-
- void GotEOF() override;
-
-protected:
- ValueObjectList m_valobj_list;
-};
-
class IOHandlerStack {
public:
- IOHandlerStack() : m_stack(), m_mutex(), m_top(nullptr) {}
-
- ~IOHandlerStack() = default;
+ IOHandlerStack() = default;
size_t GetSize() const {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
@@ -574,7 +537,7 @@ protected:
typedef std::vector<lldb::IOHandlerSP> collection;
collection m_stack;
mutable std::recursive_mutex m_mutex;
- IOHandler *m_top;
+ IOHandler *m_top = nullptr;
private:
DISALLOW_COPY_AND_ASSIGN(IOHandlerStack);
diff --git a/lldb/include/lldb/Core/IOHandlerCursesGUI.h b/lldb/include/lldb/Core/IOHandlerCursesGUI.h
new file mode 100644
index 000000000000..afa435269725
--- /dev/null
+++ b/lldb/include/lldb/Core/IOHandlerCursesGUI.h
@@ -0,0 +1,40 @@
+//===-- IOHandlerCursesGUI.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_IOHandlerCursesGUI_h_
+#define liblldb_IOHandlerCursesGUI_h_
+
+#include "lldb/Core/IOHandler.h"
+
+namespace lldb_private {
+
+class IOHandlerCursesGUI : public IOHandler {
+public:
+ IOHandlerCursesGUI(Debugger &debugger);
+
+ ~IOHandlerCursesGUI() override;
+
+ void Run() override;
+
+ void Cancel() override;
+
+ bool Interrupt() override;
+
+ void GotEOF() override;
+
+ void Activate() override;
+
+ void Deactivate() override;
+
+protected:
+ curses::ApplicationAP m_app_ap;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_IOHandlerCursesGUI_h_
diff --git a/lldb/include/lldb/Core/Mangled.h b/lldb/include/lldb/Core/Mangled.h
index 63fa0f618dae..6af68c3f5857 100644
--- a/lldb/include/lldb/Core/Mangled.h
+++ b/lldb/include/lldb/Core/Mangled.h
@@ -108,9 +108,9 @@ public:
/// A const reference to the Right Hand Side object to compare.
///
/// \return
- /// \li -1 if \a lhs is less than \a rhs
- /// \li 0 if \a lhs is equal to \a rhs
- /// \li 1 if \a lhs is greater than \a rhs
+ /// -1 if \a lhs is less than \a rhs
+ /// 0 if \a lhs is equal to \a rhs
+ /// 1 if \a lhs is greater than \a rhs
static int Compare(const Mangled &lhs, const Mangled &rhs);
/// Dump a description of this object to a Stream \a s.
@@ -261,6 +261,15 @@ public:
bool DemangleWithRichManglingInfo(RichManglingContext &context,
SkipMangledNameFn *skip_mangled_name);
+ /// Try to identify the mangling scheme used.
+ /// \param[in] name
+ /// The name we are attempting to identify the mangling scheme for.
+ ///
+ /// \return
+ /// eManglingSchemeNone if no known mangling scheme could be identified
+ /// for s, otherwise the enumerator for the mangling scheme detected.
+ static Mangled::ManglingScheme GetManglingScheme(llvm::StringRef const name);
+
private:
/// Mangled member variables.
ConstString m_mangled; ///< The mangled version of the name
diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h
index 89b731427e3f..2af18c83f23a 100644
--- a/lldb/include/lldb/Core/Module.h
+++ b/lldb/include/lldb/Core/Module.h
@@ -190,7 +190,7 @@ public:
lldb::ModuleSP CalculateSymbolContextModule() override;
void
- GetDescription(Stream *s,
+ GetDescription(llvm::raw_ostream &s,
lldb::DescriptionLevel level = lldb::eDescriptionLevelFull);
/// Get the module path and object name.
@@ -291,9 +291,6 @@ public:
/// \param[in] name
/// The name of the compile unit we are looking for.
///
- /// \param[in] namespace_decl
- /// If valid, a namespace to search in.
- ///
/// \param[in] name_type_mask
/// A bit mask of bits that indicate what kind of names should
/// be used when doing the lookup. Bits include fully qualified
@@ -317,10 +314,6 @@ public:
/// \param[in] regex
/// A regular expression to use when matching the name.
///
- /// \param[in] append
- /// If \b true, any matches will be appended to \a sc_list, else
- /// matches replace the contents of \a sc_list.
- ///
/// \param[out] sc_list
/// A symbol context list that gets filled in with all of the
/// matches.
@@ -416,7 +409,7 @@ public:
/// omitted to make finding types that a user may type
/// easier.
///
- /// \param[out] type_list
+ /// \param[out] types
/// A type list gets populated with any matches.
///
void
@@ -429,7 +422,11 @@ public:
/// This behaves like the other FindTypes method but allows to
/// specify a DeclContext and a language for the type being searched
/// for.
+ ///
+ /// \param searched_symbol_files
+ /// Prevents one file from being visited multiple times.
void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
+ llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types);
lldb::TypeSP FindFirstType(const SymbolContext &sc,
@@ -443,12 +440,8 @@ public:
/// The name of a type within a namespace that should not include
/// any qualifying namespaces (just a type basename).
///
- /// \param[in] namespace_decl
- /// The namespace declaration that this type must exist in.
- ///
/// \param[out] type_list
/// A type list gets populated with any matches.
- ///
void FindTypesInNamespace(ConstString type_name,
const CompilerDeclContext *parent_decl_ctx,
size_t max_matches, TypeList &type_list);
diff --git a/lldb/include/lldb/Core/ModuleChild.h b/lldb/include/lldb/Core/ModuleChild.h
index 8a81c1a6cf8a..0d59e4fb12ca 100644
--- a/lldb/include/lldb/Core/ModuleChild.h
+++ b/lldb/include/lldb/Core/ModuleChild.h
@@ -20,7 +20,7 @@ class ModuleChild {
public:
/// Construct with owning module.
///
- /// \param[in] module
+ /// \param[in] module_sp
/// The module that owns the object that inherits from this
/// class.
ModuleChild(const lldb::ModuleSP &module_sp);
@@ -46,15 +46,14 @@ public:
/// Set accessor for the module pointer.
///
- /// \param[in] module
+ /// \param[in] module_sp
/// A new module that owns the object that inherits from this
- /// class.
+ /// class.
void SetModule(const lldb::ModuleSP &module_sp);
protected:
- // Member variables
- lldb::ModuleWP m_module_wp; ///< The Module that owns the object that inherits
- ///< from this class.
+ /// The Module that owns the object that inherits from this class.
+ lldb::ModuleWP m_module_wp;
};
} // namespace lldb_private
diff --git a/lldb/include/lldb/Core/ModuleList.h b/lldb/include/lldb/Core/ModuleList.h
index e21655551b61..a6e80ed75c76 100644
--- a/lldb/include/lldb/Core/ModuleList.h
+++ b/lldb/include/lldb/Core/ModuleList.h
@@ -53,7 +53,7 @@ public:
bool SetClangModulesCachePath(llvm::StringRef path);
bool GetEnableExternalLookup() const;
bool SetEnableExternalLookup(bool new_value);
-};
+};
/// \class ModuleList ModuleList.h "lldb/Core/ModuleList.h"
/// A collection class for Module objects.
@@ -116,10 +116,10 @@ public:
/// If true, and a notifier function is set, the notifier function
/// will be called. Defaults to true.
///
- /// When this ModuleList is the Target's ModuleList, the notifier
- /// function is Target::ModulesDidLoad -- the call to
- /// ModulesDidLoad may be deferred when adding multiple Modules
- /// to the Target, but it must be called at the end,
+ /// When this ModuleList is the Target's ModuleList, the notifier
+ /// function is Target::ModulesDidLoad -- the call to
+ /// ModulesDidLoad may be deferred when adding multiple Modules
+ /// to the Target, but it must be called at the end,
/// before resuming execution.
void Append(const lldb::ModuleSP &module_sp, bool notify = true);
@@ -135,16 +135,14 @@ public:
/// Append a module to the module list, if it is not already there.
///
- /// \param[in] module_sp
- ///
/// \param[in] notify
/// If true, and a notifier function is set, the notifier function
/// will be called. Defaults to true.
///
- /// When this ModuleList is the Target's ModuleList, the notifier
- /// function is Target::ModulesDidLoad -- the call to
- /// ModulesDidLoad may be deferred when adding multiple Modules
- /// to the Target, but it must be called at the end,
+ /// When this ModuleList is the Target's ModuleList, the notifier
+ /// function is Target::ModulesDidLoad -- the call to
+ /// ModulesDidLoad may be deferred when adding multiple Modules
+ /// to the Target, but it must be called at the end,
/// before resuming execution.
bool AppendIfNeeded(const lldb::ModuleSP &module_sp, bool notify = true);
@@ -297,7 +295,7 @@ public:
/// Finds the first module whose file specification matches \a file_spec.
///
- /// \param[in] file_spec_ptr
+ /// \param[in] module_spec
/// A file specification object to match against the Module's
/// file specifications. If \a file_spec does not have
/// directory information, matches will occur by matching only
@@ -305,18 +303,6 @@ public:
/// NULL, then file specifications won't be compared when
/// searching for matching modules.
///
- /// \param[in] arch_ptr
- /// The architecture to search for if non-NULL. If this value
- /// is NULL no architecture matching will be performed.
- ///
- /// \param[in] uuid_ptr
- /// The uuid to search for if non-NULL. If this value is NULL
- /// no uuid matching will be performed.
- ///
- /// \param[in] object_name
- /// An optional object name that must match as well. This value
- /// can be NULL.
- ///
/// \param[out] matching_module_list
/// A module list that gets filled in with any modules that
/// match the search criteria.
@@ -351,24 +337,11 @@ public:
/// \param[in] name
/// The name of the type we are looking for.
///
- /// \param[in] append
- /// If \b true, any matches will be appended to \a
- /// variable_list, else matches replace the contents of
- /// \a variable_list.
- ///
/// \param[in] max_matches
/// Allow the number of matches to be limited to \a
/// max_matches. Specify UINT32_MAX to get all possible matches.
///
- /// \param[in] encoding
- /// Limit the search to specific types, or get all types if
- /// set to Type::invalid.
- ///
- /// \param[in] udt_name
- /// If the encoding is a user defined type, specify the name
- /// of the user defined type ("struct", "union", "class", etc).
- ///
- /// \param[out] type_list
+ /// \param[out] types
/// A type list gets populated with any matches.
///
void FindTypes(Module *search_first, ConstString name,
@@ -414,10 +387,10 @@ public:
/// If true, and a notifier function is set, the notifier function
/// will be called. Defaults to true.
///
- /// When this ModuleList is the Target's ModuleList, the notifier
- /// function is Target::ModulesDidUnload -- the call to
- /// ModulesDidUnload may be deferred when removing multiple Modules
- /// from the Target, but it must be called at the end,
+ /// When this ModuleList is the Target's ModuleList, the notifier
+ /// function is Target::ModulesDidUnload -- the call to
+ /// ModulesDidUnload may be deferred when removing multiple Modules
+ /// from the Target, but it must be called at the end,
/// before resuming execution.
bool Remove(const lldb::ModuleSP &module_sp, bool notify = true);
@@ -477,7 +450,7 @@ public:
static size_t RemoveOrphanSharedModules(bool mandatory);
static bool RemoveSharedModuleIfOrphaned(const Module *module_ptr);
-
+
void ForEach(std::function<bool(const lldb::ModuleSP &module_sp)> const
&callback) const;
diff --git a/lldb/include/lldb/Core/ModuleSpec.h b/lldb/include/lldb/Core/ModuleSpec.h
index 651d0dc869bc..6d024fe3434b 100644
--- a/lldb/include/lldb/Core/ModuleSpec.h
+++ b/lldb/include/lldb/Core/ModuleSpec.h
@@ -207,7 +207,7 @@ public:
if (dumped_something)
strm.PutCString(", ");
strm.Printf("arch = ");
- m_arch.DumpTriple(strm);
+ m_arch.DumpTriple(strm.AsRawOstream());
dumped_something = true;
}
if (m_uuid.IsValid()) {
@@ -251,24 +251,18 @@ public:
if (match_module_spec.GetObjectName() &&
match_module_spec.GetObjectName() != GetObjectName())
return false;
- if (match_module_spec.GetFileSpecPtr()) {
- const FileSpec &fspec = match_module_spec.GetFileSpec();
- if (!FileSpec::Equal(fspec, GetFileSpec(),
- !fspec.GetDirectory().IsEmpty()))
- return false;
- }
- if (GetPlatformFileSpec() && match_module_spec.GetPlatformFileSpecPtr()) {
- const FileSpec &fspec = match_module_spec.GetPlatformFileSpec();
- if (!FileSpec::Equal(fspec, GetPlatformFileSpec(),
- !fspec.GetDirectory().IsEmpty()))
- return false;
+ if (!FileSpec::Match(match_module_spec.GetFileSpec(), GetFileSpec()))
+ return false;
+ if (GetPlatformFileSpec() &&
+ !FileSpec::Match(match_module_spec.GetPlatformFileSpec(),
+ GetPlatformFileSpec())) {
+ return false;
}
// Only match the symbol file spec if there is one in this ModuleSpec
- if (GetSymbolFileSpec() && match_module_spec.GetSymbolFileSpecPtr()) {
- const FileSpec &fspec = match_module_spec.GetSymbolFileSpec();
- if (!FileSpec::Equal(fspec, GetSymbolFileSpec(),
- !fspec.GetDirectory().IsEmpty()))
- return false;
+ if (GetSymbolFileSpec() &&
+ !FileSpec::Match(match_module_spec.GetSymbolFileSpec(),
+ GetSymbolFileSpec())) {
+ return false;
}
if (match_module_spec.GetArchitecturePtr()) {
if (exact_arch_match) {
diff --git a/lldb/include/lldb/Core/PropertiesBase.td b/lldb/include/lldb/Core/PropertiesBase.td
index be97d44ae8e4..6e95ceb779ba 100644
--- a/lldb/include/lldb/Core/PropertiesBase.td
+++ b/lldb/include/lldb/Core/PropertiesBase.td
@@ -18,11 +18,13 @@ class Global {
class DefaultTrue {
int DefaultUnsignedValue = 1;
bit HasDefaultUnsignedValue = 1;
+ bit HasDefaultBooleanValue = 1;
}
class DefaultFalse {
int DefaultUnsignedValue = 0;
bit HasDefaultUnsignedValue = 1;
+ bit HasDefaultBooleanValue = 1;
}
// Gives the property a default string value.
diff --git a/lldb/include/lldb/Core/STLUtils.h b/lldb/include/lldb/Core/STLUtils.h
deleted file mode 100644
index 830aca36a116..000000000000
--- a/lldb/include/lldb/Core/STLUtils.h
+++ /dev/null
@@ -1,74 +0,0 @@
-//===-- STLUtils.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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_STLUtils_h_
-#define liblldb_STLUtils_h_
-
-#include <string.h>
-
-#include <map>
-#include <ostream>
-#include <vector>
-
-
-// C string less than compare function object
-struct CStringCompareFunctionObject {
- bool operator()(const char *s1, const char *s2) const {
- return strcmp(s1, s2) < 0;
- }
-};
-
-// C string equality function object (binary predicate).
-struct CStringEqualBinaryPredicate {
- bool operator()(const char *s1, const char *s2) const {
- return strcmp(s1, s2) == 0;
- }
-};
-
-// Templated type for finding an entry in a std::map<F,S> whose value is equal
-// to something
-template <class F, class S> class ValueEquals {
-public:
- ValueEquals(const S &val) : second_value(val) {}
-
- // Compare the second item
- bool operator()(std::pair<const F, S> elem) {
- return elem.second == second_value;
- }
-
-private:
- S second_value;
-};
-
-template <class T>
-inline void PrintAllCollectionElements(std::ostream &s, const T &coll,
- const char *header_cstr = nullptr,
- const char *separator_cstr = " ") {
- typename T::const_iterator pos;
-
- if (header_cstr)
- s << header_cstr;
- for (pos = coll.begin(); pos != coll.end(); ++pos) {
- s << *pos << separator_cstr;
- }
- s << std::endl;
-}
-
-// The function object below can be used to delete a STL container that
-// contains C++ object pointers.
-//
-// Usage: std::for_each(vector.begin(), vector.end(), for_each_delete());
-
-struct for_each_cplusplus_delete {
- template <typename T> void operator()(T *ptr) { delete ptr; }
-};
-
-typedef std::vector<std::string> STLStringArray;
-typedef std::vector<const char *> CStringArray;
-
-#endif // liblldb_STLUtils_h_
diff --git a/lldb/include/lldb/Core/SearchFilter.h b/lldb/include/lldb/Core/SearchFilter.h
index 6823daf9e3ed..74c4f3162a1c 100644
--- a/lldb/include/lldb/Core/SearchFilter.h
+++ b/lldb/include/lldb/Core/SearchFilter.h
@@ -84,7 +84,7 @@ class SearchFilter {
public:
/// The basic constructor takes a Target, which gives the space to search.
///
- /// \param[in] target
+ /// \param[in] target_sp
/// The Target that provides the module list to search.
SearchFilter(const lldb::TargetSP &target_sp);
@@ -102,7 +102,7 @@ public:
/// Call this method with a Module to see if that module passes the filter.
///
- /// \param[in] module
+ /// \param[in] module_sp
/// The Module to check against the filter.
///
/// \return
@@ -306,7 +306,7 @@ public:
/// The basic constructor takes a Target, which gives the space to search,
/// and the module to restrict the search to.
///
- /// \param[in] target
+ /// \param[in] targetSP
/// The Target that provides the module list to search.
///
/// \param[in] module
@@ -352,10 +352,10 @@ public:
/// The basic constructor takes a Target, which gives the space to search,
/// and the module list to restrict the search to.
///
- /// \param[in] target
+ /// \param[in] targetSP
/// The Target that provides the module list to search.
///
- /// \param[in] module
+ /// \param[in] module_list
/// The Module that limits the search.
SearchFilterByModuleList(const lldb::TargetSP &targetSP,
const FileSpecList &module_list);
@@ -366,8 +366,6 @@ public:
~SearchFilterByModuleList() override;
- SearchFilterByModuleList &operator=(const SearchFilterByModuleList &rhs);
-
bool ModulePasses(const lldb::ModuleSP &module_sp) override;
bool ModulePasses(const FileSpec &spec) override;
@@ -406,23 +404,12 @@ class SearchFilterByModuleListAndCU : public SearchFilterByModuleList {
public:
/// The basic constructor takes a Target, which gives the space to search,
/// and the module list to restrict the search to.
- ///
- /// \param[in] target
- /// The Target that provides the module list to search.
- ///
- /// \param[in] module
- /// The Module that limits the search.
SearchFilterByModuleListAndCU(const lldb::TargetSP &targetSP,
const FileSpecList &module_list,
const FileSpecList &cu_list);
- SearchFilterByModuleListAndCU(const SearchFilterByModuleListAndCU &rhs);
-
~SearchFilterByModuleListAndCU() override;
- SearchFilterByModuleListAndCU &
- operator=(const SearchFilterByModuleListAndCU &rhs);
-
bool AddressPasses(Address &address) override;
bool CompUnitPasses(FileSpec &fileSpec) override;
diff --git a/lldb/include/lldb/Core/SourceManager.h b/lldb/include/lldb/Core/SourceManager.h
index bca817750d8d..f1f56d0886c3 100644
--- a/lldb/include/lldb/Core/SourceManager.h
+++ b/lldb/include/lldb/Core/SourceManager.h
@@ -54,8 +54,6 @@ public:
bool LineIsValid(uint32_t line);
- bool FileSpecMatches(const FileSpec &file_spec);
-
const FileSpec &GetFileSpec() { return m_file_spec; }
uint32_t GetSourceMapModificationID() const { return m_source_map_mod_id; }
diff --git a/lldb/include/lldb/Core/StreamFile.h b/lldb/include/lldb/Core/StreamFile.h
index 712b289aa8d9..bd7d6e8e6ad3 100644
--- a/lldb/include/lldb/Core/StreamFile.h
+++ b/lldb/include/lldb/Core/StreamFile.h
@@ -21,15 +21,10 @@ namespace lldb_private {
class StreamFile : public Stream {
public:
- // Constructors and Destructors
- StreamFile();
-
StreamFile(uint32_t flags, uint32_t addr_size, lldb::ByteOrder byte_order);
StreamFile(int fd, bool transfer_ownership);
- StreamFile(const char *path);
-
StreamFile(const char *path, File::OpenOptions options,
uint32_t permissions = lldb::eFilePermissionsFileDefault);
@@ -47,7 +42,6 @@ public:
void Flush() override;
-
protected:
// Classes that inherit from StreamFile can see and modify these
std::shared_ptr<File> m_file_sp; // never NULL
diff --git a/lldb/include/lldb/Core/ThreadSafeDenseMap.h b/lldb/include/lldb/Core/ThreadSafeDenseMap.h
index c485b91acb47..420cb5763586 100644
--- a/lldb/include/lldb/Core/ThreadSafeDenseMap.h
+++ b/lldb/include/lldb/Core/ThreadSafeDenseMap.h
@@ -62,4 +62,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_ThreadSafeSTLMap_h_
+#endif // liblldb_ThreadSafeDenseMap_h_
diff --git a/lldb/include/lldb/Core/ThreadSafeSTLMap.h b/lldb/include/lldb/Core/ThreadSafeSTLMap.h
deleted file mode 100644
index df0208cd49b3..000000000000
--- a/lldb/include/lldb/Core/ThreadSafeSTLMap.h
+++ /dev/null
@@ -1,128 +0,0 @@
-//===-- ThreadSafeSTLMap.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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_ThreadSafeSTLMap_h_
-#define liblldb_ThreadSafeSTLMap_h_
-
-#include <map>
-#include <mutex>
-
-#include "lldb/lldb-defines.h"
-
-namespace lldb_private {
-
-template <typename _Key, typename _Tp> class ThreadSafeSTLMap {
-public:
- typedef std::map<_Key, _Tp> collection;
- typedef typename collection::iterator iterator;
- typedef typename collection::const_iterator const_iterator;
- // Constructors and Destructors
- ThreadSafeSTLMap() : m_collection(), m_mutex() {}
-
- ~ThreadSafeSTLMap() {}
-
- bool IsEmpty() const {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- return m_collection.empty();
- }
-
- void Clear() {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- return m_collection.clear();
- }
-
- size_t Erase(const _Key &key) {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- return EraseNoLock(key);
- }
-
- size_t EraseNoLock(const _Key &key) { return m_collection.erase(key); }
-
- bool GetValueForKey(const _Key &key, _Tp &value) const {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- return GetValueForKeyNoLock(key, value);
- }
-
- // Call this if you have already manually locked the mutex using the
- // GetMutex() accessor
- bool GetValueForKeyNoLock(const _Key &key, _Tp &value) const {
- const_iterator pos = m_collection.find(key);
- if (pos != m_collection.end()) {
- value = pos->second;
- return true;
- }
- return false;
- }
-
- bool GetFirstKeyForValue(const _Tp &value, _Key &key) const {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- return GetFirstKeyForValueNoLock(value, key);
- }
-
- bool GetFirstKeyForValueNoLock(const _Tp &value, _Key &key) const {
- const_iterator pos, end = m_collection.end();
- for (pos = m_collection.begin(); pos != end; ++pos) {
- if (pos->second == value) {
- key = pos->first;
- return true;
- }
- }
- return false;
- }
-
- bool LowerBound(const _Key &key, _Key &match_key, _Tp &match_value,
- bool decrement_if_not_equal) const {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- return LowerBoundNoLock(key, match_key, match_value,
- decrement_if_not_equal);
- }
-
- bool LowerBoundNoLock(const _Key &key, _Key &match_key, _Tp &match_value,
- bool decrement_if_not_equal) const {
- const_iterator pos = m_collection.lower_bound(key);
- if (pos != m_collection.end()) {
- match_key = pos->first;
- if (decrement_if_not_equal && key != match_key &&
- pos != m_collection.begin()) {
- --pos;
- match_key = pos->first;
- }
- match_value = pos->second;
- return true;
- }
- return false;
- }
-
- iterator lower_bound_unsafe(const _Key &key) {
- return m_collection.lower_bound(key);
- }
-
- void SetValueForKey(const _Key &key, const _Tp &value) {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- SetValueForKeyNoLock(key, value);
- }
-
- // Call this if you have already manually locked the mutex using the
- // GetMutex() accessor
- void SetValueForKeyNoLock(const _Key &key, const _Tp &value) {
- m_collection[key] = value;
- }
-
- std::recursive_mutex &GetMutex() { return m_mutex; }
-
-private:
- collection m_collection;
- mutable std::recursive_mutex m_mutex;
-
- // For ThreadSafeSTLMap only
- DISALLOW_COPY_AND_ASSIGN(ThreadSafeSTLMap);
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_ThreadSafeSTLMap_h_
diff --git a/lldb/include/lldb/Core/ThreadSafeSTLVector.h b/lldb/include/lldb/Core/ThreadSafeSTLVector.h
deleted file mode 100644
index e1666a69ef7e..000000000000
--- a/lldb/include/lldb/Core/ThreadSafeSTLVector.h
+++ /dev/null
@@ -1,72 +0,0 @@
-//===-- ThreadSafeSTLVector.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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_ThreadSafeSTLVector_h_
-#define liblldb_ThreadSafeSTLVector_h_
-
-#include <mutex>
-#include <vector>
-
-#include "lldb/lldb-defines.h"
-
-namespace lldb_private {
-
-template <typename _Object> class ThreadSafeSTLVector {
-public:
- typedef std::vector<_Object> collection;
- typedef typename collection::iterator iterator;
- typedef typename collection::const_iterator const_iterator;
- // Constructors and Destructors
- ThreadSafeSTLVector() : m_collection(), m_mutex() {}
-
- ~ThreadSafeSTLVector() = default;
-
- bool IsEmpty() const {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- return m_collection.empty();
- }
-
- void Clear() {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- return m_collection.clear();
- }
-
- size_t GetCount() {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- return m_collection.size();
- }
-
- void AppendObject(_Object &object) {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- m_collection.push_back(object);
- }
-
- _Object GetObject(size_t index) {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- return m_collection.at(index);
- }
-
- void SetObject(size_t index, const _Object &object) {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- m_collection.at(index) = object;
- }
-
- std::recursive_mutex &GetMutex() { return m_mutex; }
-
-private:
- collection m_collection;
- mutable std::recursive_mutex m_mutex;
-
- // For ThreadSafeSTLVector only
- DISALLOW_COPY_AND_ASSIGN(ThreadSafeSTLVector);
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_ThreadSafeSTLVector_h_
diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h
index 0808b86c67a1..1b000e617f0e 100644
--- a/lldb/include/lldb/Core/ValueObject.h
+++ b/lldb/include/lldb/Core/ValueObject.h
@@ -179,7 +179,6 @@ public:
eClearUserVisibleDataItemsLocation = 1u << 3,
eClearUserVisibleDataItemsDescription = 1u << 4,
eClearUserVisibleDataItemsSyntheticChildren = 1u << 5,
- eClearUserVisibleDataItemsValidator = 1u << 6,
eClearUserVisibleDataItemsAllStrings =
eClearUserVisibleDataItemsValue | eClearUserVisibleDataItemsSummary |
eClearUserVisibleDataItemsLocation |
@@ -510,8 +509,6 @@ public:
std::string &destination,
const TypeSummaryOptions &options);
- std::pair<TypeValidatorResult, std::string> GetValidationStatus();
-
const char *GetObjectDescription();
bool HasSpecialPrintableRepresentation(
@@ -711,16 +708,6 @@ public:
ClearUserVisibleData(eClearUserVisibleDataItemsSummary);
}
- lldb::TypeValidatorImplSP GetValidator() {
- UpdateFormatsIfNeeded();
- return m_type_validator_sp;
- }
-
- void SetValidator(lldb::TypeValidatorImplSP format) {
- m_type_validator_sp = format;
- ClearUserVisibleData(eClearUserVisibleDataItemsValidator);
- }
-
void SetValueFormat(lldb::TypeFormatImplSP format) {
m_type_format_sp = format;
ClearUserVisibleData(eClearUserVisibleDataItemsValue);
@@ -857,9 +844,6 @@ protected:
// differs from the summary
// in that the summary is consed up by us, the object_desc_string is builtin.
- llvm::Optional<std::pair<TypeValidatorResult, std::string>>
- m_validation_result;
-
CompilerType m_override_type; // If the type of the value object should be
// overridden, the type to impose.
@@ -888,7 +872,6 @@ protected:
lldb::TypeSummaryImplSP m_type_summary_sp;
lldb::TypeFormatImplSP m_type_format_sp;
lldb::SyntheticChildrenSP m_synthetic_children_sp;
- lldb::TypeValidatorImplSP m_type_validator_sp;
ProcessModID m_user_id_of_forced_summary;
AddressType m_address_type_of_ptr_or_ref_children;
@@ -985,6 +968,7 @@ protected:
private:
virtual CompilerType MaybeCalculateCompleteType();
+ void UpdateChildrenAddressType();
lldb::ValueObjectSP GetValueForExpressionPath_Impl(
llvm::StringRef expression_cstr,
diff --git a/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h b/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h
index 3b14a3e9f388..ec395095351d 100644
--- a/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h
+++ b/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h
@@ -9,8 +9,6 @@
#ifndef liblldb_ValueObjectSyntheticFilter_h_
#define liblldb_ValueObjectSyntheticFilter_h_
-#include "lldb/Core/ThreadSafeSTLMap.h"
-#include "lldb/Core/ThreadSafeSTLVector.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Utility/ConstString.h"
@@ -135,19 +133,24 @@ protected:
lldb::SyntheticChildrenSP m_synth_sp;
std::unique_ptr<SyntheticChildrenFrontEnd> m_synth_filter_up;
- typedef ThreadSafeSTLMap<uint32_t, ValueObject *> ByIndexMap;
- typedef ThreadSafeSTLMap<const char *, uint32_t> NameToIndexMap;
- typedef ThreadSafeSTLVector<lldb::ValueObjectSP> SyntheticChildrenCache;
+ typedef std::map<uint32_t, ValueObject *> ByIndexMap;
+ typedef std::map<const char *, uint32_t> NameToIndexMap;
+ typedef std::vector<lldb::ValueObjectSP> SyntheticChildrenCache;
typedef ByIndexMap::iterator ByIndexIterator;
typedef NameToIndexMap::iterator NameToIndexIterator;
+ std::mutex m_child_mutex;
+ /// Guarded by m_child_mutex;
ByIndexMap m_children_byindex;
+ /// Guarded by m_child_mutex;
NameToIndexMap m_name_toindex;
+ /// Guarded by m_child_mutex;
+ SyntheticChildrenCache m_synthetic_children_cache;
+
uint32_t m_synthetic_children_count; // FIXME use the ValueObject's
// ChildrenManager instead of a special
// purpose solution
- SyntheticChildrenCache m_synthetic_children_cache;
ConstString m_parent_type_name;
diff --git a/lldb/include/lldb/DataFormatters/DataVisualization.h b/lldb/include/lldb/DataFormatters/DataVisualization.h
index cdb2eab995fc..f5c3487bcb3b 100644
--- a/lldb/include/lldb/DataFormatters/DataVisualization.h
+++ b/lldb/include/lldb/DataFormatters/DataVisualization.h
@@ -51,12 +51,6 @@ public:
static lldb::SyntheticChildrenSP
GetSyntheticChildren(ValueObject &valobj, lldb::DynamicValueType use_dynamic);
- static lldb::TypeValidatorImplSP
- GetValidator(ValueObject &valobj, lldb::DynamicValueType use_dynamic);
-
- static lldb::TypeValidatorImplSP
- GetValidatorForType(lldb::TypeNameSpecifierImplSP type_sp);
-
static bool
AnyMatches(ConstString type_name,
TypeCategoryImpl::FormatCategoryItems items =
diff --git a/lldb/include/lldb/DataFormatters/FormatCache.h b/lldb/include/lldb/DataFormatters/FormatCache.h
index 7a6774b7f837..f9dbe414640d 100644
--- a/lldb/include/lldb/DataFormatters/FormatCache.h
+++ b/lldb/include/lldb/DataFormatters/FormatCache.h
@@ -24,45 +24,26 @@ private:
bool m_format_cached : 1;
bool m_summary_cached : 1;
bool m_synthetic_cached : 1;
- bool m_validator_cached : 1;
lldb::TypeFormatImplSP m_format_sp;
lldb::TypeSummaryImplSP m_summary_sp;
lldb::SyntheticChildrenSP m_synthetic_sp;
- lldb::TypeValidatorImplSP m_validator_sp;
public:
Entry();
- Entry(lldb::TypeFormatImplSP);
- Entry(lldb::TypeSummaryImplSP);
- Entry(lldb::SyntheticChildrenSP);
- Entry(lldb::TypeValidatorImplSP);
- Entry(lldb::TypeFormatImplSP, lldb::TypeSummaryImplSP,
- lldb::SyntheticChildrenSP, lldb::TypeValidatorImplSP);
+ template<typename ImplSP> bool IsCached();
bool IsFormatCached();
-
bool IsSummaryCached();
-
bool IsSyntheticCached();
- bool IsValidatorCached();
-
- lldb::TypeFormatImplSP GetFormat();
-
- lldb::TypeSummaryImplSP GetSummary();
-
- lldb::SyntheticChildrenSP GetSynthetic();
-
- lldb::TypeValidatorImplSP GetValidator();
-
- void SetFormat(lldb::TypeFormatImplSP);
-
- void SetSummary(lldb::TypeSummaryImplSP);
-
- void SetSynthetic(lldb::SyntheticChildrenSP);
+ void Get(lldb::TypeFormatImplSP &);
+ void Get(lldb::TypeSummaryImplSP &);
+ void Get(lldb::SyntheticChildrenSP &);
- void SetValidator(lldb::TypeValidatorImplSP);
+ void Set(lldb::TypeFormatImplSP);
+ void Set(lldb::TypeSummaryImplSP);
+ void Set(lldb::SyntheticChildrenSP);
};
typedef std::map<ConstString, Entry> CacheMap;
CacheMap m_map;
@@ -76,25 +57,10 @@ private:
public:
FormatCache();
- bool GetFormat(ConstString type, lldb::TypeFormatImplSP &format_sp);
-
- bool GetSummary(ConstString type, lldb::TypeSummaryImplSP &summary_sp);
-
- bool GetSynthetic(ConstString type,
- lldb::SyntheticChildrenSP &synthetic_sp);
-
- bool GetValidator(ConstString type,
- lldb::TypeValidatorImplSP &summary_sp);
-
- void SetFormat(ConstString type, lldb::TypeFormatImplSP &format_sp);
-
- void SetSummary(ConstString type, lldb::TypeSummaryImplSP &summary_sp);
-
- void SetSynthetic(ConstString type,
- lldb::SyntheticChildrenSP &synthetic_sp);
-
- void SetValidator(ConstString type,
- lldb::TypeValidatorImplSP &synthetic_sp);
+ template <typename ImplSP> bool Get(ConstString type, ImplSP &format_impl_sp);
+ void Set(ConstString type, lldb::TypeFormatImplSP &format_sp);
+ void Set(ConstString type, lldb::TypeSummaryImplSP &summary_sp);
+ void Set(ConstString type, lldb::SyntheticChildrenSP &synthetic_sp);
void Clear();
@@ -102,6 +68,7 @@ public:
uint64_t GetCacheMisses() { return m_cache_misses; }
};
+
} // namespace lldb_private
#endif // lldb_FormatCache_h_
diff --git a/lldb/include/lldb/DataFormatters/FormatClasses.h b/lldb/include/lldb/DataFormatters/FormatClasses.h
index 5144bc6079a9..91ce444244cc 100644
--- a/lldb/include/lldb/DataFormatters/FormatClasses.h
+++ b/lldb/include/lldb/DataFormatters/FormatClasses.h
@@ -17,7 +17,6 @@
#include "lldb/DataFormatters/TypeFormat.h"
#include "lldb/DataFormatters/TypeSummary.h"
#include "lldb/DataFormatters/TypeSynthetic.h"
-#include "lldb/DataFormatters/TypeValidator.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/Type.h"
#include "lldb/lldb-enumerations.h"
@@ -40,7 +39,6 @@ public:
typedef HardcodedFormatterFinders<TypeFormatImpl> HardcodedFormatFinder;
typedef HardcodedFormatterFinders<TypeSummaryImpl> HardcodedSummaryFinder;
typedef HardcodedFormatterFinders<SyntheticChildren> HardcodedSyntheticFinder;
- typedef HardcodedFormatterFinders<TypeValidatorImpl> HardcodedValidatorFinder;
};
class FormattersMatchCandidate {
diff --git a/lldb/include/lldb/DataFormatters/FormatManager.h b/lldb/include/lldb/DataFormatters/FormatManager.h
index afaafda47e76..dd522c487c8f 100644
--- a/lldb/include/lldb/DataFormatters/FormatManager.h
+++ b/lldb/include/lldb/DataFormatters/FormatManager.h
@@ -52,24 +52,15 @@ public:
void
EnableCategory(ConstString category_name,
TypeCategoryMap::Position pos = TypeCategoryMap::Default) {
- EnableCategory(category_name, pos,
- std::initializer_list<lldb::LanguageType>());
+ EnableCategory(category_name, pos, {});
}
void EnableCategory(ConstString category_name,
TypeCategoryMap::Position pos, lldb::LanguageType lang) {
- std::initializer_list<lldb::LanguageType> langs = {lang};
- EnableCategory(category_name, pos, langs);
- }
-
- void EnableCategory(ConstString category_name,
- TypeCategoryMap::Position pos = TypeCategoryMap::Default,
- std::initializer_list<lldb::LanguageType> langs = {}) {
TypeCategoryMap::ValueSP category_sp;
if (m_categories_map.Get(category_name, category_sp) && category_sp) {
m_categories_map.Enable(category_sp, pos);
- for (const lldb::LanguageType lang : langs)
- category_sp->AddLanguage(lang);
+ category_sp->AddLanguage(lang);
}
}
@@ -127,9 +118,6 @@ public:
lldb::ScriptedSyntheticChildrenSP
GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp);
- lldb::TypeValidatorImplSP
- GetValidatorForType(lldb::TypeNameSpecifierImplSP type_sp);
-
lldb::TypeFormatImplSP GetFormat(ValueObject &valobj,
lldb::DynamicValueType use_dynamic);
@@ -139,9 +127,6 @@ public:
lldb::SyntheticChildrenSP
GetSyntheticChildren(ValueObject &valobj, lldb::DynamicValueType use_dynamic);
- lldb::TypeValidatorImplSP GetValidator(ValueObject &valobj,
- lldb::DynamicValueType use_dynamic);
-
bool
AnyMatches(ConstString type_name,
TypeCategoryImpl::FormatCategoryItems items =
@@ -198,9 +183,6 @@ public:
GetCandidateLanguages(lldb::LanguageType lang_type);
private:
- static std::vector<lldb::LanguageType>
- GetCandidateLanguages(ValueObject &valobj);
-
static void GetPossibleMatches(ValueObject &valobj,
CompilerType compiler_type, uint32_t reason,
lldb::DynamicValueType use_dynamic,
@@ -220,14 +202,10 @@ private:
ConstString m_system_category_name;
ConstString m_vectortypes_category_name;
- lldb::TypeFormatImplSP GetHardcodedFormat(FormattersMatchData &);
-
- lldb::TypeSummaryImplSP GetHardcodedSummaryFormat(FormattersMatchData &);
-
- lldb::SyntheticChildrenSP
- GetHardcodedSyntheticChildren(FormattersMatchData &);
-
- lldb::TypeValidatorImplSP GetHardcodedValidator(FormattersMatchData &);
+ template <typename ImplSP>
+ ImplSP Get(ValueObject &valobj, lldb::DynamicValueType use_dynamic);
+ template <typename ImplSP> ImplSP GetCached(FormattersMatchData &match_data);
+ template <typename ImplSP> ImplSP GetHardcoded(FormattersMatchData &);
TypeCategoryMap &GetCategories() { return m_categories_map; }
diff --git a/lldb/include/lldb/DataFormatters/FormattersContainer.h b/lldb/include/lldb/DataFormatters/FormattersContainer.h
index de2edb103151..86023dd9bf0b 100644
--- a/lldb/include/lldb/DataFormatters/FormattersContainer.h
+++ b/lldb/include/lldb/DataFormatters/FormattersContainer.h
@@ -22,7 +22,6 @@
#include "lldb/DataFormatters/TypeFormat.h"
#include "lldb/DataFormatters/TypeSummary.h"
#include "lldb/DataFormatters/TypeSynthetic.h"
-#include "lldb/DataFormatters/TypeValidator.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/StringLexer.h"
diff --git a/lldb/include/lldb/DataFormatters/LanguageCategory.h b/lldb/include/lldb/DataFormatters/LanguageCategory.h
index f109d46194ad..1cffff91c197 100644
--- a/lldb/include/lldb/DataFormatters/LanguageCategory.h
+++ b/lldb/include/lldb/DataFormatters/LanguageCategory.h
@@ -25,27 +25,11 @@ public:
LanguageCategory(lldb::LanguageType lang_type);
- bool Get(FormattersMatchData &match_data, lldb::TypeFormatImplSP &format_sp);
-
- bool Get(FormattersMatchData &match_data, lldb::TypeSummaryImplSP &format_sp);
-
- bool Get(FormattersMatchData &match_data,
- lldb::SyntheticChildrenSP &format_sp);
-
- bool Get(FormattersMatchData &match_data,
- lldb::TypeValidatorImplSP &format_sp);
-
- bool GetHardcoded(FormatManager &fmt_mgr, FormattersMatchData &match_data,
- lldb::TypeFormatImplSP &format_sp);
-
+ template <typename ImplSP>
+ bool Get(FormattersMatchData &match_data, ImplSP &format_sp);
+ template <typename ImplSP>
bool GetHardcoded(FormatManager &fmt_mgr, FormattersMatchData &match_data,
- lldb::TypeSummaryImplSP &format_sp);
-
- bool GetHardcoded(FormatManager &fmt_mgr, FormattersMatchData &match_data,
- lldb::SyntheticChildrenSP &format_sp);
-
- bool GetHardcoded(FormatManager &fmt_mgr, FormattersMatchData &match_data,
- lldb::TypeValidatorImplSP &format_sp);
+ ImplSP &format_sp);
lldb::TypeCategoryImplSP GetCategory() const;
@@ -63,7 +47,9 @@ private:
HardcodedFormatters::HardcodedFormatFinder m_hardcoded_formats;
HardcodedFormatters::HardcodedSummaryFinder m_hardcoded_summaries;
HardcodedFormatters::HardcodedSyntheticFinder m_hardcoded_synthetics;
- HardcodedFormatters::HardcodedValidatorFinder m_hardcoded_validators;
+
+ template <typename ImplSP>
+ auto &GetHardcodedFinder();
lldb_private::FormatCache m_format_cache;
diff --git a/lldb/include/lldb/DataFormatters/TypeCategory.h b/lldb/include/lldb/DataFormatters/TypeCategory.h
index a5438226bbbb..d5aab6dc3a52 100644
--- a/lldb/include/lldb/DataFormatters/TypeCategory.h
+++ b/lldb/include/lldb/DataFormatters/TypeCategory.h
@@ -67,7 +67,6 @@ private:
typedef FormatterContainerPair<TypeFormatImpl> FormatContainer;
typedef FormatterContainerPair<TypeSummaryImpl> SummaryContainer;
typedef FormatterContainerPair<TypeFilterImpl> FilterContainer;
- typedef FormatterContainerPair<TypeValidatorImpl> ValidatorContainer;
typedef FormatterContainerPair<SyntheticChildren> SynthContainer;
public:
@@ -86,9 +85,6 @@ public:
typedef SynthContainer::ExactMatchContainerSP SynthContainerSP;
typedef SynthContainer::RegexMatchContainerSP RegexSynthContainerSP;
- typedef ValidatorContainer::ExactMatchContainerSP ValidatorContainerSP;
- typedef ValidatorContainer::RegexMatchContainerSP RegexValidatorContainerSP;
-
template <typename T> class ForEachCallbacks {
public:
ForEachCallbacks() = default;
@@ -145,18 +141,6 @@ public:
m_synth_regex = callback;
return *this;
}
- template <typename U = TypeValidatorImpl>
- typename std::enable_if<std::is_same<U, T>::value, ForEachCallbacks &>::type
- SetExact(ValidatorContainer::ExactMatchForEachCallback callback) {
- m_validator_exact = callback;
- return *this;
- }
- template <typename U = TypeValidatorImpl>
- typename std::enable_if<std::is_same<U, T>::value, ForEachCallbacks &>::type
- SetWithRegex(ValidatorContainer::RegexMatchForEachCallback callback) {
- m_validator_regex = callback;
- return *this;
- }
FormatContainer::ExactMatchForEachCallback GetFormatExactCallback() const {
return m_format_exact;
@@ -188,15 +172,6 @@ public:
return m_synth_regex;
}
- ValidatorContainer::ExactMatchForEachCallback
- GetValidatorExactCallback() const {
- return m_validator_exact;
- }
- ValidatorContainer::RegexMatchForEachCallback
- GetValidatorRegexCallback() const {
- return m_validator_regex;
- }
-
private:
FormatContainer::ExactMatchForEachCallback m_format_exact;
FormatContainer::RegexMatchForEachCallback m_format_regex;
@@ -209,13 +184,9 @@ public:
SynthContainer::ExactMatchForEachCallback m_synth_exact;
SynthContainer::RegexMatchForEachCallback m_synth_regex;
-
- ValidatorContainer::ExactMatchForEachCallback m_validator_exact;
- ValidatorContainer::RegexMatchForEachCallback m_validator_regex;
};
- TypeCategoryImpl(IFormatChangeListener *clist, ConstString name,
- std::initializer_list<lldb::LanguageType> langs = {});
+ TypeCategoryImpl(IFormatChangeListener *clist, ConstString name);
template <typename T> void ForEach(const ForEachCallbacks<T> &foreach) {
GetTypeFormatsContainer()->ForEach(foreach.GetFormatExactCallback());
@@ -230,10 +201,6 @@ public:
GetTypeSyntheticsContainer()->ForEach(foreach.GetSynthExactCallback());
GetRegexTypeSyntheticsContainer()->ForEach(foreach.GetSynthRegexCallback());
-
- GetTypeValidatorsContainer()->ForEach(foreach.GetValidatorExactCallback());
- GetRegexTypeValidatorsContainer()->ForEach(
- foreach.GetValidatorRegexCallback());
}
FormatContainerSP GetTypeFormatsContainer() {
@@ -278,9 +245,6 @@ public:
SynthContainer::MapValueType
GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp);
- ValidatorContainer::MapValueType
- GetValidatorForType(lldb::TypeNameSpecifierImplSP type_sp);
-
lldb::TypeNameSpecifierImplSP
GetTypeNameSpecifierForFormatAtIndex(size_t index);
@@ -311,19 +275,6 @@ public:
lldb::TypeNameSpecifierImplSP
GetTypeNameSpecifierForSyntheticAtIndex(size_t index);
- ValidatorContainerSP GetTypeValidatorsContainer() {
- return m_validator_cont.GetExactMatch();
- }
-
- RegexValidatorContainerSP GetRegexTypeValidatorsContainer() {
- return m_validator_cont.GetRegexMatch();
- }
-
- ValidatorContainer::MapValueType GetValidatorAtIndex(size_t index);
-
- lldb::TypeNameSpecifierImplSP
- GetTypeNameSpecifierForValidatorAtIndex(size_t index);
-
bool IsEnabled() const { return m_enabled; }
uint32_t GetEnabledPosition() {
@@ -333,18 +284,15 @@ public:
return m_enabled_position;
}
- bool Get(ValueObject &valobj, const FormattersMatchVector &candidates,
+ bool Get(lldb::LanguageType lang, const FormattersMatchVector &candidates,
lldb::TypeFormatImplSP &entry, uint32_t *reason = nullptr);
- bool Get(ValueObject &valobj, const FormattersMatchVector &candidates,
+ bool Get(lldb::LanguageType lang, const FormattersMatchVector &candidates,
lldb::TypeSummaryImplSP &entry, uint32_t *reason = nullptr);
- bool Get(ValueObject &valobj, const FormattersMatchVector &candidates,
+ bool Get(lldb::LanguageType lang, const FormattersMatchVector &candidates,
lldb::SyntheticChildrenSP &entry, uint32_t *reason = nullptr);
- bool Get(ValueObject &valobj, const FormattersMatchVector &candidates,
- lldb::TypeValidatorImplSP &entry, uint32_t *reason = nullptr);
-
void Clear(FormatCategoryItems items = ALL_ITEM_TYPES);
bool Delete(ConstString name, FormatCategoryItems items = ALL_ITEM_TYPES);
@@ -359,8 +307,6 @@ public:
void AddLanguage(lldb::LanguageType lang);
- bool HasLanguage(lldb::LanguageType lang);
-
std::string GetDescription();
bool AnyMatches(ConstString type_name,
@@ -376,7 +322,6 @@ private:
SummaryContainer m_summary_cont;
FilterContainer m_filter_cont;
SynthContainer m_synth_cont;
- ValidatorContainer m_validator_cont;
bool m_enabled;
@@ -394,7 +339,7 @@ private:
void Disable() { Enable(false, UINT32_MAX); }
- bool IsApplicable(ValueObject &valobj);
+ bool IsApplicable(lldb::LanguageType lang);
uint32_t GetLastEnabledPosition() { return m_enabled_position; }
@@ -417,9 +362,6 @@ private:
friend class FormattersContainer<lldb::RegularExpressionSP,
ScriptedSyntheticChildren>;
- friend class FormattersContainer<ConstString, TypeValidatorImpl>;
- friend class FormattersContainer<lldb::RegularExpressionSP,
- TypeValidatorImpl>;
};
} // namespace lldb_private
diff --git a/lldb/include/lldb/DataFormatters/TypeCategoryMap.h b/lldb/include/lldb/DataFormatters/TypeCategoryMap.h
index 753b58cb465e..ae577a334014 100644
--- a/lldb/include/lldb/DataFormatters/TypeCategoryMap.h
+++ b/lldb/include/lldb/DataFormatters/TypeCategoryMap.h
@@ -77,14 +77,7 @@ public:
uint32_t GetCount() { return m_map.size(); }
- lldb::TypeFormatImplSP GetFormat(FormattersMatchData &match_data);
-
- lldb::TypeSummaryImplSP GetSummaryFormat(FormattersMatchData &match_data);
-
- lldb::SyntheticChildrenSP
- GetSyntheticChildren(FormattersMatchData &match_data);
-
- lldb::TypeValidatorImplSP GetValidator(FormattersMatchData &match_data);
+ template <typename ImplSP> void Get(FormattersMatchData &, ImplSP &);
private:
class delete_matching_categories {
diff --git a/lldb/include/lldb/DataFormatters/TypeValidator.h b/lldb/include/lldb/DataFormatters/TypeValidator.h
deleted file mode 100644
index 531812eeb056..000000000000
--- a/lldb/include/lldb/DataFormatters/TypeValidator.h
+++ /dev/null
@@ -1,201 +0,0 @@
-//===-- TypeValidator.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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef lldb_TypeValidator_h_
-#define lldb_TypeValidator_h_
-
-
-#include <functional>
-#include <string>
-
-
-#include "lldb/lldb-enumerations.h"
-#include "lldb/lldb-private-enumerations.h"
-#include "lldb/lldb-public.h"
-
-namespace lldb_private {
-
-class TypeValidatorImpl {
-public:
- class Flags {
- public:
- Flags() : m_flags(lldb::eTypeOptionCascade) {}
-
- Flags(const Flags &other) : m_flags(other.m_flags) {}
-
- Flags(uint32_t value) : m_flags(value) {}
-
- Flags &operator=(const Flags &rhs) {
- if (&rhs != this)
- m_flags = rhs.m_flags;
-
- return *this;
- }
-
- Flags &operator=(const uint32_t &rhs) {
- m_flags = rhs;
- return *this;
- }
-
- Flags &Clear() {
- m_flags = 0;
- return *this;
- }
-
- bool GetCascades() const {
- return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade;
- }
-
- Flags &SetCascades(bool value = true) {
- if (value)
- m_flags |= lldb::eTypeOptionCascade;
- else
- m_flags &= ~lldb::eTypeOptionCascade;
- return *this;
- }
-
- bool GetSkipPointers() const {
- return (m_flags & lldb::eTypeOptionSkipPointers) ==
- lldb::eTypeOptionSkipPointers;
- }
-
- Flags &SetSkipPointers(bool value = true) {
- if (value)
- m_flags |= lldb::eTypeOptionSkipPointers;
- else
- m_flags &= ~lldb::eTypeOptionSkipPointers;
- return *this;
- }
-
- bool GetSkipReferences() const {
- return (m_flags & lldb::eTypeOptionSkipReferences) ==
- lldb::eTypeOptionSkipReferences;
- }
-
- Flags &SetSkipReferences(bool value = true) {
- if (value)
- m_flags |= lldb::eTypeOptionSkipReferences;
- else
- m_flags &= ~lldb::eTypeOptionSkipReferences;
- return *this;
- }
-
- bool GetNonCacheable() const {
- return (m_flags & lldb::eTypeOptionNonCacheable) ==
- lldb::eTypeOptionNonCacheable;
- }
-
- Flags &SetNonCacheable(bool value = true) {
- if (value)
- m_flags |= lldb::eTypeOptionNonCacheable;
- else
- m_flags &= ~lldb::eTypeOptionNonCacheable;
- return *this;
- }
-
- uint32_t GetValue() { return m_flags; }
-
- void SetValue(uint32_t value) { m_flags = value; }
-
- private:
- uint32_t m_flags;
- };
-
- TypeValidatorImpl(const Flags &flags = Flags());
-
- typedef std::shared_ptr<TypeValidatorImpl> SharedPointer;
-
- virtual ~TypeValidatorImpl();
-
- bool Cascades() const { return m_flags.GetCascades(); }
- bool SkipsPointers() const { return m_flags.GetSkipPointers(); }
- bool SkipsReferences() const { return m_flags.GetSkipReferences(); }
- bool NonCacheable() const { return m_flags.GetNonCacheable(); }
-
- void SetCascades(bool value) { m_flags.SetCascades(value); }
-
- void SetSkipsPointers(bool value) { m_flags.SetSkipPointers(value); }
-
- void SetSkipsReferences(bool value) { m_flags.SetSkipReferences(value); }
-
- void SetNonCacheable(bool value) { m_flags.SetNonCacheable(value); }
-
- uint32_t GetOptions() { return m_flags.GetValue(); }
-
- void SetOptions(uint32_t value) { m_flags.SetValue(value); }
-
- uint32_t &GetRevision() { return m_my_revision; }
-
- enum class Type { eTypeUnknown, eTypeCXX };
-
- struct ValidationResult {
- TypeValidatorResult m_result;
- std::string m_message;
- };
-
- virtual Type GetType() { return Type::eTypeUnknown; }
-
- // we are using a ValueObject* instead of a ValueObjectSP because we do not
- // need to hold on to this for extended periods of time and we trust the
- // ValueObject to stay around for as long as it is required for us to
- // generate its value
- virtual ValidationResult FormatObject(ValueObject *valobj) const = 0;
-
- virtual std::string GetDescription() = 0;
-
- static ValidationResult Success();
-
- static ValidationResult Failure(std::string message);
-
-protected:
- Flags m_flags;
- uint32_t m_my_revision;
-
-private:
- DISALLOW_COPY_AND_ASSIGN(TypeValidatorImpl);
-};
-
-class TypeValidatorImpl_CXX : public TypeValidatorImpl {
-public:
- typedef std::function<TypeValidatorImpl::ValidationResult(
- ValueObject *valobj)>
- ValidatorFunction;
-
- TypeValidatorImpl_CXX(ValidatorFunction f, std::string d,
- const TypeValidatorImpl::Flags &flags = Flags());
-
- typedef std::shared_ptr<TypeValidatorImpl_CXX> SharedPointer;
-
- ~TypeValidatorImpl_CXX() override;
-
- ValidatorFunction GetValidatorFunction() const {
- return m_validator_function;
- }
-
- void SetValidatorFunction(ValidatorFunction f) { m_validator_function = f; }
-
- TypeValidatorImpl::Type GetType() override {
- return TypeValidatorImpl::Type::eTypeCXX;
- }
-
- ValidationResult FormatObject(ValueObject *valobj) const override;
-
- std::string GetDescription() override;
-
-protected:
- std::string m_description;
- ValidatorFunction m_validator_function;
-
-private:
- DISALLOW_COPY_AND_ASSIGN(TypeValidatorImpl_CXX);
-};
-
-} // namespace lldb_private
-
-#endif // lldb_TypeValidator_h_
diff --git a/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h b/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
index 41adc2d2b5b2..33813b38701c 100644
--- a/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
+++ b/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
@@ -62,8 +62,6 @@ protected:
bool ShouldPrintValueObject();
- bool ShouldPrintValidation();
-
bool IsNil();
bool IsUninitialized();
@@ -76,10 +74,6 @@ protected:
bool IsAggregate();
- bool PrintValidationMarkerIfNeeded();
-
- bool PrintValidationErrorIfNeeded();
-
bool PrintLocationIfNeeded();
void PrintDecl();
@@ -145,7 +139,6 @@ private:
std::string m_summary;
std::string m_error;
bool m_val_summary_ok;
- std::pair<TypeValidatorResult, std::string> m_validation;
friend struct StringSummaryFormat;
diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h
index 44015b4e418f..bfae142d5e01 100644
--- a/lldb/include/lldb/Expression/DWARFExpression.h
+++ b/lldb/include/lldb/Expression/DWARFExpression.h
@@ -34,15 +34,6 @@ namespace lldb_private {
/// location expression or a location list and interprets it.
class DWARFExpression {
public:
- enum LocationListFormat : uint8_t {
- NonLocationList, // Not a location list
- RegularLocationList, // Location list format used in non-split dwarf files
- SplitDwarfLocationList, // Location list format used in pre-DWARF v5 split
- // dwarf files (.debug_loc.dwo)
- LocLists, // Location list format used in DWARF v5
- // (.debug_loclists/.debug_loclists.dwo).
- };
-
DWARFExpression();
/// Constructor
@@ -85,8 +76,8 @@ public:
/// Search for a load address in the location list
///
- /// \param[in] process
- /// The process to use when resolving the load address
+ /// \param[in] func_load_addr
+ /// The actual address of the function containing this location list.
///
/// \param[in] addr
/// The address to resolve
@@ -98,7 +89,7 @@ public:
// LocationListContainsLoadAddress (Process* process, const Address &addr)
// const;
//
- bool LocationListContainsAddress(lldb::addr_t loclist_base_addr,
+ bool LocationListContainsAddress(lldb::addr_t func_load_addr,
lldb::addr_t addr) const;
/// If a location is not a location list, return true if the location
@@ -138,13 +129,15 @@ public:
/// Tells the expression that it refers to a location list.
///
- /// \param[in] slide
- /// This value should be a slide that is applied to any values
- /// in the location list data so the values become zero based
- /// offsets into the object that owns the location list. We need
- /// to make location lists relative to the objects that own them
- /// so we can relink addresses on the fly.
- void SetLocationListSlide(lldb::addr_t slide);
+ /// \param[in] cu_file_addr
+ /// The base address to use for interpreting relative location list
+ /// entries.
+ /// \param[in] func_file_addr
+ /// The file address of the function containing this location list. This
+ /// address will be used to relocate the location list on the fly (in
+ /// conjuction with the func_load_addr arguments).
+ void SetLocationListAddresses(lldb::addr_t cu_file_addr,
+ lldb::addr_t func_file_addr);
/// Return the call-frame-info style register kind
int GetRegisterKind();
@@ -158,8 +151,7 @@ public:
/// Wrapper for the static evaluate function that accepts an
/// ExecutionContextScope instead of an ExecutionContext and uses member
/// variables to populate many operands
- bool Evaluate(ExecutionContextScope *exe_scope,
- lldb::addr_t loclist_base_load_addr,
+ bool Evaluate(ExecutionContextScope *exe_scope, lldb::addr_t func_load_addr,
const Value *initial_value_ptr, const Value *object_address_ptr,
Value &result, Status *error_ptr) const;
@@ -184,19 +176,6 @@ public:
/// This is a static method so the opcodes need to be provided
/// explicitly.
///
- /// \param[in] expr_locals
- /// If the location expression was produced by the expression parser,
- /// the list of local variables referenced by the DWARF expression.
- /// This list should already have been populated during parsing;
- /// the DWARF expression refers to variables by index. Can be NULL if
- /// the location expression uses no locals.
- ///
- /// \param[in] decl_map
- /// If the location expression was produced by the expression parser,
- /// the list of external variables referenced by the location
- /// expression. Can be NULL if the location expression uses no
- /// external variables.
- ///
/// \param[in] reg_ctx
/// An optional parameter which provides a RegisterContext for use
/// when evaluating the expression (i.e. for fetching register values).
@@ -235,8 +214,8 @@ public:
}
bool DumpLocationForAddress(Stream *s, lldb::DescriptionLevel level,
- lldb::addr_t loclist_base_load_addr,
- lldb::addr_t address, ABI *abi);
+ lldb::addr_t func_load_addr, lldb::addr_t address,
+ ABI *abi);
static bool PrintDWARFExpression(Stream &s, const DataExtractor &data,
int address_size, int dwarf_ref_size,
@@ -251,7 +230,7 @@ public:
private:
/// Pretty-prints the location expression to a stream
///
- /// \param[in] stream
+ /// \param[in] s
/// The stream to use for pretty-printing.
///
/// \param[in] offset
@@ -266,18 +245,12 @@ private:
/// \param[in] abi
/// An optional ABI plug-in that can be used to resolve register
/// names.
- void DumpLocation(Stream *s, lldb::offset_t offset, lldb::offset_t length,
+ void DumpLocation(Stream *s, const DataExtractor &data,
lldb::DescriptionLevel level, ABI *abi) const;
- bool GetLocation(lldb::addr_t base_addr, lldb::addr_t pc,
- lldb::offset_t &offset, lldb::offset_t &len);
-
- static bool AddressRangeForLocationListEntry(
- const DWARFUnit *dwarf_cu, const DataExtractor &debug_loc_data,
- lldb::offset_t *offset_ptr, lldb::addr_t &low_pc, lldb::addr_t &high_pc);
-
- bool GetOpAndEndOffsets(StackFrame &frame, lldb::offset_t &op_offset,
- lldb::offset_t &end_offset);
+ llvm::Optional<DataExtractor>
+ GetLocationExpression(lldb::addr_t load_function_start,
+ lldb::addr_t addr) const;
/// Module which defined this expression.
lldb::ModuleWP m_module_wp;
@@ -293,10 +266,11 @@ private:
/// One of the defines that starts with LLDB_REGKIND_
lldb::RegisterKind m_reg_kind;
- /// A value used to slide the location list offsets so that m_c they are
- /// relative to the object that owns the location list (the function for
- /// frame base and variable location lists)
- lldb::addr_t m_loclist_slide;
+ struct LoclistAddresses {
+ lldb::addr_t cu_file_addr;
+ lldb::addr_t func_file_addr;
+ };
+ llvm::Optional<LoclistAddresses> m_loclist_addresses;
};
} // namespace lldb_private
diff --git a/lldb/include/lldb/Expression/Expression.h b/lldb/include/lldb/Expression/Expression.h
index 2f0183cf269b..e0ea7e99f4f9 100644
--- a/lldb/include/lldb/Expression/Expression.h
+++ b/lldb/include/lldb/Expression/Expression.h
@@ -32,22 +32,11 @@ class RecordingMemoryManager;
/// LLVM IR from the expression.
class Expression {
public:
- /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
- enum ExpressionKind {
- eKindFunctionCaller,
- eKindClangFunctionCaller,
- eKindUserExpression,
- eKindLLVMUserExpression,
- eKindClangUserExpression,
- eKindUtilityFunction,
- eKindClangUtilityFunction,
- };
-
enum ResultType { eResultTypeAny, eResultTypeId };
- Expression(Target &target, ExpressionKind kind);
+ Expression(Target &target);
- Expression(ExecutionContextScope &exe_scope, ExpressionKind kind);
+ Expression(ExecutionContextScope &exe_scope);
/// Destructor
virtual ~Expression() {}
@@ -64,6 +53,10 @@ public:
/// default, return eLanguageTypeUnknown.
virtual lldb::LanguageType Language() { return lldb::eLanguageTypeUnknown; }
+ /// Return the Materializer that the parser should use when registering
+ /// external values.
+ virtual Materializer *GetMaterializer() { return nullptr; }
+
/// Return the desired result type of the function, or eResultTypeAny if
/// indifferent.
virtual ResultType DesiredResultType() { return eResultTypeAny; }
@@ -90,12 +83,9 @@ public:
virtual ExpressionTypeSystemHelper *GetTypeSystemHelper() { return nullptr; }
- /// LLVM-style RTTI support.
- ExpressionKind getKind() const { return m_kind; }
-
-private:
- /// LLVM-style RTTI support.
- const ExpressionKind m_kind;
+ // LLVM RTTI support
+ virtual bool isA(const void *ClassID) const = 0;
+
protected:
lldb::TargetWP m_target_wp; /// Expression's always have to have a target...
lldb::ProcessWP m_jit_process_wp; /// An expression might have a process, but
diff --git a/lldb/include/lldb/Expression/ExpressionParser.h b/lldb/include/lldb/Expression/ExpressionParser.h
index 59f7c1592e83..2e7b3075d509 100644
--- a/lldb/include/lldb/Expression/ExpressionParser.h
+++ b/lldb/include/lldb/Expression/ExpressionParser.h
@@ -29,7 +29,7 @@ public:
///
/// Initializes class variables.
///
- /// \param[in] exe_scope,
+ /// \param[in] exe_scope
/// If non-NULL, an execution context scope that can help to
/// correctly create an expression with a valid process for
/// optional tuning Objective-C runtime support. Can be NULL.
@@ -76,17 +76,6 @@ public:
virtual bool Complete(CompletionRequest &request, unsigned line, unsigned pos,
unsigned typed_pos) = 0;
- /// Parse a single expression and convert it to IR using Clang. Don't wrap
- /// the expression in anything at all.
- ///
- /// \param[in] diagnostic_manager
- /// The diagnostic manager in which to store the errors and warnings.
- ///
- /// \return
- /// The number of errors encountered during parsing. 0 means
- /// success.
- virtual unsigned Parse(DiagnosticManager &diagnostic_manager) = 0;
-
/// Try to use the FixIts in the diagnostic_manager to rewrite the
/// expression. If successful, the rewritten expression is stored in the
/// diagnostic_manager, get it out with GetFixedExpression.
diff --git a/lldb/include/lldb/Expression/ExpressionSourceCode.h b/lldb/include/lldb/Expression/ExpressionSourceCode.h
index e7d39e7ca24a..db8ef967ab15 100644
--- a/lldb/include/lldb/Expression/ExpressionSourceCode.h
+++ b/lldb/include/lldb/Expression/ExpressionSourceCode.h
@@ -11,6 +11,7 @@
#include "lldb/lldb-enumerations.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
#include <string>
diff --git a/lldb/include/lldb/Expression/ExpressionVariable.h b/lldb/include/lldb/Expression/ExpressionVariable.h
index 08c987270bfe..c20c2301bb54 100644
--- a/lldb/include/lldb/Expression/ExpressionVariable.h
+++ b/lldb/include/lldb/Expression/ExpressionVariable.h
@@ -98,9 +98,7 @@ public:
EVTypeIsReference = 1 << 6, ///< The original type of this variable is a
///reference, so materialize the value rather
///than the location
- EVUnknownType = 1 << 7, ///< This is a symbol of unknown type, and the type
- ///must be resolved after parsing is complete
- EVBareRegister = 1 << 8 ///< This variable is a direct reference to $pc or
+ EVBareRegister = 1 << 7 ///< This variable is a direct reference to $pc or
///some other entity.
};
diff --git a/lldb/include/lldb/Expression/FunctionCaller.h b/lldb/include/lldb/Expression/FunctionCaller.h
index ea9d0205bf86..1303655f449f 100644
--- a/lldb/include/lldb/Expression/FunctionCaller.h
+++ b/lldb/include/lldb/Expression/FunctionCaller.h
@@ -54,22 +54,20 @@ namespace lldb_private {
/// Any of the methods that take arg_addr_ptr can be passed nullptr, and the
/// argument space will be managed for you.
class FunctionCaller : public Expression {
+ // LLVM RTTI support
+ static char ID;
+
public:
- /// LLVM-style RTTI support.
- static bool classof(const Expression *E) {
- return E->getKind() == eKindFunctionCaller;
- }
-
+ bool isA(const void *ClassID) const override { return ClassID == &ID; }
+ static bool classof(const Expression *obj) { return obj->isA(&ID); }
+
/// Constructor
///
/// \param[in] exe_scope
/// An execution context scope that gets us at least a target and
/// process.
///
- /// \param[in] ast_context
- /// The AST context to evaluate argument types in.
- ///
- /// \param[in] return_qualtype
+ /// \param[in] return_type
/// An opaque Clang QualType for the function result. Should be
/// defined in ast_context.
///
@@ -223,21 +221,12 @@ public:
/// The execution context to insert the function and its arguments
/// into.
///
- /// \param[in] func_addr
- /// The address of the function in the target process.
- ///
/// \param[in] args_addr
/// The address of the argument struct.
///
/// \param[in] diagnostic_manager
/// The diagnostic manager to report errors to.
///
- /// \param[in] stop_others
- /// True if other threads should pause during execution.
- ///
- /// \param[in] unwind_on_error
- /// True if the thread plan may simply be discarded if an error occurs.
- ///
/// \return
/// A ThreadPlan shared pointer for executing the function.
lldb::ThreadPlanSP
diff --git a/lldb/include/lldb/Expression/IRExecutionUnit.h b/lldb/include/lldb/Expression/IRExecutionUnit.h
index beff44db9d5e..05f2f8471ef8 100644
--- a/lldb/include/lldb/Expression/IRExecutionUnit.h
+++ b/lldb/include/lldb/Expression/IRExecutionUnit.h
@@ -173,6 +173,8 @@ private:
/// The address in the target process.
lldb::addr_t GetRemoteAddressForLocal(lldb::addr_t local_address);
+ typedef std::pair<lldb::addr_t, uintptr_t> AddrRange;
+
/// Look up the object in m_address_map that contains a given address, find
/// where it was copied to, and return its address range in the target
/// process
@@ -182,12 +184,11 @@ private:
///
/// \return
/// The range of the containing object in the target process.
- typedef std::pair<lldb::addr_t, uintptr_t> AddrRange;
AddrRange GetRemoteRangeForLocal(lldb::addr_t local_address);
/// Commit all allocations to the process and record where they were stored.
///
- /// \param[in] process
+ /// \param[in] process_sp
/// The process to allocate memory in.
///
/// \return
@@ -204,7 +205,7 @@ private:
/// Write the contents of all allocations to the process.
///
- /// \param[in] local_address
+ /// \param[in] process_sp
/// The process containing the allocations.
///
/// \return
@@ -298,16 +299,18 @@ private:
return false;
}
+ // Ignore any EHFrame registration.
void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
size_t Size) override {}
+ void deregisterEHFrames() override {}
uint64_t getSymbolAddress(const std::string &Name) override;
-
+
// Find the address of the symbol Name. If Name is a missing weak symbol
// then missing_weak will be true.
- uint64_t GetSymbolAddressAndPresence(const std::string &Name,
+ uint64_t GetSymbolAddressAndPresence(const std::string &Name,
bool &missing_weak);
-
+
llvm::JITSymbol findSymbol(const std::string &Name) override;
void *getPointerToNamedFunction(const std::string &Name,
@@ -326,18 +329,16 @@ private:
static const unsigned eSectionIDInvalid = (unsigned)-1;
- /// \class AllocationRecord IRExecutionUnit.h
- /// "lldb/Expression/IRExecutionUnit.h" Encapsulates a single allocation
- /// request made by the JIT.
- ///
- /// Allocations made by the JIT are first queued up and then applied in bulk
- /// to the underlying process.
enum class AllocationKind { Stub, Code, Data, Global, Bytes };
static lldb::SectionType
GetSectionTypeFromSectionName(const llvm::StringRef &name,
AllocationKind alloc_kind);
+ /// Encapsulates a single allocation request made by the JIT.
+ ///
+ /// Allocations made by the JIT are first queued up and then applied in bulk
+ /// to the underlying process.
struct AllocationRecord {
std::string m_name;
lldb::addr_t m_process_address;
diff --git a/lldb/include/lldb/Expression/LLVMUserExpression.h b/lldb/include/lldb/Expression/LLVMUserExpression.h
index c3b8ed506f17..2679c01a4e00 100644
--- a/lldb/include/lldb/Expression/LLVMUserExpression.h
+++ b/lldb/include/lldb/Expression/LLVMUserExpression.h
@@ -30,11 +30,14 @@ namespace lldb_private {
/// implementations of LLVMUserExpression - which will be vended through the
/// appropriate TypeSystem.
class LLVMUserExpression : public UserExpression {
+ // LLVM RTTI support
+ static char ID;
+
public:
- /// LLVM-style RTTI support.
- static bool classof(const Expression *E) {
- return E->getKind() == eKindLLVMUserExpression;
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || UserExpression::isA(ClassID);
}
+ static bool classof(const Expression *obj) { return obj->isA(&ID); }
// The IRPasses struct is filled in by a runtime after an expression is
// compiled and can be used to to run fixups/analysis passes as required.
@@ -51,8 +54,7 @@ public:
LLVMUserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr,
llvm::StringRef prefix, lldb::LanguageType language,
ResultType desired_type,
- const EvaluateExpressionOptions &options,
- ExpressionKind kind);
+ const EvaluateExpressionOptions &options);
~LLVMUserExpression() override;
bool FinalizeJITExecution(
@@ -63,6 +65,8 @@ public:
bool CanInterpret() override { return m_can_interpret; }
+ Materializer *GetMaterializer() override { return m_materializer_up.get(); }
+
/// Return the string that the parser should parse. Must be a full
/// translation unit.
const char *Text() override { return m_transformed_text.c_str(); }
diff --git a/lldb/include/lldb/Expression/REPL.h b/lldb/include/lldb/Expression/REPL.h
index d34a792f58f1..035ad63271e4 100644
--- a/lldb/include/lldb/Expression/REPL.h
+++ b/lldb/include/lldb/Expression/REPL.h
@@ -32,7 +32,7 @@ public:
/// Get a REPL with an existing target (or, failing that, a debugger to use),
/// and (optional) extra arguments for the compiler.
///
- /// \param[out] error
+ /// \param[out] Status
/// If this language is supported but the REPL couldn't be created, this
/// error is populated with the reason.
///
diff --git a/lldb/include/lldb/Expression/UserExpression.h b/lldb/include/lldb/Expression/UserExpression.h
index b1d52f8ddd55..83122d8ba518 100644
--- a/lldb/include/lldb/Expression/UserExpression.h
+++ b/lldb/include/lldb/Expression/UserExpression.h
@@ -33,12 +33,13 @@ namespace lldb_private {
/// implementations of UserExpression - which will be vended through the
/// appropriate TypeSystem.
class UserExpression : public Expression {
+ /// LLVM RTTI support.
+ static char ID;
+
public:
- /// LLVM-style RTTI support.
- static bool classof(const Expression *E) {
- return E->getKind() == eKindUserExpression;
- }
-
+ bool isA(const void *ClassID) const override { return ClassID == &ID; }
+ static bool classof(const Expression *obj) { return obj->isA(&ID); }
+
enum { kDefaultTimeout = 500000u };
/// Constructor
@@ -46,10 +47,6 @@ public:
/// \param[in] expr
/// The expression to parse.
///
- /// \param[in] expr_prefix
- /// If non-nullptr, a C string containing translation-unit level
- /// definitions to be included when the expression is parsed.
- ///
/// \param[in] language
/// If not eLanguageTypeUnknown, a language to use when parsing
/// the expression. Currently restricted to those languages
@@ -61,8 +58,7 @@ public:
UserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr,
llvm::StringRef prefix, lldb::LanguageType language,
ResultType desired_type,
- const EvaluateExpressionOptions &options,
- ExpressionKind kind);
+ const EvaluateExpressionOptions &options);
/// Destructor
~UserExpression() override;
@@ -166,8 +162,14 @@ public:
/// A pointer to direct at the persistent variable in which the
/// expression's result is stored.
///
- /// \param[in] function_stack_pointer
- /// A pointer to the base of the function's stack frame. This
+ /// \param[in] function_stack_bottom
+ /// A pointer to the bottom of the function's stack frame. This
+ /// is used to determine whether the expression result resides in
+ /// memory that will still be valid, or whether it needs to be
+ /// treated as homeless for the purpose of future expressions.
+ ///
+ /// \param[in] function_stack_top
+ /// A pointer to the top of the function's stack frame. This
/// is used to determine whether the expression result resides in
/// memory that will still be valid, or whether it needs to be
/// treated as homeless for the purpose of future expressions.
diff --git a/lldb/include/lldb/Expression/UtilityFunction.h b/lldb/include/lldb/Expression/UtilityFunction.h
index 26da081ddced..c3d185899b0f 100644
--- a/lldb/include/lldb/Expression/UtilityFunction.h
+++ b/lldb/include/lldb/Expression/UtilityFunction.h
@@ -28,12 +28,13 @@ namespace lldb_private {
/// self-contained function meant to be used from other code. Utility
/// functions can perform error-checking for ClangUserExpressions,
class UtilityFunction : public Expression {
+ // LLVM RTTI support
+ static char ID;
+
public:
- /// LLVM-style RTTI support.
- static bool classof(const Expression *E) {
- return E->getKind() == eKindUtilityFunction;
- }
-
+ bool isA(const void *ClassID) const override { return ClassID == &ID; }
+ static bool classof(const Expression *obj) { return obj->isA(&ID); }
+
/// Constructor
///
/// \param[in] text
@@ -42,7 +43,7 @@ public:
/// \param[in] name
/// The name of the function, as used in the text.
UtilityFunction(ExecutionContextScope &exe_scope, const char *text,
- const char *name, ExpressionKind kind);
+ const char *name);
~UtilityFunction() override;
@@ -59,16 +60,16 @@ public:
virtual bool Install(DiagnosticManager &diagnostic_manager,
ExecutionContext &exe_ctx) = 0;
- /// Check whether the given PC is inside the function
+ /// Check whether the given address is inside the function
///
/// Especially useful if the function dereferences nullptr to indicate a
/// failed assert.
///
- /// \param[in] pc
- /// The program counter to check.
+ /// \param[in] address
+ /// The address to check.
///
/// \return
- /// True if the program counter falls within the function's bounds;
+ /// True if the address falls within the function's bounds;
/// false if not (or the function is not JIT compiled)
bool ContainsAddress(lldb::addr_t address) {
// nothing is both >= LLDB_INVALID_ADDRESS and < LLDB_INVALID_ADDRESS, so
diff --git a/lldb/include/lldb/Host/Config.h.cmake b/lldb/include/lldb/Host/Config.h.cmake
index 662c07668d14..e9065ed04caa 100644
--- a/lldb/include/lldb/Host/Config.h.cmake
+++ b/lldb/include/lldb/Host/Config.h.cmake
@@ -9,15 +9,10 @@
#ifndef LLDB_HOST_CONFIG_H
#define LLDB_HOST_CONFIG_H
-#cmakedefine LLDB_CONFIG_TERMIOS_SUPPORTED
-
#cmakedefine01 LLDB_EDITLINE_USE_WCHAR
#cmakedefine01 LLDB_HAVE_EL_RFUNC_T
-#cmakedefine LLDB_DISABLE_POSIX
-
-#define LLDB_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}"
#cmakedefine01 HAVE_SYS_TYPES_H
@@ -35,6 +30,24 @@
#cmakedefine HAVE_LIBCOMPRESSION
#endif
+#cmakedefine01 LLDB_ENABLE_POSIX
+
+#cmakedefine01 LLDB_ENABLE_TERMIOS
+
#cmakedefine01 LLDB_ENABLE_LZMA
+#cmakedefine01 LLDB_ENABLE_CURSES
+
+#cmakedefine01 LLDB_ENABLE_LIBEDIT
+
+#cmakedefine01 LLDB_ENABLE_LIBXML2
+
+#cmakedefine01 LLDB_ENABLE_LUA
+
+#cmakedefine01 LLDB_ENABLE_PYTHON
+
+#cmakedefine LLDB_PYTHON_HOME "${LLDB_PYTHON_HOME}"
+
+#define LLDB_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}"
+
#endif // #ifndef LLDB_HOST_CONFIG_H
diff --git a/lldb/include/lldb/Host/Editline.h b/lldb/include/lldb/Host/Editline.h
index 65bf15531bc4..db3d9e48cfbb 100644
--- a/lldb/include/lldb/Host/Editline.h
+++ b/lldb/include/lldb/Host/Editline.h
@@ -32,6 +32,8 @@
#define liblldb_Editline_h_
#if defined(__cplusplus)
+#include "lldb/Host/Config.h"
+
#if LLDB_EDITLINE_USE_WCHAR
#include <codecvt>
#endif
@@ -133,6 +135,15 @@ enum class CursorLocation {
/// session
BlockEnd
};
+
+/// Operation for the history.
+enum class HistoryOperation {
+ Oldest,
+ Older,
+ Current,
+ Newer,
+ Newest
+};
}
using namespace line_editor;
@@ -258,11 +269,7 @@ private:
StringList GetInputAsStringList(int line_count = UINT32_MAX);
/// Replaces the current multi-line session with the next entry from history.
- /// When the parameter is
- /// true it will take the next earlier entry from history, when it is false it
- /// takes the next most
- /// recent.
- unsigned char RecallHistory(bool earlier);
+ unsigned char RecallHistory(HistoryOperation op);
/// Character reading implementation for EditLine that supports our multi-line
/// editing trickery.
diff --git a/lldb/include/lldb/Host/File.h b/lldb/include/lldb/Host/File.h
index 0102beb141ee..9beb20556dcd 100644
--- a/lldb/include/lldb/Host/File.h
+++ b/lldb/include/lldb/Host/File.h
@@ -76,9 +76,7 @@ public:
/// that takes an "off_t &offset" to ensure correct operation in multi-
/// threaded environments.
///
- /// \param[out] buf
- ///
- /// \param[in,out] num_bytes.
+ /// \param[in,out] num_bytes
/// Pass in the size of buf. Read will pass out the number
/// of bytes read. Zero bytes read with no error indicates
/// EOF.
@@ -93,8 +91,6 @@ public:
/// that takes an "off_t &offset" to ensure correct operation in multi-
/// threaded environments.
///
- /// \param[in] buf
- ///
/// \param[in,out] num_bytes
/// Pass in the size of buf. Write will pass out the number
/// of bytes written. Write will attempt write the full number
diff --git a/lldb/include/lldb/Host/HostInfoBase.h b/lldb/include/lldb/Host/HostInfoBase.h
index 6f6688941ac7..c59050cb34e9 100644
--- a/lldb/include/lldb/Host/HostInfoBase.h
+++ b/lldb/include/lldb/Host/HostInfoBase.h
@@ -33,17 +33,12 @@ public:
static void Initialize();
static void Terminate();
- /// Gets the host target triple as a const string.
+ /// Gets the host target triple.
///
/// \return
- /// A const string object containing the host target triple.
- static llvm::StringRef GetTargetTriple();
+ /// The host target triple.
+ static llvm::Triple GetTargetTriple();
- /// Gets the host architecture.
- ///
- /// \return
- /// A const architecture object that represents the host
- /// architecture.
enum ArchitectureKind {
eArchKindDefault, // The overall default architecture that applications will
// run on this host
diff --git a/lldb/include/lldb/Host/HostProcess.h b/lldb/include/lldb/Host/HostProcess.h
index d48ff1fc90ee..fcea52a284d9 100644
--- a/lldb/include/lldb/Host/HostProcess.h
+++ b/lldb/include/lldb/Host/HostProcess.h
@@ -12,7 +12,6 @@
#include "lldb/Host/Host.h"
#include "lldb/lldb-types.h"
-/// \class HostInfo HostInfo.h "lldb/Host/HostProcess.h"
/// A class that represents a running process on the host machine.
///
/// HostProcess allows querying and manipulation of processes running on the
diff --git a/lldb/include/lldb/Host/PseudoTerminal.h b/lldb/include/lldb/Host/PseudoTerminal.h
index 8b27890ddeeb..18679b6fcdd9 100644
--- a/lldb/include/lldb/Host/PseudoTerminal.h
+++ b/lldb/include/lldb/Host/PseudoTerminal.h
@@ -61,14 +61,14 @@ public:
/// PseudoTerminal::ReleaseMasterFileDescriptor() @li
/// PseudoTerminal::ReleaseSaveFileDescriptor()
///
- /// \param[out] error
+ /// \param[out] error_str
/// An pointer to an error that can describe any errors that
/// occur. This can be NULL if no error status is desired.
///
/// \return
- /// \li \b Parent process: a child process ID that is greater
+ /// \b Parent process: a child process ID that is greater
/// than zero, or -1 if the fork fails.
- /// \li \b Child process: zero.
+ /// \b Child process: zero.
lldb::pid_t Fork(char *error_str, size_t error_len);
/// The master file descriptor accessor.
@@ -104,7 +104,7 @@ public:
/// A master pseudo terminal should already be valid prior to
/// calling this function.
///
- /// \param[out] error
+ /// \param[out] error_str
/// An pointer to an error that can describe any errors that
/// occur. This can be NULL if no error status is desired.
///
@@ -136,14 +136,14 @@ public:
/// Flags to use when calling \c posix_openpt(\a oflag).
/// A value of "O_RDWR|O_NOCTTY" is suggested.
///
- /// \param[out] error
+ /// \param[out] error_str
/// An pointer to an error that can describe any errors that
/// occur. This can be NULL if no error status is desired.
///
/// \return
- /// \li \b true when the master files descriptor is
+ /// \b true when the master files descriptor is
/// successfully opened.
- /// \li \b false if anything goes wrong.
+ /// \b false if anything goes wrong.
///
/// \see PseudoTerminal::GetMasterFileDescriptor() @see
/// PseudoTerminal::ReleaseMasterFileDescriptor()
@@ -165,14 +165,14 @@ public:
/// \param[in] oflag
/// Flags to use when calling \c open(\a oflag).
///
- /// \param[out] error
+ /// \param[out] error_str
/// An pointer to an error that can describe any errors that
/// occur. This can be NULL if no error status is desired.
///
/// \return
- /// \li \b true when the master files descriptor is
+ /// \b true when the master files descriptor is
/// successfully opened.
- /// \li \b false if anything goes wrong.
+ /// \b false if anything goes wrong.
///
/// \see PseudoTerminal::OpenFirstAvailableMaster() @see
/// PseudoTerminal::GetSlaveFileDescriptor() @see
diff --git a/lldb/include/lldb/Host/SocketAddress.h b/lldb/include/lldb/Host/SocketAddress.h
index 620827ff6eb1..766303a3c1fd 100644
--- a/lldb/include/lldb/Host/SocketAddress.h
+++ b/lldb/include/lldb/Host/SocketAddress.h
@@ -48,8 +48,6 @@ public:
~SocketAddress();
// Operators
- const SocketAddress &operator=(const SocketAddress &rhs);
-
const SocketAddress &operator=(const struct addrinfo *addr_info);
const SocketAddress &operator=(const struct sockaddr &s);
diff --git a/lldb/include/lldb/Host/Terminal.h b/lldb/include/lldb/Host/Terminal.h
index e5e96eeda3fe..671f8d63f89f 100644
--- a/lldb/include/lldb/Host/Terminal.h
+++ b/lldb/include/lldb/Host/Terminal.h
@@ -117,7 +117,7 @@ protected:
// Member variables
Terminal m_tty; ///< A terminal
int m_tflags; ///< Cached tflags information.
-#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
+#if LLDB_ENABLE_TERMIOS
std::unique_ptr<struct termios>
m_termios_up; ///< Cached terminal state information.
#endif
diff --git a/lldb/include/lldb/Host/XML.h b/lldb/include/lldb/Host/XML.h
index 625cf4381286..ca51d304dc8f 100644
--- a/lldb/include/lldb/Host/XML.h
+++ b/lldb/include/lldb/Host/XML.h
@@ -9,7 +9,9 @@
#ifndef liblldb_XML_h_
#define liblldb_XML_h_
-#if defined(LIBXML2_DEFINED)
+#include "lldb/Host/Config.h"
+
+#if LLDB_ENABLE_LIBXML2
#include <libxml/xmlreader.h>
#endif
@@ -25,7 +27,7 @@
namespace lldb_private {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
typedef xmlNodePtr XMLNodeImpl;
typedef xmlDocPtr XMLDocumentImpl;
#else
diff --git a/lldb/include/lldb/Interpreter/CommandInterpreter.h b/lldb/include/lldb/Interpreter/CommandInterpreter.h
index 3b98b2a521dd..d08951e608cb 100644
--- a/lldb/include/lldb/Interpreter/CommandInterpreter.h
+++ b/lldb/include/lldb/Interpreter/CommandInterpreter.h
@@ -51,7 +51,7 @@ public:
/// \param[in] echo_comments
/// If \b true, echo command even if it is a pure comment line. If
/// \b false, print no ouput in this case. This setting has an effect only
- /// if \param echo_commands is \b true.
+ /// if echo_commands is \b true.
/// \param[in] print_results
/// If \b true and the command succeeds, print the results of the command
/// after executing it. If \b false, execute silently.
@@ -428,13 +428,14 @@ public:
void RunCommandInterpreter(bool auto_handle_events, bool spawn_thread,
CommandInterpreterRunOptions &options);
+
void GetLLDBCommandsFromIOHandler(const char *prompt,
IOHandlerDelegate &delegate,
- bool asynchronously, void *baton);
+ void *baton = nullptr);
void GetPythonCommandsFromIOHandler(const char *prompt,
IOHandlerDelegate &delegate,
- bool asynchronously, void *baton);
+ void *baton = nullptr);
const char *GetCommandPrefix();
@@ -443,13 +444,13 @@ public:
bool GetPromptOnQuit() const;
- void SetPromptOnQuit(bool b);
+ void SetPromptOnQuit(bool enable);
bool GetEchoCommands() const;
- void SetEchoCommands(bool b);
+ void SetEchoCommands(bool enable);
bool GetEchoCommentCommands() const;
- void SetEchoCommentCommands(bool b);
+ void SetEchoCommentCommands(bool enable);
/// Specify if the command interpreter should allow that the user can
/// specify a custom exit code when calling 'quit'.
diff --git a/lldb/include/lldb/Interpreter/CommandObject.h b/lldb/include/lldb/Interpreter/CommandObject.h
index 2dad84f036c0..f4dc2d606dda 100644
--- a/lldb/include/lldb/Interpreter/CommandObject.h
+++ b/lldb/include/lldb/Interpreter/CommandObject.h
@@ -226,7 +226,7 @@ public:
/// option. Don't override this method, override HandleArgumentCompletion
/// instead unless you have special reasons.
///
- /// \param[in/out] request
+ /// \param[in,out] request
/// The completion request that needs to be answered.
virtual void HandleCompletion(CompletionRequest &request);
@@ -235,7 +235,7 @@ public:
/// We've constructed the map of options and their arguments as well if that
/// is helpful for the completion.
///
- /// \param[in/out] request
+ /// \param[in,out] request
/// The completion request that needs to be answered.
virtual void
HandleArgumentCompletion(CompletionRequest &request,
@@ -261,8 +261,8 @@ public:
/// Get the command that appropriate for a "repeat" of the current command.
///
- /// \param[in] current_command_line
- /// The complete current command line.
+ /// \param[in] current_command_args
+ /// The command arguments.
///
/// \return
/// nullptr if there is no special repeat command - it will use the
diff --git a/lldb/include/lldb/Interpreter/CommandReturnObject.h b/lldb/include/lldb/Interpreter/CommandReturnObject.h
index 61e57fb798a1..8af76e07e5ae 100644
--- a/lldb/include/lldb/Interpreter/CommandReturnObject.h
+++ b/lldb/include/lldb/Interpreter/CommandReturnObject.h
@@ -9,7 +9,6 @@
#ifndef liblldb_CommandReturnObject_h_
#define liblldb_CommandReturnObject_h_
-#include "lldb/Core/STLUtils.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StreamTee.h"
diff --git a/lldb/include/lldb/Interpreter/OptionGroupPythonClassWithDict.h b/lldb/include/lldb/Interpreter/OptionGroupPythonClassWithDict.h
index 6aec7eb0f0b8..2229c1aa08a2 100644
--- a/lldb/include/lldb/Interpreter/OptionGroupPythonClassWithDict.h
+++ b/lldb/include/lldb/Interpreter/OptionGroupPythonClassWithDict.h
@@ -24,13 +24,10 @@ namespace lldb_private {
class OptionGroupPythonClassWithDict : public OptionGroup {
public:
OptionGroupPythonClassWithDict(const char *class_use,
- int class_option = 'C',
- int key_option = 'k',
- int value_option = 'v',
- const char *class_long_option = "python-class",
- const char *key_long_option = "python-class-key",
- const char *value_long_option = "python-class-value",
- bool required = false);
+ bool is_class = true,
+ int class_option = 'C',
+ int key_option = 'k',
+ int value_option = 'v');
~OptionGroupPythonClassWithDict() override;
@@ -48,16 +45,17 @@ public:
const StructuredData::DictionarySP GetStructuredData() {
return m_dict_sp;
}
- const std::string &GetClassName() {
- return m_class_name;
+ const std::string &GetName() {
+ return m_name;
}
protected:
- std::string m_class_name;
+ std::string m_name;
std::string m_current_key;
StructuredData::DictionarySP m_dict_sp;
std::string m_class_usage_text, m_key_usage_text, m_value_usage_text;
- OptionDefinition m_option_definition[3];
+ bool m_is_class;
+ OptionDefinition m_option_definition[4];
};
} // namespace lldb_private
diff --git a/lldb/include/lldb/Interpreter/OptionValue.h b/lldb/include/lldb/Interpreter/OptionValue.h
index 9fc18551c26a..44c7f621a582 100644
--- a/lldb/include/lldb/Interpreter/OptionValue.h
+++ b/lldb/include/lldb/Interpreter/OptionValue.h
@@ -58,12 +58,7 @@ public:
eDumpGroupExport = (eDumpOptionCommand | eDumpOptionName | eDumpOptionValue)
};
- OptionValue()
- : m_callback(nullptr), m_baton(nullptr), m_value_was_set(false) {}
-
- OptionValue(const OptionValue &rhs)
- : m_callback(rhs.m_callback), m_baton(rhs.m_baton),
- m_value_was_set(rhs.m_value_was_set) {}
+ OptionValue() : m_value_was_set(false) {}
virtual ~OptionValue() = default;
@@ -308,22 +303,19 @@ public:
m_parent_wp = parent_sp;
}
- void SetValueChangedCallback(OptionValueChangedCallback callback,
- void *baton) {
- assert(m_callback == nullptr);
- m_callback = callback;
- m_baton = baton;
+ void SetValueChangedCallback(std::function<void()> callback) {
+ assert(!m_callback);
+ m_callback = std::move(callback);
}
void NotifyValueChanged() {
if (m_callback)
- m_callback(m_baton, this);
+ m_callback();
}
protected:
lldb::OptionValueWP m_parent_wp;
- OptionValueChangedCallback m_callback;
- void *m_baton;
+ std::function<void()> m_callback;
bool m_value_was_set; // This can be used to see if a value has been set
// by a call to SetValueFromCString(). It is often
// handy to know if an option value was set from the
diff --git a/lldb/include/lldb/Interpreter/OptionValueProperties.h b/lldb/include/lldb/Interpreter/OptionValueProperties.h
index bea2b3c91e00..980f01183ef5 100644
--- a/lldb/include/lldb/Interpreter/OptionValueProperties.h
+++ b/lldb/include/lldb/Interpreter/OptionValueProperties.h
@@ -198,8 +198,7 @@ public:
ConstString name);
void SetValueChangedCallback(uint32_t property_idx,
- OptionValueChangedCallback callback,
- void *baton);
+ std::function<void()> callback);
protected:
Property *ProtectedGetPropertyAtIndex(uint32_t idx) {
diff --git a/lldb/include/lldb/Interpreter/Options.h b/lldb/include/lldb/Interpreter/Options.h
index b6c824d5a199..d07c2560ef2d 100644
--- a/lldb/include/lldb/Interpreter/Options.h
+++ b/lldb/include/lldb/Interpreter/Options.h
@@ -163,7 +163,7 @@ public:
/// Handles the generic bits of figuring out whether we are in an option,
/// and if so completing it.
///
- /// \param[in/out] request
+ /// \param[in,out] request
/// The completion request that we need to act upon.
///
/// \param[in] interpreter
@@ -182,7 +182,7 @@ public:
/// Handles the generic bits of figuring out whether we are in an option,
/// and if so completing it.
///
- /// \param[in/out] request
+ /// \param[in,out] request
/// The completion request that we need to act upon.
///
/// \param[in] interpreter
diff --git a/lldb/include/lldb/Interpreter/Property.h b/lldb/include/lldb/Interpreter/Property.h
index 797aee4be815..76264832705b 100644
--- a/lldb/include/lldb/Interpreter/Property.h
+++ b/lldb/include/lldb/Interpreter/Property.h
@@ -64,8 +64,7 @@ public:
uint32_t output_width,
bool display_qualified_name) const;
- void SetValueChangedCallback(OptionValueChangedCallback callback,
- void *baton);
+ void SetValueChangedCallback(std::function<void()> callback);
protected:
ConstString m_name;
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index 23fadf02e591..1784c93adbac 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -120,8 +120,10 @@ public:
return error;
}
- virtual Status GenerateBreakpointCommandCallbackData(StringList &input,
- std::string &output) {
+ virtual Status GenerateBreakpointCommandCallbackData(
+ StringList &input,
+ std::string &output,
+ bool has_extra_args) {
Status error;
error.SetErrorString("not implemented");
return error;
@@ -311,14 +313,20 @@ public:
return error;
}
- void SetBreakpointCommandCallbackFunction(
+ Status SetBreakpointCommandCallbackFunction(
std::vector<BreakpointOptions *> &bp_options_vec,
- const char *function_name);
+ const char *function_name, StructuredData::ObjectSP extra_args_sp);
- /// Set a one-liner as the callback for the breakpoint.
- virtual void
- SetBreakpointCommandCallbackFunction(BreakpointOptions *bp_options,
- const char *function_name) {}
+ /// Set a script function as the callback for the breakpoint.
+ virtual Status
+ SetBreakpointCommandCallbackFunction(
+ BreakpointOptions *bp_options,
+ const char *function_name,
+ StructuredData::ObjectSP extra_args_sp) {
+ Status error;
+ error.SetErrorString("unimplemented");
+ return error;
+ }
/// Set a one-liner as the callback for the watchpoint.
virtual void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
@@ -449,12 +457,9 @@ public:
virtual bool CheckObjectExists(const char *name) { return false; }
virtual bool
- LoadScriptingModule(const char *filename, bool can_reload, bool init_session,
+ LoadScriptingModule(const char *filename, bool init_session,
lldb_private::Status &error,
- StructuredData::ObjectSP *module_sp = nullptr) {
- error.SetErrorString("loading unimplemented");
- return false;
- }
+ StructuredData::ObjectSP *module_sp = nullptr);
virtual bool IsReservedWord(const char *word) { return false; }
@@ -464,6 +469,12 @@ public:
int GetMasterFileDescriptor();
+ virtual llvm::Expected<unsigned>
+ GetMaxPositionalArgumentsForCallable(const llvm::StringRef &callable_name) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(), "Unimplemented function");
+ }
+
static std::string LanguageToString(lldb::ScriptLanguage language);
static lldb::ScriptLanguage StringToLanguage(const llvm::StringRef &string);
diff --git a/lldb/include/lldb/Symbol/Block.h b/lldb/include/lldb/Symbol/Block.h
index 36d0944f12b0..c2760dddf45f 100644
--- a/lldb/include/lldb/Symbol/Block.h
+++ b/lldb/include/lldb/Symbol/Block.h
@@ -57,12 +57,6 @@ public:
/// depth parsing. Common values would be the index into a
/// table, or an offset into the debug information.
///
- /// \param[in] depth
- /// The integer depth of this block in the block list hierarchy.
- ///
- /// \param[in] block_list
- /// The block list that this object belongs to.
- ///
/// \see BlockList
Block(lldb::user_id_t uid);
@@ -77,14 +71,6 @@ public:
void AddChild(const lldb::BlockSP &child_block_sp);
/// Add a new offset range to this block.
- ///
- /// \param[in] start_offset
- /// An offset into this Function's address range that
- /// describes the start address of a range for this block.
- ///
- /// \param[in] end_offset
- /// An offset into this Function's address range that
- /// describes the end address of a range for this block.
void AddRange(const Range &range);
void FinalizeRanges();
@@ -232,10 +218,6 @@ public:
/// Get the variable list for this block and optionally all child blocks if
/// \a get_child_variables is \b true.
///
- /// \param[in] get_child_variables
- /// If \b true, all variables from all child blocks will be
- /// added to the variable list.
- ///
/// \param[in] can_create
/// If \b true, the variables can be parsed if they already
/// haven't been, else the current state of the block will be
@@ -243,11 +225,9 @@ public:
/// to see the current state of what has been parsed up to this
/// point.
///
- /// \param[in] add_inline_child_block_variables
- /// If this is \b false, no child variables of child blocks
- /// that are inlined functions will be gotten. If \b true then
- /// all child variables will be added regardless of whether they
- /// come from inlined functions or not.
+ /// \param[in] get_child_block_variables
+ /// If \b true, all variables from all child blocks will be
+ /// added to the variable list.
///
/// \return
/// A variable list shared pointer that contains all variables
diff --git a/lldb/include/lldb/Symbol/ClangASTContext.h b/lldb/include/lldb/Symbol/ClangASTContext.h
index c5d840973ae6..338417b20b8a 100644
--- a/lldb/include/lldb/Symbol/ClangASTContext.h
+++ b/lldb/include/lldb/Symbol/ClangASTContext.h
@@ -21,7 +21,6 @@
#include <vector>
#include "clang/AST/ASTContext.h"
-#include "clang/AST/ExternalASTMerger.h"
#include "clang/AST/TemplateBase.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/SmallVector.h"
@@ -30,7 +29,10 @@
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/TypeSystem.h"
+#include "lldb/Target/Target.h"
#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Logging.h"
#include "lldb/lldb-enumerations.h"
class DWARFASTParserClang;
@@ -41,19 +43,25 @@ namespace lldb_private {
class Declaration;
class ClangASTContext : public TypeSystem {
+ // LLVM RTTI support
+ static char ID;
+
public:
typedef void (*CompleteTagDeclCallback)(void *baton, clang::TagDecl *);
typedef void (*CompleteObjCInterfaceDeclCallback)(void *baton,
clang::ObjCInterfaceDecl *);
// llvm casting support
- static bool classof(const TypeSystem *ts) {
- return ts->getKind() == TypeSystem::eKindClang;
- }
+ bool isA(const void *ClassID) const override { return ClassID == &ID; }
+ static bool classof(const TypeSystem *ts) { return ts->isA(&ID); }
- // Constructors and Destructors
- explicit ClangASTContext(llvm::StringRef triple = "");
- explicit ClangASTContext(ArchSpec arch);
+ /// Constructs a ClangASTContext with an ASTContext using the given triple.
+ ///
+ /// \param triple The llvm::Triple used for the ASTContext. The triple defines
+ /// certain characteristics of the ASTContext and its types
+ /// (e.g., whether certain primitive types exist or what their
+ /// signedness is).
+ explicit ClangASTContext(llvm::Triple triple);
/// Constructs a ClangASTContext that uses an existing ASTContext internally.
/// Useful when having an existing ASTContext created by Clang.
@@ -84,23 +92,19 @@ public:
static ClangASTContext *GetASTContext(clang::ASTContext *ast_ctx);
- clang::ASTContext *getASTContext();
-
- clang::Builtin::Context *getBuiltinContext();
-
- clang::IdentifierTable *getIdentifierTable();
-
- clang::LangOptions *getLanguageOptions();
-
- clang::SelectorTable *getSelectorTable();
-
- clang::FileManager *getFileManager();
-
- clang::SourceManager *getSourceManager();
-
- clang::DiagnosticsEngine *getDiagnosticsEngine();
+ static ClangASTContext *GetScratch(Target &target,
+ bool create_on_demand = true) {
+ auto type_system_or_err = target.GetScratchTypeSystemForLanguage(
+ lldb::eLanguageTypeC, create_on_demand);
+ if (auto err = type_system_or_err.takeError()) {
+ LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TARGET),
+ std::move(err), "Couldn't get scratch ClangASTContext");
+ return nullptr;
+ }
+ return llvm::dyn_cast<ClangASTContext>(&type_system_or_err.get());
+ }
- clang::DiagnosticConsumer *getDiagnosticConsumer();
+ clang::ASTContext &getASTContext();
clang::MangleContext *getMangleContext();
@@ -117,7 +121,7 @@ public:
llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> &ast_source_up);
bool GetCompleteDecl(clang::Decl *decl) {
- return ClangASTContext::GetCompleteDecl(getASTContext(), decl);
+ return ClangASTContext::GetCompleteDecl(&getASTContext(), decl);
}
static void DumpDeclHiearchy(clang::Decl *decl);
@@ -128,75 +132,63 @@ public:
static bool GetCompleteDecl(clang::ASTContext *ast, clang::Decl *decl);
- void SetMetadataAsUserID(const void *object, lldb::user_id_t user_id);
+ void SetMetadataAsUserID(const clang::Decl *decl, lldb::user_id_t user_id);
+ void SetMetadataAsUserID(const clang::Type *type, lldb::user_id_t user_id);
- void SetMetadata(const void *object, ClangASTMetadata &meta_data) {
- SetMetadata(getASTContext(), object, meta_data);
- }
-
- static void SetMetadata(clang::ASTContext *ast, const void *object,
- ClangASTMetadata &meta_data);
+ void SetMetadata(const clang::Decl *object, ClangASTMetadata &meta_data);
- ClangASTMetadata *GetMetadata(const void *object) {
- return GetMetadata(getASTContext(), object);
- }
-
- static ClangASTMetadata *GetMetadata(clang::ASTContext *ast,
- const void *object);
+ void SetMetadata(const clang::Type *object, ClangASTMetadata &meta_data);
+ ClangASTMetadata *GetMetadata(const clang::Decl *object);
+ ClangASTMetadata *GetMetadata(const clang::Type *object);
// Basic Types
CompilerType GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
size_t bit_size) override;
- static CompilerType GetBuiltinTypeForEncodingAndBitSize(
- clang::ASTContext *ast, lldb::Encoding encoding, uint32_t bit_size);
-
CompilerType GetBasicType(lldb::BasicType type);
- static CompilerType GetBasicType(clang::ASTContext *ast,
- lldb::BasicType type);
-
- static CompilerType GetBasicType(clang::ASTContext *ast,
- ConstString name);
-
static lldb::BasicType GetBasicTypeEnumeration(ConstString name);
- CompilerType GetBuiltinTypeForDWARFEncodingAndBitSize(const char *type_name,
- uint32_t dw_ate,
- uint32_t bit_size);
+ CompilerType
+ GetBuiltinTypeForDWARFEncodingAndBitSize(llvm::StringRef type_name,
+ uint32_t dw_ate, uint32_t bit_size);
CompilerType GetCStringType(bool is_const);
- static CompilerType GetUnknownAnyType(clang::ASTContext *ast);
-
- CompilerType GetUnknownAnyType() {
- return ClangASTContext::GetUnknownAnyType(getASTContext());
- }
-
static clang::DeclContext *GetDeclContextForType(clang::QualType type);
static clang::DeclContext *GetDeclContextForType(const CompilerType &type);
uint32_t GetPointerByteSize() override;
- static clang::DeclContext *GetTranslationUnitDecl(clang::ASTContext *ast);
-
- clang::DeclContext *GetTranslationUnitDecl() {
- return GetTranslationUnitDecl(getASTContext());
+ clang::TranslationUnitDecl *GetTranslationUnitDecl() {
+ return getASTContext().getTranslationUnitDecl();
}
- static clang::Decl *CopyDecl(clang::ASTContext *dest_context,
- clang::ASTContext *source_context,
- clang::Decl *source_decl);
-
static bool AreTypesSame(CompilerType type1, CompilerType type2,
bool ignore_qualifiers = false);
- static CompilerType GetTypeForDecl(clang::NamedDecl *decl);
+ /// Creates a CompilerType form the given QualType with the current
+ /// ClangASTContext instance as the CompilerType's typesystem.
+ /// \param qt The QualType for a type that belongs to the ASTContext of this
+ /// ClangASTContext.
+ /// \return The CompilerType representing the given QualType. If the
+ /// QualType's type pointer is a nullptr then the function returns an
+ /// invalid CompilerType.
+ CompilerType GetType(clang::QualType qt) {
+ if (qt.getTypePtrOrNull() == nullptr)
+ return CompilerType();
+ // Check that the type actually belongs to this ClangASTContext.
+ assert(qt->getAsTagDecl() == nullptr ||
+ &qt->getAsTagDecl()->getASTContext() == &getASTContext());
+ return CompilerType(this, qt.getAsOpaquePtr());
+ }
- static CompilerType GetTypeForDecl(clang::TagDecl *decl);
+ CompilerType GetTypeForDecl(clang::NamedDecl *decl);
- static CompilerType GetTypeForDecl(clang::ObjCInterfaceDecl *objc_decl);
+ CompilerType GetTypeForDecl(clang::TagDecl *decl);
+
+ CompilerType GetTypeForDecl(clang::ObjCInterfaceDecl *objc_decl);
template <typename RecordDeclType>
CompilerType
@@ -205,27 +197,23 @@ public:
CompilerType compiler_type;
if (type_name.GetLength()) {
- clang::ASTContext *ast = getASTContext();
- if (ast) {
- if (!decl_context)
- decl_context = ast->getTranslationUnitDecl();
-
- clang::IdentifierInfo &myIdent =
- ast->Idents.get(type_name.GetCString());
- clang::DeclarationName myName =
- ast->DeclarationNames.getIdentifier(&myIdent);
-
- clang::DeclContext::lookup_result result =
- decl_context->lookup(myName);
-
- if (!result.empty()) {
- clang::NamedDecl *named_decl = result[0];
- if (const RecordDeclType *record_decl =
- llvm::dyn_cast<RecordDeclType>(named_decl))
- compiler_type.SetCompilerType(
- this, clang::QualType(record_decl->getTypeForDecl(), 0)
- .getAsOpaquePtr());
- }
+ clang::ASTContext &ast = getASTContext();
+ if (!decl_context)
+ decl_context = ast.getTranslationUnitDecl();
+
+ clang::IdentifierInfo &myIdent = ast.Idents.get(type_name.GetCString());
+ clang::DeclarationName myName =
+ ast.DeclarationNames.getIdentifier(&myIdent);
+
+ clang::DeclContext::lookup_result result = decl_context->lookup(myName);
+
+ if (!result.empty()) {
+ clang::NamedDecl *named_decl = result[0];
+ if (const RecordDeclType *record_decl =
+ llvm::dyn_cast<RecordDeclType>(named_decl))
+ compiler_type.SetCompilerType(
+ this, clang::QualType(record_decl->getTypeForDecl(), 0)
+ .getAsOpaquePtr());
}
}
@@ -259,9 +247,11 @@ public:
bool omit_empty_base_classes);
CompilerType CreateRecordType(clang::DeclContext *decl_ctx,
- lldb::AccessType access_type, const char *name,
- int kind, lldb::LanguageType language,
- ClangASTMetadata *metadata = nullptr);
+ lldb::AccessType access_type,
+ llvm::StringRef name, int kind,
+ lldb::LanguageType language,
+ ClangASTMetadata *metadata = nullptr,
+ bool exports_symbols = false);
class TemplateParameterInfos {
public:
@@ -307,10 +297,7 @@ public:
class_template_specialization_decl);
static clang::DeclContext *
- GetAsDeclContext(clang::CXXMethodDecl *cxx_method_decl);
-
- static clang::DeclContext *
- GetAsDeclContext(clang::ObjCMethodDecl *objc_method_decl);
+ GetAsDeclContext(clang::FunctionDecl *function_decl);
static bool CheckOverloadedOperatorKindParameterCount(
bool is_method, clang::OverloadedOperatorKind op_kind,
@@ -318,13 +305,11 @@ public:
bool FieldIsBitfield(clang::FieldDecl *field, uint32_t &bitfield_bit_size);
- static bool FieldIsBitfield(clang::ASTContext *ast, clang::FieldDecl *field,
- uint32_t &bitfield_bit_size);
-
static bool RecordHasFields(const clang::RecordDecl *record_decl);
- CompilerType CreateObjCClass(const char *name, clang::DeclContext *decl_ctx,
- bool isForwardDecl, bool isInternal,
+ CompilerType CreateObjCClass(llvm::StringRef name,
+ clang::DeclContext *decl_ctx, bool isForwardDecl,
+ bool isInternal,
ClangASTMetadata *metadata = nullptr);
bool SetTagTypeKind(clang::QualType type, int kind) const;
@@ -343,11 +328,6 @@ public:
GetUniqueNamespaceDeclaration(const char *name, clang::DeclContext *decl_ctx,
bool is_inline = false);
- static clang::NamespaceDecl *
- GetUniqueNamespaceDeclaration(clang::ASTContext *ast, const char *name,
- clang::DeclContext *decl_ctx,
- bool is_inline = false);
-
// Function Types
clang::FunctionDecl *
@@ -355,36 +335,16 @@ public:
const CompilerType &function_Type, int storage,
bool is_inline);
- static CompilerType CreateFunctionType(clang::ASTContext *ast,
- const CompilerType &result_type,
- const CompilerType *args,
- unsigned num_args, bool is_variadic,
- unsigned type_quals,
- clang::CallingConv cc);
-
- static CompilerType CreateFunctionType(clang::ASTContext *ast,
- const CompilerType &result_type,
- const CompilerType *args,
- unsigned num_args, bool is_variadic,
- unsigned type_quals) {
- return ClangASTContext::CreateFunctionType(
- ast, result_type, args, num_args, is_variadic, type_quals, clang::CC_C);
- }
-
CompilerType CreateFunctionType(const CompilerType &result_type,
const CompilerType *args, unsigned num_args,
- bool is_variadic, unsigned type_quals) {
- return ClangASTContext::CreateFunctionType(
- getASTContext(), result_type, args, num_args, is_variadic, type_quals);
- }
+ bool is_variadic, unsigned type_quals,
+ clang::CallingConv cc);
CompilerType CreateFunctionType(const CompilerType &result_type,
const CompilerType *args, unsigned num_args,
- bool is_variadic, unsigned type_quals,
- clang::CallingConv cc) {
- return ClangASTContext::CreateFunctionType(getASTContext(), result_type,
- args, num_args, is_variadic,
- type_quals, cc);
+ bool is_variadic, unsigned type_quals) {
+ return CreateFunctionType(result_type, args, num_args, is_variadic,
+ type_quals, clang::CC_C);
}
clang::ParmVarDecl *CreateParameterDeclaration(clang::DeclContext *decl_ctx,
@@ -412,15 +372,9 @@ public:
// Integer type functions
- static CompilerType GetIntTypeFromBitSize(clang::ASTContext *ast,
- size_t bit_size, bool is_signed);
+ CompilerType GetIntTypeFromBitSize(size_t bit_size, bool is_signed);
- CompilerType GetPointerSizedIntType(bool is_signed) {
- return GetPointerSizedIntType(getASTContext(), is_signed);
- }
-
- static CompilerType GetPointerSizedIntType(clang::ASTContext *ast,
- bool is_signed);
+ CompilerType GetPointerSizedIntType(bool is_signed);
// Floating point functions
@@ -432,14 +386,12 @@ public:
PDBASTParser *GetPDBParser() override;
// ClangASTContext callbacks for external source lookups.
- static void CompleteTagDecl(void *baton, clang::TagDecl *);
+ void CompleteTagDecl(clang::TagDecl *);
- static void CompleteObjCInterfaceDecl(void *baton,
- clang::ObjCInterfaceDecl *);
+ void CompleteObjCInterfaceDecl(clang::ObjCInterfaceDecl *);
- static bool LayoutRecordType(
- void *baton, const clang::RecordDecl *record_decl, uint64_t &size,
- uint64_t &alignment,
+ bool LayoutRecordType(
+ const clang::RecordDecl *record_decl, uint64_t &size, uint64_t &alignment,
llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
&base_offsets,
@@ -464,12 +416,16 @@ public:
// CompilerDeclContext override functions
+ /// Creates a CompilerDeclContext from the given DeclContext
+ /// with the current ClangASTContext instance as its typesystem.
+ /// The DeclContext has to come from the ASTContext of this
+ /// ClangASTContext.
+ CompilerDeclContext CreateDeclContext(clang::DeclContext *ctx);
+
std::vector<CompilerDecl>
DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name,
const bool ignore_using_decls) override;
- bool DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) override;
-
ConstString DeclContextGetName(void *opaque_decl_ctx) override;
ConstString DeclContextGetScopeQualifiedName(void *opaque_decl_ctx) override;
@@ -500,7 +456,7 @@ public:
DeclContextGetAsNamespaceDecl(const CompilerDeclContext &dc);
static ClangASTMetadata *DeclContextGetMetaData(const CompilerDeclContext &dc,
- const void *object);
+ const clang::Decl *object);
static clang::ASTContext *
DeclContextGetClangASTContext(const CompilerDeclContext &dc);
@@ -600,8 +556,7 @@ public:
bool SupportsLanguage(lldb::LanguageType language) override;
- static bool GetCXXClassName(const CompilerType &type,
- std::string &class_name);
+ static llvm::Optional<std::string> GetCXXClassName(const CompilerType &type);
// Type Completion
@@ -668,6 +623,8 @@ public:
CompilerType
GetRValueReferenceType(lldb::opaque_compiler_type_t type) override;
+ CompilerType GetAtomicType(lldb::opaque_compiler_type_t type) override;
+
CompilerType AddConstModifier(lldb::opaque_compiler_type_t type) override;
CompilerType AddVolatileModifier(lldb::opaque_compiler_type_t type) override;
@@ -811,13 +768,11 @@ public:
const CompilerType &var_type,
lldb::AccessType access);
- clang::CXXMethodDecl *
- AddMethodToCXXRecordType(lldb::opaque_compiler_type_t type, const char *name,
- const char *mangled_name,
- const CompilerType &method_type,
- lldb::AccessType access, bool is_virtual,
- bool is_static, bool is_inline, bool is_explicit,
- bool is_attr_used, bool is_artificial);
+ clang::CXXMethodDecl *AddMethodToCXXRecordType(
+ lldb::opaque_compiler_type_t type, llvm::StringRef name,
+ const char *mangled_name, const CompilerType &method_type,
+ lldb::AccessType access, bool is_virtual, bool is_static, bool is_inline,
+ bool is_explicit, bool is_attr_used, bool is_artificial);
void AddMethodOverridesForCXXRecordType(lldb::opaque_compiler_type_t type);
@@ -849,7 +804,7 @@ public:
// (lldb::opaque_compiler_type_t type, "-[NString
// stringWithCString:]")
const CompilerType &method_compiler_type, lldb::AccessType access,
- bool is_artificial, bool is_variadic);
+ bool is_artificial, bool is_variadic, bool is_objc_direct_call);
static bool SetHasExternalStorage(lldb::opaque_compiler_type_t type,
bool has_extern);
@@ -927,7 +882,8 @@ public:
static clang::TypedefNameDecl *GetAsTypedefDecl(const CompilerType &type);
- clang::CXXRecordDecl *GetAsCXXRecordDecl(lldb::opaque_compiler_type_t type);
+ static clang::CXXRecordDecl *
+ GetAsCXXRecordDecl(lldb::opaque_compiler_type_t type);
static clang::ObjCInterfaceDecl *
GetAsObjCInterfaceDecl(const CompilerType &type);
@@ -968,11 +924,8 @@ public:
clang::DeclarationName
GetDeclarationName(const char *name, const CompilerType &function_clang_type);
-
- virtual const clang::ExternalASTMerger::OriginMap &GetOriginMap() {
- return m_origins;
- }
-protected:
+
+private:
const clang::ClassTemplateSpecializationDecl *
GetAsTemplateSpecialization(lldb::opaque_compiler_type_t type);
@@ -991,20 +944,23 @@ protected:
std::unique_ptr<clang::Builtin::Context> m_builtins_up;
std::unique_ptr<DWARFASTParserClang> m_dwarf_ast_parser_up;
std::unique_ptr<PDBASTParser> m_pdb_ast_parser_up;
- std::unique_ptr<ClangASTSource> m_scratch_ast_source_up;
std::unique_ptr<clang::MangleContext> m_mangle_ctx_up;
- CompleteTagDeclCallback m_callback_tag_decl = nullptr;
- CompleteObjCInterfaceDeclCallback m_callback_objc_decl = nullptr;
- void *m_callback_baton = nullptr;
- clang::ExternalASTMerger::OriginMap m_origins;
uint32_t m_pointer_byte_size = 0;
bool m_ast_owned = false;
+
+ typedef llvm::DenseMap<const clang::Decl *, ClangASTMetadata> DeclMetadataMap;
+ /// Maps Decls to their associated ClangASTMetadata.
+ DeclMetadataMap m_decl_metadata;
+
+ typedef llvm::DenseMap<const clang::Type *, ClangASTMetadata> TypeMetadataMap;
+ /// Maps Types to their associated ClangASTMetadata.
+ TypeMetadataMap m_type_metadata;
+
/// The sema associated that is currently used to build this ASTContext.
/// May be null if we are already done parsing this ASTContext or the
/// ASTContext wasn't created by parsing source code.
clang::Sema *m_sema = nullptr;
-private:
// For ClangASTContext only
ClangASTContext(const ClangASTContext &);
const ClangASTContext &operator=(const ClangASTContext &);
@@ -1015,10 +971,12 @@ private:
class ClangASTContextForExpressions : public ClangASTContext {
public:
- ClangASTContextForExpressions(Target &target, ArchSpec arch);
+ ClangASTContextForExpressions(Target &target, llvm::Triple triple);
~ClangASTContextForExpressions() override = default;
+ void Finalize() override;
+
UserExpression *
GetUserExpression(llvm::StringRef expr, llvm::StringRef prefix,
lldb::LanguageType language,
@@ -1035,17 +993,12 @@ public:
const char *name) override;
PersistentExpressionState *GetPersistentExpressionState() override;
-
- clang::ExternalASTMerger &GetMergerUnchecked();
-
- const clang::ExternalASTMerger::OriginMap &GetOriginMap() override {
- return GetMergerUnchecked().GetOrigins();
- }
private:
lldb::TargetWP m_target_wp;
std::unique_ptr<PersistentExpressionState>
m_persistent_variables; // These are the persistent variables associated
// with this process for the expression parser
+ std::unique_ptr<ClangASTSource> m_scratch_ast_source_up;
};
} // namespace lldb_private
diff --git a/lldb/include/lldb/Symbol/ClangASTImporter.h b/lldb/include/lldb/Symbol/ClangASTImporter.h
index f963f9b2b1dc..faec3a77b56f 100644
--- a/lldb/include/lldb/Symbol/ClangASTImporter.h
+++ b/lldb/include/lldb/Symbol/ClangASTImporter.h
@@ -30,57 +30,6 @@
namespace lldb_private {
-class ClangASTMetrics {
-public:
- static void DumpCounters(Log *log);
- static void ClearLocalCounters() { local_counters = {0, 0, 0, 0, 0, 0}; }
-
- static void RegisterVisibleQuery() {
- ++global_counters.m_visible_query_count;
- ++local_counters.m_visible_query_count;
- }
-
- static void RegisterLexicalQuery() {
- ++global_counters.m_lexical_query_count;
- ++local_counters.m_lexical_query_count;
- }
-
- static void RegisterLLDBImport() {
- ++global_counters.m_lldb_import_count;
- ++local_counters.m_lldb_import_count;
- }
-
- static void RegisterClangImport() {
- ++global_counters.m_clang_import_count;
- ++local_counters.m_clang_import_count;
- }
-
- static void RegisterDeclCompletion() {
- ++global_counters.m_decls_completed_count;
- ++local_counters.m_decls_completed_count;
- }
-
- static void RegisterRecordLayout() {
- ++global_counters.m_record_layout_count;
- ++local_counters.m_record_layout_count;
- }
-
-private:
- struct Counters {
- uint64_t m_visible_query_count;
- uint64_t m_lexical_query_count;
- uint64_t m_lldb_import_count;
- uint64_t m_clang_import_count;
- uint64_t m_decls_completed_count;
- uint64_t m_record_layout_count;
- };
-
- static Counters global_counters;
- static Counters local_counters;
-
- static void DumpCounters(Log *log, Counters &counters);
-};
-
class ClangASTImporter {
public:
struct LayoutInfo {
@@ -99,26 +48,22 @@ public:
: m_file_manager(clang::FileSystemOptions(),
FileSystem::Instance().GetVirtualFileSystem()) {}
- clang::QualType CopyType(clang::ASTContext *dst_ctx,
- clang::ASTContext *src_ctx, clang::QualType type);
-
- lldb::opaque_compiler_type_t CopyType(clang::ASTContext *dst_ctx,
- clang::ASTContext *src_ctx,
- lldb::opaque_compiler_type_t type);
-
CompilerType CopyType(ClangASTContext &dst, const CompilerType &src_type);
- clang::Decl *CopyDecl(clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx,
- clang::Decl *decl);
+ clang::Decl *CopyDecl(clang::ASTContext *dst_ctx, clang::Decl *decl);
- lldb::opaque_compiler_type_t DeportType(clang::ASTContext *dst_ctx,
- clang::ASTContext *src_ctx,
- lldb::opaque_compiler_type_t type);
+ CompilerType DeportType(ClangASTContext &dst, const CompilerType &src_type);
- clang::Decl *DeportDecl(clang::ASTContext *dst_ctx,
- clang::ASTContext *src_ctx, clang::Decl *decl);
+ clang::Decl *DeportDecl(clang::ASTContext *dst_ctx, clang::Decl *decl);
- void InsertRecordDecl(clang::RecordDecl *decl, const LayoutInfo &layout);
+ /// Sets the layout for the given RecordDecl. The layout will later be
+ /// used by Clang's during code generation. Not calling this function for
+ /// a RecordDecl will cause that Clang's codegen tries to layout the
+ /// record by itself.
+ ///
+ /// \param decl The RecordDecl to set the layout for.
+ /// \param layout The layout for the record.
+ void SetRecordLayout(clang::RecordDecl *decl, const LayoutInfo &layout);
bool LayoutRecordType(
const clang::RecordDecl *record_decl, uint64_t &bit_size,
@@ -147,19 +92,6 @@ public:
bool RequireCompleteType(clang::QualType type);
- bool ResolveDeclOrigin(const clang::Decl *decl, clang::Decl **original_decl,
- clang::ASTContext **original_ctx) {
- DeclOrigin origin = GetDeclOrigin(decl);
-
- if (original_decl)
- *original_decl = origin.decl;
-
- if (original_ctx)
- *original_ctx = origin.ctx;
-
- return origin.Valid();
- }
-
void SetDeclOrigin(const clang::Decl *decl, clang::Decl *original_decl);
ClangASTMetadata *GetDeclMetadata(const clang::Decl *decl);
@@ -233,7 +165,7 @@ public:
clang::Decl *decl;
};
- typedef std::map<const clang::Decl *, DeclOrigin> OriginMap;
+ typedef llvm::DenseMap<const clang::Decl *, DeclOrigin> OriginMap;
/// Listener interface used by the ASTImporterDelegate to inform other code
/// about decls that have been imported the first time.
@@ -313,7 +245,7 @@ public:
/// ASTContext. Used by the CxxModuleHandler to mark declarations that
/// were created from the 'std' C++ module to prevent that the Importer
/// tries to sync them with the broken equivalent in the debug info AST.
- std::set<clang::Decl *> m_decls_to_ignore;
+ llvm::SmallPtrSet<clang::Decl *, 16> m_decls_to_ignore;
ClangASTImporter &m_master;
clang::ASTContext *m_source_ctx;
CxxModuleHandler *m_std_handler = nullptr;
@@ -322,8 +254,8 @@ public:
};
typedef std::shared_ptr<ASTImporterDelegate> ImporterDelegateSP;
- typedef std::map<clang::ASTContext *, ImporterDelegateSP> DelegateMap;
- typedef std::map<const clang::NamespaceDecl *, NamespaceMapSP>
+ typedef llvm::DenseMap<clang::ASTContext *, ImporterDelegateSP> DelegateMap;
+ typedef llvm::DenseMap<const clang::NamespaceDecl *, NamespaceMapSP>
NamespaceMetaMap;
struct ASTContextMetadata {
@@ -340,7 +272,7 @@ public:
};
typedef std::shared_ptr<ASTContextMetadata> ASTContextMetadataSP;
- typedef std::map<const clang::ASTContext *, ASTContextMetadataSP>
+ typedef llvm::DenseMap<const clang::ASTContext *, ASTContextMetadataSP>
ContextMetadataMap;
ContextMetadataMap m_metadata_map;
@@ -353,9 +285,8 @@ public:
ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
m_metadata_map[dst_ctx] = context_md;
return context_md;
- } else {
- return context_md_iter->second;
}
+ return context_md_iter->second;
}
ASTContextMetadataSP MaybeGetContextMetadata(clang::ASTContext *dst_ctx) {
@@ -363,8 +294,7 @@ public:
if (context_md_iter != m_metadata_map.end())
return context_md_iter->second;
- else
- return ASTContextMetadataSP();
+ return ASTContextMetadataSP();
}
ImporterDelegateSP GetDelegate(clang::ASTContext *dst_ctx,
@@ -379,9 +309,8 @@ public:
ImporterDelegateSP(new ASTImporterDelegate(*this, dst_ctx, src_ctx));
delegates[src_ctx] = delegate;
return delegate;
- } else {
- return delegate_iter->second;
}
+ return delegate_iter->second;
}
public:
diff --git a/lldb/include/lldb/Symbol/ClangExternalASTSourceCommon.h b/lldb/include/lldb/Symbol/ClangASTMetadata.h
index 8e69f6d3e4eb..fdf4388f0847 100644
--- a/lldb/include/lldb/Symbol/ClangExternalASTSourceCommon.h
+++ b/lldb/include/lldb/Symbol/ClangASTMetadata.h
@@ -1,4 +1,4 @@
-//===-- ClangExternalASTSourceCommon.h --------------------------*- C++ -*-===//
+//===-- ClangASTMetadata.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.
@@ -6,34 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_ClangExternalASTSourceCommon_h
-#define liblldb_ClangExternalASTSourceCommon_h
-
-// Clang headers like to use NDEBUG inside of them to enable/disable debug
-// related features using "#ifndef NDEBUG" preprocessor blocks to do one thing
-// or another. This is bad because it means that if clang was built in release
-// mode, it assumes that you are building in release mode which is not always
-// the case. You can end up with functions that are defined as empty in header
-// files when NDEBUG is not defined, and this can cause link errors with the
-// clang .a files that you have since you might be missing functions in the .a
-// file. So we have to define NDEBUG when including clang headers to avoid any
-// mismatches. This is covered by rdar://problem/8691220
-
-#if !defined(NDEBUG) && !defined(LLVM_NDEBUG_OFF)
-#define LLDB_DEFINED_NDEBUG_FOR_CLANG
-#define NDEBUG
-// Need to include assert.h so it is as clang would expect it to be (disabled)
-#include <assert.h>
-#endif
-
-#ifdef LLDB_DEFINED_NDEBUG_FOR_CLANG
-#undef NDEBUG
-#undef LLDB_DEFINED_NDEBUG_FOR_CLANG
-// Need to re-include assert.h so it is as _we_ would expect it to be (enabled)
-#include <assert.h>
-#endif
-
-#include "clang/AST/ExternalASTSource.h"
+#ifndef liblldb_ClangASTMetadata_h
+#define liblldb_ClangASTMetadata_h
#include "lldb/Core/dwarf.h"
#include "lldb/lldb-defines.h"
@@ -121,23 +95,6 @@ private:
m_is_self : 1, m_is_dynamic_cxx : 1;
};
-class ClangExternalASTSourceCommon : public clang::ExternalASTSource {
-public:
- ClangExternalASTSourceCommon();
- ~ClangExternalASTSourceCommon() override;
-
- ClangASTMetadata *GetMetadata(const void *object);
- void SetMetadata(const void *object, ClangASTMetadata &metadata);
- bool HasMetadata(const void *object);
-
- static ClangExternalASTSourceCommon *Lookup(clang::ExternalASTSource *source);
-
-private:
- typedef llvm::DenseMap<const void *, ClangASTMetadata> MetadataMap;
-
- MetadataMap m_metadata;
-};
-
} // namespace lldb_private
-#endif // liblldb_ClangExternalASTSourceCommon_h
+#endif // liblldb_ClangASTMetadata_h
diff --git a/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h b/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h
index a2d4f8137a05..290ecc9b9017 100644
--- a/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h
+++ b/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h
@@ -9,86 +9,22 @@
#ifndef liblldb_ClangExternalASTSourceCallbacks_h_
#define liblldb_ClangExternalASTSourceCallbacks_h_
-#include <stdint.h>
-
-#include "clang/AST/CharUnits.h"
-#include "llvm/ADT/DenseMap.h"
-
-#include "lldb/Core/ClangForward.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/lldb-enumerations.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "clang/AST/ExternalASTSource.h"
namespace lldb_private {
-class ClangExternalASTSourceCallbacks : public ClangExternalASTSourceCommon {
-public:
- typedef void (*CompleteTagDeclCallback)(void *baton, clang::TagDecl *);
- typedef void (*CompleteObjCInterfaceDeclCallback)(void *baton,
- clang::ObjCInterfaceDecl *);
- typedef void (*FindExternalVisibleDeclsByNameCallback)(
- void *baton, const clang::DeclContext *DC, clang::DeclarationName Name,
- llvm::SmallVectorImpl<clang::NamedDecl *> *results);
- typedef bool (*LayoutRecordTypeCallback)(
- void *baton, const clang::RecordDecl *Record, uint64_t &Size,
- uint64_t &Alignment,
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
- &BaseOffsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
- &VirtualBaseOffsets);
-
- ClangExternalASTSourceCallbacks(
- CompleteTagDeclCallback tag_decl_callback,
- CompleteObjCInterfaceDeclCallback objc_decl_callback,
- FindExternalVisibleDeclsByNameCallback find_by_name_callback,
- LayoutRecordTypeCallback layout_record_type_callback,
- void *callback_baton)
- : m_callback_tag_decl(tag_decl_callback),
- m_callback_objc_decl(objc_decl_callback),
- m_callback_find_by_name(find_by_name_callback),
- m_callback_layout_record_type(layout_record_type_callback),
- m_callback_baton(callback_baton) {}
-
- // clang::ExternalASTSource
+class ClangASTContext;
- clang::Decl *GetExternalDecl(uint32_t ID) override {
- // This method only needs to be implemented if the AST source ever passes
- // back decl sets as VisibleDeclaration objects.
- return nullptr;
- }
-
- clang::Stmt *GetExternalDeclStmt(uint64_t Offset) override {
- // This operation is meant to be used via a LazyOffsetPtr. It only needs
- // to be implemented if the AST source uses methods like
- // FunctionDecl::setLazyBody when building decls.
- return nullptr;
- }
-
- clang::Selector GetExternalSelector(uint32_t ID) override {
- // This operation only needs to be implemented if the AST source returns
- // non-zero for GetNumKnownSelectors().
- return clang::Selector();
- }
-
- uint32_t GetNumExternalSelectors() override { return 0; }
-
- clang::CXXBaseSpecifier *
- GetExternalCXXBaseSpecifiers(uint64_t Offset) override {
- return nullptr;
- }
-
- virtual void MaterializeVisibleDecls(const clang::DeclContext *decl_ctx) {}
+class ClangExternalASTSourceCallbacks : public clang::ExternalASTSource {
+public:
+ ClangExternalASTSourceCallbacks(ClangASTContext &ast) : m_ast(ast) {}
void FindExternalLexicalDecls(
const clang::DeclContext *DC,
llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
llvm::SmallVectorImpl<clang::Decl *> &Result) override;
- bool
- FindExternalVisibleDeclsByName(const clang::DeclContext *decl_ctx,
- clang::DeclarationName decl_name) override;
-
void CompleteType(clang::TagDecl *tag_decl) override;
void CompleteType(clang::ObjCInterfaceDecl *objc_decl) override;
@@ -101,36 +37,8 @@ public:
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
&VirtualBaseOffsets) override;
- void SetExternalSourceCallbacks(
- CompleteTagDeclCallback tag_decl_callback,
- CompleteObjCInterfaceDeclCallback objc_decl_callback,
- FindExternalVisibleDeclsByNameCallback find_by_name_callback,
- LayoutRecordTypeCallback layout_record_type_callback,
- void *callback_baton) {
- m_callback_tag_decl = tag_decl_callback;
- m_callback_objc_decl = objc_decl_callback;
- m_callback_find_by_name = find_by_name_callback;
- m_callback_layout_record_type = layout_record_type_callback;
- m_callback_baton = callback_baton;
- }
-
- void RemoveExternalSourceCallbacks(void *callback_baton) {
- if (callback_baton == m_callback_baton) {
- m_callback_tag_decl = nullptr;
- m_callback_objc_decl = nullptr;
- m_callback_find_by_name = nullptr;
- m_callback_layout_record_type = nullptr;
- }
- }
-
-protected:
- // Classes that inherit from ClangExternalASTSourceCallbacks can see and
- // modify these
- CompleteTagDeclCallback m_callback_tag_decl;
- CompleteObjCInterfaceDeclCallback m_callback_objc_decl;
- FindExternalVisibleDeclsByNameCallback m_callback_find_by_name;
- LayoutRecordTypeCallback m_callback_layout_record_type;
- void *m_callback_baton;
+private:
+ ClangASTContext &m_ast;
};
} // namespace lldb_private
diff --git a/lldb/include/lldb/Symbol/ClangUtil.h b/lldb/include/lldb/Symbol/ClangUtil.h
index d6106032190c..5ffbce340e59 100644
--- a/lldb/include/lldb/Symbol/ClangUtil.h
+++ b/lldb/include/lldb/Symbol/ClangUtil.h
@@ -11,6 +11,7 @@
#ifndef LLDB_SYMBOL_CLANGUTIL_H
#define LLDB_SYMBOL_CLANGUTIL_H
+#include "clang/AST/DeclBase.h"
#include "clang/AST/Type.h"
#include "lldb/Symbol/CompilerType.h"
@@ -30,6 +31,15 @@ struct ClangUtil {
static CompilerType RemoveFastQualifiers(const CompilerType &ct);
static clang::TagDecl *GetAsTagDecl(const CompilerType &type);
+
+ /// Returns a textual representation of the given Decl's AST. Does not
+ /// deserialize any child nodes.
+ static std::string DumpDecl(const clang::Decl *d);
+ /// Returns a textual representation of the given type.
+ static std::string ToString(const clang::Type *t);
+ /// Returns a textual representation of the given CompilerType (assuming
+ /// its underlying type is a Clang type).
+ static std::string ToString(const CompilerType &c);
};
}
diff --git a/lldb/include/lldb/Symbol/CompileUnit.h b/lldb/include/lldb/Symbol/CompileUnit.h
index d132c367b999..aec5cc7c8743 100644
--- a/lldb/include/lldb/Symbol/CompileUnit.h
+++ b/lldb/include/lldb/Symbol/CompileUnit.h
@@ -13,12 +13,14 @@
#include "lldb/Core/ModuleChild.h"
#include "lldb/Symbol/DebugMacros.h"
#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/SourceModule.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/UserID.h"
#include "lldb/lldb-enumerations.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
namespace lldb_private {
/// \class CompileUnit CompileUnit.h "lldb/Symbol/CompileUnit.h"
@@ -34,7 +36,6 @@ namespace lldb_private {
/// table.
class CompileUnit : public std::enable_shared_from_this<CompileUnit>,
public ModuleChild,
- public FileSpec,
public UserID,
public SymbolContextScope {
public:
@@ -44,7 +45,7 @@ public:
/// convert into a FileSpec, the SymbolFile plug-in supplied \a uid, and the
/// source language type.
///
- /// \param[in] module
+ /// \param[in] module_sp
/// The parent module that owns this compile unit. This value
/// must be a valid pointer value.
///
@@ -82,7 +83,7 @@ public:
/// convert into a FileSpec, the SymbolFile plug-in supplied \a uid, and the
/// source language type.
///
- /// \param[in] module
+ /// \param[in] module_sp
/// The parent module that owns this compile unit. This value
/// must be a valid pointer value.
///
@@ -115,9 +116,6 @@ public:
const FileSpec &file_spec, lldb::user_id_t uid,
lldb::LanguageType language, lldb_private::LazyBool is_optimized);
- /// Destructor
- ~CompileUnit() override;
-
/// Add a function to this compile unit.
///
/// Typically called by the SymbolFile plug-ins as they partially parse the
@@ -163,6 +161,18 @@ public:
void ForeachFunction(
llvm::function_ref<bool(const lldb::FunctionSP &)> lambda) const;
+ /// Find a function in the compile unit based on the predicate matching_lambda
+ ///
+ /// \param[in] matching_lambda
+ /// A predicate that will be used within FindFunction to evaluate each
+ /// FunctionSP in m_functions_by_uid. When the predicate returns true
+ /// FindFunction will return the corresponding FunctionSP.
+ ///
+ /// \return
+ /// The first FunctionSP that the matching_lambda prediate returns true for.
+ lldb::FunctionSP FindFunction(
+ llvm::function_ref<bool(const lldb::FunctionSP &)> matching_lambda);
+
/// Dump the compile unit contents to the stream \a s.
///
/// \param[in] s
@@ -212,6 +222,9 @@ public:
const FileSpec *file_spec_ptr, bool exact,
LineEntry *line_entry);
+ /// Return the primary source file associated with this compile unit.
+ const FileSpec &GetPrimaryFile() const { return m_file_spec; }
+
/// Get the line table for the compile unit.
///
/// Called by clients and the SymbolFile plug-in. The SymbolFile plug-ins
@@ -229,9 +242,20 @@ public:
/// compilation unit. Recursively also descends into the referenced external
/// modules of any encountered compilation unit.
///
+ /// \param visited_symbol_files
+ /// A set of SymbolFiles that were already visited to avoid
+ /// visiting one file more than once.
+ ///
/// \param[in] lambda
- /// The lambda that should be applied to every module.
- void ForEachExternalModule(llvm::function_ref<void(lldb::ModuleSP)> f);
+ /// The lambda that should be applied to every function. The lambda can
+ /// return true if the iteration should be aborted earlier.
+ ///
+ /// \return
+ /// If the lambda early-exited, this function returns true to
+ /// propagate the early exit.
+ virtual bool ForEachExternalModule(
+ llvm::DenseSet<lldb_private::SymbolFile *> &visited_symbol_files,
+ llvm::function_ref<bool(Module &)> lambda);
/// Get the compile unit's support file list.
///
@@ -357,14 +381,11 @@ public:
/// A SymbolContext list class that will get any matching
/// entries appended to.
///
- /// \return
- /// The number of new matches that were added to \a sc_list.
- ///
/// \see enum SymbolContext::Scope
- uint32_t ResolveSymbolContext(const FileSpec &file_spec, uint32_t line,
- bool check_inlines, bool exact,
- lldb::SymbolContextItem resolve_scope,
- SymbolContextList &sc_list);
+ void ResolveSymbolContext(const FileSpec &file_spec, uint32_t line,
+ bool check_inlines, bool exact,
+ lldb::SymbolContextItem resolve_scope,
+ SymbolContextList &sc_list);
/// Get whether compiler optimizations were enabled for this compile unit
///
@@ -394,6 +415,8 @@ protected:
/// All modules, including the current module, imported by this
/// compile unit.
std::vector<SourceModule> m_imported_modules;
+ /// The primary file associated with this compile unit.
+ FileSpec m_file_spec;
/// Files associated with this compile unit's line table and
/// declarations.
FileSpecList m_support_files;
diff --git a/lldb/include/lldb/Symbol/CompilerDecl.h b/lldb/include/lldb/Symbol/CompilerDecl.h
index 4817ec4b2267..4fd269d4730e 100644
--- a/lldb/include/lldb/Symbol/CompilerDecl.h
+++ b/lldb/include/lldb/Symbol/CompilerDecl.h
@@ -15,16 +15,28 @@
namespace lldb_private {
+/// Represents a generic declaration such as a function declaration.
+///
+/// This class serves as an abstraction for a declaration inside one of the
+/// TypeSystems implemented by the language plugins. It does not have any actual
+/// logic in it but only stores an opaque pointer and a pointer to the
+/// TypeSystem that gives meaning to this opaque pointer. All methods of this
+/// class should call their respective method in the TypeSystem interface and
+/// pass the opaque pointer along.
+///
+/// \see lldb_private::TypeSystem
class CompilerDecl {
public:
// Constructors and Destructors
- CompilerDecl() : m_type_system(nullptr), m_opaque_decl(nullptr) {}
+ CompilerDecl() = default;
+ /// Creates a CompilerDecl with the given TypeSystem and opaque pointer.
+ ///
+ /// This constructor should only be called from the respective TypeSystem
+ /// implementation.
CompilerDecl(TypeSystem *type_system, void *decl)
: m_type_system(type_system), m_opaque_decl(decl) {}
- ~CompilerDecl() {}
-
// Tests
explicit operator bool() const { return IsValid(); }
@@ -39,8 +51,6 @@ public:
return m_type_system != nullptr && m_opaque_decl != nullptr;
}
- bool IsClang() const;
-
// Accessors
TypeSystem *GetTypeSystem() const { return m_type_system; }
@@ -75,8 +85,8 @@ public:
CompilerType GetFunctionArgumentType(size_t arg_idx) const;
private:
- TypeSystem *m_type_system;
- void *m_opaque_decl;
+ TypeSystem *m_type_system = nullptr;
+ void *m_opaque_decl = nullptr;
};
bool operator==(const CompilerDecl &lhs, const CompilerDecl &rhs);
diff --git a/lldb/include/lldb/Symbol/CompilerDeclContext.h b/lldb/include/lldb/Symbol/CompilerDeclContext.h
index e7958c08d833..6db6f4d3f623 100644
--- a/lldb/include/lldb/Symbol/CompilerDeclContext.h
+++ b/lldb/include/lldb/Symbol/CompilerDeclContext.h
@@ -16,16 +16,32 @@
namespace lldb_private {
+/// Represents a generic declaration context in a program. A declaration context
+/// is data structure that contains declarations (e.g. namespaces).
+///
+/// This class serves as an abstraction for a declaration context inside one of
+/// the TypeSystems implemented by the language plugins. It does not have any
+/// actual logic in it but only stores an opaque pointer and a pointer to the
+/// TypeSystem that gives meaning to this opaque pointer. All methods of this
+/// class should call their respective method in the TypeSystem interface and
+/// pass the opaque pointer along.
+///
+/// \see lldb_private::TypeSystem
class CompilerDeclContext {
public:
- // Constructors and Destructors
- CompilerDeclContext() : m_type_system(nullptr), m_opaque_decl_ctx(nullptr) {}
+ /// Constructs an invalid CompilerDeclContext.
+ CompilerDeclContext() = default;
+ /// Constructs a CompilerDeclContext with the given opaque decl context
+ /// and its respective TypeSystem instance.
+ ///
+ /// This constructor should only be called from the respective TypeSystem
+ /// implementation.
+ ///
+ /// \see lldb_private::ClangASTContext::CreateDeclContext(clang::DeclContext*)
CompilerDeclContext(TypeSystem *type_system, void *decl_ctx)
: m_type_system(type_system), m_opaque_decl_ctx(decl_ctx) {}
- ~CompilerDeclContext() {}
-
// Tests
explicit operator bool() const { return IsValid(); }
@@ -40,8 +56,6 @@ public:
return m_type_system != nullptr && m_opaque_decl_ctx != nullptr;
}
- bool IsClang() const;
-
std::vector<CompilerDecl> FindDeclByName(ConstString name,
const bool ignore_using_decls);
@@ -102,11 +116,9 @@ public:
ConstString GetScopeQualifiedName() const;
- bool IsStructUnionOrClass() const;
-
private:
- TypeSystem *m_type_system;
- void *m_opaque_decl_ctx;
+ TypeSystem *m_type_system = nullptr;
+ void *m_opaque_decl_ctx = nullptr;
};
bool operator==(const CompilerDeclContext &lhs, const CompilerDeclContext &rhs);
diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h
index bb9881c0bae3..37e826291c88 100644
--- a/lldb/include/lldb/Symbol/CompilerType.h
+++ b/lldb/include/lldb/Symbol/CompilerType.h
@@ -20,24 +20,31 @@ namespace lldb_private {
class DataExtractor;
-// A class that can carry around a clang ASTContext and a opaque clang
-// QualType. A clang::QualType can be easily reconstructed from an opaque clang
-// type and often the ASTContext is needed when doing various type related
-// tasks, so this class allows both items to travel in a single very
-// lightweight class that can be used. There are many static equivalents of the
-// member functions that allow the ASTContext and the opaque clang QualType to
-// be specified for ease of use and to avoid code duplication.
+/// Represents a generic type in a programming language.
+///
+/// This class serves as an abstraction for a type inside one of the TypeSystems
+/// implemented by the language plugins. It does not have any actual logic in it
+/// but only stores an opaque pointer and a pointer to the TypeSystem that
+/// gives meaning to this opaque pointer. All methods of this class should call
+/// their respective method in the TypeSystem interface and pass the opaque
+/// pointer along.
+///
+/// \see lldb_private::TypeSystem
class CompilerType {
public:
- // Constructors and Destructors
- CompilerType(TypeSystem *type_system, lldb::opaque_compiler_type_t type);
+ /// Creates a CompilerType with the given TypeSystem and opaque compiler type.
+ ///
+ /// This constructor should only be called from the respective TypeSystem
+ /// implementation.
+ ///
+ /// \see lldb_private::ClangASTContext::GetType(clang::QualType)
+ CompilerType(TypeSystem *type_system, lldb::opaque_compiler_type_t type)
+ : m_type(type), m_type_system(type_system) {}
CompilerType(const CompilerType &rhs)
: m_type(rhs.m_type), m_type_system(rhs.m_type_system) {}
- CompilerType() : m_type(nullptr), m_type_system(nullptr) {}
-
- ~CompilerType();
+ CompilerType() = default;
// Operators
@@ -108,11 +115,6 @@ public:
bool IsPolymorphicClass() const;
- bool
- IsPossibleCPlusPlusDynamicType(CompilerType *target_type = nullptr) const {
- return IsPossibleDynamicType(target_type, true, false);
- }
-
bool IsPossibleDynamicType(CompilerType *target_type, // Can pass nullptr
bool check_cplusplus, bool check_objc) const;
@@ -223,6 +225,11 @@ public:
// an invalid type.
CompilerType AddVolatileModifier() const;
+ // Return a new CompilerType that is the atomic type of this type. If this
+ // type is not valid or the type system doesn't support atomic types, this
+ // returns an invalid type.
+ CompilerType GetAtomicType() const;
+
// Return a new CompilerType adds a restrict modifier to this type if this
// type is valid and the type system supports restrict modifiers, else return
// an invalid type.
@@ -362,22 +369,14 @@ public:
bool GetValueAsScalar(const DataExtractor &data, lldb::offset_t data_offset,
size_t data_byte_size, Scalar &value) const;
- bool SetValueFromScalar(const Scalar &value, Stream &strm);
-
- bool ReadFromMemory(ExecutionContext *exe_ctx, lldb::addr_t addr,
- AddressType address_type, DataExtractor &data);
-
- bool WriteToMemory(ExecutionContext *exe_ctx, lldb::addr_t addr,
- AddressType address_type, StreamString &new_value);
-
void Clear() {
m_type = nullptr;
m_type_system = nullptr;
}
private:
- lldb::opaque_compiler_type_t m_type;
- TypeSystem *m_type_system;
+ lldb::opaque_compiler_type_t m_type = nullptr;
+ TypeSystem *m_type_system = nullptr;
};
bool operator==(const CompilerType &lhs, const CompilerType &rhs);
diff --git a/lldb/include/lldb/Symbol/DebugMacros.h b/lldb/include/lldb/Symbol/DebugMacros.h
index d364299ef490..da46c8b23c1d 100644
--- a/lldb/include/lldb/Symbol/DebugMacros.h
+++ b/lldb/include/lldb/Symbol/DebugMacros.h
@@ -23,7 +23,9 @@ typedef std::shared_ptr<DebugMacros> DebugMacrosSP;
class DebugMacroEntry {
public:
- enum EntryType { INVALID, DEFINE, UNDEF, START_FILE, END_FILE, INDIRECT };
+ enum EntryType : uint8_t {
+ INVALID, DEFINE, UNDEF, START_FILE, END_FILE, INDIRECT
+ };
public:
static DebugMacroEntry CreateDefineEntry(uint32_t line, const char *str);
@@ -42,7 +44,7 @@ public:
~DebugMacroEntry() = default;
- EntryType GetType() const { return m_type; }
+ EntryType GetType() const { return static_cast<EntryType>(m_type); }
uint64_t GetLineNumber() const { return m_line; }
@@ -60,7 +62,7 @@ private:
DebugMacroEntry(EntryType type, const DebugMacrosSP &debug_macros_sp);
- EntryType m_type : 3;
+ uint32_t m_type : 3;
uint32_t m_line : 29;
uint32_t m_debug_line_file_idx;
ConstString m_str;
diff --git a/lldb/include/lldb/Symbol/Declaration.h b/lldb/include/lldb/Symbol/Declaration.h
index 63798f883e5f..a751d6ba039f 100644
--- a/lldb/include/lldb/Symbol/Declaration.h
+++ b/lldb/include/lldb/Symbol/Declaration.h
@@ -55,16 +55,6 @@ public:
{
}
- /// Construct with a reference to another Declaration object.
- Declaration(const Declaration &rhs)
- : m_file(rhs.m_file), m_line(rhs.m_line)
-#ifdef LLDB_ENABLE_DECLARATION_COLUMNS
- ,
- m_column(rhs.m_column)
-#endif
- {
- }
-
/// Construct with a pointer to another Declaration object.
Declaration(const Declaration *decl_ptr)
: m_file(), m_line(0)
@@ -102,9 +92,9 @@ public:
/// The Right Hand Side const Declaration object reference.
///
/// \return
- /// \li -1 if lhs < rhs
- /// \li 0 if lhs == rhs
- /// \li 1 if lhs > rhs
+ /// -1 if lhs < rhs
+ /// 0 if lhs == rhs
+ /// 1 if lhs > rhs
static int Compare(const Declaration &lhs, const Declaration &rhs);
/// Checks if this object has the same file and line as another declaration
diff --git a/lldb/include/lldb/Symbol/Function.h b/lldb/include/lldb/Symbol/Function.h
index 1b23a99373ca..f675b5fdffa6 100644
--- a/lldb/include/lldb/Symbol/Function.h
+++ b/lldb/include/lldb/Symbol/Function.h
@@ -19,6 +19,8 @@
namespace lldb_private {
+class ExecutionContext;
+
/// \class FunctionInfo Function.h "lldb/Symbol/Function.h"
/// A class that contains generic function information.
///
@@ -68,9 +70,9 @@ public:
/// The Right Hand Side const FunctionInfo object reference.
///
/// \return
- /// \li -1 if lhs < rhs
- /// \li 0 if lhs == rhs
- /// \li 1 if lhs > rhs
+ /// -1 if lhs < rhs
+ /// 0 if lhs == rhs
+ /// 1 if lhs > rhs
static int Compare(const FunctionInfo &lhs, const FunctionInfo &rhs);
/// Dump a description of this object to a Stream.
@@ -183,9 +185,9 @@ public:
/// reference.
///
/// \return
- /// \li -1 if lhs < rhs
- /// \li 0 if lhs == rhs
- /// \li 1 if lhs > rhs
+ /// -1 if lhs < rhs
+ /// 0 if lhs == rhs
+ /// 1 if lhs > rhs
int Compare(const InlineFunctionInfo &lhs, const InlineFunctionInfo &rhs);
/// Dump a description of this object to a Stream.
@@ -264,23 +266,14 @@ using CallSiteParameterArray = llvm::SmallVector<CallSiteParameter, 0>;
/// in the call graph between two functions, or to evaluate DW_OP_entry_value.
class CallEdge {
public:
- /// Construct a call edge using a symbol name to identify the calling
- /// function, and a return PC within the calling function to identify a
- /// specific call site.
- ///
- /// TODO: A symbol name may not be globally unique. To disambiguate ODR
- /// conflicts, it's necessary to determine the \c Target a call edge is
- /// associated with before resolving it.
- CallEdge(const char *symbol_name, lldb::addr_t return_pc,
- CallSiteParameterArray parameters);
-
- CallEdge(CallEdge &&) = default;
- CallEdge &operator=(CallEdge &&) = default;
+ virtual ~CallEdge() {}
/// Get the callee's definition.
///
- /// Note that this might lazily invoke the DWARF parser.
- Function *GetCallee(ModuleList &images);
+ /// Note that this might lazily invoke the DWARF parser. A register context
+ /// from the caller's activation is needed to find indirect call targets.
+ virtual Function *GetCallee(ModuleList &images,
+ ExecutionContext &exe_ctx) = 0;
/// Get the load PC address of the instruction which executes after the call
/// returns. Returns LLDB_INVALID_ADDRESS iff this is a tail call. \p caller
@@ -293,29 +286,72 @@ public:
lldb::addr_t GetUnresolvedReturnPCAddress() const { return return_pc; }
/// Get the call site parameters available at this call edge.
- llvm::ArrayRef<CallSiteParameter> GetCallSiteParameters() const;
+ llvm::ArrayRef<CallSiteParameter> GetCallSiteParameters() const {
+ return parameters;
+ }
+
+protected:
+ CallEdge(lldb::addr_t return_pc, CallSiteParameterArray &&parameters)
+ : return_pc(return_pc), parameters(std::move(parameters)) {}
+
+ /// An invalid address if this is a tail call. Otherwise, the function-local
+ /// PC offset. Adding this PC offset to the function's base load address
+ /// gives the return PC for the call.
+ lldb::addr_t return_pc;
+
+ CallSiteParameterArray parameters;
+};
+
+/// A direct call site. Used to represent call sites where the address of the
+/// callee is fixed (e.g. a function call in C in which the call target is not
+/// a function pointer).
+class DirectCallEdge : public CallEdge {
+public:
+ /// Construct a call edge using a symbol name to identify the callee, and a
+ /// return PC within the calling function to identify a specific call site.
+ DirectCallEdge(const char *symbol_name, lldb::addr_t return_pc,
+ CallSiteParameterArray &&parameters)
+ : CallEdge(return_pc, std::move(parameters)) {
+ lazy_callee.symbol_name = symbol_name;
+ }
+
+ Function *GetCallee(ModuleList &images, ExecutionContext &exe_ctx) override;
private:
void ParseSymbolFileAndResolve(ModuleList &images);
- /// Either the callee's mangled name or its definition, discriminated by
- /// \ref resolved.
+ // Used to describe a direct call.
+ //
+ // Either the callee's mangled name or its definition, discriminated by
+ // \ref resolved.
union {
const char *symbol_name;
Function *def;
} lazy_callee;
- /// An invalid address if this is a tail call. Otherwise, the function-local
- /// PC offset. Adding this PC offset to the function's base load address
- /// gives the return PC for the call.
- lldb::addr_t return_pc;
+ /// Whether or not an attempt was made to find the callee's definition.
+ bool resolved = false;
+};
- CallSiteParameterArray parameters;
+/// An indirect call site. Used to represent call sites where the address of
+/// the callee is not fixed, e.g. a call to a C++ virtual function (where the
+/// address is loaded out of a vtable), or a call to a function pointer in C.
+class IndirectCallEdge : public CallEdge {
+public:
+ /// Construct a call edge using a DWARFExpression to identify the callee, and
+ /// a return PC within the calling function to identify a specific call site.
+ IndirectCallEdge(DWARFExpression call_target, lldb::addr_t return_pc,
+ CallSiteParameterArray &&parameters)
+ : CallEdge(return_pc, std::move(parameters)),
+ call_target(std::move(call_target)) {}
- /// Whether or not an attempt was made to find the callee's definition.
- bool resolved;
+ Function *GetCallee(ModuleList &images, ExecutionContext &exe_ctx) override;
- DISALLOW_COPY_AND_ASSIGN(CallEdge);
+private:
+ // Used to describe an indirect call.
+ //
+ // Specifies the location of the callee address in the calling frame.
+ DWARFExpression call_target;
};
/// \class Function Function.h "lldb/Symbol/Function.h"
@@ -414,11 +450,11 @@ public:
/// Get the outgoing call edges from this function, sorted by their return
/// PC addresses (in increasing order).
- llvm::MutableArrayRef<CallEdge> GetCallEdges();
+ llvm::ArrayRef<std::unique_ptr<CallEdge>> GetCallEdges();
/// Get the outgoing tail-calling edges from this function. If none exist,
/// return None.
- llvm::MutableArrayRef<CallEdge> GetTailCallingEdges();
+ llvm::ArrayRef<std::unique_ptr<CallEdge>> GetTailCallingEdges();
/// Get the outgoing call edge from this function which has the given return
/// address \p return_pc, or return nullptr. Note that this will not return a
@@ -587,11 +623,9 @@ protected:
uint32_t
m_prologue_byte_size; ///< Compute the prologue size once and cache it
- // TODO: Use a layer of indirection to point to call edges, to save space
- // when call info hasn't been parsed.
bool m_call_edges_resolved = false; ///< Whether call site info has been
/// parsed.
- std::vector<CallEdge> m_call_edges; ///< Outgoing call edges.
+ std::vector<std::unique_ptr<CallEdge>> m_call_edges; ///< Outgoing call edges.
private:
DISALLOW_COPY_AND_ASSIGN(Function);
};
diff --git a/lldb/include/lldb/Symbol/LineEntry.h b/lldb/include/lldb/Symbol/LineEntry.h
index fe97a78e3ed4..32ffef72ee5e 100644
--- a/lldb/include/lldb/Symbol/LineEntry.h
+++ b/lldb/include/lldb/Symbol/LineEntry.h
@@ -42,11 +42,6 @@ struct LineEntry {
/// \param[in] s
/// The stream to which to dump the object description.
///
- /// \param[in] comp_unit
- /// The compile unit object that contains the support file
- /// list so the line entry can dump the file name (since this
- /// object contains a file index into the support file list).
- ///
/// \param[in] show_file
/// If \b true, display the filename with the line entry which
/// requires that the compile unit object \a comp_unit be a
@@ -75,11 +70,6 @@ struct LineEntry {
/// \param[in] s
/// The stream to which to dump the object description.
///
- /// \param[in] comp_unit
- /// The compile unit object that contains the support file
- /// list so the line entry can dump the file name (since this
- /// object contains a file index into the support file list).
- ///
/// \return
/// Returns \b true if the file and line were properly dumped,
/// \b false otherwise.
@@ -102,9 +92,9 @@ struct LineEntry {
/// The Right Hand Side const LineEntry object reference.
///
/// \return
- /// \li -1 if lhs < rhs
- /// \li 0 if lhs == rhs
- /// \li 1 if lhs > rhs
+ /// -1 if lhs < rhs
+ /// 0 if lhs == rhs
+ /// 1 if lhs > rhs
static int Compare(const LineEntry &lhs, const LineEntry &rhs);
/// Give the range for this LineEntry + any additional LineEntries for this
@@ -143,7 +133,6 @@ struct LineEntry {
///
/// \param[in] target_sp
/// Shared pointer to the target this LineEntry belongs to.
-
void ApplyFileMappings(lldb::TargetSP target_sp);
// Member variables.
diff --git a/lldb/include/lldb/Symbol/LineTable.h b/lldb/include/lldb/Symbol/LineTable.h
index d24cc35e10f3..043f3eb895cb 100644
--- a/lldb/include/lldb/Symbol/LineTable.h
+++ b/lldb/include/lldb/Symbol/LineTable.h
@@ -135,8 +135,8 @@ public:
/// If true, match only if you find a line entry exactly matching \a line.
/// If false, return the closest line entry greater than \a line.
///
- /// \param[out] line_entry
- /// A reference to a line entry object that will get a copy of
+ /// \param[out] line_entry_ptr
+ /// A pointer to a line entry object that will get a copy of
/// the line entry if \b true is returned, otherwise \a
/// line_entry is left untouched.
///
@@ -194,16 +194,6 @@ public:
size_t GetContiguousFileAddressRanges(FileAddressRanges &file_ranges,
bool append);
- /// Given a file range link map, relink the current line table and return a
- /// fixed up line table.
- ///
- /// \param[out] file_range_map
- /// A collection of file ranges that maps to new file ranges
- /// that will be used when linking the line table.
- ///
- /// \return
- /// A new line table if at least one line table entry was able
- /// to be mapped.
typedef RangeDataVector<lldb::addr_t, lldb::addr_t, lldb::addr_t>
FileRangeMap;
diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h
index 4d04f23a8286..841a38e5b15a 100644
--- a/lldb/include/lldb/Symbol/ObjectFile.h
+++ b/lldb/include/lldb/Symbol/ObjectFile.h
@@ -130,7 +130,7 @@ public:
/// ObjectFile plug-in interface and returns the first instance that can
/// parse the file.
///
- /// \param[in] module
+ /// \param[in] module_sp
/// The parent module that owns this object file.
///
/// \param[in] file_spec
@@ -158,7 +158,7 @@ public:
/// ObjectFile plug-in interface and returns the first instance that can
/// parse the file.
///
- /// \param[in] module
+ /// \param[in] module_sp
/// The parent module that owns this object file.
///
/// \param[in] process_sp
@@ -356,13 +356,6 @@ public:
/// Frees the symbol table.
///
/// This function should only be used when an object file is
- ///
- /// \param[in] flags
- /// eSymtabFromUnifiedSectionList: Whether to clear symbol table
- /// for unified module section list, or object file.
- ///
- /// \return
- /// The symbol table for this object file.
virtual void ClearSymtab();
/// Gets the UUID for this object file.
@@ -487,8 +480,8 @@ public:
/// \return
/// Returns the identifier string if one exists, else an empty
/// string.
- virtual std::string GetIdentifierString () {
- return std::string();
+ virtual std::string GetIdentifierString () {
+ return std::string();
}
/// When the ObjectFile is a core file, lldb needs to locate the "binary" in
@@ -652,8 +645,6 @@ public:
///
/// \param[in] target
/// Target where to load.
- ///
- /// \return
virtual std::vector<LoadableData> GetLoadableData(Target &target);
/// Creates a plugin-specific call frame info
diff --git a/lldb/include/lldb/Symbol/Symbol.h b/lldb/include/lldb/Symbol/Symbol.h
index b7f179d1449b..36f89c044ea9 100644
--- a/lldb/include/lldb/Symbol/Symbol.h
+++ b/lldb/include/lldb/Symbol/Symbol.h
@@ -43,7 +43,9 @@ public:
bool Compare(ConstString name, lldb::SymbolType type) const;
- void Dump(Stream *s, Target *target, uint32_t index) const;
+ void Dump(Stream *s, Target *target, uint32_t index,
+ Mangled::NamePreference name_preference =
+ Mangled::ePreferDemangled) const;
bool ValueIsAddress() const;
diff --git a/lldb/include/lldb/Symbol/SymbolContext.h b/lldb/include/lldb/Symbol/SymbolContext.h
index 76ec1a7de68e..4c7b727fe618 100644
--- a/lldb/include/lldb/Symbol/SymbolContext.h
+++ b/lldb/include/lldb/Symbol/SymbolContext.h
@@ -51,7 +51,7 @@ public:
///
/// Initialize all pointer to the specified values.
///
- /// \param[in] module
+ /// \param[in] module_sp
/// A Module pointer to the module for this context.
///
/// \param[in] comp_unit
@@ -84,18 +84,6 @@ public:
~SymbolContext();
- /// Assignment operator.
- ///
- /// Copies the address value from another SymbolContext object \a rhs into
- /// \a this object.
- ///
- /// \param[in] rhs
- /// A const SymbolContext object reference to copy.
- ///
- /// \return
- /// A const SymbolContext object reference to \a this.
- const SymbolContext &operator=(const SymbolContext &rhs);
-
/// Clear the object's state.
///
/// Resets all pointer members to nullptr, and clears any class objects to
@@ -279,11 +267,6 @@ public:
/// For instance, if the symbol context contains an inlined block, it will
/// return the inlined function name.
///
- /// \param[in] prefer_mangled
- /// if \btrue, then the mangled name will be returned if there
- /// is one. Otherwise the unmangled name will be returned if it
- /// is available.
- ///
/// \return
/// The name of the function represented by this symbol context.
ConstString GetFunctionName(
@@ -298,14 +281,6 @@ public:
/// ModuleList::FindFunctions(...) call in order to get the correct line
/// table information for the symbol context. it will return the inlined
/// function name.
- ///
- /// \param[in] prefer_mangled
- /// if \btrue, then the mangled name will be returned if there
- /// is one. Otherwise the unmangled name will be returned if it
- /// is available.
- ///
- /// \return
- /// The name of the function represented by this symbol context.
LineEntry GetFunctionStartLineEntry() const;
/// Find the block containing the inlined block that contains this block.
@@ -319,13 +294,13 @@ public:
/// \param[out] next_frame_sc
/// A new symbol context that does what the title says it does.
///
- /// \param[out] next_frame_addr
+ /// \param[out] inlined_frame_addr
/// This is what you should report as the PC in \a next_frame_sc.
///
/// \return
/// \b true if this SymbolContext specifies a block contained in an
/// inlined block. If this returns \b true, \a next_frame_sc and
- /// \a next_frame_addr will be filled in correctly.
+ /// \a inlined_frame_addr will be filled in correctly.
bool GetParentOfInlinedScope(const Address &curr_frame_pc,
SymbolContext &next_frame_sc,
Address &inlined_frame_addr) const;
diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h
index 6724b425abf3..fdd812eb5167 100644
--- a/lldb/include/lldb/Symbol/SymbolFile.h
+++ b/lldb/include/lldb/Symbol/SymbolFile.h
@@ -33,7 +33,16 @@
namespace lldb_private {
class SymbolFile : public PluginInterface {
+ /// LLVM RTTI support.
+ static char ID;
+
public:
+ /// LLVM RTTI support.
+ /// \{
+ virtual bool isA(const void *ClassID) const { return ClassID == &ID; }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
+
// Symbol file ability bits.
//
// Each symbol file can claim to support one or more symbol file abilities.
@@ -122,9 +131,35 @@ public:
virtual size_t ParseFunctions(CompileUnit &comp_unit) = 0;
virtual bool ParseLineTable(CompileUnit &comp_unit) = 0;
virtual bool ParseDebugMacros(CompileUnit &comp_unit) = 0;
- virtual void
- ForEachExternalModule(CompileUnit &comp_unit,
- llvm::function_ref<void(lldb::ModuleSP)> f) {}
+
+ /// Apply a lambda to each external lldb::Module referenced by this
+ /// \p comp_unit. Recursively also descends into the referenced external
+ /// modules of any encountered compilation unit.
+ ///
+ /// \param comp_unit
+ /// When this SymbolFile consists of multiple auxilliary
+ /// SymbolFiles, for example, a Darwin debug map that references
+ /// multiple .o files, comp_unit helps choose the auxilliary
+ /// file. In most other cases comp_unit's symbol file is
+ /// identiacal with *this.
+ ///
+ /// \param[in] lambda
+ /// The lambda that should be applied to every function. The lambda can
+ /// return true if the iteration should be aborted earlier.
+ ///
+ /// \param visited_symbol_files
+ /// A set of SymbolFiles that were already visited to avoid
+ /// visiting one file more than once.
+ ///
+ /// \return
+ /// If the lambda early-exited, this function returns true to
+ /// propagate the early exit.
+ virtual bool ForEachExternalModule(
+ lldb_private::CompileUnit &comp_unit,
+ llvm::DenseSet<lldb_private::SymbolFile *> &visited_symbol_files,
+ llvm::function_ref<bool(Module &)> lambda) {
+ return false;
+ }
virtual bool ParseSupportFiles(CompileUnit &comp_unit,
FileSpecList &support_files) = 0;
virtual size_t ParseTypes(CompileUnit &comp_unit) = 0;
@@ -193,9 +228,14 @@ public:
TypeMap &types);
/// Find types specified by a CompilerContextPattern.
- /// \param languages Only return results in these languages.
- virtual void FindTypes(llvm::ArrayRef<CompilerContext> pattern,
- LanguageSet languages, TypeMap &types);
+ /// \param languages
+ /// Only return results in these languages.
+ /// \param searched_symbol_files
+ /// Prevents one file from being visited multiple times.
+ virtual void
+ FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
+ llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
+ TypeMap &types);
virtual void
GetMangledNamesForFunction(const std::string &scope_qualified_name,
@@ -220,7 +260,8 @@ public:
const ObjectFile *GetObjectFile() const { return m_objfile_sp.get(); }
ObjectFile *GetMainObjectFile();
- virtual std::vector<CallEdge> ParseCallEdgesInFunction(UserID func_id) {
+ virtual std::vector<std::unique_ptr<CallEdge>>
+ ParseCallEdgesInFunction(UserID func_id) {
return {};
}
diff --git a/lldb/include/lldb/Symbol/Symtab.h b/lldb/include/lldb/Symbol/Symtab.h
index 99d15771ccc5..f121bef1bfbe 100644
--- a/lldb/include/lldb/Symbol/Symtab.h
+++ b/lldb/include/lldb/Symbol/Symtab.h
@@ -40,8 +40,12 @@ public:
uint32_t AddSymbol(const Symbol &symbol);
size_t GetNumSymbols() const;
void SectionFileAddressesChanged();
- void Dump(Stream *s, Target *target, SortOrder sort_type);
- void Dump(Stream *s, Target *target, std::vector<uint32_t> &indexes) const;
+ void
+ Dump(Stream *s, Target *target, SortOrder sort_type,
+ Mangled::NamePreference name_preference = Mangled::ePreferDemangled);
+ void Dump(Stream *s, Target *target, std::vector<uint32_t> &indexes,
+ Mangled::NamePreference name_preference =
+ Mangled::ePreferDemangled) const;
uint32_t GetIndexForSymbol(const Symbol *symbol) const;
std::recursive_mutex &GetMutex() { return m_mutex; }
Symbol *FindSymbolByID(lldb::user_id_t uid) const;
@@ -139,7 +143,29 @@ protected:
typedef std::vector<Symbol> collection;
typedef collection::iterator iterator;
typedef collection::const_iterator const_iterator;
- typedef RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t>
+ class FileRangeToIndexMapCompare {
+ public:
+ FileRangeToIndexMapCompare(const Symtab &symtab) : m_symtab(symtab) {}
+ bool operator()(const uint32_t a_data, const uint32_t b_data) const {
+ return rank(a_data) > rank(b_data);
+ }
+
+ private:
+ // How much preferred is this symbol?
+ int rank(const uint32_t data) const {
+ const Symbol &symbol = *m_symtab.SymbolAtIndex(data);
+ if (symbol.IsExternal())
+ return 3;
+ if (symbol.IsWeak())
+ return 2;
+ if (symbol.IsDebug())
+ return 0;
+ return 1;
+ }
+ const Symtab &m_symtab;
+ };
+ typedef RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t, 0,
+ FileRangeToIndexMapCompare>
FileRangeToIndexMap;
void InitNameIndexes();
void InitAddressIndexes();
diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h
index 446e043a95ee..95a3bc497517 100644
--- a/lldb/include/lldb/Symbol/Type.h
+++ b/lldb/include/lldb/Symbol/Type.h
@@ -80,22 +80,18 @@ public:
eEncodingIsLValueReferenceUID, ///< This type is L value reference to a type
/// whose UID is m_encoding_uid
eEncodingIsRValueReferenceUID, ///< This type is R value reference to a type
- /// whose UID is m_encoding_uid
+ /// whose UID is m_encoding_uid,
+ eEncodingIsAtomicUID, ///< This type is the type whose UID is
+ /// m_encoding_uid as an atomic type.
eEncodingIsSyntheticUID
};
- // We must force the underlying type of the enum to be unsigned here. Not
- // all compilers behave the same with regards to the default underlying type
- // of an enum, but because this enum is used in an enum bitfield and integer
- // comparisons are done with the value we need to guarantee that it's always
- // unsigned so that, for example, eResolveStateFull doesn't compare less than
- // eResolveStateUnresolved when used in a 2-bit bitfield.
- typedef enum ResolveStateTag : unsigned {
- eResolveStateUnresolved = 0,
- eResolveStateForward = 1,
- eResolveStateLayout = 2,
- eResolveStateFull = 3
- } ResolveState;
+ enum class ResolveState : unsigned char {
+ Unresolved = 0,
+ Forward = 1,
+ Layout = 2,
+ Full = 3
+ };
Type(lldb::user_id_t uid, SymbolFile *symbol_file, ConstString name,
llvm::Optional<uint64_t> byte_size, SymbolContextScope *context,
@@ -200,17 +196,17 @@ public:
uint32_t GetEncodingMask();
- bool IsCompleteObjCClass() { return m_flags.is_complete_objc_class; }
+ bool IsCompleteObjCClass() { return m_is_complete_objc_class; }
void SetIsCompleteObjCClass(bool is_complete_objc_class) {
- m_flags.is_complete_objc_class = is_complete_objc_class;
+ m_is_complete_objc_class = is_complete_objc_class;
}
protected:
ConstString m_name;
SymbolFile *m_symbol_file;
- SymbolContextScope
- *m_context; // The symbol context in which this type is defined
+ /// The symbol context in which this type is defined.
+ SymbolContextScope *m_context;
Type *m_encoding_type;
lldb::user_id_t m_encoding_uid;
EncodingDataType m_encoding_uid_type;
@@ -218,16 +214,8 @@ protected:
uint64_t m_byte_size_has_value : 1;
Declaration m_decl;
CompilerType m_compiler_type;
-
- struct Flags {
-#ifdef __GNUC__
- // using unsigned type here to work around a very noisy gcc warning
- unsigned compiler_type_resolve_state : 2;
-#else
- ResolveState compiler_type_resolve_state : 2;
-#endif
- bool is_complete_objc_class : 1;
- } m_flags;
+ ResolveState m_compiler_type_resolve_state;
+ bool m_is_complete_objc_class;
Type *GetEncodingType();
diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h
index 07295c244a5d..91f751acf6c7 100644
--- a/lldb/include/lldb/Symbol/TypeSystem.h
+++ b/lldb/include/lldb/Symbol/TypeSystem.h
@@ -49,51 +49,32 @@ struct LanguageSet {
bool operator[](unsigned i) const;
};
-/// Interface for representing the Type Systems in different languages.
+/// Interface for representing a type system.
+///
+/// Implemented by language plugins to define the type system for a given
+/// language.
+///
+/// This interface extensively used opaque pointers to prevent that generic
+/// LLDB code has dependencies on language plugins. The type and semantics of
+/// these opaque pointers are defined by the TypeSystem implementation inside
+/// the respective language plugin. Opaque pointers from one TypeSystem
+/// instance should never be passed to a different TypeSystem instance (even
+/// when the language plugin for both TypeSystem instances is the same).
+///
+/// Most of the functions in this class should not be called directly but only
+/// called by their respective counterparts in CompilerType, CompilerDecl and
+/// CompilerDeclContext.
+///
+/// \see lldb_private::CompilerType
+/// \see lldb_private::CompilerDecl
+/// \see lldb_private::CompilerDeclContext
class TypeSystem : public PluginInterface {
public:
- // Intrusive type system that allows us to use llvm casting.
- //
- // To add a new type system:
- //
- // 1 - Add a new enumeration for llvm casting below for your TypeSystem
- // subclass, here we will use eKindFoo
- //
- // 2 - Your TypeSystem subclass will inherit from TypeSystem and needs
- // to implement a static classof() function that returns your
- // enumeration:
- //
- // class Foo : public lldb_private::TypeSystem
- // {
- // static bool classof(const TypeSystem *ts)
- // {
- // return ts->getKind() == TypeSystem::eKindFoo;
- // }
- // };
- //
- // 3 - Contruct your TypeSystem subclass with the enumeration from below
- //
- // Foo() :
- // TypeSystem(TypeSystem::eKindFoo),
- // ...
- // {
- // }
- //
- // Then you can use the llvm casting on any "TypeSystem *" to get an instance
- // of your subclass.
- enum LLVMCastKind {
- eKindClang,
- eKindSwift,
- eKindOCaml,
- kNumKinds
- };
-
// Constructors and Destructors
- TypeSystem(LLVMCastKind kind);
-
~TypeSystem() override;
- LLVMCastKind getKind() const { return m_kind; }
+ // LLVM RTTI support
+ virtual bool isA(const void *ClassID) const = 0;
static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language,
Module *module);
@@ -135,8 +116,6 @@ public:
DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name,
const bool ignore_imported_decls);
- virtual bool DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) = 0;
-
virtual ConstString DeclContextGetName(void *opaque_decl_ctx) = 0;
virtual ConstString
@@ -265,6 +244,8 @@ public:
virtual CompilerType
GetRValueReferenceType(lldb::opaque_compiler_type_t type);
+ virtual CompilerType GetAtomicType(lldb::opaque_compiler_type_t type);
+
virtual CompilerType AddConstModifier(lldb::opaque_compiler_type_t type);
virtual CompilerType AddVolatileModifier(lldb::opaque_compiler_type_t type);
@@ -494,8 +475,7 @@ public:
virtual bool IsMeaninglessWithoutDynamicResolution(void *type);
protected:
- const LLVMCastKind m_kind; // Support for llvm casting
- SymbolFile *m_sym_file;
+ SymbolFile *m_sym_file = nullptr;
};
class TypeSystemMap {
diff --git a/lldb/include/lldb/Symbol/VariableList.h b/lldb/include/lldb/Symbol/VariableList.h
index 54d27583cd7b..87f98668a8a8 100644
--- a/lldb/include/lldb/Symbol/VariableList.h
+++ b/lldb/include/lldb/Symbol/VariableList.h
@@ -16,6 +16,8 @@
namespace lldb_private {
class VariableList {
+ typedef std::vector<lldb::VariableSP> collection;
+
public:
// Constructors and Destructors
// VariableList(const SymbolContext &symbol_context);
@@ -65,11 +67,15 @@ public:
size_t GetSize() const;
bool Empty() const { return m_variables.empty(); }
-protected:
- typedef std::vector<lldb::VariableSP> collection;
typedef collection::iterator iterator;
typedef collection::const_iterator const_iterator;
+ iterator begin() { return m_variables.begin(); }
+ iterator end() { return m_variables.end(); }
+ const_iterator begin() const { return m_variables.begin(); }
+ const_iterator end() const { return m_variables.end(); }
+
+protected:
collection m_variables;
private:
diff --git a/lldb/include/lldb/Target/ABI.h b/lldb/include/lldb/Target/ABI.h
index 93378abc2ac2..1aff1e2f7817 100644
--- a/lldb/include/lldb/Target/ABI.h
+++ b/lldb/include/lldb/Target/ABI.h
@@ -126,12 +126,7 @@ public:
llvm::MCRegisterInfo &GetMCRegisterInfo() { return *m_mc_register_info_up; }
- virtual const RegisterInfo *GetRegisterInfoArray(uint32_t &count) = 0;
-
- bool GetRegisterInfoByName(ConstString name, RegisterInfo &info);
-
- bool GetRegisterInfoByKind(lldb::RegisterKind reg_kind, uint32_t reg_num,
- RegisterInfo &info);
+ virtual void AugmentRegisterInfo(RegisterInfo &info);
virtual bool GetPointerReturnRegister(const char *&name) { return false; }
@@ -143,6 +138,10 @@ protected:
assert(m_mc_register_info_up && "ABI must have MCRegisterInfo");
}
+ bool GetRegisterInfoByName(ConstString name, RegisterInfo &info);
+
+ virtual const RegisterInfo *GetRegisterInfoArray(uint32_t &count) = 0;
+
/// Utility function to construct a MCRegisterInfo using the ArchSpec triple.
/// Plugins wishing to customize the construction can construct the
/// MCRegisterInfo themselves.
diff --git a/lldb/include/lldb/Target/Language.h b/lldb/include/lldb/Target/Language.h
index b49e96eeac17..e00b042ac253 100644
--- a/lldb/include/lldb/Target/Language.h
+++ b/lldb/include/lldb/Target/Language.h
@@ -176,9 +176,6 @@ public:
virtual HardcodedFormatters::HardcodedSyntheticFinder
GetHardcodedSynthetics();
- virtual HardcodedFormatters::HardcodedValidatorFinder
- GetHardcodedValidators();
-
virtual std::vector<ConstString>
GetPossibleFormattersMatches(ValueObject &valobj,
lldb::DynamicValueType use_dynamic);
diff --git a/lldb/include/lldb/Target/MemoryRegionInfo.h b/lldb/include/lldb/Target/MemoryRegionInfo.h
index 5cab2efea77c..07e50188843e 100644
--- a/lldb/include/lldb/Target/MemoryRegionInfo.h
+++ b/lldb/include/lldb/Target/MemoryRegionInfo.h
@@ -21,11 +21,13 @@ public:
enum OptionalBool { eDontKnow = -1, eNo = 0, eYes = 1 };
- MemoryRegionInfo()
- : m_range(), m_read(eDontKnow), m_write(eDontKnow), m_execute(eDontKnow),
- m_mapped(eDontKnow), m_flash(eDontKnow), m_blocksize(0) {}
-
- ~MemoryRegionInfo() {}
+ MemoryRegionInfo() = default;
+ MemoryRegionInfo(RangeType range, OptionalBool read, OptionalBool write,
+ OptionalBool execute, OptionalBool mapped, ConstString name,
+ OptionalBool flash, lldb::offset_t blocksize)
+ : m_range(range), m_read(read), m_write(write), m_execute(execute),
+ m_mapped(mapped), m_name(name), m_flash(flash), m_blocksize(blocksize) {
+ }
RangeType &GetRange() { return m_range; }
@@ -88,20 +90,21 @@ public:
bool operator==(const MemoryRegionInfo &rhs) const {
return m_range == rhs.m_range && m_read == rhs.m_read &&
m_write == rhs.m_write && m_execute == rhs.m_execute &&
- m_mapped == rhs.m_mapped;
+ m_mapped == rhs.m_mapped && m_name == rhs.m_name &&
+ m_flash == rhs.m_flash && m_blocksize == rhs.m_blocksize;
}
bool operator!=(const MemoryRegionInfo &rhs) const { return !(*this == rhs); }
protected:
RangeType m_range;
- OptionalBool m_read;
- OptionalBool m_write;
- OptionalBool m_execute;
- OptionalBool m_mapped;
+ OptionalBool m_read = eDontKnow;
+ OptionalBool m_write = eDontKnow;
+ OptionalBool m_execute = eDontKnow;
+ OptionalBool m_mapped = eDontKnow;
ConstString m_name;
- OptionalBool m_flash;
- lldb::offset_t m_blocksize;
+ OptionalBool m_flash = eDontKnow;
+ lldb::offset_t m_blocksize = 0;
};
inline bool operator<(const MemoryRegionInfo &lhs,
@@ -117,6 +120,9 @@ inline bool operator<(lldb::addr_t lhs, const MemoryRegionInfo &rhs) {
return lhs < rhs.GetRange().GetRangeBase();
}
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const MemoryRegionInfo &Info);
+
// Forward-declarable wrapper.
class MemoryRegionInfos : public std::vector<lldb_private::MemoryRegionInfo> {
public:
@@ -127,21 +133,13 @@ public:
namespace llvm {
template <>
+/// If Options is empty, prints a textual representation of the value. If
+/// Options is a single character, it uses that character for the "yes" value,
+/// while "no" is printed as "-", and "don't know" as "?". This can be used to
+/// print the permissions in the traditional "rwx" form.
struct format_provider<lldb_private::MemoryRegionInfo::OptionalBool> {
static void format(const lldb_private::MemoryRegionInfo::OptionalBool &B,
- raw_ostream &OS, StringRef Options) {
- switch(B) {
- case lldb_private::MemoryRegionInfo::eNo:
- OS << "no";
- return;
- case lldb_private::MemoryRegionInfo::eYes:
- OS << "yes";
- return;
- case lldb_private::MemoryRegionInfo::eDontKnow:
- OS << "don't know";
- return;
- }
- }
+ raw_ostream &OS, StringRef Options);
};
}
diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h
index 6f643df53d1e..72b6be21b770 100644
--- a/lldb/include/lldb/Target/Platform.h
+++ b/lldb/include/lldb/Target/Platform.h
@@ -380,9 +380,6 @@ public:
/// attached to the process, or an empty shared pointer with an appropriate
/// error.
///
- /// \param[in] pid
- /// The process ID that we should attempt to attach to.
- ///
/// \return
/// An appropriate ProcessSP containing a valid shared pointer
/// to the default Process subclass for the platform that is
@@ -777,7 +774,7 @@ public:
/// given an install name and a set (e.g. DYLD_LIBRARY_PATH provided) of
/// alternate paths.
///
- /// \param[in] path_list
+ /// \param[in] paths
/// The list of paths to use to search for the library. First
/// match wins.
///
@@ -788,7 +785,7 @@ public:
/// \param[out] loaded_path
/// If non-null, the path to the dylib that was successfully loaded
/// is stored in this path.
- ///
+ ///
/// \return
/// A token that represents the shared library which can be
/// passed to UnloadImage. A value of
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index a4ef1cc40414..2ba996d4995f 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -85,9 +85,6 @@ public:
std::chrono::seconds GetUtilityExpressionTimeout() const;
protected:
- static void OptionValueChangedCallback(void *baton,
- OptionValue *option_value);
-
Process *m_process; // Can be nullptr for global ProcessProperties
};
@@ -520,14 +517,6 @@ public:
/// Process plug-in interface and returns the first instance that can debug
/// the file.
///
- /// \param[in] module_sp
- /// The module shared pointer that this process will debug.
- ///
- /// \param[in] plugin_name
- /// If nullptr, select the best plug-in for the binary. If non-nullptr
- /// then look for a plugin whose PluginInfo's name matches
- /// this string.
- ///
/// \see Process::CanDebug ()
static lldb::ProcessSP FindPlugin(lldb::TargetSP target_sp,
llvm::StringRef plugin_name,
@@ -714,8 +703,8 @@ public:
/// char *) will be called to actually do the attach. If DoAttach returns \b
/// true, then Process::DidAttach() will be called.
///
- /// \param[in] pid
- /// The process ID that we should attempt to attach to.
+ /// \param[in] attach_info
+ /// The process attach info.
///
/// \return
/// Returns \a pid if attaching was successful, or
@@ -1392,7 +1381,8 @@ public:
/// the core file.
///
/// \return
- // true if the user should be warned about detaching from this process.
+ /// Returns \b true if the user should be warned about detaching from
+ /// this process.
virtual bool WarnBeforeDetach() const { return true; }
/// Actually do the reading of memory from a process.
@@ -1722,8 +1712,9 @@ public:
/// lldb,
/// just not by the process itself.
///
- /// \param[in/out] error
+ /// \param[in,out] error
/// An error object to fill in if things go wrong.
+ ///
/// \return
/// The address of the allocated buffer in the process, or
/// LLDB_INVALID_ADDRESS if the allocation failed.
@@ -2171,7 +2162,7 @@ public:
/// WaitFor* calls above. Be sure to call RestoreProcessEvents when you are
/// done.
///
- /// \param[in] listener
+ /// \param[in] listener_sp
/// This is the new listener to whom all process events will be delivered.
///
/// \return
@@ -2191,11 +2182,9 @@ public:
OperatingSystem *GetOperatingSystem() { return m_os_up.get(); }
- std::vector<LanguageRuntime *>
- GetLanguageRuntimes(bool retry_if_null = true);
+ std::vector<LanguageRuntime *> GetLanguageRuntimes();
- LanguageRuntime *GetLanguageRuntime(lldb::LanguageType language,
- bool retry_if_null = true);
+ LanguageRuntime *GetLanguageRuntime(lldb::LanguageType language);
bool IsPossibleDynamicValue(ValueObject &in_value);
@@ -2272,7 +2261,7 @@ public:
void ClearPreResumeAction(PreResumeActionCallback callback, void *baton);
ProcessRunLock &GetRunLock();
-
+
bool CurrentThreadIsPrivateStateThread();
virtual Status SendEventData(const char *data) {
@@ -2372,7 +2361,7 @@ public:
/// The StructuredData type name as previously discovered by
/// the Process-derived instance.
///
- /// \param[in] config
+ /// \param[in] config_sp
/// Configuration data for the feature being enabled. This config
/// data, which may be null, will be passed along to the feature
/// to process. The feature will dictate whether this is a dictionary,
@@ -2750,7 +2739,7 @@ protected:
StructuredDataPluginMap m_structured_data_plugin_map;
enum { eCanJITDontKnow = 0, eCanJITYes, eCanJITNo } m_can_jit;
-
+
std::unique_ptr<UtilityFunction> m_dlopen_utility_func_up;
llvm::once_flag m_dlopen_utility_func_flag_once;
diff --git a/lldb/include/lldb/Target/Queue.h b/lldb/include/lldb/Target/Queue.h
index 01e8994f2441..10b9e0242070 100644
--- a/lldb/include/lldb/Target/Queue.h
+++ b/lldb/include/lldb/Target/Queue.h
@@ -126,10 +126,7 @@ public:
m_pending_items.push_back(item);
}
- /// Return the kind (serial, concurrent) of this queue
- ///
- /// \return
- // Whether this is a serial or a concurrent queue
+ /// Return the kind (serial, concurrent) of this queue.
lldb::QueueKind GetKind();
void SetKind(lldb::QueueKind kind);
diff --git a/lldb/include/lldb/Target/StackFrame.h b/lldb/include/lldb/Target/StackFrame.h
index d2e5795162cf..1c6a2b481160 100644
--- a/lldb/include/lldb/Target/StackFrame.h
+++ b/lldb/include/lldb/Target/StackFrame.h
@@ -99,8 +99,6 @@ public:
/// \param [in] pc
/// The current pc value of this stack frame.
///
- /// \param [in] frame_kind
- ///
/// \param [in] sc_ptr
/// Optionally seed the StackFrame with the SymbolContext information that
/// has
@@ -289,18 +287,18 @@ public:
llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
uint32_t options, lldb::VariableSP &var_sp, Status &error);
- /// Determine whether this StackFrame has debug information available or not
+ /// Determine whether this StackFrame has debug information available or not.
///
/// \return
- // true if debug information is available for this frame (function,
- // compilation unit, block, etc.)
+ /// true if debug information is available for this frame (function,
+ /// compilation unit, block, etc.)
bool HasDebugInformation();
/// Return the disassembly for the instructions of this StackFrame's
/// function as a single C string.
///
/// \return
- // C string with the assembly instructions for this function.
+ /// C string with the assembly instructions for this function.
const char *Disassemble();
/// Print a description for this frame using the frame-format formatter
@@ -407,7 +405,7 @@ public:
/// is sufficient. One of the DynamicValueType enumerated values.
///
/// \return
- // A ValueObject for this variable.
+ /// A ValueObject for this variable.
lldb::ValueObjectSP
GetValueObjectForFrameVariable(const lldb::VariableSP &variable_sp,
lldb::DynamicValueType use_dynamic);
@@ -424,7 +422,7 @@ public:
/// is sufficient. One of the DynamicValueType enumerated values.
///
/// \return
- // A ValueObject for this variable.
+ /// A ValueObject for this variable.
lldb::ValueObjectSP TrackGlobalVariable(const lldb::VariableSP &variable_sp,
lldb::DynamicValueType use_dynamic);
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index e465046959f2..1e9153c401ef 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -203,34 +203,21 @@ public:
void SetInjectLocalVariables(ExecutionContext *exe_ctx, bool b);
- bool GetUseModernTypeLookup() const;
-
void SetRequireHardwareBreakpoints(bool b);
bool GetRequireHardwareBreakpoints() const;
private:
// Callbacks for m_launch_info.
- static void Arg0ValueChangedCallback(void *target_property_ptr,
- OptionValue *);
- static void RunArgsValueChangedCallback(void *target_property_ptr,
- OptionValue *);
- static void EnvVarsValueChangedCallback(void *target_property_ptr,
- OptionValue *);
- static void InheritEnvValueChangedCallback(void *target_property_ptr,
- OptionValue *);
- static void InputPathValueChangedCallback(void *target_property_ptr,
- OptionValue *);
- static void OutputPathValueChangedCallback(void *target_property_ptr,
- OptionValue *);
- static void ErrorPathValueChangedCallback(void *target_property_ptr,
- OptionValue *);
- static void DetachOnErrorValueChangedCallback(void *target_property_ptr,
- OptionValue *);
- static void DisableASLRValueChangedCallback(void *target_property_ptr,
- OptionValue *);
- static void DisableSTDIOValueChangedCallback(void *target_property_ptr,
- OptionValue *);
+ void Arg0ValueChangedCallback();
+ void RunArgsValueChangedCallback();
+ void EnvVarsValueChangedCallback();
+ void InputPathValueChangedCallback();
+ void OutputPathValueChangedCallback();
+ void ErrorPathValueChangedCallback();
+ void DetachOnErrorValueChangedCallback();
+ void DisableASLRValueChangedCallback();
+ void DisableSTDIOValueChangedCallback();
// Member variables.
ProcessLaunchInfo m_launch_info;
@@ -906,8 +893,8 @@ public:
/// The target call at present just consults the Platform's call of the
/// same name.
///
- /// \param[in] module_sp
- /// A shared pointer reference to the module that checked.
+ /// \param[in] module_spec
+ /// Path to the module.
///
/// \return \b true if the module should be excluded, \b false otherwise.
bool ModuleIsExcludedForUnconstrainedSearches(const FileSpec &module_spec);
@@ -1067,8 +1054,6 @@ public:
const char *name,
Status &error);
- ClangASTContext *GetScratchClangASTContext(bool create_on_demand = true);
-
lldb::ClangASTImporterSP GetClangASTImporter();
// Install any files through the platform that need be to installed prior to
diff --git a/lldb/include/lldb/Target/TargetList.h b/lldb/include/lldb/Target/TargetList.h
index ece0705ae71c..50a7a321ead1 100644
--- a/lldb/include/lldb/Target/TargetList.h
+++ b/lldb/include/lldb/Target/TargetList.h
@@ -55,12 +55,12 @@ public:
/// \param[in] debugger
/// The debugger to associate this target with
///
- /// \param[in] file_spec
+ /// \param[in] user_exe_path
/// The main executable file for a debug target. This value
- /// can be nullptr and the file can be set later using:
+ /// can be empty and the file can be set later using:
/// Target::SetExecutableModule (ModuleSP&)
///
- /// \param[in] triple_cstr
+ /// \param[in] triple_str
/// A target triple string to be used for the target. This can
/// be nullptr if the triple is not known or when attaching to a
/// process.
diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
index 7c5ff6093baf..cdc8d39251c6 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -128,10 +128,6 @@ public:
/// Constructor
///
- /// \param [in] process
- ///
- /// \param [in] tid
- ///
/// \param [in] use_invalid_index_id
/// Optional parameter, defaults to false. The only subclass that
/// is likely to set use_invalid_index_id == true is the HistoryThread
@@ -760,6 +756,8 @@ public:
/// \b true if we will stop other threads while we single step this one.
///
/// \param[in] stop_vote
+ /// See standard meanings for the stop & run votes in ThreadPlan.h.
+ ///
/// \param[in] run_vote
/// See standard meanings for the stop & run votes in ThreadPlan.h.
///
@@ -807,11 +805,13 @@ public:
/// \b true if we will stop other threads while we single step this one.
///
/// \param[in] stop_vote
+ /// See standard meanings for the stop & run votes in ThreadPlan.h.
///
/// \param[in] run_vote
/// See standard meanings for the stop & run votes in ThreadPlan.h.
///
/// \param[in] frame_idx
+ /// The fame index.
///
/// \param[out] status
/// A status with an error if queuing failed.
@@ -899,7 +899,7 @@ public:
virtual lldb::ThreadPlanSP
QueueThreadPlanForStepScripted(bool abort_other_plans, const char *class_name,
- StructuredData::ObjectSP extra_args_sp,
+ StructuredData::ObjectSP extra_args_sp,
bool stop_other_threads, Status &status);
// Thread Plan accessors:
@@ -1004,7 +1004,7 @@ public:
/// including the plan in that matches \a thread_index counting only
/// the non-Private plans.
///
- /// \param[in] up_to_plan_sp
+ /// \param[in] thread_index
/// Discard all plans up to and including this user plan given by this
/// index.
///
@@ -1102,9 +1102,9 @@ public:
// right even if you have not calculated this yourself, or if it disagrees
// with what you might have calculated.
virtual lldb::StopInfoSP GetPrivateStopInfo();
-
+
// Calculate the stop info that will be shown to lldb clients. For instance,
- // a "step out" is implemented by running to a breakpoint on the function
+ // a "step out" is implemented by running to a breakpoint on the function
// return PC, so the process plugin initially sets the stop info to a
// StopInfoBreakpoint. But once we've run the ShouldStop machinery, we
// discover that there's a completed ThreadPlanStepOut, and that's really
diff --git a/lldb/include/lldb/Target/ThreadPlanStepOut.h b/lldb/include/lldb/Target/ThreadPlanStepOut.h
index 00984db2dca9..576b416c3f2c 100644
--- a/lldb/include/lldb/Target/ThreadPlanStepOut.h
+++ b/lldb/include/lldb/Target/ThreadPlanStepOut.h
@@ -72,6 +72,7 @@ private:
std::vector<lldb::StackFrameSP> m_stepped_past_frames;
lldb::ValueObjectSP m_return_valobj_sp;
bool m_calculate_return_value;
+ StreamString m_constructor_errors;
friend lldb::ThreadPlanSP Thread::QueueThreadPlanForStepOut(
bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
diff --git a/lldb/include/lldb/Target/ThreadPlanStepRange.h b/lldb/include/lldb/Target/ThreadPlanStepRange.h
index 93d54ad7dfd5..28209623a1e1 100644
--- a/lldb/include/lldb/Target/ThreadPlanStepRange.h
+++ b/lldb/include/lldb/Target/ThreadPlanStepRange.h
@@ -76,6 +76,12 @@ protected:
lldb::BreakpointSP m_next_branch_bp_sp;
bool m_use_fast_step;
bool m_given_ranges_only;
+ bool m_found_calls = false; // When we set the next branch breakpoint for
+ // step over, we now extend them past call insns
+ // that directly return. But if we do that we
+ // need to run all threads, or we might cause
+ // deadlocks. This tells us whether we found
+ // any calls in setting the next branch breakpoint.
private:
std::vector<lldb::DisassemblerSP> m_instruction_ranges;
diff --git a/lldb/include/lldb/Utility/ArchSpec.h b/lldb/include/lldb/Utility/ArchSpec.h
index 3bfc988abf0b..15e2fdb10c32 100644
--- a/lldb/include/lldb/Utility/ArchSpec.h
+++ b/lldb/include/lldb/Utility/ArchSpec.h
@@ -101,6 +101,7 @@ public:
eCore_arm_armv6,
eCore_arm_armv6m,
eCore_arm_armv7,
+ eCore_arm_armv7l,
eCore_arm_armv7f,
eCore_arm_armv7s,
eCore_arm_armv7k,
@@ -122,6 +123,7 @@ public:
eCore_thumbv7em,
eCore_arm_arm64,
eCore_arm_armv8,
+ eCore_arm_armv8l,
eCore_arm_arm64_32,
eCore_arm_aarch64,
@@ -258,13 +260,6 @@ public:
/// Destructor.
~ArchSpec();
- /// Assignment operator.
- ///
- /// \param[in] rhs another ArchSpec object to copy.
- ///
- /// \return A const reference to this object.
- const ArchSpec &operator=(const ArchSpec &rhs);
-
/// Returns true if the OS, vendor and environment fields of the triple are
/// unset. The triple is expected to be normalized
/// (llvm::Triple::normalize).
@@ -438,7 +433,7 @@ public:
/// \return A triple describing this ArchSpec.
const llvm::Triple &GetTriple() const { return m_triple; }
- void DumpTriple(Stream &s) const;
+ void DumpTriple(llvm::raw_ostream &s) const;
/// Architecture triple setter.
///
diff --git a/lldb/include/lldb/Utility/Args.h b/lldb/include/lldb/Utility/Args.h
index 7987787e7af5..1308f4038dbd 100644
--- a/lldb/include/lldb/Utility/Args.h
+++ b/lldb/include/lldb/Utility/Args.h
@@ -252,35 +252,6 @@ public:
// For re-setting or blanking out the list of arguments.
void Clear();
- static bool UInt64ValueIsValidForByteSize(uint64_t uval64,
- size_t total_byte_size) {
- if (total_byte_size > 8)
- return false;
-
- if (total_byte_size == 8)
- return true;
-
- const uint64_t max = (static_cast<uint64_t>(1)
- << static_cast<uint64_t>(total_byte_size * 8)) -
- 1;
- return uval64 <= max;
- }
-
- static bool SInt64ValueIsValidForByteSize(int64_t sval64,
- size_t total_byte_size) {
- if (total_byte_size > 8)
- return false;
-
- if (total_byte_size == 8)
- return true;
-
- const int64_t max = (static_cast<int64_t>(1)
- << static_cast<uint64_t>(total_byte_size * 8 - 1)) -
- 1;
- const int64_t min = ~(max);
- return min <= sval64 && sval64 <= max;
- }
-
static lldb::Encoding
StringToEncoding(llvm::StringRef s,
lldb::Encoding fail_value = lldb::eEncodingInvalid);
diff --git a/lldb/include/lldb/Utility/Baton.h b/lldb/include/lldb/Utility/Baton.h
index 4050f2af2bf0..c42867489c65 100644
--- a/lldb/include/lldb/Utility/Baton.h
+++ b/lldb/include/lldb/Utility/Baton.h
@@ -12,6 +12,8 @@
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-public.h"
+#include "llvm/Support/raw_ostream.h"
+
#include <memory>
namespace lldb_private {
@@ -37,8 +39,9 @@ public:
virtual void *data() = 0;
- virtual void GetDescription(Stream *s,
- lldb::DescriptionLevel level) const = 0;
+ virtual void GetDescription(llvm::raw_ostream &s,
+ lldb::DescriptionLevel level,
+ unsigned indentation) const = 0;
};
class UntypedBaton : public Baton {
@@ -50,7 +53,8 @@ public:
}
void *data() override { return m_data; }
- void GetDescription(Stream *s, lldb::DescriptionLevel level) const override;
+ void GetDescription(llvm::raw_ostream &s, lldb::DescriptionLevel level,
+ unsigned indentation) const override;
void *m_data; // Leave baton public for easy access
};
@@ -63,7 +67,8 @@ public:
const T *getItem() const { return Item.get(); }
void *data() override { return Item.get(); }
- void GetDescription(Stream *s, lldb::DescriptionLevel level) const override {}
+ void GetDescription(llvm::raw_ostream &s, lldb::DescriptionLevel level,
+ unsigned indentation) const override {}
protected:
std::unique_ptr<T> Item;
diff --git a/lldb/include/lldb/Utility/Broadcaster.h b/lldb/include/lldb/Utility/Broadcaster.h
index fe4d1ca479b8..ead597d626d7 100644
--- a/lldb/include/lldb/Utility/Broadcaster.h
+++ b/lldb/include/lldb/Utility/Broadcaster.h
@@ -65,7 +65,6 @@ public:
}
bool operator<(const BroadcastEventSpec &rhs) const;
- BroadcastEventSpec &operator=(const BroadcastEventSpec &rhs);
private:
ConstString m_broadcaster_class;
diff --git a/lldb/include/lldb/Utility/Connection.h b/lldb/include/lldb/Utility/Connection.h
index 77f3ef4a76ba..9e66dee1363b 100644
--- a/lldb/include/lldb/Utility/Connection.h
+++ b/lldb/include/lldb/Utility/Connection.h
@@ -171,7 +171,7 @@ public:
///
/// \return
/// The underlying IOObject used for reading.
- virtual lldb::IOObjectSP GetReadObject() { return lldb::IOObjectSP(); }
+ virtual lldb::IOObjectSP GetReadObject() { return lldb::IOObjectSP(); };
private:
// For Connection only
diff --git a/lldb/include/lldb/Utility/ConstString.h b/lldb/include/lldb/Utility/ConstString.h
index 9a9ee458239f..74750459d16f 100644
--- a/lldb/include/lldb/Utility/ConstString.h
+++ b/lldb/include/lldb/Utility/ConstString.h
@@ -147,8 +147,8 @@ public:
/// Another string object to compare this object to.
///
/// \return
- /// \li \b true if this object is equal to \a rhs.
- /// \li \b false if this object is not equal to \a rhs.
+ /// true if this object is equal to \a rhs.
+ /// false if this object is not equal to \a rhs.
bool operator==(ConstString rhs) const {
// We can do a pointer compare to compare these strings since they must
// come from the same pool in order to be equal.
@@ -166,8 +166,8 @@ public:
/// Another string object to compare this object to.
///
/// \return
- /// \li \b true if this object is equal to \a rhs.
- /// \li \b false if this object is not equal to \a rhs.
+ /// \b true if this object is equal to \a rhs.
+ /// \b false if this object is not equal to \a rhs.
bool operator==(const char *rhs) const {
// ConstString differentiates between empty strings and nullptr strings, but
// StringRef doesn't. Therefore we have to do this check manually now.
@@ -189,8 +189,8 @@ public:
/// Another string object to compare this object to.
///
/// \return
- /// \li \b true if this object is not equal to \a rhs.
- /// \li \b false if this object is equal to \a rhs.
+ /// \b true if this object is not equal to \a rhs.
+ /// \b false if this object is equal to \a rhs.
bool operator!=(ConstString rhs) const {
return m_string != rhs.m_string;
}
@@ -328,15 +328,15 @@ public:
/// Test for empty string.
///
/// \return
- /// \li \b true if the contained string is empty.
- /// \li \b false if the contained string is not empty.
+ /// \b true if the contained string is empty.
+ /// \b false if the contained string is not empty.
bool IsEmpty() const { return m_string == nullptr || m_string[0] == '\0'; }
/// Test for null string.
///
/// \return
- /// \li \b true if there is no string associated with this instance.
- /// \li \b false if there is a string associated with this instance.
+ /// \b true if there is no string associated with this instance.
+ /// \b false if there is a string associated with this instance.
bool IsNull() const { return m_string == nullptr; }
/// Set the C string value.
diff --git a/lldb/include/lldb/Utility/DataEncoder.h b/lldb/include/lldb/Utility/DataEncoder.h
index 7d44afd2ce69..f4964b250b9d 100644
--- a/lldb/include/lldb/Utility/DataEncoder.h
+++ b/lldb/include/lldb/Utility/DataEncoder.h
@@ -21,8 +21,9 @@
namespace lldb_private {
-/// \class DataEncoder DataEncoder.h "lldb/Core/DataEncoder.h" An binary data
-/// encoding class.
+/// \class DataEncoder
+///
+/// An binary data encoding class.
///
/// DataEncoder is a class that can encode binary data (swapping if needed) to
/// a data buffer. The data buffer can be caller owned, or can be shared data
@@ -86,74 +87,6 @@ public:
/// any references to shared data that this object may contain.
void Clear();
- /// Get the current address size.
- ///
- /// Return the size in bytes of any address values this object will extract.
- ///
- /// \return
- /// The size in bytes of address values that will be extracted.
- uint8_t GetAddressByteSize() const { return m_addr_size; }
-
- /// Get the number of bytes contained in this object.
- ///
- /// \return
- /// The total number of bytes of data this object refers to.
- size_t GetByteSize() const { return m_end - m_start; }
-
- /// Get the data end pointer.
- ///
- /// \return
- /// Returns a pointer to the next byte contained in this
- /// object's data, or NULL of there is no data in this object.
- uint8_t *GetDataEnd() { return m_end; }
-
- const uint8_t *GetDataEnd() const { return m_end; }
-
- /// Get the shared data offset.
- ///
- /// Get the offset of the first byte of data in the shared data (if any).
- ///
- /// \return
- /// If this object contains shared data, this function returns
- /// the offset in bytes into that shared data, zero otherwise.
- size_t GetSharedDataOffset() const;
-
- /// Get the current byte order value.
- ///
- /// \return
- /// The current byte order value from this object's internal
- /// state.
- lldb::ByteOrder GetByteOrder() const { return m_byte_order; }
-
- /// Get the data start pointer.
- ///
- /// \return
- /// Returns a pointer to the first byte contained in this
- /// object's data, or NULL of there is no data in this object.
- uint8_t *GetDataStart() { return m_start; }
-
- const uint8_t *GetDataStart() const { return m_start; }
-
- /// Encode unsigned integer values into the data at \a offset.
- ///
- /// \param[in] offset
- /// The offset within the contained data at which to put the
- /// data.
- ///
- /// \param[in] value
- /// The value to encode into the data.
- ///
- /// \return
- /// The next offset in the bytes of this data if the data
- /// was successfully encoded, UINT32_MAX if the encoding failed.
- uint32_t PutU8(uint32_t offset, uint8_t value);
-
- uint32_t PutU16(uint32_t offset, uint16_t value);
-
- uint32_t PutU32(uint32_t offset, uint32_t value);
-
- uint32_t PutU64(uint32_t offset, uint64_t value);
-
/// Encode an unsigned integer of size \a byte_size to \a offset.
///
/// Encode a single integer value at \a offset and return the offset that
@@ -176,7 +109,7 @@ public:
/// \return
/// The next offset in the bytes of this data if the integer
/// was successfully encoded, UINT32_MAX if the encoding failed.
- uint32_t PutMaxU64(uint32_t offset, uint32_t byte_size, uint64_t value);
+ uint32_t PutUnsigned(uint32_t offset, uint32_t byte_size, uint64_t value);
/// Encode an arbitrary number of bytes.
///
@@ -232,36 +165,27 @@ public:
/// NULL will be returned.
uint32_t PutCString(uint32_t offset, const char *cstr);
- lldb::DataBufferSP &GetSharedDataBuffer() { return m_data_sp; }
+private:
+ uint32_t PutU8(uint32_t offset, uint8_t value);
+ uint32_t PutU16(uint32_t offset, uint16_t value);
+ uint32_t PutU32(uint32_t offset, uint32_t value);
+ uint32_t PutU64(uint32_t offset, uint64_t value);
- /// Set the address byte size.
- ///
- /// Set the size in bytes that will be used when extracting any address and
- /// pointer values from data contained in this object.
- ///
- /// \param[in] addr_size
- /// The size in bytes to use when extracting addresses.
- void SetAddressByteSize(uint8_t addr_size) { m_addr_size = addr_size; }
+ uint32_t BytesLeft(uint32_t offset) const {
+ const uint32_t size = GetByteSize();
+ if (size > offset)
+ return size - offset;
+ return 0;
+ }
- /// Set data with a buffer that is caller owned.
- ///
- /// Use data that is owned by the caller when extracting values. The data
- /// must stay around as long as this object, or any object that copies a
- /// subset of this object's data, is valid. If \a bytes is NULL, or \a
- /// length is zero, this object will contain no data.
- ///
- /// \param[in] bytes
- /// A pointer to caller owned data.
- ///
- /// \param[in] length
- /// The length in bytes of \a bytes.
- ///
- /// \param[in] byte_order
- /// A byte order of the data that we are extracting from.
+ /// Test the availability of \a length bytes of data from \a offset.
///
/// \return
- /// The number of bytes that this object now contains.
- uint32_t SetData(void *bytes, uint32_t length, lldb::ByteOrder byte_order);
+ /// \b true if \a offset is a valid offset and there are \a
+ /// length bytes available at that offset, \b false otherwise.
+ bool ValidOffsetForDataOfSize(uint32_t offset, uint32_t length) const {
+ return length <= BytesLeft(offset);
+ }
/// Adopt a subset of shared data in \a data_sp.
///
@@ -288,15 +212,6 @@ public:
uint32_t SetData(const lldb::DataBufferSP &data_sp, uint32_t offset = 0,
uint32_t length = UINT32_MAX);
- /// Set the byte_order value.
- ///
- /// Sets the byte order of the data to extract. Extracted values will be
- /// swapped if necessary when decoding.
- ///
- /// \param[in] byte_order
- /// The byte order value to use when extracting data.
- void SetByteOrder(lldb::ByteOrder byte_order) { m_byte_order = byte_order; }
-
/// Test the validity of \a offset.
///
/// \return
@@ -304,34 +219,30 @@ public:
/// object, \b false otherwise.
bool ValidOffset(uint32_t offset) const { return offset < GetByteSize(); }
- /// Test the availability of \a length bytes of data from \a offset.
+ /// Get the number of bytes contained in this object.
///
/// \return
- /// \b true if \a offset is a valid offset and there are \a
- /// length bytes available at that offset, \b false otherwise.
- bool ValidOffsetForDataOfSize(uint32_t offset, uint32_t length) const {
- return length <= BytesLeft(offset);
- }
+ /// The total number of bytes of data this object refers to.
+ size_t GetByteSize() const { return m_end - m_start; }
- uint32_t BytesLeft(uint32_t offset) const {
- const uint32_t size = GetByteSize();
- if (size > offset)
- return size - offset;
- return 0;
- }
+private:
+ /// A pointer to the first byte of data.
+ uint8_t *m_start;
-protected:
- // Member variables
- uint8_t *m_start; ///< A pointer to the first byte of data.
- uint8_t *m_end; ///< A pointer to the byte that is past the end of the data.
- lldb::ByteOrder
- m_byte_order; ///< The byte order of the data we are extracting from.
- uint8_t m_addr_size; ///< The address size to use when extracting pointers or
- /// addresses
- mutable lldb::DataBufferSP m_data_sp; ///< The shared pointer to data that can
- /// be shared among multiple instances
+ /// A pointer to the byte that is past the end of the data.
+ uint8_t *m_end;
+
+ /// The byte order of the data we are extracting from.
+ lldb::ByteOrder m_byte_order;
+
+ /// The address size to use when extracting pointers or
+ /// addresses
+ uint8_t m_addr_size;
+
+ /// The shared pointer to data that can
+ /// be shared among multiple instances
+ mutable lldb::DataBufferSP m_data_sp;
-private:
DISALLOW_COPY_AND_ASSIGN(DataEncoder);
};
diff --git a/lldb/include/lldb/Utility/DataExtractor.h b/lldb/include/lldb/Utility/DataExtractor.h
index 333baf9fd349..bf0d1055cf43 100644
--- a/lldb/include/lldb/Utility/DataExtractor.h
+++ b/lldb/include/lldb/Utility/DataExtractor.h
@@ -188,16 +188,11 @@ public:
/// The type of objects to use when dumping data from this
/// object. See DataExtractor::Type.
///
- /// \param[in] type_format
- /// The optional format to use for the \a type objects. If this
- /// is nullptr, the default format for the \a type will be used.
- ///
/// \return
/// The offset at which dumping ended.
lldb::offset_t PutToLog(Log *log, lldb::offset_t offset,
lldb::offset_t length, uint64_t base_addr,
- uint32_t num_per_line, Type type,
- const char *type_format = nullptr) const;
+ uint32_t num_per_line, Type type) const;
/// Extract an arbitrary number of bytes in the specified byte order.
///
diff --git a/lldb/include/lldb/Utility/FileSpec.h b/lldb/include/lldb/Utility/FileSpec.h
index 50ad1f1600d8..533426671cc6 100644
--- a/lldb/include/lldb/Utility/FileSpec.h
+++ b/lldb/include/lldb/Utility/FileSpec.h
@@ -75,33 +75,10 @@ public:
explicit FileSpec(llvm::StringRef path, const llvm::Triple &triple);
- /// Copy constructor
- ///
- /// Makes a copy of the uniqued directory and filename strings from \a rhs
- /// if it is not nullptr.
- ///
- /// \param[in] rhs
- /// A const FileSpec object pointer to copy if non-nullptr.
- FileSpec(const FileSpec *rhs);
-
- /// Destructor.
- ~FileSpec();
-
bool DirectoryEquals(const FileSpec &other) const;
bool FileEquals(const FileSpec &other) const;
- /// Assignment operator.
- ///
- /// Makes a copy of the uniqued directory and filename strings from \a rhs.
- ///
- /// \param[in] rhs
- /// A const FileSpec object reference to assign to this object.
- ///
- /// \return
- /// A const reference to this object.
- const FileSpec &operator=(const FileSpec &rhs);
-
/// Equal to operator
///
/// Tests if this object is equal to \a rhs.
@@ -206,6 +183,12 @@ public:
static bool Equal(const FileSpec &a, const FileSpec &b, bool full);
+ /// Match FileSpec \a pattern against FileSpec \a file. If \a pattern has a
+ /// directory component, then the \a file must have the same directory
+ /// component. Otherwise, just it matches just the filename. An empty \a
+ /// pattern matches everything.
+ static bool Match(const FileSpec &pattern, const FileSpec &file);
+
/// Attempt to guess path style for a given path string. It returns a style,
/// if it was able to make a reasonable guess, or None if it wasn't. The guess
/// will be correct if the input path was a valid absolute path on the system
@@ -228,7 +211,7 @@ public:
///
/// \param[in] s
/// The stream to which to dump the object description.
- void Dump(Stream *s) const;
+ void Dump(llvm::raw_ostream &s) const;
Style GetPathStyle() const;
diff --git a/lldb/include/lldb/Utility/Flags.h b/lldb/include/lldb/Utility/Flags.h
index aa869eca0c6e..254a5ec443c3 100644
--- a/lldb/include/lldb/Utility/Flags.h
+++ b/lldb/include/lldb/Utility/Flags.h
@@ -33,17 +33,6 @@ public:
/// The initial value for all flags.
Flags(ValueType flags = 0) : m_flags(flags) {}
- /// Copy constructor.
- ///
- /// Construct and copy the flags from \a rhs.
- ///
- /// \param[in] rhs
- /// A const Flags object reference to copy.
- Flags(const Flags &rhs) : m_flags(rhs.m_flags) {}
-
- /// Destructor.
- ~Flags() {}
-
/// Get accessor for all flags.
///
/// \return
diff --git a/lldb/include/lldb/Utility/GDBRemote.h b/lldb/include/lldb/Utility/GDBRemote.h
index b4adeb368524..21b2c8cd73cd 100644
--- a/lldb/include/lldb/Utility/GDBRemote.h
+++ b/lldb/include/lldb/Utility/GDBRemote.h
@@ -9,6 +9,8 @@
#ifndef liblldb_GDBRemote_h_
#define liblldb_GDBRemote_h_
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/Reproducer.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-public.h"
@@ -69,7 +71,6 @@ struct GDBRemotePacket {
std::string data;
};
- void Serialize(llvm::raw_ostream &strm) const;
void Dump(Stream &strm) const;
BinaryData packet;
@@ -82,6 +83,46 @@ private:
llvm::StringRef GetTypeStr() const;
};
+namespace repro {
+class PacketRecorder : public AbstractRecorder {
+public:
+ PacketRecorder(const FileSpec &filename, std::error_code &ec)
+ : AbstractRecorder(filename, ec) {}
+
+ static llvm::Expected<std::unique_ptr<PacketRecorder>>
+ Create(const FileSpec &filename);
+
+ void Record(const GDBRemotePacket &packet);
+};
+
+class GDBRemoteProvider : public repro::Provider<GDBRemoteProvider> {
+public:
+ struct Info {
+ static const char *name;
+ static const char *file;
+ };
+
+ GDBRemoteProvider(const FileSpec &directory) : Provider(directory) {}
+
+ llvm::raw_ostream *GetHistoryStream();
+ PacketRecorder *GetNewPacketRecorder();
+
+ void SetCallback(std::function<void()> callback) {
+ m_callback = std::move(callback);
+ }
+
+ void Keep() override;
+ void Discard() override;
+
+ static char ID;
+
+private:
+ std::function<void()> m_callback;
+ std::unique_ptr<llvm::raw_fd_ostream> m_stream_up;
+ std::vector<std::unique_ptr<PacketRecorder>> m_packet_recorders;
+};
+
+} // namespace repro
} // namespace lldb_private
LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(lldb_private::GDBRemotePacket)
diff --git a/lldb/include/lldb/Utility/Log.h b/lldb/include/lldb/Utility/Log.h
index 09c0f6954478..01edec044565 100644
--- a/lldb/include/lldb/Utility/Log.h
+++ b/lldb/include/lldb/Utility/Log.h
@@ -166,10 +166,10 @@ public:
bool GetVerbose() const;
-private:
void VAPrintf(const char *format, va_list args);
void VAError(const char *format, va_list args);
+private:
Channel &m_channel;
// The mutex makes sure enable/disable operations are thread-safe. The
diff --git a/lldb/include/lldb/Utility/RangeMap.h b/lldb/include/lldb/Utility/RangeMap.h
index 709b5d2f66c7..9e0307351836 100644
--- a/lldb/include/lldb/Utility/RangeMap.h
+++ b/lldb/include/lldb/Utility/RangeMap.h
@@ -599,36 +599,17 @@ struct RangeData : public Range<B, S> {
RangeData(B base, S size) : Range<B, S>(base, size), data() {}
RangeData(B base, S size, DataType d) : Range<B, S>(base, size), data(d) {}
-
- bool operator<(const RangeData &rhs) const {
- if (this->base == rhs.base) {
- if (this->size == rhs.size)
- return this->data < rhs.data;
- else
- return this->size < rhs.size;
- }
- return this->base < rhs.base;
- }
-
- bool operator==(const RangeData &rhs) const {
- return this->GetRangeBase() == rhs.GetRangeBase() &&
- this->GetByteSize() == rhs.GetByteSize() && this->data == rhs.data;
- }
-
- bool operator!=(const RangeData &rhs) const {
- return this->GetRangeBase() != rhs.GetRangeBase() ||
- this->GetByteSize() != rhs.GetByteSize() || this->data != rhs.data;
- }
};
-template <typename B, typename S, typename T, unsigned N = 0>
+template <typename B, typename S, typename T, unsigned N = 0,
+ class Compare = std::less<T>>
class RangeDataVector {
public:
typedef lldb_private::Range<B, S> Range;
typedef RangeData<B, S, T> Entry;
typedef llvm::SmallVector<Entry, N> Collection;
- RangeDataVector() = default;
+ RangeDataVector(Compare compare = Compare()) : m_compare(compare) {}
~RangeDataVector() = default;
@@ -636,7 +617,14 @@ public:
void Sort() {
if (m_entries.size() > 1)
- std::stable_sort(m_entries.begin(), m_entries.end());
+ std::stable_sort(m_entries.begin(), m_entries.end(),
+ [&compare = m_compare](const Entry &a, const Entry &b) {
+ if (a.base != b.base)
+ return a.base < b.base;
+ if (a.size != b.size)
+ return a.size < b.size;
+ return compare(a.data, b.data);
+ });
}
#ifdef ASSERT_RANGEMAP_ARE_SORTED
@@ -817,6 +805,7 @@ public:
protected:
Collection m_entries;
+ Compare m_compare;
};
// A simple range with data class where you get to define the type of
diff --git a/lldb/include/lldb/Utility/Reproducer.h b/lldb/include/lldb/Utility/Reproducer.h
index 3db98a781d4c..0d23fe8571ff 100644
--- a/lldb/include/lldb/Utility/Reproducer.h
+++ b/lldb/include/lldb/Utility/Reproducer.h
@@ -153,24 +153,13 @@ public:
static char ID;
};
-class DataRecorder {
-public:
- DataRecorder(const FileSpec &filename, std::error_code &ec)
+class AbstractRecorder {
+protected:
+ AbstractRecorder(const FileSpec &filename, std::error_code &ec)
: m_filename(filename.GetFilename().GetStringRef()),
m_os(filename.GetPath(), ec, llvm::sys::fs::OF_Text), m_record(true) {}
- static llvm::Expected<std::unique_ptr<DataRecorder>>
- Create(const FileSpec &filename);
-
- template <typename T> void Record(const T &t, bool newline = false) {
- if (!m_record)
- return;
- m_os << t;
- if (newline)
- m_os << '\n';
- m_os.flush();
- }
-
+public:
const FileSpec &GetFilename() { return m_filename; }
void Stop() {
@@ -180,10 +169,30 @@ public:
private:
FileSpec m_filename;
+
+protected:
llvm::raw_fd_ostream m_os;
bool m_record;
};
+class DataRecorder : public AbstractRecorder {
+public:
+ DataRecorder(const FileSpec &filename, std::error_code &ec)
+ : AbstractRecorder(filename, ec) {}
+
+ static llvm::Expected<std::unique_ptr<DataRecorder>>
+ Create(const FileSpec &filename);
+
+ template <typename T> void Record(const T &t, bool newline = false) {
+ if (!m_record)
+ return;
+ m_os << t;
+ if (newline)
+ m_os << '\n';
+ m_os.flush();
+ }
+};
+
class CommandProvider : public Provider<CommandProvider> {
public:
struct Info {
@@ -204,32 +213,6 @@ private:
std::vector<std::unique_ptr<DataRecorder>> m_data_recorders;
};
-class ProcessGDBRemoteProvider
- : public repro::Provider<ProcessGDBRemoteProvider> {
-public:
- struct Info {
- static const char *name;
- static const char *file;
- };
-
- ProcessGDBRemoteProvider(const FileSpec &directory) : Provider(directory) {}
-
- llvm::raw_ostream *GetHistoryStream();
-
- void SetCallback(std::function<void()> callback) {
- m_callback = std::move(callback);
- }
-
- void Keep() override { m_callback(); }
- void Discard() override { m_callback(); }
-
- static char ID;
-
-private:
- std::function<void()> m_callback;
- std::unique_ptr<llvm::raw_fd_ostream> m_stream_up;
-};
-
/// The generator is responsible for the logic needed to generate a
/// reproducer. For doing so it relies on providers, who serialize data that
/// is necessary for reproducing a failure.
@@ -288,7 +271,7 @@ private:
FileSpec m_root;
/// Flag to ensure that we never call both keep and discard.
- bool m_done;
+ bool m_done = false;
};
class Loader final {
@@ -359,13 +342,43 @@ private:
mutable std::mutex m_mutex;
};
-/// Helper class for replaying commands through the reproducer.
-class CommandLoader {
+template <typename T> class MultiLoader {
public:
- CommandLoader(std::vector<std::string> files) : m_files(files) {}
+ MultiLoader(std::vector<std::string> files) : m_files(files) {}
+
+ static std::unique_ptr<MultiLoader> Create(Loader *loader) {
+ if (!loader)
+ return {};
+
+ FileSpec file = loader->GetFile<typename T::Info>();
+ if (!file)
+ return {};
+
+ auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath());
+ if (auto err = error_or_file.getError())
+ return {};
- static std::unique_ptr<CommandLoader> Create(Loader *loader);
- llvm::Optional<std::string> GetNextFile();
+ std::vector<std::string> files;
+ llvm::yaml::Input yin((*error_or_file)->getBuffer());
+ yin >> files;
+
+ if (auto err = yin.error())
+ return {};
+
+ for (auto &file : files) {
+ FileSpec absolute_path =
+ loader->GetRoot().CopyByAppendingPathComponent(file);
+ file = absolute_path.GetPath();
+ }
+
+ return std::make_unique<MultiLoader<T>>(std::move(files));
+ }
+
+ llvm::Optional<std::string> GetNextFile() {
+ if (m_index >= m_files.size())
+ return {};
+ return m_files[m_index++];
+ }
private:
std::vector<std::string> m_files;
diff --git a/lldb/include/lldb/Utility/Scalar.h b/lldb/include/lldb/Utility/Scalar.h
index 72f153ff97cd..69c948ec6222 100644
--- a/lldb/include/lldb/Utility/Scalar.h
+++ b/lldb/include/lldb/Utility/Scalar.h
@@ -172,7 +172,6 @@ public:
Scalar &operator=(double v);
Scalar &operator=(long double v);
Scalar &operator=(llvm::APInt v);
- Scalar &operator=(const Scalar &rhs); // Assignment operator
Scalar &operator+=(const Scalar &rhs);
Scalar &operator<<=(const Scalar &rhs); // Shift left
Scalar &operator>>=(const Scalar &rhs); // Shift right (arithmetic)
diff --git a/lldb/include/lldb/Utility/Status.h b/lldb/include/lldb/Utility/Status.h
index e6a0a8e7fce1..36f52922c9bc 100644
--- a/lldb/include/lldb/Utility/Status.h
+++ b/lldb/include/lldb/Utility/Status.h
@@ -64,8 +64,6 @@ public:
explicit Status(const char *format, ...)
__attribute__((format(printf, 2, 3)));
- const Status &operator=(const Status &rhs);
-
~Status();
// llvm::Error support
diff --git a/lldb/include/lldb/Utility/Stream.h b/lldb/include/lldb/Utility/Stream.h
index 414f92177303..18a16a3461c1 100644
--- a/lldb/include/lldb/Utility/Stream.h
+++ b/lldb/include/lldb/Utility/Stream.h
@@ -213,126 +213,14 @@ public:
/// in one statement.
Stream &operator<<(char ch);
- /// Output a uint8_t \a uval to the stream \a s.
- ///
- /// \param[in] uval
- /// A uint8_t value.
- ///
- /// \return
- /// A reference to this class so multiple things can be streamed
- /// in one statement.
- Stream &operator<<(uint8_t uval);
-
- /// Output a uint16_t \a uval to the stream \a s.
- ///
- /// \param[in] uval
- /// A uint16_t value.
- ///
- /// \return
- /// A reference to this class so multiple things can be streamed
- /// in one statement.
- Stream &operator<<(uint16_t uval);
-
- /// Output a uint32_t \a uval to the stream \a s.
- ///
- /// \param[in] uval
- /// A uint32_t value.
- ///
- /// \return
- /// A reference to this class so multiple things can be streamed
- /// in one statement.
- Stream &operator<<(uint32_t uval);
-
- /// Output a uint64_t \a uval to the stream \a s.
- ///
- /// \param[in] uval
- /// A uint64_t value.
- ///
- /// \return
- /// A reference to this class so multiple things can be streamed
- /// in one statement.
- Stream &operator<<(uint64_t uval);
-
- /// Output a int8_t \a sval to the stream \a s.
- ///
- /// \param[in] sval
- /// A int8_t value.
- ///
- /// \return
- /// A reference to this class so multiple things can be streamed
- /// in one statement.
- Stream &operator<<(int8_t sval);
-
- /// Output a int16_t \a sval to the stream \a s.
- ///
- /// \param[in] sval
- /// A int16_t value.
- ///
- /// \return
- /// A reference to this class so multiple things can be streamed
- /// in one statement.
- Stream &operator<<(int16_t sval);
-
- /// Output a int32_t \a sval to the stream \a s.
- ///
- /// \param[in] sval
- /// A int32_t value.
- ///
- /// \return
- /// A reference to this class so multiple things can be streamed
- /// in one statement.
- Stream &operator<<(int32_t sval);
-
- /// Output a int64_t \a sval to the stream \a s.
- ///
- /// \param[in] sval
- /// A int64_t value.
- ///
- /// \return
- /// A reference to this class so multiple things can be streamed
- /// in one statement.
- Stream &operator<<(int64_t sval);
-
- /// Output an address value to this stream.
- ///
- /// Put an address \a addr out to the stream with optional \a prefix and \a
- /// suffix strings.
- ///
- /// \param[in] addr
- /// An address value.
- ///
- /// \param[in] addr_size
- /// Size in bytes of the address, used for formatting.
- ///
- /// \param[in] prefix
- /// A prefix C string. If nullptr, no prefix will be output.
- ///
- /// \param[in] suffix
- /// A suffix C string. If nullptr, no suffix will be output.
- void Address(uint64_t addr, uint32_t addr_size, const char *prefix = nullptr,
- const char *suffix = nullptr);
-
- /// Output an address range to this stream.
- ///
- /// Put an address range \a lo_addr - \a hi_addr out to the stream with
- /// optional \a prefix and \a suffix strings.
- ///
- /// \param[in] lo_addr
- /// The start address of the address range.
- ///
- /// \param[in] hi_addr
- /// The end address of the address range.
- ///
- /// \param[in] addr_size
- /// Size in bytes of the address, used for formatting.
- ///
- /// \param[in] prefix
- /// A prefix C string. If nullptr, no prefix will be output.
- ///
- /// \param[in] suffix
- /// A suffix C string. If nullptr, no suffix will be output.
- void AddressRange(uint64_t lo_addr, uint64_t hi_addr, uint32_t addr_size,
- const char *prefix = nullptr, const char *suffix = nullptr);
+ Stream &operator<<(uint8_t uval) = delete;
+ Stream &operator<<(uint16_t uval) = delete;
+ Stream &operator<<(uint32_t uval) = delete;
+ Stream &operator<<(uint64_t uval) = delete;
+ Stream &operator<<(int8_t sval) = delete;
+ Stream &operator<<(int16_t sval) = delete;
+ Stream &operator<<(int32_t sval) = delete;
+ Stream &operator<<(int64_t sval) = delete;
/// Output a C string to the stream.
///
@@ -373,8 +261,8 @@ public:
/// Get the current indentation level.
///
/// \return
- /// The current indentation level as an integer.
- int GetIndentLevel() const;
+ /// The current indentation level.
+ unsigned GetIndentLevel() const;
/// Indent the current line in the stream.
///
@@ -388,10 +276,10 @@ public:
size_t Indent(llvm::StringRef s);
/// Decrement the current indentation level.
- void IndentLess(int amount = 2);
+ void IndentLess(unsigned amount = 2);
/// Increment the current indentation level.
- void IndentMore(int amount = 2);
+ void IndentMore(unsigned amount = 2);
/// Output an offset value.
///
@@ -446,7 +334,7 @@ public:
///
/// \param[in] level
/// The new indentation level.
- void SetIndentLevel(int level);
+ void SetIndentLevel(unsigned level);
/// Output a SLEB128 number to the stream.
///
@@ -477,7 +365,7 @@ protected:
uint32_t m_addr_size; ///< Size of an address in bytes.
lldb::ByteOrder
m_byte_order; ///< Byte order to use when encoding scalar types.
- int m_indent_level; ///< Indention level.
+ unsigned m_indent_level; ///< Indention level.
std::size_t m_bytes_written = 0; ///< Number of bytes written so far.
void _PutHex8(uint8_t uvalue, bool add_prefix);
@@ -523,6 +411,54 @@ protected:
RawOstreamForward m_forwarder;
};
+/// Output an address value to this stream.
+///
+/// Put an address \a addr out to the stream with optional \a prefix and \a
+/// suffix strings.
+///
+/// \param[in] s
+/// The output stream.
+///
+/// \param[in] addr
+/// An address value.
+///
+/// \param[in] addr_size
+/// Size in bytes of the address, used for formatting.
+///
+/// \param[in] prefix
+/// A prefix C string. If nullptr, no prefix will be output.
+///
+/// \param[in] suffix
+/// A suffix C string. If nullptr, no suffix will be output.
+void DumpAddress(llvm::raw_ostream &s, uint64_t addr, uint32_t addr_size,
+ const char *prefix = nullptr, const char *suffix = nullptr);
+
+/// Output an address range to this stream.
+///
+/// Put an address range \a lo_addr - \a hi_addr out to the stream with
+/// optional \a prefix and \a suffix strings.
+///
+/// \param[in] s
+/// The output stream.
+///
+/// \param[in] lo_addr
+/// The start address of the address range.
+///
+/// \param[in] hi_addr
+/// The end address of the address range.
+///
+/// \param[in] addr_size
+/// Size in bytes of the address, used for formatting.
+///
+/// \param[in] prefix
+/// A prefix C string. If nullptr, no prefix will be output.
+///
+/// \param[in] suffix
+/// A suffix C string. If nullptr, no suffix will be output.
+void DumpAddressRange(llvm::raw_ostream &s, uint64_t lo_addr, uint64_t hi_addr,
+ uint32_t addr_size, const char *prefix = nullptr,
+ const char *suffix = nullptr);
+
} // namespace lldb_private
#endif // liblldb_Stream_h_
diff --git a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h
index cbf6e0c29e8e..715f3cb2541d 100644
--- a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h
+++ b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h
@@ -31,11 +31,6 @@ public:
StringExtractorGDBRemote(const char *cstr)
: StringExtractor(cstr), m_validator(nullptr) {}
- StringExtractorGDBRemote(const StringExtractorGDBRemote &rhs)
- : StringExtractor(rhs), m_validator(rhs.m_validator) {}
-
- ~StringExtractorGDBRemote() override {}
-
bool ValidateResponse() const;
void CopyResponseValidator(const StringExtractorGDBRemote &rhs);
diff --git a/lldb/include/lldb/Utility/VMRange.h b/lldb/include/lldb/Utility/VMRange.h
index 9c2f9d090919..72f859b67582 100644
--- a/lldb/include/lldb/Utility/VMRange.h
+++ b/lldb/include/lldb/Utility/VMRange.h
@@ -10,16 +10,13 @@
#define liblldb_VMRange_h_
#include "lldb/lldb-types.h"
+#include "llvm/Support/raw_ostream.h"
#include <stddef.h>
#include <stdint.h>
#include <vector>
namespace lldb_private {
-class Stream;
-}
-
-namespace lldb_private {
// A vm address range. These can represent offsets ranges or actual
// addresses.
@@ -81,7 +78,7 @@ public:
return false;
}
- void Dump(Stream *s, lldb::addr_t base_addr = 0,
+ void Dump(llvm::raw_ostream &s, lldb::addr_t base_addr = 0,
uint32_t addr_width = 8) const;
static bool ContainsValue(const VMRange::collection &coll,
diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index 3c80bcffec20..8cbb459ee1ea 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -211,10 +211,11 @@ enum DescriptionLevel {
/// Script interpreter types.
enum ScriptLanguage {
- eScriptLanguageNone,
+ eScriptLanguageNone = 0,
eScriptLanguagePython,
- eScriptLanguageDefault = eScriptLanguagePython,
- eScriptLanguageUnknown
+ eScriptLanguageLua,
+ eScriptLanguageUnknown,
+ eScriptLanguageDefault = eScriptLanguagePython
};
/// Register numbering types.
@@ -690,6 +691,9 @@ enum SectionType {
eSectionTypeDWARFDebugStrDwo,
eSectionTypeDWARFDebugStrOffsetsDwo,
eSectionTypeDWARFDebugTypesDwo,
+ eSectionTypeDWARFDebugRngListsDwo,
+ eSectionTypeDWARFDebugLocDwo,
+ eSectionTypeDWARFDebugLocListsDwo,
};
FLAGS_ENUM(EmulateInstructionOptions){
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index 8315fbb27346..d2371f94f4b8 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -260,7 +260,6 @@ class TypeEnumMemberImpl;
class TypeEnumMemberListImpl;
class TypeFormatImpl;
class TypeNameSpecifierImpl;
-class TypeValidatorImpl;
class UUID;
class UnixSignals;
class Unwind;
@@ -461,7 +460,6 @@ typedef std::shared_ptr<lldb_private::TypeNameSpecifierImpl>
TypeNameSpecifierImplSP;
typedef std::shared_ptr<lldb_private::TypeSummaryImpl> TypeSummaryImplSP;
typedef std::shared_ptr<lldb_private::TypeSummaryOptions> TypeSummaryOptionsSP;
-typedef std::shared_ptr<lldb_private::TypeValidatorImpl> TypeValidatorImplSP;
typedef std::shared_ptr<lldb_private::ScriptedSyntheticChildren>
ScriptedSyntheticChildrenSP;
typedef std::shared_ptr<lldb_private::UnixSignals> UnixSignalsSP;
diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h
index 04b78bcc19f8..27a2c4c3f27f 100644
--- a/lldb/include/lldb/lldb-private-interfaces.h
+++ b/lldb/include/lldb/lldb-private-interfaces.h
@@ -82,8 +82,6 @@ typedef bool (*BreakpointHitCallback)(void *baton,
typedef bool (*WatchpointHitCallback)(void *baton,
StoppointCallbackContext *context,
lldb::user_id_t watch_id);
-typedef void (*OptionValueChangedCallback)(void *baton,
- OptionValue *option_value);
typedef bool (*ThreadPlanShouldStopHereCallback)(
ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation,
Status &status, void *baton);
diff --git a/lldb/source/API/SBBreakpoint.cpp b/lldb/source/API/SBBreakpoint.cpp
index 45eaea6b6181..8159b851d58c 100644
--- a/lldb/source/API/SBBreakpoint.cpp
+++ b/lldb/source/API/SBBreakpoint.cpp
@@ -14,6 +14,7 @@
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStringList.h"
+#include "lldb/API/SBStructuredData.h"
#include "lldb/API/SBThread.h"
#include "lldb/Breakpoint/Breakpoint.h"
@@ -25,6 +26,7 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Target/Process.h"
@@ -590,22 +592,38 @@ void SBBreakpoint ::SetCallback(SBBreakpointHitCallback callback, void *baton) {
}
void SBBreakpoint::SetScriptCallbackFunction(
- const char *callback_function_name) {
- LLDB_RECORD_METHOD(void, SBBreakpoint, SetScriptCallbackFunction,
- (const char *), callback_function_name);
-
+ const char *callback_function_name) {
+LLDB_RECORD_METHOD(void, SBBreakpoint, SetScriptCallbackFunction,
+ (const char *), callback_function_name);
+ SBStructuredData empty_args;
+ SetScriptCallbackFunction(callback_function_name, empty_args);
+}
+
+SBError SBBreakpoint::SetScriptCallbackFunction(
+ const char *callback_function_name,
+ SBStructuredData &extra_args) {
+ LLDB_RECORD_METHOD(SBError, SBBreakpoint, SetScriptCallbackFunction,
+ (const char *, SBStructuredData &), callback_function_name, extra_args);
+ SBError sb_error;
BreakpointSP bkpt_sp = GetSP();
if (bkpt_sp) {
+ Status error;
std::lock_guard<std::recursive_mutex> guard(
bkpt_sp->GetTarget().GetAPIMutex());
BreakpointOptions *bp_options = bkpt_sp->GetOptions();
- bkpt_sp->GetTarget()
+ error = bkpt_sp->GetTarget()
.GetDebugger()
.GetScriptInterpreter()
->SetBreakpointCommandCallbackFunction(bp_options,
- callback_function_name);
- }
+ callback_function_name,
+ extra_args.m_impl_up
+ ->GetObjectSP());
+ sb_error.SetError(error);
+ } else
+ sb_error.SetErrorString("invalid breakpoint");
+
+ return LLDB_RECORD_RESULT(sb_error);
}
SBError SBBreakpoint::SetScriptCallbackBody(const char *callback_body_text) {
@@ -992,6 +1010,8 @@ void RegisterMethods<SBBreakpoint>(Registry &R) {
(lldb::SBAddress &));
LLDB_REGISTER_METHOD(void, SBBreakpoint, SetScriptCallbackFunction,
(const char *));
+ LLDB_REGISTER_METHOD(lldb::SBError, SBBreakpoint, SetScriptCallbackFunction,
+ (const char *, SBStructuredData &));
LLDB_REGISTER_METHOD(lldb::SBError, SBBreakpoint, SetScriptCallbackBody,
(const char *));
LLDB_REGISTER_METHOD(bool, SBBreakpoint, AddName, (const char *));
diff --git a/lldb/source/API/SBBreakpointLocation.cpp b/lldb/source/API/SBBreakpointLocation.cpp
index 640545f55ef9..2b62a69a21ef 100644
--- a/lldb/source/API/SBBreakpointLocation.cpp
+++ b/lldb/source/API/SBBreakpointLocation.cpp
@@ -12,12 +12,14 @@
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBStream.h"
+#include "lldb/API/SBStructuredData.h"
#include "lldb/API/SBStringList.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Target/Target.h"
@@ -207,23 +209,38 @@ bool SBBreakpointLocation::GetAutoContinue() {
}
void SBBreakpointLocation::SetScriptCallbackFunction(
- const char *callback_function_name) {
- LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetScriptCallbackFunction,
- (const char *), callback_function_name);
+ const char *callback_function_name) {
+LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetScriptCallbackFunction,
+ (const char *), callback_function_name);
+}
+SBError SBBreakpointLocation::SetScriptCallbackFunction(
+ const char *callback_function_name,
+ SBStructuredData &extra_args) {
+ LLDB_RECORD_METHOD(SBError, SBBreakpointLocation, SetScriptCallbackFunction,
+ (const char *, SBStructuredData &),
+ callback_function_name, extra_args);
+ SBError sb_error;
BreakpointLocationSP loc_sp = GetSP();
if (loc_sp) {
+ Status error;
std::lock_guard<std::recursive_mutex> guard(
loc_sp->GetTarget().GetAPIMutex());
BreakpointOptions *bp_options = loc_sp->GetLocationOptions();
- loc_sp->GetBreakpoint()
+ error = loc_sp->GetBreakpoint()
.GetTarget()
.GetDebugger()
.GetScriptInterpreter()
->SetBreakpointCommandCallbackFunction(bp_options,
- callback_function_name);
- }
+ callback_function_name,
+ extra_args.m_impl_up
+ ->GetObjectSP());
+ sb_error.SetError(error);
+ } else
+ sb_error.SetErrorString("invalid breakpoint");
+
+ return LLDB_RECORD_RESULT(sb_error);
}
SBError
@@ -482,6 +499,8 @@ void RegisterMethods<SBBreakpointLocation>(Registry &R) {
LLDB_REGISTER_METHOD(bool, SBBreakpointLocation, GetAutoContinue, ());
LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetScriptCallbackFunction,
(const char *));
+ LLDB_REGISTER_METHOD(SBError, SBBreakpointLocation, SetScriptCallbackFunction,
+ (const char *, SBStructuredData &));
LLDB_REGISTER_METHOD(lldb::SBError, SBBreakpointLocation,
SetScriptCallbackBody, (const char *));
LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetCommandLineCommands,
diff --git a/lldb/source/API/SBBreakpointName.cpp b/lldb/source/API/SBBreakpointName.cpp
index 1c794fca8ca5..5bd7732ebb60 100644
--- a/lldb/source/API/SBBreakpointName.cpp
+++ b/lldb/source/API/SBBreakpointName.cpp
@@ -12,11 +12,13 @@
#include "lldb/API/SBError.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStringList.h"
+#include "lldb/API/SBStructuredData.h"
#include "lldb/API/SBTarget.h"
#include "lldb/Breakpoint/BreakpointName.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
+#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Target/Target.h"
@@ -565,24 +567,41 @@ void SBBreakpointName::SetCallback(SBBreakpointHitCallback callback,
}
void SBBreakpointName::SetScriptCallbackFunction(
- const char *callback_function_name) {
- LLDB_RECORD_METHOD(void, SBBreakpointName, SetScriptCallbackFunction,
- (const char *), callback_function_name);
-
+ const char *callback_function_name) {
+LLDB_RECORD_METHOD(void, SBBreakpointName, SetScriptCallbackFunction,
+ (const char *), callback_function_name);
+ SBStructuredData empty_args;
+ SetScriptCallbackFunction(callback_function_name, empty_args);
+}
+
+SBError SBBreakpointName::SetScriptCallbackFunction(
+ const char *callback_function_name,
+ SBStructuredData &extra_args) {
+ LLDB_RECORD_METHOD(SBError, SBBreakpointName, SetScriptCallbackFunction,
+ (const char *, SBStructuredData &),
+ callback_function_name, extra_args);
+ SBError sb_error;
BreakpointName *bp_name = GetBreakpointName();
- if (!bp_name)
- return;
+ if (!bp_name) {
+ sb_error.SetErrorString("unrecognized breakpoint name");
+ return LLDB_RECORD_RESULT(sb_error);
+ }
std::lock_guard<std::recursive_mutex> guard(
m_impl_up->GetTarget()->GetAPIMutex());
BreakpointOptions &bp_options = bp_name->GetOptions();
- m_impl_up->GetTarget()
+ Status error;
+ error = m_impl_up->GetTarget()
->GetDebugger()
.GetScriptInterpreter()
->SetBreakpointCommandCallbackFunction(&bp_options,
- callback_function_name);
+ callback_function_name,
+ extra_args.m_impl_up
+ ->GetObjectSP());
+ sb_error.SetError(error);
UpdateName(*bp_name);
+ return LLDB_RECORD_RESULT(sb_error);
}
SBError
@@ -728,6 +747,8 @@ void RegisterMethods<SBBreakpointName>(Registry &R) {
(lldb::SBStream &));
LLDB_REGISTER_METHOD(void, SBBreakpointName, SetScriptCallbackFunction,
(const char *));
+ LLDB_REGISTER_METHOD(SBError, SBBreakpointName, SetScriptCallbackFunction,
+ (const char *, SBStructuredData &));
LLDB_REGISTER_METHOD(lldb::SBError, SBBreakpointName, SetScriptCallbackBody,
(const char *));
LLDB_REGISTER_METHOD_CONST(bool, SBBreakpointName, GetAllowList, ());
diff --git a/lldb/source/API/SBCompileUnit.cpp b/lldb/source/API/SBCompileUnit.cpp
index 581bda363507..d52040d850a9 100644
--- a/lldb/source/API/SBCompileUnit.cpp
+++ b/lldb/source/API/SBCompileUnit.cpp
@@ -50,7 +50,7 @@ SBFileSpec SBCompileUnit::GetFileSpec() const {
SBFileSpec file_spec;
if (m_opaque_ptr)
- file_spec.SetFileSpec(*m_opaque_ptr);
+ file_spec.SetFileSpec(m_opaque_ptr->GetPrimaryFile());
return LLDB_RECORD_RESULT(file_spec);
}
@@ -106,7 +106,7 @@ uint32_t SBCompileUnit::FindLineEntryIndex(uint32_t start_idx, uint32_t line,
if (inline_file_spec && inline_file_spec->IsValid())
file_spec = inline_file_spec->ref();
else
- file_spec = *m_opaque_ptr;
+ file_spec = m_opaque_ptr->GetPrimaryFile();
index = m_opaque_ptr->FindLineEntry(
start_idx, line, inline_file_spec ? inline_file_spec->get() : nullptr,
diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp
index 82dc60489008..b7ac8047f8e5 100644
--- a/lldb/source/API/SBDebugger.cpp
+++ b/lldb/source/API/SBDebugger.cpp
@@ -40,6 +40,7 @@
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/DataFormatters/DataVisualization.h"
+#include "lldb/Host/Config.h"
#include "lldb/Host/XML.h"
#include "lldb/Initialization/SystemLifetimeManager.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -294,7 +295,7 @@ void SBDebugger::SetInputFileHandle(FILE *fh, bool transfer_ownership) {
SBError SBDebugger::SetInputFile(FileSP file_sp) {
LLDB_RECORD_METHOD(SBError, SBDebugger, SetInputFile, (FileSP), file_sp);
- return SetInputFile(SBFile(file_sp));
+ return LLDB_RECORD_RESULT(SetInputFile(SBFile(file_sp)));
}
// Shouldn't really be settable after initialization as this could cause lots
@@ -306,7 +307,7 @@ SBError SBDebugger::SetInputFile(SBFile file) {
SBError error;
if (!m_opaque_sp) {
error.ref().SetErrorString("invalid debugger");
- return error;
+ return LLDB_RECORD_RESULT(error);
}
repro::DataRecorder *recorder = nullptr;
@@ -315,8 +316,9 @@ SBError SBDebugger::SetInputFile(SBFile file) {
FileSP file_sp = file.m_opaque_sp;
- static std::unique_ptr<repro::CommandLoader> loader =
- repro::CommandLoader::Create(repro::Reproducer::Instance().GetLoader());
+ static std::unique_ptr<repro::MultiLoader<repro::CommandProvider>> loader =
+ repro::MultiLoader<repro::CommandProvider>::Create(
+ repro::Reproducer::Instance().GetLoader());
if (loader) {
llvm::Optional<std::string> nextfile = loader->GetNextFile();
FILE *fh = nextfile ? FileSystem::Instance().Fopen(nextfile->c_str(), "r")
@@ -330,16 +332,16 @@ SBError SBDebugger::SetInputFile(SBFile file) {
if (!file_sp || !file_sp->IsValid()) {
error.ref().SetErrorString("invalid file");
- return error;
+ return LLDB_RECORD_RESULT(error);
}
m_opaque_sp->SetInputFile(file_sp, recorder);
- return error;
+ return LLDB_RECORD_RESULT(error);
}
SBError SBDebugger::SetOutputFile(FileSP file_sp) {
LLDB_RECORD_METHOD(SBError, SBDebugger, SetOutputFile, (FileSP), file_sp);
- return SetOutputFile(SBFile(file_sp));
+ return LLDB_RECORD_RESULT(SetOutputFile(SBFile(file_sp)));
}
void SBDebugger::SetOutputFileHandle(FILE *fh, bool transfer_ownership) {
@@ -353,14 +355,14 @@ SBError SBDebugger::SetOutputFile(SBFile file) {
SBError error;
if (!m_opaque_sp) {
error.ref().SetErrorString("invalid debugger");
- return error;
+ return LLDB_RECORD_RESULT(error);
}
if (!file) {
error.ref().SetErrorString("invalid file");
- return error;
+ return LLDB_RECORD_RESULT(error);
}
m_opaque_sp->SetOutputFile(file.m_opaque_sp);
- return error;
+ return LLDB_RECORD_RESULT(error);
}
void SBDebugger::SetErrorFileHandle(FILE *fh, bool transfer_ownership) {
@@ -371,7 +373,7 @@ void SBDebugger::SetErrorFileHandle(FILE *fh, bool transfer_ownership) {
SBError SBDebugger::SetErrorFile(FileSP file_sp) {
LLDB_RECORD_METHOD(SBError, SBDebugger, SetErrorFile, (FileSP), file_sp);
- return SetErrorFile(SBFile(file_sp));
+ return LLDB_RECORD_RESULT(SetErrorFile(SBFile(file_sp)));
}
SBError SBDebugger::SetErrorFile(SBFile file) {
@@ -379,14 +381,14 @@ SBError SBDebugger::SetErrorFile(SBFile file) {
SBError error;
if (!m_opaque_sp) {
error.ref().SetErrorString("invalid debugger");
- return error;
+ return LLDB_RECORD_RESULT(error);
}
if (!file) {
error.ref().SetErrorString("invalid file");
- return error;
+ return LLDB_RECORD_RESULT(error);
}
m_opaque_sp->SetErrorFile(file.m_opaque_sp);
- return error;
+ return LLDB_RECORD_RESULT(error);
}
FILE *SBDebugger::GetInputFileHandle() {
@@ -395,7 +397,7 @@ FILE *SBDebugger::GetInputFileHandle() {
File &file_sp = m_opaque_sp->GetInputFile();
return LLDB_RECORD_RESULT(file_sp.GetStream());
}
- return nullptr;
+ return LLDB_RECORD_RESULT(nullptr);
}
SBFile SBDebugger::GetInputFile() {
@@ -412,7 +414,7 @@ FILE *SBDebugger::GetOutputFileHandle() {
StreamFile &stream_file = m_opaque_sp->GetOutputStream();
return LLDB_RECORD_RESULT(stream_file.GetFile().GetStream());
}
- return nullptr;
+ return LLDB_RECORD_RESULT(nullptr);
}
SBFile SBDebugger::GetOutputFile() {
@@ -431,7 +433,7 @@ FILE *SBDebugger::GetErrorFileHandle() {
StreamFile &stream_file = m_opaque_sp->GetErrorStream();
return LLDB_RECORD_RESULT(stream_file.GetFile().GetStream());
}
- return nullptr;
+ return LLDB_RECORD_RESULT(nullptr);
}
SBFile SBDebugger::GetErrorFile() {
@@ -681,13 +683,21 @@ SBStructuredData SBDebugger::GetBuildConfiguration() {
AddBoolConfigEntry(
*config_up, "xml", XMLDocument::XMLEnabled(),
"A boolean value that indicates if XML support is enabled in LLDB");
- bool have_curses = true;
-#ifdef LLDB_DISABLE_CURSES
- have_curses = false;
-#endif
AddBoolConfigEntry(
- *config_up, "curses", have_curses,
+ *config_up, "curses", LLDB_ENABLE_CURSES,
"A boolean value that indicates if curses support is enabled in LLDB");
+ AddBoolConfigEntry(
+ *config_up, "editline", LLDB_ENABLE_LIBEDIT,
+ "A boolean value that indicates if editline support is enabled in LLDB");
+ AddBoolConfigEntry(
+ *config_up, "lzma", LLDB_ENABLE_LZMA,
+ "A boolean value that indicates if lzma support is enabled in LLDB");
+ AddBoolConfigEntry(
+ *config_up, "python", LLDB_ENABLE_PYTHON,
+ "A boolean value that indicates if python support is enabled in LLDB");
+ AddBoolConfigEntry(
+ *config_up, "lua", LLDB_ENABLE_LUA,
+ "A boolean value that indicates if lua support is enabled in LLDB");
AddLLVMTargets(*config_up);
SBStructuredData data;
diff --git a/lldb/source/API/SBEvent.cpp b/lldb/source/API/SBEvent.cpp
index 75ca2830df9f..fb2ad10ddcf9 100644
--- a/lldb/source/API/SBEvent.cpp
+++ b/lldb/source/API/SBEvent.cpp
@@ -175,7 +175,7 @@ const char *SBEvent::GetCStringFromEvent(const SBEvent &event) {
LLDB_RECORD_STATIC_METHOD(const char *, SBEvent, GetCStringFromEvent,
(const lldb::SBEvent &), event);
- return reinterpret_cast<const char *>(
+ return static_cast<const char *>(
EventDataBytes::GetBytesFromEvent(event.get()));
}
diff --git a/lldb/source/API/SBFile.cpp b/lldb/source/API/SBFile.cpp
index f5a38efe4a77..277402f31abf 100644
--- a/lldb/source/API/SBFile.cpp
+++ b/lldb/source/API/SBFile.cpp
@@ -100,24 +100,27 @@ SBError SBFile::Close() {
SBFile::operator bool() const {
LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFile, operator bool);
- return LLDB_RECORD_RESULT(IsValid());
+ return IsValid();
}
bool SBFile::operator!() const {
LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFile, operator!);
- return LLDB_RECORD_RESULT(!IsValid());
+ return !IsValid();
}
FileSP SBFile::GetFile() const {
LLDB_RECORD_METHOD_CONST_NO_ARGS(FileSP, SBFile, GetFile);
- return m_opaque_sp;
+ return LLDB_RECORD_RESULT(m_opaque_sp);
}
namespace lldb_private {
namespace repro {
template <> void RegisterMethods<SBFile>(Registry &R) {
-
+ LLDB_REGISTER_CONSTRUCTOR(SBFile, ());
+ LLDB_REGISTER_CONSTRUCTOR(SBFile, (FileSP));
+ LLDB_REGISTER_CONSTRUCTOR(SBFile, (FILE *, bool));
+ LLDB_REGISTER_CONSTRUCTOR(SBFile, (int, const char *, bool));
LLDB_REGISTER_METHOD(lldb::SBError, SBFile, Flush, ());
LLDB_REGISTER_METHOD_CONST(bool, SBFile, IsValid, ());
LLDB_REGISTER_METHOD_CONST(bool, SBFile, operator bool,());
diff --git a/lldb/source/API/SBFileSpec.cpp b/lldb/source/API/SBFileSpec.cpp
index 2f910b9ba294..2e7eba42bc90 100644
--- a/lldb/source/API/SBFileSpec.cpp
+++ b/lldb/source/API/SBFileSpec.cpp
@@ -143,7 +143,7 @@ void SBFileSpec::SetDirectory(const char *directory) {
}
uint32_t SBFileSpec::GetPath(char *dst_path, size_t dst_len) const {
- LLDB_RECORD_METHOD_CONST(uint32_t, SBFileSpec, GetPath, (char *, size_t),
+ LLDB_RECORD_DUMMY(uint32_t, SBFileSpec, GetPath, (char *, size_t),
dst_path, dst_len);
uint32_t result = m_opaque_up->GetPath(dst_path, dst_len);
diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp
index c0e272e1bcd4..af42be9ac75e 100644
--- a/lldb/source/API/SBFrame.cpp
+++ b/lldb/source/API/SBFrame.cpp
@@ -831,14 +831,12 @@ SBValueList SBFrame::GetVariables(const lldb::SBVariablesOptions &options) {
if (stop_locker.TryLock(&process->GetRunLock())) {
frame = exe_ctx.GetFramePtr();
if (frame) {
- size_t i;
VariableList *variable_list = nullptr;
variable_list = frame->GetVariableList(true);
if (variable_list) {
const size_t num_variables = variable_list->GetSize();
if (num_variables) {
- for (i = 0; i < num_variables; ++i) {
- VariableSP variable_sp(variable_list->GetVariableAtIndex(i));
+ for (const VariableSP &variable_sp : *variable_list) {
if (variable_sp) {
bool add_variable = false;
switch (variable_sp->GetScope()) {
diff --git a/lldb/source/API/SBHostOS.cpp b/lldb/source/API/SBHostOS.cpp
index c3c92e68140d..6ac8717237e7 100644
--- a/lldb/source/API/SBHostOS.cpp
+++ b/lldb/source/API/SBHostOS.cpp
@@ -6,9 +6,10 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/API/SBHostOS.h"
#include "SBReproducerPrivate.h"
#include "lldb/API/SBError.h"
-#include "lldb/API/SBHostOS.h"
+#include "lldb/Host/Config.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
@@ -18,7 +19,7 @@
#include "lldb/Utility/FileSpec.h"
#include "Plugins/ExpressionParser/Clang/ClangHost.h"
-#ifndef LLDB_DISABLE_PYTHON
+#if LLDB_ENABLE_PYTHON
#include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h"
#endif
@@ -60,7 +61,7 @@ SBFileSpec SBHostOS::GetLLDBPath(lldb::PathType path_type) {
fspec = HostInfo::GetHeaderDir();
break;
case ePathTypePythonDir:
-#ifndef LLDB_DISABLE_PYTHON
+#if LLDB_ENABLE_PYTHON
fspec = ScriptInterpreterPython::GetPythonDir();
#endif
break;
diff --git a/lldb/source/API/SBModule.cpp b/lldb/source/API/SBModule.cpp
index 6cc6d2628ace..4e9dfb0c1e62 100644
--- a/lldb/source/API/SBModule.cpp
+++ b/lldb/source/API/SBModule.cpp
@@ -245,7 +245,7 @@ bool SBModule::GetDescription(SBStream &description) {
ModuleSP module_sp(GetSP());
if (module_sp) {
- module_sp->GetDescription(&strm);
+ module_sp->GetDescription(strm.AsRawOstream());
} else
strm.PutCString("No value");
@@ -419,16 +419,12 @@ SBValueList SBModule::FindGlobalVariables(SBTarget &target, const char *name,
VariableList variable_list;
module_sp->FindGlobalVariables(ConstString(name), nullptr, max_matches,
variable_list);
- const uint32_t match_count = variable_list.GetSize();
- if (match_count > 0) {
- for (uint32_t i = 0; i < match_count; ++i) {
- lldb::ValueObjectSP valobj_sp;
- TargetSP target_sp(target.GetSP());
- valobj_sp = ValueObjectVariable::Create(
- target_sp.get(), variable_list.GetVariableAtIndex(i));
- if (valobj_sp)
- sb_value_list.Append(SBValue(valobj_sp));
- }
+ for (const VariableSP &var_sp : variable_list) {
+ lldb::ValueObjectSP valobj_sp;
+ TargetSP target_sp(target.GetSP());
+ valobj_sp = ValueObjectVariable::Create(target_sp.get(), var_sp);
+ if (valobj_sp)
+ sb_value_list.Append(SBValue(valobj_sp));
}
}
diff --git a/lldb/source/API/SBReproducer.cpp b/lldb/source/API/SBReproducer.cpp
index 6e11b2c6366f..3d2de0727444 100644
--- a/lldb/source/API/SBReproducer.cpp
+++ b/lldb/source/API/SBReproducer.cpp
@@ -22,15 +22,15 @@
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBHostOS.h"
#include "lldb/API/SBReproducer.h"
-
#include "lldb/Host/FileSystem.h"
+#include "lldb/lldb-private.h"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::repro;
SBRegistry::SBRegistry() {
- Registry& R = *this;
+ Registry &R = *this;
RegisterMethods<SBAddress>(R);
RegisterMethods<SBAttachInfo>(R);
@@ -125,6 +125,10 @@ const char *SBReproducer::Capture(const char *path) {
}
const char *SBReproducer::Replay(const char *path) {
+ return SBReproducer::Replay(path, false);
+}
+
+const char *SBReproducer::Replay(const char *path, bool skip_version_check) {
static std::string error;
if (auto e = Reproducer::Initialize(ReproducerMode::Replay, FileSpec(path))) {
error = llvm::toString(std::move(e));
@@ -137,6 +141,22 @@ const char *SBReproducer::Replay(const char *path) {
return error.c_str();
}
+ if (!skip_version_check) {
+ llvm::Expected<std::string> version = loader->LoadBuffer<VersionProvider>();
+ if (!version) {
+ error = llvm::toString(version.takeError());
+ return error.c_str();
+ }
+ if (lldb_private::GetVersion() != llvm::StringRef(*version).rtrim()) {
+ error = "reproducer capture and replay version don't match:\n";
+ error.append("reproducer captured with:\n");
+ error.append(*version);
+ error.append("reproducer replayed with:\n");
+ error.append(lldb_private::GetVersion());
+ return error.c_str();
+ }
+ }
+
FileSpec file = loader->GetFile<SBProvider::Info>();
if (!file) {
error = "unable to get replay data from reproducer.";
@@ -149,6 +169,22 @@ const char *SBReproducer::Replay(const char *path) {
return nullptr;
}
+bool SBReproducer::Generate() {
+ auto &r = Reproducer::Instance();
+ if (auto generator = r.GetGenerator()) {
+ generator->Keep();
+ return true;
+ }
+ return false;
+}
+
+const char *SBReproducer::GetPath() {
+ static std::string path;
+ auto &r = Reproducer::Instance();
+ path = r.GetReproducerPath().GetCString();
+ return path.c_str();
+}
+
char lldb_private::repro::SBProvider::ID = 0;
const char *SBProvider::Info::name = "sbapi";
const char *SBProvider::Info::file = "sbapi.bin";
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index 1d13087eef69..312e4df75863 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -36,7 +36,6 @@
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Core/STLUtils.h"
#include "lldb/Core/SearchFilter.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StructuredDataImpl.h"
@@ -1177,12 +1176,15 @@ bool SBTarget::FindBreakpointsByName(const char *name,
TargetSP target_sp(GetSP());
if (target_sp) {
std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
- BreakpointList bkpt_list(false);
- bool is_valid =
- target_sp->GetBreakpointList().FindBreakpointsByName(name, bkpt_list);
- if (!is_valid)
+ llvm::Expected<std::vector<BreakpointSP>> expected_vector =
+ target_sp->GetBreakpointList().FindBreakpointsByName(name);
+ if (!expected_vector) {
+ LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS),
+ "invalid breakpoint name: {}",
+ llvm::toString(expected_vector.takeError()));
return false;
- for (BreakpointSP bkpt_sp : bkpt_list.Breakpoints()) {
+ }
+ for (BreakpointSP bkpt_sp : *expected_vector) {
bkpts.AppendByID(bkpt_sp->GetID());
}
}
@@ -1598,7 +1600,7 @@ lldb::SBModule SBTarget::AddModule(const SBModuleSpec &module_spec) {
lldb::SBModule sb_module;
TargetSP target_sp(GetSP());
if (target_sp)
- sb_module.SetSP(target_sp->GetOrCreateModule(*module_spec.m_opaque_up,
+ sb_module.SetSP(target_sp->GetOrCreateModule(*module_spec.m_opaque_up,
true /* notify */));
return LLDB_RECORD_RESULT(sb_module);
}
@@ -1930,14 +1932,13 @@ SBValueList SBTarget::FindGlobalVariables(const char *name,
VariableList variable_list;
target_sp->GetImages().FindGlobalVariables(ConstString(name), max_matches,
variable_list);
- const uint32_t match_count = variable_list.GetSize();
- if (match_count > 0) {
+ if (!variable_list.Empty()) {
ExecutionContextScope *exe_scope = target_sp->GetProcessSP().get();
if (exe_scope == nullptr)
exe_scope = target_sp.get();
- for (uint32_t i = 0; i < match_count; ++i) {
- lldb::ValueObjectSP valobj_sp(ValueObjectVariable::Create(
- exe_scope, variable_list.GetVariableAtIndex(i)));
+ for (const VariableSP &var_sp : variable_list) {
+ lldb::ValueObjectSP valobj_sp(
+ ValueObjectVariable::Create(exe_scope, var_sp));
if (valobj_sp)
sb_value_list.Append(SBValue(valobj_sp));
}
@@ -1962,7 +1963,6 @@ SBValueList SBTarget::FindGlobalVariables(const char *name,
VariableList variable_list;
std::string regexstr;
- uint32_t match_count;
switch (matchtype) {
case eMatchTypeNormal:
target_sp->GetImages().FindGlobalVariables(ConstString(name), max_matches,
@@ -1978,14 +1978,13 @@ SBValueList SBTarget::FindGlobalVariables(const char *name,
max_matches, variable_list);
break;
}
- match_count = variable_list.GetSize();
- if (match_count > 0) {
+ if (!variable_list.Empty()) {
ExecutionContextScope *exe_scope = target_sp->GetProcessSP().get();
if (exe_scope == nullptr)
exe_scope = target_sp.get();
- for (uint32_t i = 0; i < match_count; ++i) {
- lldb::ValueObjectSP valobj_sp(ValueObjectVariable::Create(
- exe_scope, variable_list.GetVariableAtIndex(i)));
+ for (const VariableSP &var_sp : variable_list) {
+ lldb::ValueObjectSP valobj_sp(
+ ValueObjectVariable::Create(exe_scope, var_sp));
if (valobj_sp)
sb_value_list.Append(SBValue(valobj_sp));
}
diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp
index 8d4930bf6edb..f7f748f56832 100644
--- a/lldb/source/API/SBThread.cpp
+++ b/lldb/source/API/SBThread.cpp
@@ -914,9 +914,10 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
const bool exact = false;
SymbolContextList sc_list;
- const uint32_t num_matches = frame_sc.comp_unit->ResolveSymbolContext(
- step_file_spec, line, check_inlines, exact, eSymbolContextLineEntry,
- sc_list);
+ frame_sc.comp_unit->ResolveSymbolContext(step_file_spec, line,
+ check_inlines, exact,
+ eSymbolContextLineEntry, sc_list);
+ const uint32_t num_matches = sc_list.GetSize();
if (num_matches > 0) {
SymbolContext sc;
for (uint32_t i = 0; i < num_matches; ++i) {
@@ -1036,7 +1037,7 @@ SBError SBThread::JumpToLine(lldb::SBFileSpec &file_spec, uint32_t line) {
Thread *thread = exe_ctx.GetThreadPtr();
- Status err = thread->JumpToLine(file_spec.get(), line, true);
+ Status err = thread->JumpToLine(file_spec.ref(), line, true);
sb_error.SetError(err);
return LLDB_RECORD_RESULT(sb_error);
}
diff --git a/lldb/source/API/SBType.cpp b/lldb/source/API/SBType.cpp
index 8efc701a79fb..33b67ad4c004 100644
--- a/lldb/source/API/SBType.cpp
+++ b/lldb/source/API/SBType.cpp
@@ -212,8 +212,10 @@ SBType SBType::GetArrayElementType() {
if (!IsValid())
return LLDB_RECORD_RESULT(SBType());
- return LLDB_RECORD_RESULT(SBType(TypeImplSP(
- new TypeImpl(m_opaque_sp->GetCompilerType(true).GetArrayElementType()))));
+ CompilerType canonical_type =
+ m_opaque_sp->GetCompilerType(true).GetCanonicalType();
+ return LLDB_RECORD_RESULT(
+ SBType(TypeImplSP(new TypeImpl(canonical_type.GetArrayElementType()))));
}
SBType SBType::GetArrayType(uint64_t size) {
diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp
index 838300763522..396a9d3ea10c 100644
--- a/lldb/source/API/SBValue.cpp
+++ b/lldb/source/API/SBValue.cpp
@@ -391,25 +391,6 @@ const char *SBValue::GetObjectDescription() {
return cstr;
}
-const char *SBValue::GetTypeValidatorResult() {
- LLDB_RECORD_METHOD_NO_ARGS(const char *, SBValue, GetTypeValidatorResult);
-
- const char *cstr = nullptr;
- ValueLocker locker;
- lldb::ValueObjectSP value_sp(GetSP(locker));
- if (value_sp) {
- const auto &validation(value_sp->GetValidationStatus());
- if (TypeValidatorResult::Failure == validation.first) {
- if (validation.second.empty())
- cstr = "unknown error";
- else
- cstr = validation.second.c_str();
- }
- }
-
- return cstr;
-}
-
SBType SBValue::GetType() {
LLDB_RECORD_METHOD_NO_ARGS(lldb::SBType, SBValue, GetType);
@@ -1585,7 +1566,6 @@ void RegisterMethods<SBValue>(Registry &R) {
LLDB_REGISTER_METHOD(const char *, SBValue, GetValue, ());
LLDB_REGISTER_METHOD(lldb::ValueType, SBValue, GetValueType, ());
LLDB_REGISTER_METHOD(const char *, SBValue, GetObjectDescription, ());
- LLDB_REGISTER_METHOD(const char *, SBValue, GetTypeValidatorResult, ());
LLDB_REGISTER_METHOD(lldb::SBType, SBValue, GetType, ());
LLDB_REGISTER_METHOD(bool, SBValue, GetValueDidChange, ());
LLDB_REGISTER_METHOD(const char *, SBValue, GetSummary, ());
diff --git a/lldb/source/API/SystemInitializerFull.cpp b/lldb/source/API/SystemInitializerFull.cpp
index 0acc496ff879..06f1a6cd3b75 100644
--- a/lldb/source/API/SystemInitializerFull.cpp
+++ b/lldb/source/API/SystemInitializerFull.cpp
@@ -7,13 +7,17 @@
//===----------------------------------------------------------------------===//
#include "SystemInitializerFull.h"
-
#include "lldb/API/SBCommandInterpreter.h"
+#include "lldb/Host/Config.h"
-#if !defined(LLDB_DISABLE_PYTHON)
+#if LLDB_ENABLE_PYTHON
#include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h"
#endif
+#if LLDB_ENABLE_LUA
+#include "Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h"
+#endif
+
#include "lldb/Core/Debugger.h"
#include "lldb/Host/Host.h"
#include "lldb/Initialization/SystemInitializerCommon.h"
@@ -179,14 +183,18 @@ llvm::Error SystemInitializerFull::Initialize() {
ScriptInterpreterNone::Initialize();
-#ifndef LLDB_DISABLE_PYTHON
+#if LLDB_ENABLE_PYTHON
OperatingSystemPython::Initialize();
#endif
-#if !defined(LLDB_DISABLE_PYTHON)
+#if LLDB_ENABLE_PYTHON
ScriptInterpreterPython::Initialize();
#endif
+#if LLDB_ENABLE_LUA
+ ScriptInterpreterLua::Initialize();
+#endif
+
platform_freebsd::PlatformFreeBSD::Initialize();
platform_linux::PlatformLinux::Initialize();
platform_netbsd::PlatformNetBSD::Initialize();
@@ -375,7 +383,7 @@ void SystemInitializerFull::Terminate() {
DynamicLoaderStatic::Terminate();
DynamicLoaderWindowsDYLD::Terminate();
-#ifndef LLDB_DISABLE_PYTHON
+#if LLDB_ENABLE_PYTHON
OperatingSystemPython::Terminate();
#endif
diff --git a/lldb/source/Breakpoint/Breakpoint.cpp b/lldb/source/Breakpoint/Breakpoint.cpp
index a112542803c4..13acf4bb92e2 100644
--- a/lldb/source/Breakpoint/Breakpoint.cpp
+++ b/lldb/source/Breakpoint/Breakpoint.cpp
@@ -638,7 +638,8 @@ static bool SymbolContextsMightBeEquivalent(SymbolContext &old_sc,
} else {
// Otherwise we will compare by name...
if (old_sc.comp_unit && new_sc.comp_unit) {
- if (FileSpec::Equal(*old_sc.comp_unit, *new_sc.comp_unit, true)) {
+ if (old_sc.comp_unit->GetPrimaryFile() ==
+ new_sc.comp_unit->GetPrimaryFile()) {
// Now check the functions:
if (old_sc.function && new_sc.function &&
(old_sc.function->GetName() == new_sc.function->GetName())) {
diff --git a/lldb/source/Breakpoint/BreakpointList.cpp b/lldb/source/Breakpoint/BreakpointList.cpp
index c80fb917b490..5b23c633d14c 100644
--- a/lldb/source/Breakpoint/BreakpointList.cpp
+++ b/lldb/source/Breakpoint/BreakpointList.cpp
@@ -10,6 +10,8 @@
#include "lldb/Target/Target.h"
+#include "llvm/Support/Errc.h"
+
using namespace lldb;
using namespace lldb_private;
@@ -128,22 +130,24 @@ BreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) const {
return {};
}
-bool BreakpointList::FindBreakpointsByName(const char *name,
- BreakpointList &matching_bps) {
- Status error;
+llvm::Expected<std::vector<lldb::BreakpointSP>>
+BreakpointList::FindBreakpointsByName(const char *name) {
if (!name)
- return false;
+ return llvm::createStringError(llvm::errc::invalid_argument,
+ "FindBreakpointsByName requires a name");
+ Status error;
if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(name), error))
- return false;
+ return error.ToError();
+ std::vector<lldb::BreakpointSP> matching_bps;
for (BreakpointSP bkpt_sp : Breakpoints()) {
if (bkpt_sp->MatchesName(name)) {
- matching_bps.Add(bkpt_sp, false);
+ matching_bps.push_back(bkpt_sp);
}
}
- return true;
+ return matching_bps;
}
void BreakpointList::Dump(Stream *s) const {
diff --git a/lldb/source/Breakpoint/BreakpointLocation.cpp b/lldb/source/Breakpoint/BreakpointLocation.cpp
index 46b8f25c5668..7f08b08c6055 100644
--- a/lldb/source/Breakpoint/BreakpointLocation.cpp
+++ b/lldb/source/Breakpoint/BreakpointLocation.cpp
@@ -519,13 +519,13 @@ void BreakpointLocation::GetDescription(Stream *s,
if (sc.module_sp) {
s->EOL();
s->Indent("module = ");
- sc.module_sp->GetFileSpec().Dump(s);
+ sc.module_sp->GetFileSpec().Dump(s->AsRawOstream());
}
if (sc.comp_unit != nullptr) {
s->EOL();
s->Indent("compile unit = ");
- static_cast<FileSpec *>(sc.comp_unit)->GetFilename().Dump(s);
+ sc.comp_unit->GetPrimaryFile().GetFilename().Dump(s);
if (sc.function != nullptr) {
s->EOL();
diff --git a/lldb/source/Breakpoint/BreakpointOptions.cpp b/lldb/source/Breakpoint/BreakpointOptions.cpp
index 0d4c6173c3c5..8fd16f420c04 100644
--- a/lldb/source/Breakpoint/BreakpointOptions.cpp
+++ b/lldb/source/Breakpoint/BreakpointOptions.cpp
@@ -566,7 +566,8 @@ void BreakpointOptions::GetDescription(Stream *s,
if (m_callback_baton_sp.get()) {
if (level != eDescriptionLevelBrief) {
s->EOL();
- m_callback_baton_sp->GetDescription(s, level);
+ m_callback_baton_sp->GetDescription(s->AsRawOstream(), level,
+ s->GetIndentLevel());
}
}
if (!m_condition_text.empty()) {
@@ -578,35 +579,33 @@ void BreakpointOptions::GetDescription(Stream *s,
}
void BreakpointOptions::CommandBaton::GetDescription(
- Stream *s, lldb::DescriptionLevel level) const {
+ llvm::raw_ostream &s, lldb::DescriptionLevel level,
+ unsigned indentation) const {
const CommandData *data = getItem();
if (level == eDescriptionLevelBrief) {
- s->Printf(", commands = %s",
- (data && data->user_source.GetSize() > 0) ? "yes" : "no");
+ s << ", commands = "
+ << ((data && data->user_source.GetSize() > 0) ? "yes" : "no");
return;
}
- s->IndentMore();
- s->Indent("Breakpoint commands");
+ indentation += 2;
+ s.indent(indentation);
+ s << "Breakpoint commands";
if (data->interpreter != eScriptLanguageNone)
- s->Printf(" (%s):\n",
- ScriptInterpreter::LanguageToString(data->interpreter).c_str());
+ s << llvm::formatv(" ({0}):\n",
+ ScriptInterpreter::LanguageToString(data->interpreter));
else
- s->PutCString(":\n");
+ s << ":\n";
- s->IndentMore();
+ indentation += 2;
if (data && data->user_source.GetSize() > 0) {
- const size_t num_strings = data->user_source.GetSize();
- for (size_t i = 0; i < num_strings; ++i) {
- s->Indent(data->user_source.GetStringAtIndex(i));
- s->EOL();
+ for (llvm::StringRef str : data->user_source) {
+ s.indent(indentation);
+ s << str << "\n";
}
- } else {
- s->PutCString("No commands.\n");
- }
- s->IndentLess();
- s->IndentLess();
+ } else
+ s << "No commands.\n";
}
void BreakpointOptions::SetCommandDataCallback(
diff --git a/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp b/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp
index 3cb04263c6dc..6b600a7cf128 100644
--- a/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp
+++ b/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp
@@ -102,7 +102,7 @@ Searcher::CallbackReturn BreakpointResolverFileRegex::SearchCallback(
return eCallbackReturnContinue;
CompileUnit *cu = context.comp_unit;
- FileSpec cu_file_spec = *(static_cast<FileSpec *>(cu));
+ FileSpec cu_file_spec = cu->GetPrimaryFile();
std::vector<uint32_t> line_matches;
context.target_sp->GetSourceManager().FindLinesMatchingRegex(
cu_file_spec, m_regex, 1, UINT32_MAX, line_matches);
diff --git a/lldb/source/Breakpoint/WatchpointOptions.cpp b/lldb/source/Breakpoint/WatchpointOptions.cpp
index cd5ef930e5dc..026bf2f746ae 100644
--- a/lldb/source/Breakpoint/WatchpointOptions.cpp
+++ b/lldb/source/Breakpoint/WatchpointOptions.cpp
@@ -121,7 +121,8 @@ void WatchpointOptions::GetCallbackDescription(
Stream *s, lldb::DescriptionLevel level) const {
if (m_callback_baton_sp.get()) {
s->EOL();
- m_callback_baton_sp->GetDescription(s, level);
+ m_callback_baton_sp->GetDescription(s->AsRawOstream(), level,
+ s->GetIndentLevel());
}
}
@@ -156,27 +157,26 @@ void WatchpointOptions::GetDescription(Stream *s,
}
void WatchpointOptions::CommandBaton::GetDescription(
- Stream *s, lldb::DescriptionLevel level) const {
+ llvm::raw_ostream &s, lldb::DescriptionLevel level,
+ unsigned indentation) const {
const CommandData *data = getItem();
if (level == eDescriptionLevelBrief) {
- s->Printf(", commands = %s",
- (data && data->user_source.GetSize() > 0) ? "yes" : "no");
+ s << ", commands = %s"
+ << ((data && data->user_source.GetSize() > 0) ? "yes" : "no");
return;
}
- s->IndentMore();
- s->Indent("watchpoint commands:\n");
+ indentation += 2;
+ s.indent(indentation);
+ s << "watchpoint commands:\n";
- s->IndentMore();
+ indentation += 2;
if (data && data->user_source.GetSize() > 0) {
for (const std::string &line : data->user_source) {
- s->Indent(line);
- s->EOL();
+ s.indent(indentation);
+ s << line << "\n";
}
- } else {
- s->PutCString("No commands.\n");
- }
- s->IndentLess();
- s->IndentLess();
+ } else
+ s << "No commands.\n";
}
diff --git a/lldb/source/Commands/CommandCompletions.cpp b/lldb/source/Commands/CommandCompletions.cpp
index 469a6bbbadf6..d9bee66b442a 100644
--- a/lldb/source/Commands/CommandCompletions.cpp
+++ b/lldb/source/Commands/CommandCompletions.cpp
@@ -6,11 +6,6 @@
//
//===----------------------------------------------------------------------===//
-#include <sys/stat.h>
-#if defined(__APPLE__) || defined(__linux__)
-#include <pwd.h>
-#endif
-
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSet.h"
@@ -23,13 +18,10 @@
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Variable.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Utility/Args.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/TildeExpressionResolver.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -378,8 +370,10 @@ CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter,
}
}
} else {
- const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
- const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
+ const char *cur_file_name =
+ context.comp_unit->GetPrimaryFile().GetFilename().GetCString();
+ const char *cur_dir_name =
+ context.comp_unit->GetPrimaryFile().GetDirectory().GetCString();
bool match = false;
if (m_file_name && cur_file_name &&
@@ -391,7 +385,7 @@ CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter,
match = false;
if (match) {
- m_matching_files.AppendIfUnique(context.comp_unit);
+ m_matching_files.AppendIfUnique(context.comp_unit->GetPrimaryFile());
}
}
}
@@ -411,10 +405,7 @@ void CommandCompletions::SourceFileCompleter::DoCompletion(
// SymbolCompleter
static bool regex_chars(const char comp) {
- return (comp == '[' || comp == ']' || comp == '(' || comp == ')' ||
- comp == '{' || comp == '}' || comp == '+' || comp == '.' ||
- comp == '*' || comp == '|' || comp == '^' || comp == '$' ||
- comp == '\\' || comp == '?');
+ return llvm::StringRef("[](){}+.*|^$\\?").contains(comp);
}
CommandCompletions::SymbolCompleter::SymbolCompleter(
diff --git a/lldb/source/Commands/CommandObjectApropos.cpp b/lldb/source/Commands/CommandObjectApropos.cpp
index 7ba0b250fbd5..15a20737273d 100644
--- a/lldb/source/Commands/CommandObjectApropos.cpp
+++ b/lldb/source/Commands/CommandObjectApropos.cpp
@@ -10,7 +10,6 @@
#include "CommandObjectApropos.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/Property.h"
#include "lldb/Utility/Args.h"
diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp
index ad699975b507..7c4c50ecf3f9 100644
--- a/lldb/source/Commands/CommandObjectBreakpoint.cpp
+++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp
@@ -12,7 +12,6 @@
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Host/OptionParser.h"
-#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
@@ -24,7 +23,6 @@
#include "lldb/Target/Language.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
-#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/StreamString.h"
@@ -48,13 +46,10 @@ static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
#define LLDB_OPTIONS_breakpoint_modify
#include "CommandOptions.inc"
-class lldb_private::BreakpointOptionGroup : public OptionGroup
-{
+class lldb_private::BreakpointOptionGroup : public OptionGroup {
public:
- BreakpointOptionGroup() :
- OptionGroup(),
- m_bp_opts(false) {}
-
+ BreakpointOptionGroup() : OptionGroup(), m_bp_opts(false) {}
+
~BreakpointOptionGroup() override = default;
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@@ -62,9 +57,10 @@ public:
}
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
- ExecutionContext *execution_context) override {
+ ExecutionContext *execution_context) override {
Status error;
- const int short_option = g_breakpoint_modify_options[option_idx].short_option;
+ const int short_option =
+ g_breakpoint_modify_options[option_idx].short_option;
switch (short_option) {
case 'c':
@@ -91,18 +87,15 @@ public:
error.SetErrorStringWithFormat(
"invalid boolean value '%s' passed for -G option",
option_arg.str().c_str());
- }
- break;
- case 'i':
- {
+ } break;
+ case 'i': {
uint32_t ignore_count;
if (option_arg.getAsInteger(0, ignore_count))
error.SetErrorStringWithFormat("invalid ignore count '%s'",
option_arg.str().c_str());
else
m_bp_opts.SetIgnoreCount(ignore_count);
- }
- break;
+ } break;
case 'o': {
bool value, success;
value = OptionArgParser::ToBoolean(option_arg, false, &success);
@@ -113,8 +106,7 @@ public:
"invalid boolean value '%s' passed for -o option",
option_arg.str().c_str());
} break;
- case 't':
- {
+ case 't': {
lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
if (option_arg[0] != '\0') {
if (option_arg.getAsInteger(0, thread_id))
@@ -122,16 +114,14 @@ public:
option_arg.str().c_str());
}
m_bp_opts.SetThreadID(thread_id);
- }
- break;
+ } break;
case 'T':
m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
break;
case 'q':
m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
break;
- case 'x':
- {
+ case 'x': {
uint32_t thread_index = UINT32_MAX;
if (option_arg[0] != '\n') {
if (option_arg.getAsInteger(0, thread_index))
@@ -139,8 +129,7 @@ public:
option_arg.str().c_str());
}
m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
- }
- break;
+ } break;
default:
llvm_unreachable("Unimplemented option");
}
@@ -152,43 +141,33 @@ public:
m_bp_opts.Clear();
m_commands.clear();
}
-
+
Status OptionParsingFinished(ExecutionContext *execution_context) override {
- if (!m_commands.empty())
- {
- if (!m_commands.empty())
- {
- auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
-
- for (std::string &str : m_commands)
- cmd_data->user_source.AppendString(str);
-
- cmd_data->stop_on_error = true;
- m_bp_opts.SetCommandDataCallback(cmd_data);
- }
+ if (!m_commands.empty()) {
+ auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
+
+ for (std::string &str : m_commands)
+ cmd_data->user_source.AppendString(str);
+
+ cmd_data->stop_on_error = true;
+ m_bp_opts.SetCommandDataCallback(cmd_data);
}
return Status();
}
-
- const BreakpointOptions &GetBreakpointOptions()
- {
- return m_bp_opts;
- }
+
+ const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; }
std::vector<std::string> m_commands;
BreakpointOptions m_bp_opts;
-
};
#define LLDB_OPTIONS_breakpoint_dummy
#include "CommandOptions.inc"
-class BreakpointDummyOptionGroup : public OptionGroup
-{
+class BreakpointDummyOptionGroup : public OptionGroup {
public:
- BreakpointDummyOptionGroup() :
- OptionGroup() {}
-
+ BreakpointDummyOptionGroup() : OptionGroup() {}
+
~BreakpointDummyOptionGroup() override = default;
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@@ -196,14 +175,15 @@ public:
}
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
- ExecutionContext *execution_context) override {
+ ExecutionContext *execution_context) override {
Status error;
- const int short_option = g_breakpoint_modify_options[option_idx].short_option;
+ const int short_option =
+ g_breakpoint_dummy_options[option_idx].short_option;
switch (short_option) {
- case 'D':
- m_use_dummy = true;
- break;
+ case 'D':
+ m_use_dummy = true;
+ break;
default:
llvm_unreachable("Unimplemented option");
}
@@ -216,7 +196,6 @@ public:
}
bool m_use_dummy;
-
};
#define LLDB_OPTIONS_breakpoint_set
@@ -242,11 +221,11 @@ public:
interpreter, "breakpoint set",
"Sets a breakpoint or set of breakpoints in the executable.",
"breakpoint set <cmd-options>"),
- m_bp_opts(), m_python_class_options("scripted breakpoint", 'P'),
+ m_bp_opts(), m_python_class_options("scripted breakpoint", true, 'P'),
m_options() {
// We're picking up all the normal options, commands and disable.
- m_all_options.Append(&m_python_class_options, LLDB_OPT_SET_1,
- LLDB_OPT_SET_11);
+ m_all_options.Append(&m_python_class_options,
+ LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11);
m_all_options.Append(&m_bp_opts,
LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
LLDB_OPT_SET_ALL);
@@ -262,21 +241,23 @@ public:
class CommandOptions : public OptionGroup {
public:
CommandOptions()
- : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
- m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
- m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
- m_catch_bp(false), m_throw_bp(true), m_hardware(false),
+ : OptionGroup(), m_condition(), m_filenames(), m_line_num(0),
+ m_column(0), m_func_names(),
+ m_func_name_type_mask(eFunctionNameTypeNone), m_func_regexp(),
+ m_source_text_regexp(), m_modules(), m_load_addr(), m_catch_bp(false),
+ m_throw_bp(true), m_hardware(false),
m_exception_language(eLanguageTypeUnknown),
m_language(lldb::eLanguageTypeUnknown),
- m_skip_prologue(eLazyBoolCalculate),
- m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
+ m_skip_prologue(eLazyBoolCalculate), m_all_files(false),
+ m_move_to_nearest_code(eLazyBoolCalculate) {}
~CommandOptions() override = default;
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
ExecutionContext *execution_context) override {
Status error;
- const int short_option = g_breakpoint_set_options[option_idx].short_option;
+ const int short_option =
+ g_breakpoint_set_options[option_idx].short_option;
switch (short_option) {
case 'a': {
@@ -342,7 +323,7 @@ public:
m_func_names.push_back(option_arg);
m_func_name_type_mask |= eFunctionNameTypeFull;
break;
-
+
case 'h': {
bool success;
m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
@@ -355,7 +336,7 @@ public:
case 'H':
m_hardware = true;
break;
-
+
case 'K': {
bool success;
bool value;
@@ -436,7 +417,7 @@ public:
case 'p':
m_source_text_regexp.assign(option_arg);
break;
-
+
case 'r':
m_func_regexp.assign(option_arg);
break;
@@ -543,7 +524,7 @@ protected:
BreakpointSetType break_type = eSetTypeInvalid;
- if (!m_python_class_options.GetClassName().empty())
+ if (!m_python_class_options.GetName().empty())
break_type = eSetTypeScripted;
else if (m_options.m_line_num != 0)
break_type = eSetTypeFileAndLine;
@@ -635,22 +616,21 @@ protected:
case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
// name
- {
- RegularExpression regexp(m_options.m_func_regexp);
- if (llvm::Error err = regexp.GetError()) {
- result.AppendErrorWithFormat(
- "Function name regular expression could not be compiled: \"%s\"",
- llvm::toString(std::move(err)).c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- bp_sp = target.CreateFuncRegexBreakpoint(
- &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
- m_options.m_language, m_options.m_skip_prologue, internal,
- m_options.m_hardware);
+ {
+ RegularExpression regexp(m_options.m_func_regexp);
+ if (llvm::Error err = regexp.GetError()) {
+ result.AppendErrorWithFormat(
+ "Function name regular expression could not be compiled: \"%s\"",
+ llvm::toString(std::move(err)).c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
}
- break;
+
+ bp_sp = target.CreateFuncRegexBreakpoint(
+ &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
+ m_options.m_language, m_options.m_skip_prologue, internal,
+ m_options.m_hardware);
+ } break;
case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
{
const size_t num_files = m_options.m_filenames.GetSize();
@@ -699,13 +679,12 @@ protected:
Status error;
bp_sp = target.CreateScriptedBreakpoint(
- m_python_class_options.GetClassName().c_str(), &(m_options.m_modules),
+ m_python_class_options.GetName().c_str(), &(m_options.m_modules),
&(m_options.m_filenames), false, m_options.m_hardware,
m_python_class_options.GetStructuredData(), &error);
if (error.Fail()) {
result.AppendErrorWithFormat(
- "Error setting extra exception arguments: %s",
- error.AsCString());
+ "Error setting extra exception arguments: %s", error.AsCString());
target.RemoveBreakpointByID(bp_sp->GetID());
result.SetStatus(eReturnStatusFailed);
return false;
@@ -733,12 +712,12 @@ protected:
}
}
}
-
+
if (bp_sp) {
Stream &output_stream = result.GetOutputStream();
const bool show_locations = false;
bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
- show_locations);
+ show_locations);
if (&target == &GetDummyTarget())
output_stream.Printf("Breakpoint set in dummy target, will get copied "
"into future targets.\n");
@@ -822,9 +801,9 @@ public:
// Add the entry for the first argument for this command to the object's
// arguments vector.
m_arguments.push_back(arg);
-
- m_options.Append(&m_bp_opts,
- LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
+
+ m_options.Append(&m_bp_opts,
+ LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
LLDB_OPT_SET_ALL);
m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
m_options.Finalize();
@@ -859,11 +838,11 @@ protected:
BreakpointLocation *location =
bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
if (location)
- location->GetLocationOptions()
- ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
+ location->GetLocationOptions()->CopyOverSetOptions(
+ m_bp_opts.GetBreakpointOptions());
} else {
- bp->GetOptions()
- ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
+ bp->GetOptions()->CopyOverSetOptions(
+ m_bp_opts.GetBreakpointOptions());
}
}
}
@@ -1183,7 +1162,7 @@ protected:
for (size_t i = 0; i < num_breakpoints; ++i) {
Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
if (breakpoint->AllowList())
- AddBreakpointDescription(&output_stream, breakpoint,
+ AddBreakpointDescription(&output_stream, breakpoint,
m_options.m_level);
}
result.SetStatus(eReturnStatusSuccessFinishNoResult);
@@ -1580,62 +1559,61 @@ public:
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
ExecutionContext *execution_context) override {
Status error;
- const int short_option
- = g_breakpoint_access_options[option_idx].short_option;
+ const int short_option =
+ g_breakpoint_access_options[option_idx].short_option;
switch (short_option) {
- case 'L': {
- bool value, success;
- value = OptionArgParser::ToBoolean(option_arg, false, &success);
- if (success) {
- m_permissions.SetAllowList(value);
- } else
- error.SetErrorStringWithFormat(
- "invalid boolean value '%s' passed for -L option",
- option_arg.str().c_str());
- } break;
- case 'A': {
- bool value, success;
- value = OptionArgParser::ToBoolean(option_arg, false, &success);
- if (success) {
- m_permissions.SetAllowDisable(value);
- } else
- error.SetErrorStringWithFormat(
- "invalid boolean value '%s' passed for -L option",
- option_arg.str().c_str());
- } break;
- case 'D': {
- bool value, success;
- value = OptionArgParser::ToBoolean(option_arg, false, &success);
- if (success) {
- m_permissions.SetAllowDelete(value);
- } else
- error.SetErrorStringWithFormat(
- "invalid boolean value '%s' passed for -L option",
- option_arg.str().c_str());
- } break;
- default:
- llvm_unreachable("Unimplemented option");
+ case 'L': {
+ bool value, success;
+ value = OptionArgParser::ToBoolean(option_arg, false, &success);
+ if (success) {
+ m_permissions.SetAllowList(value);
+ } else
+ error.SetErrorStringWithFormat(
+ "invalid boolean value '%s' passed for -L option",
+ option_arg.str().c_str());
+ } break;
+ case 'A': {
+ bool value, success;
+ value = OptionArgParser::ToBoolean(option_arg, false, &success);
+ if (success) {
+ m_permissions.SetAllowDisable(value);
+ } else
+ error.SetErrorStringWithFormat(
+ "invalid boolean value '%s' passed for -L option",
+ option_arg.str().c_str());
+ } break;
+ case 'D': {
+ bool value, success;
+ value = OptionArgParser::ToBoolean(option_arg, false, &success);
+ if (success) {
+ m_permissions.SetAllowDelete(value);
+ } else
+ error.SetErrorStringWithFormat(
+ "invalid boolean value '%s' passed for -L option",
+ option_arg.str().c_str());
+ } break;
+ default:
+ llvm_unreachable("Unimplemented option");
}
-
+
return error;
}
-
- void OptionParsingStarting(ExecutionContext *execution_context) override {
- }
-
- const BreakpointName::Permissions &GetPermissions() const
- {
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {}
+
+ const BreakpointName::Permissions &GetPermissions() const {
return m_permissions;
}
- BreakpointName::Permissions m_permissions;
+ BreakpointName::Permissions m_permissions;
};
class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
public:
CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
: CommandObjectParsed(
- interpreter, "configure", "Configure the options for the breakpoint"
+ interpreter, "configure",
+ "Configure the options for the breakpoint"
" name provided. "
"If you provide a breakpoint id, the options will be copied from "
"the breakpoint, otherwise only the options specified will be set "
@@ -1652,14 +1630,10 @@ public:
arg1.push_back(id_arg);
m_arguments.push_back(arg1);
- m_option_group.Append(&m_bp_opts,
- LLDB_OPT_SET_ALL,
- LLDB_OPT_SET_1);
- m_option_group.Append(&m_access_options,
- LLDB_OPT_SET_ALL,
+ m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
+ m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL,
LLDB_OPT_SET_ALL);
- m_option_group.Append(&m_bp_id,
- LLDB_OPT_SET_2|LLDB_OPT_SET_4,
+ m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4,
LLDB_OPT_SET_ALL);
m_option_group.Finalize();
}
@@ -1686,8 +1660,7 @@ protected:
// Make a pass through first to see that all the names are legal.
for (auto &entry : command.entries()) {
Status error;
- if (!BreakpointID::StringIsBreakpointName(entry.ref(), error))
- {
+ if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) {
result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
entry.c_str(), error.AsCString());
result.SetStatus(eReturnStatusFailed);
@@ -1697,14 +1670,12 @@ protected:
// Now configure them, we already pre-checked the names so we don't need to
// check the error:
BreakpointSP bp_sp;
- if (m_bp_id.m_breakpoint.OptionWasSet())
- {
+ if (m_bp_id.m_breakpoint.OptionWasSet()) {
lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
bp_sp = target.GetBreakpointByID(bp_id);
- if (!bp_sp)
- {
+ if (!bp_sp) {
result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
- bp_id);
+ bp_id);
result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1718,7 +1689,7 @@ protected:
continue;
if (m_bp_id.m_help_string.OptionWasSet())
bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
-
+
if (bp_sp)
target.ConfigureBreakpointName(*bp_name, *bp_sp->GetOptions(),
m_access_options.GetPermissions());
@@ -1797,7 +1768,7 @@ protected:
}
size_t num_valid_ids = valid_bp_ids.GetSize();
const char *bp_name = m_name_options.m_name.GetCurrentValue();
- Status error; // This error reports illegal names, but we've already
+ Status error; // This error reports illegal names, but we've already
// checked that, so we don't need to check it again here.
for (size_t index = 0; index < num_valid_ids; index++) {
lldb::break_id_t bp_id =
@@ -1918,12 +1889,11 @@ protected:
if (command.empty()) {
target.GetBreakpointNames(name_list);
} else {
- for (const Args::ArgEntry &arg : command)
- {
+ for (const Args::ArgEntry &arg : command) {
name_list.push_back(arg.c_str());
}
}
-
+
if (name_list.empty()) {
result.AppendMessage("No breakpoint names found.");
} else {
@@ -1933,15 +1903,13 @@ protected:
Status error;
BreakpointName *bp_name =
target.FindBreakpointName(ConstString(name), false, error);
- if (bp_name)
- {
+ if (bp_name) {
StreamString s;
result.AppendMessageWithFormat("Name: %s\n", name);
- if (bp_name->GetDescription(&s, eDescriptionLevelFull))
- {
+ if (bp_name->GetDescription(&s, eDescriptionLevelFull)) {
result.AppendMessage(s.GetString());
}
-
+
std::unique_lock<std::recursive_mutex> lock;
target.GetBreakpointList().GetListMutex(lock);
@@ -2274,13 +2242,10 @@ CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
-void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
- bool allow_locations,
- CommandReturnObject &result,
- BreakpointIDList *valid_ids,
- BreakpointName::Permissions
- ::PermissionKinds
- purpose) {
+void CommandObjectMultiwordBreakpoint::VerifyIDs(
+ Args &args, Target *target, bool allow_locations,
+ CommandReturnObject &result, BreakpointIDList *valid_ids,
+ BreakpointName::Permissions ::PermissionKinds purpose) {
// args can be strings representing 1). integers (for breakpoint ids)
// 2). the full breakpoint & location
// canonical representation
@@ -2313,7 +2278,7 @@ void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
// breakpoint ids in the range, and shove all of those breakpoint id strings
// into TEMP_ARGS.
- BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
+ BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
purpose, result, temp_args);
// NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
diff --git a/lldb/source/Commands/CommandObjectBreakpoint.h b/lldb/source/Commands/CommandObjectBreakpoint.h
index cba1f3f774ee..b29bbc0a74fa 100644
--- a/lldb/source/Commands/CommandObjectBreakpoint.h
+++ b/lldb/source/Commands/CommandObjectBreakpoint.h
@@ -10,16 +10,8 @@
#define liblldb_CommandObjectBreakpoint_h_
-#include <utility>
-#include <vector>
-
-#include "lldb/lldb-private.h"
#include "lldb/Breakpoint/BreakpointName.h"
-#include "lldb/Core/Address.h"
-#include "lldb/Core/STLUtils.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
-#include "lldb/Interpreter/Options.h"
-
namespace lldb_private {
@@ -31,19 +23,17 @@ public:
~CommandObjectMultiwordBreakpoint() override;
- static void VerifyBreakpointOrLocationIDs(Args &args, Target *target,
- CommandReturnObject &result,
- BreakpointIDList *valid_ids,
- BreakpointName::Permissions
- ::PermissionKinds purpose) {
+ static void VerifyBreakpointOrLocationIDs(
+ Args &args, Target *target, CommandReturnObject &result,
+ BreakpointIDList *valid_ids,
+ BreakpointName::Permissions ::PermissionKinds purpose) {
VerifyIDs(args, target, true, result, valid_ids, purpose);
}
- static void VerifyBreakpointIDs(Args &args, Target *target,
- CommandReturnObject &result,
- BreakpointIDList *valid_ids,
- BreakpointName::Permissions::PermissionKinds
- purpose) {
+ static void
+ VerifyBreakpointIDs(Args &args, Target *target, CommandReturnObject &result,
+ BreakpointIDList *valid_ids,
+ BreakpointName::Permissions::PermissionKinds purpose) {
VerifyIDs(args, target, false, result, valid_ids, purpose);
}
@@ -51,8 +41,7 @@ private:
static void VerifyIDs(Args &args, Target *target, bool allow_locations,
CommandReturnObject &result,
BreakpointIDList *valid_ids,
- BreakpointName::Permissions::PermissionKinds
- purpose);
+ BreakpointName::Permissions::PermissionKinds purpose);
};
} // namespace lldb_private
diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
index a6bcd1d8dc32..bbd2ca570126 100644
--- a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
+++ b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
@@ -11,17 +11,13 @@
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
+#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
#include "lldb/Target/Target.h"
-#include "lldb/Target/Thread.h"
-#include "lldb/Utility/State.h"
-
-#include "llvm/ADT/STLExtras.h"
using namespace lldb;
using namespace lldb_private;
@@ -41,7 +37,12 @@ static constexpr OptionEnumValueElement g_script_option_enumeration[] = {
"Commands are in the Python language.",
},
{
- eSortOrderByName,
+ eScriptLanguageLua,
+ "lua",
+ "Commands are in the Lua language.",
+ },
+ {
+ eScriptLanguageDefault,
"default-script",
"Commands are in the default scripting language.",
},
@@ -66,7 +67,7 @@ public:
nullptr),
IOHandlerDelegateMultiline("DONE",
IOHandlerDelegate::Completion::LLDBCommand),
- m_options() {
+ m_options(), m_func_options("breakpoint command", false, 'F') {
SetHelpLong(
R"(
General information about entering breakpoint commands
@@ -201,6 +202,11 @@ LLDB to stop."
"Final Note: A warning that no breakpoint command was generated when there \
are no syntax errors may indicate that a function was declared but never called.");
+ m_all_options.Append(&m_options);
+ m_all_options.Append(&m_func_options, LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
+ LLDB_OPT_SET_2);
+ m_all_options.Finalize();
+
CommandArgumentEntry arg;
CommandArgumentData bp_id_arg;
@@ -218,7 +224,7 @@ are no syntax errors may indicate that a function was declared but never called.
~CommandObjectBreakpointCommandAdd() override = default;
- Options *GetOptions() override { return &m_options; }
+ Options *GetOptions() override { return &m_all_options; }
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
@@ -250,7 +256,6 @@ are no syntax errors may indicate that a function was declared but never called.
m_interpreter.GetLLDBCommandsFromIOHandler(
"> ", // Prompt
*this, // IOHandlerDelegate
- true, // Run IOHandler in async mode
&bp_options_vec); // Baton for the "io_handler" that will be passed back
// into our IOHandlerDelegate functions
}
@@ -269,19 +274,20 @@ are no syntax errors may indicate that a function was declared but never called.
}
}
- class CommandOptions : public Options {
+ class CommandOptions : public OptionGroup {
public:
CommandOptions()
- : Options(), m_use_commands(false), m_use_script_language(false),
+ : OptionGroup(), m_use_commands(false), m_use_script_language(false),
m_script_language(eScriptLanguageNone), m_use_one_liner(false),
- m_one_liner(), m_function_name() {}
+ m_one_liner() {}
~CommandOptions() override = default;
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
ExecutionContext *execution_context) override {
Status error;
- const int short_option = m_getopt_table[option_idx].val;
+ const int short_option =
+ g_breakpoint_command_add_options[option_idx].short_option;
switch (short_option) {
case 'o':
@@ -294,12 +300,15 @@ are no syntax errors may indicate that a function was declared but never called.
option_arg,
g_breakpoint_command_add_options[option_idx].enum_values,
eScriptLanguageNone, error);
-
- if (m_script_language == eScriptLanguagePython ||
- m_script_language == eScriptLanguageDefault) {
+ switch (m_script_language) {
+ case eScriptLanguagePython:
+ case eScriptLanguageLua:
m_use_script_language = true;
- } else {
+ break;
+ case eScriptLanguageNone:
+ case eScriptLanguageUnknown:
m_use_script_language = false;
+ break;
}
break;
@@ -313,12 +322,6 @@ are no syntax errors may indicate that a function was declared but never called.
option_arg.str().c_str());
} break;
- case 'F':
- m_use_one_liner = false;
- m_use_script_language = true;
- m_function_name.assign(option_arg);
- break;
-
case 'D':
m_use_dummy = true;
break;
@@ -337,7 +340,6 @@ are no syntax errors may indicate that a function was declared but never called.
m_use_one_liner = false;
m_stop_on_error = true;
m_one_liner.clear();
- m_function_name.clear();
m_use_dummy = false;
}
@@ -355,7 +357,6 @@ are no syntax errors may indicate that a function was declared but never called.
bool m_use_one_liner;
std::string m_one_liner;
bool m_stop_on_error;
- std::string m_function_name;
bool m_use_dummy;
};
@@ -372,12 +373,12 @@ protected:
return false;
}
- if (!m_options.m_use_script_language &&
- !m_options.m_function_name.empty()) {
- result.AppendError("need to enable scripting to have a function run as a "
- "breakpoint command");
- result.SetStatus(eReturnStatusFailed);
- return false;
+ if (!m_func_options.GetName().empty()) {
+ m_options.m_use_one_liner = false;
+ if (!m_options.m_use_script_language) {
+ m_options.m_script_language = GetDebugger().GetScriptLanguage();
+ m_options.m_use_script_language = true;
+ }
}
BreakpointIDList valid_bp_ids;
@@ -416,14 +417,18 @@ protected:
// to set or collect command callback. Otherwise, call the methods
// associated with this object.
if (m_options.m_use_script_language) {
- ScriptInterpreter *script_interp = GetDebugger().GetScriptInterpreter();
+ ScriptInterpreter *script_interp = GetDebugger().GetScriptInterpreter(
+ /*can_create=*/true, m_options.m_script_language);
// Special handling for one-liner specified inline.
if (m_options.m_use_one_liner) {
script_interp->SetBreakpointCommandCallback(
m_bp_options_vec, m_options.m_one_liner.c_str());
- } else if (!m_options.m_function_name.empty()) {
- script_interp->SetBreakpointCommandCallbackFunction(
- m_bp_options_vec, m_options.m_function_name.c_str());
+ } else if (!m_func_options.GetName().empty()) {
+ Status error = script_interp->SetBreakpointCommandCallbackFunction(
+ m_bp_options_vec, m_func_options.GetName().c_str(),
+ m_func_options.GetStructuredData());
+ if (!error.Success())
+ result.SetError(error);
} else {
script_interp->CollectDataForBreakpointCommandCallback(
m_bp_options_vec, result);
@@ -443,6 +448,9 @@ protected:
private:
CommandOptions m_options;
+ OptionGroupPythonClassWithDict m_func_options;
+ OptionGroupOptions m_all_options;
+
std::vector<BreakpointOptions *> m_bp_options_vec; // This stores the
// breakpoint options that
// we are currently
@@ -646,9 +654,8 @@ protected:
if (bp) {
BreakpointLocationSP bp_loc_sp;
if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
- bp_loc_sp = bp->FindLocationByID(cur_bp_id.GetLocationID());
- if (!bp_loc_sp)
- {
+ bp_loc_sp = bp->FindLocationByID(cur_bp_id.GetLocationID());
+ if (!bp_loc_sp) {
result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
cur_bp_id.GetBreakpointID(),
cur_bp_id.GetLocationID());
@@ -663,19 +670,20 @@ protected:
cur_bp_id.GetLocationID());
const Baton *baton = nullptr;
if (bp_loc_sp)
- baton = bp_loc_sp
- ->GetOptionsSpecifyingKind(BreakpointOptions::eCallback)
- ->GetBaton();
+ baton =
+ bp_loc_sp
+ ->GetOptionsSpecifyingKind(BreakpointOptions::eCallback)
+ ->GetBaton();
else
baton = bp->GetOptions()->GetBaton();
if (baton) {
result.GetOutputStream().Printf("Breakpoint %s:\n",
id_str.GetData());
- result.GetOutputStream().IndentMore();
- baton->GetDescription(&result.GetOutputStream(),
- eDescriptionLevelFull);
- result.GetOutputStream().IndentLess();
+ baton->GetDescription(result.GetOutputStream().AsRawOstream(),
+ eDescriptionLevelFull,
+ result.GetOutputStream().GetIndentLevel() +
+ 2);
} else {
result.AppendMessageWithFormat(
"Breakpoint %s does not have an associated command.\n",
@@ -700,9 +708,10 @@ protected:
CommandObjectBreakpointCommand::CommandObjectBreakpointCommand(
CommandInterpreter &interpreter)
: CommandObjectMultiword(
- interpreter, "command", "Commands for adding, removing and listing "
- "LLDB commands executed when a breakpoint is "
- "hit.",
+ interpreter, "command",
+ "Commands for adding, removing and listing "
+ "LLDB commands executed when a breakpoint is "
+ "hit.",
"command <sub-command> [<sub-command-options>] <breakpoint-id>") {
CommandObjectSP add_command_object(
new CommandObjectBreakpointCommandAdd(interpreter));
diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.h b/lldb/source/Commands/CommandObjectBreakpointCommand.h
index b18e003368be..fb246d47abfd 100644
--- a/lldb/source/Commands/CommandObjectBreakpointCommand.h
+++ b/lldb/source/Commands/CommandObjectBreakpointCommand.h
@@ -9,13 +9,7 @@
#ifndef liblldb_CommandObjectBreakpointCommand_h_
#define liblldb_CommandObjectBreakpointCommand_h_
-
-
-#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
-#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Interpreter/Options.h"
-#include "lldb/lldb-types.h"
namespace lldb_private {
diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp
index 259affbe6e0a..388db6fad631 100644
--- a/lldb/source/Commands/CommandObjectCommands.cpp
+++ b/lldb/source/Commands/CommandObjectCommands.cpp
@@ -12,7 +12,6 @@
#include "CommandObjectHelp.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/IOHandler.h"
-#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandHistory.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObjectRegexCommand.h"
@@ -900,9 +899,10 @@ class CommandObjectCommandsAddRegex : public CommandObjectParsed,
public:
CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
: CommandObjectParsed(
- interpreter, "command regex", "Define a custom command in terms of "
- "existing commands by matching "
- "regular expressions.",
+ interpreter, "command regex",
+ "Define a custom command in terms of "
+ "existing commands by matching "
+ "regular expressions.",
"command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
IOHandlerDelegateMultiline("",
IOHandlerDelegate::Completion::LLDBCommand),
@@ -1197,8 +1197,8 @@ public:
CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
std::string funct, std::string help,
ScriptedCommandSynchronicity synch)
- : CommandObjectRaw(interpreter, name),
- m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) {
+ : CommandObjectRaw(interpreter, name), m_function_name(funct),
+ m_synchro(synch), m_fetched_help_long(false) {
if (!help.empty())
SetHelp(help);
else {
@@ -1241,10 +1241,9 @@ protected:
result.SetStatus(eReturnStatusInvalid);
- if (!scripter ||
- !scripter->RunScriptBasedCommand(m_function_name.c_str(),
- raw_command_line, m_synchro, result,
- error, m_exe_ctx)) {
+ if (!scripter || !scripter->RunScriptBasedCommand(
+ m_function_name.c_str(), raw_command_line, m_synchro,
+ result, error, m_exe_ctx)) {
result.AppendError(error.AsCString());
result.SetStatus(eReturnStatusFailed);
} else {
@@ -1272,8 +1271,8 @@ public:
std::string name,
StructuredData::GenericSP cmd_obj_sp,
ScriptedCommandSynchronicity synch)
- : CommandObjectRaw(interpreter, name),
- m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false),
+ : CommandObjectRaw(interpreter, name), m_cmd_obj_sp(cmd_obj_sp),
+ m_synchro(synch), m_fetched_help_short(false),
m_fetched_help_long(false) {
StreamString stream;
stream.Printf("For more information run 'help %s'", name.c_str());
@@ -1404,7 +1403,7 @@ protected:
switch (short_option) {
case 'r':
- m_allow_reload = true;
+ // NO-OP
break;
default:
llvm_unreachable("Unimplemented option");
@@ -1414,26 +1413,14 @@ protected:
}
void OptionParsingStarting(ExecutionContext *execution_context) override {
- m_allow_reload = true;
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
return llvm::makeArrayRef(g_script_import_options);
}
-
- // Instance variables to hold the values for command options.
-
- bool m_allow_reload;
};
bool DoExecute(Args &command, CommandReturnObject &result) override {
- if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) {
- result.AppendError("only scripting language supported for module "
- "importing is currently Python");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
if (command.empty()) {
result.AppendError("command script import needs one or more arguments");
result.SetStatus(eReturnStatusFailed);
@@ -1454,7 +1441,7 @@ protected:
// more)
m_exe_ctx.Clear();
if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule(
- entry.c_str(), m_options.m_allow_reload, init_session, error)) {
+ entry.c_str(), init_session, error)) {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
result.AppendErrorWithFormat("module importing failed: %s",
@@ -1663,11 +1650,8 @@ protected:
if (m_options.m_class_name.empty()) {
if (m_options.m_funct_name.empty()) {
m_interpreter.GetPythonCommandsFromIOHandler(
- " ", // Prompt
- *this, // IOHandlerDelegate
- true, // Run IOHandler in async mode
- nullptr); // Baton for the "io_handler" that will be passed back
- // into our IOHandlerDelegate functions
+ " ", // Prompt
+ *this); // IOHandlerDelegate
} else {
CommandObjectSP new_cmd(new CommandObjectPythonFunction(
m_interpreter, m_cmd_name, m_options.m_funct_name,
@@ -1821,9 +1805,10 @@ class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
public:
CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
: CommandObjectMultiword(
- interpreter, "command script", "Commands for managing custom "
- "commands implemented by "
- "interpreter scripts.",
+ interpreter, "command script",
+ "Commands for managing custom "
+ "commands implemented by "
+ "interpreter scripts.",
"command script <subcommand> [<subcommand-options>]") {
LoadSubCommand("add", CommandObjectSP(
new CommandObjectCommandsScriptAdd(interpreter)));
diff --git a/lldb/source/Commands/CommandObjectCommands.h b/lldb/source/Commands/CommandObjectCommands.h
index 468ee53344f1..dcf02f3a7da9 100644
--- a/lldb/source/Commands/CommandObjectCommands.h
+++ b/lldb/source/Commands/CommandObjectCommands.h
@@ -10,8 +10,6 @@
#ifndef liblldb_CommandObjectCommands_h_
#define liblldb_CommandObjectCommands_h_
-#include "lldb/Core/STLUtils.h"
-#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
namespace lldb_private {
diff --git a/lldb/source/Commands/CommandObjectDisassemble.cpp b/lldb/source/Commands/CommandObjectDisassemble.cpp
index 69e2d757b5fe..63679e996e70 100644
--- a/lldb/source/Commands/CommandObjectDisassemble.cpp
+++ b/lldb/source/Commands/CommandObjectDisassemble.cpp
@@ -10,16 +10,13 @@
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/SourceManager.h"
#include "lldb/Host/OptionParser.h"
-#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
-#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
@@ -249,9 +246,8 @@ bool CommandObjectDisassemble::DoExecute(Args &command,
m_options.arch.GetArchitectureName());
result.SetStatus(eReturnStatusFailed);
return false;
- } else if (flavor_string != nullptr &&
- !disassembler->FlavorValidForArchSpec(m_options.arch,
- flavor_string))
+ } else if (flavor_string != nullptr && !disassembler->FlavorValidForArchSpec(
+ m_options.arch, flavor_string))
result.AppendWarningWithFormat(
"invalid disassembler flavor \"%s\", using default.\n", flavor_string);
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index 9bafdc149804..db90dde98eff 100644
--- a/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -6,29 +6,20 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "CommandObjectExpression.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Value.h"
-#include "lldb/Core/ValueObjectVariable.h"
-#include "lldb/DataFormatters/ValueObjectPrinter.h"
-#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Expression/REPL.h"
#include "lldb/Expression/UserExpression.h"
-#include "lldb/Host/Host.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/Variable.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
-#include "lldb/Target/Thread.h"
using namespace lldb;
using namespace lldb_private;
@@ -202,11 +193,12 @@ CommandObjectExpression::CommandOptions::GetDefinitions() {
CommandObjectExpression::CommandObjectExpression(
CommandInterpreter &interpreter)
- : CommandObjectRaw(
- interpreter, "expression", "Evaluate an expression on the current "
- "thread. Displays any returned value "
- "with LLDB's default formatting.",
- "", eCommandProcessMustBePaused | eCommandTryTargetAPILock),
+ : CommandObjectRaw(interpreter, "expression",
+ "Evaluate an expression on the current "
+ "thread. Displays any returned value "
+ "with LLDB's default formatting.",
+ "",
+ eCommandProcessMustBePaused | eCommandTryTargetAPILock),
IOHandlerDelegate(IOHandlerDelegate::Completion::Expression),
m_option_group(), m_format_options(eFormatDefault),
m_repl_option(LLDB_OPT_SET_1, false, "repl", 'r', "Drop into REPL", false,
@@ -588,60 +580,58 @@ bool CommandObjectExpression::DoExecute(llvm::StringRef command,
return false;
if (m_repl_option.GetOptionValue().GetCurrentValue()) {
- Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
- if (target) {
- // Drop into REPL
- m_expr_lines.clear();
- m_expr_line_count = 0;
-
- Debugger &debugger = target->GetDebugger();
-
- // Check if the LLDB command interpreter is sitting on top of a REPL
- // that launched it...
- if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::CommandInterpreter,
- IOHandler::Type::REPL)) {
- // the LLDB command interpreter is sitting on top of a REPL that
- // launched it, so just say the command interpreter is done and
- // fall back to the existing REPL
- m_interpreter.GetIOHandler(false)->SetIsDone(true);
- } else {
- // We are launching the REPL on top of the current LLDB command
- // interpreter, so just push one
- bool initialize = false;
- Status repl_error;
- REPLSP repl_sp(target->GetREPL(repl_error, m_command_options.language,
- nullptr, false));
-
- if (!repl_sp) {
- initialize = true;
- repl_sp = target->GetREPL(repl_error, m_command_options.language,
- nullptr, true);
- if (!repl_error.Success()) {
- result.SetError(repl_error);
- return result.Succeeded();
- }
+ Target &target = GetSelectedOrDummyTarget();
+ // Drop into REPL
+ m_expr_lines.clear();
+ m_expr_line_count = 0;
+
+ Debugger &debugger = target.GetDebugger();
+
+ // Check if the LLDB command interpreter is sitting on top of a REPL
+ // that launched it...
+ if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::CommandInterpreter,
+ IOHandler::Type::REPL)) {
+ // the LLDB command interpreter is sitting on top of a REPL that
+ // launched it, so just say the command interpreter is done and
+ // fall back to the existing REPL
+ m_interpreter.GetIOHandler(false)->SetIsDone(true);
+ } else {
+ // We are launching the REPL on top of the current LLDB command
+ // interpreter, so just push one
+ bool initialize = false;
+ Status repl_error;
+ REPLSP repl_sp(target.GetREPL(repl_error, m_command_options.language,
+ nullptr, false));
+
+ if (!repl_sp) {
+ initialize = true;
+ repl_sp = target.GetREPL(repl_error, m_command_options.language,
+ nullptr, true);
+ if (!repl_error.Success()) {
+ result.SetError(repl_error);
+ return result.Succeeded();
}
+ }
- if (repl_sp) {
- if (initialize) {
- repl_sp->SetEvaluateOptions(
- GetExprOptions(exe_ctx, m_command_options));
- repl_sp->SetFormatOptions(m_format_options);
- repl_sp->SetValueObjectDisplayOptions(m_varobj_options);
- }
+ if (repl_sp) {
+ if (initialize) {
+ repl_sp->SetEvaluateOptions(
+ GetExprOptions(exe_ctx, m_command_options));
+ repl_sp->SetFormatOptions(m_format_options);
+ repl_sp->SetValueObjectDisplayOptions(m_varobj_options);
+ }
- IOHandlerSP io_handler_sp(repl_sp->GetIOHandler());
+ IOHandlerSP io_handler_sp(repl_sp->GetIOHandler());
- io_handler_sp->SetIsDone(false);
+ io_handler_sp->SetIsDone(false);
- debugger.PushIOHandler(io_handler_sp);
- } else {
- repl_error.SetErrorStringWithFormat(
- "Couldn't create a REPL for %s",
- Language::GetNameForLanguageType(m_command_options.language));
- result.SetError(repl_error);
- return result.Succeeded();
- }
+ debugger.PushIOHandler(io_handler_sp);
+ } else {
+ repl_error.SetErrorStringWithFormat(
+ "Couldn't create a REPL for %s",
+ Language::GetNameForLanguageType(m_command_options.language));
+ result.SetError(repl_error);
+ return result.Succeeded();
}
}
}
diff --git a/lldb/source/Commands/CommandObjectExpression.h b/lldb/source/Commands/CommandObjectExpression.h
index 8ef764239069..de159863b43a 100644
--- a/lldb/source/Commands/CommandObjectExpression.h
+++ b/lldb/source/Commands/CommandObjectExpression.h
@@ -14,7 +14,6 @@
#include "lldb/Interpreter/OptionGroupBoolean.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
-#include "lldb/Target/ExecutionContext.h"
#include "lldb/lldb-private-enumerations.h"
namespace lldb_private {
diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp
index 6a7facdaff35..50d5c751de5c 100644
--- a/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/lldb/source/Commands/CommandObjectFrame.cpp
@@ -7,14 +7,10 @@
//===----------------------------------------------------------------------===//
#include "CommandObjectFrame.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/StreamFile.h"
-#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObject.h"
-#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
-#include "lldb/Host/Host.h"
+#include "lldb/Host/Config.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -23,23 +19,16 @@
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Interpreter/OptionGroupVariable.h"
#include "lldb/Interpreter/Options.h"
-#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/Function.h"
-#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
-#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"
-#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Args.h"
-#include "lldb/Utility/LLDBAssert.h"
-#include "lldb/Utility/StreamString.h"
-#include "lldb/Utility/Timer.h"
#include <memory>
#include <string>
@@ -177,10 +166,10 @@ protected:
return false;
}
-
- DumpValueObjectOptions::DeclPrintingHelper helper = [&valobj_sp](
- ConstString type, ConstString var, const DumpValueObjectOptions &opts,
- Stream &stream) -> bool {
+ DumpValueObjectOptions::DeclPrintingHelper helper =
+ [&valobj_sp](ConstString type, ConstString var,
+ const DumpValueObjectOptions &opts,
+ Stream &stream) -> bool {
const ValueObject::GetExpressionPathFormat format = ValueObject::
GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers;
const bool qualify_cxx_base_classes = false;
@@ -209,12 +198,13 @@ protected:
class CommandObjectFrameInfo : public CommandObjectParsed {
public:
CommandObjectFrameInfo(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "frame info", "List information about the current "
- "stack frame in the current thread.",
- "frame info",
- eCommandRequiresFrame | eCommandTryTargetAPILock |
- eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
+ : CommandObjectParsed(interpreter, "frame info",
+ "List information about the current "
+ "stack frame in the current thread.",
+ "frame info",
+ eCommandRequiresFrame | eCommandTryTargetAPILock |
+ eCommandProcessMustBeLaunched |
+ eCommandProcessMustBePaused) {}
~CommandObjectFrameInfo() override = default;
@@ -275,13 +265,14 @@ public:
};
CommandObjectFrameSelect(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "frame select", "Select the current stack frame by "
- "index from within the current thread "
- "(see 'thread backtrace'.)",
- nullptr,
- eCommandRequiresThread | eCommandTryTargetAPILock |
- eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
+ : CommandObjectParsed(interpreter, "frame select",
+ "Select the current stack frame by "
+ "index from within the current thread "
+ "(see 'thread backtrace'.)",
+ nullptr,
+ eCommandRequiresThread | eCommandTryTargetAPILock |
+ eCommandProcessMustBeLaunched |
+ eCommandProcessMustBePaused),
m_options() {
CommandArgumentEntry arg;
CommandArgumentData index_arg;
@@ -415,14 +406,14 @@ public:
"uses debug information and memory reads directly, rather than "
"parsing and evaluating an expression, which may even involve "
"JITing and running code in the target program.",
- nullptr, eCommandRequiresFrame | eCommandTryTargetAPILock |
- eCommandProcessMustBeLaunched |
- eCommandProcessMustBePaused | eCommandRequiresProcess),
+ nullptr,
+ eCommandRequiresFrame | eCommandTryTargetAPILock |
+ eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
+ eCommandRequiresProcess),
m_option_group(),
m_option_variable(
true), // Include the frame specific options by passing "true"
- m_option_format(eFormatDefault),
- m_varobj_options() {
+ m_option_format(eFormatDefault), m_varobj_options() {
CommandArgumentEntry arg;
CommandArgumentData var_name_arg;
@@ -849,7 +840,7 @@ Process 1234 stopped
bool CommandObjectFrameRecognizerAdd::DoExecute(Args &command,
CommandReturnObject &result) {
-#ifndef LLDB_DISABLE_PYTHON
+#if LLDB_ENABLE_PYTHON
if (m_options.m_class_name.empty()) {
result.AppendErrorWithFormat(
"%s needs a Python class name (-l argument).\n", m_cmd_name.c_str());
@@ -875,9 +866,8 @@ bool CommandObjectFrameRecognizerAdd::DoExecute(Args &command,
if (interpreter &&
!interpreter->CheckObjectExists(m_options.m_class_name.c_str())) {
- result.AppendWarning(
- "The provided class does not exist - please define it "
- "before attempting to use this frame recognizer");
+ result.AppendWarning("The provided class does not exist - please define it "
+ "before attempting to use this frame recognizer");
}
StackFrameRecognizerSP recognizer_sp =
@@ -904,7 +894,7 @@ class CommandObjectFrameRecognizerClear : public CommandObjectParsed {
public:
CommandObjectFrameRecognizerClear(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "frame recognizer clear",
- "Delete all frame recognizers.", nullptr) {}
+ "Delete all frame recognizers.", nullptr) {}
~CommandObjectFrameRecognizerClear() override = default;
@@ -917,14 +907,14 @@ protected:
};
class CommandObjectFrameRecognizerDelete : public CommandObjectParsed {
- public:
+public:
CommandObjectFrameRecognizerDelete(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "frame recognizer delete",
"Delete an existing frame recognizer.", nullptr) {}
~CommandObjectFrameRecognizerDelete() override = default;
- protected:
+protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
if (command.GetArgumentCount() == 0) {
if (!m_interpreter.Confirm(
@@ -957,7 +947,7 @@ class CommandObjectFrameRecognizerDelete : public CommandObjectParsed {
};
class CommandObjectFrameRecognizerList : public CommandObjectParsed {
- public:
+public:
CommandObjectFrameRecognizerList(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "frame recognizer list",
"Show a list of active frame recognizers.",
@@ -965,14 +955,15 @@ class CommandObjectFrameRecognizerList : public CommandObjectParsed {
~CommandObjectFrameRecognizerList() override = default;
- protected:
+protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
bool any_printed = false;
StackFrameRecognizerManager::ForEach(
[&result, &any_printed](uint32_t recognizer_id, std::string name,
std::string function, std::string symbol,
bool regexp) {
- if (name == "") name = "(internal)";
+ if (name == "")
+ name = "(internal)";
result.GetOutputStream().Printf(
"%d: %s, module %s, function %s%s\n", recognizer_id, name.c_str(),
function.c_str(), symbol.c_str(), regexp ? " (regexp)" : "");
@@ -990,7 +981,7 @@ class CommandObjectFrameRecognizerList : public CommandObjectParsed {
};
class CommandObjectFrameRecognizerInfo : public CommandObjectParsed {
- public:
+public:
CommandObjectFrameRecognizerInfo(CommandInterpreter &interpreter)
: CommandObjectParsed(
interpreter, "frame recognizer info",
@@ -1013,7 +1004,7 @@ class CommandObjectFrameRecognizerInfo : public CommandObjectParsed {
~CommandObjectFrameRecognizerInfo() override = default;
- protected:
+protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
Process *process = m_exe_ctx.GetProcessPtr();
if (process == nullptr) {
@@ -1061,27 +1052,24 @@ class CommandObjectFrameRecognizerInfo : public CommandObjectParsed {
};
class CommandObjectFrameRecognizer : public CommandObjectMultiword {
- public:
+public:
CommandObjectFrameRecognizer(CommandInterpreter &interpreter)
: CommandObjectMultiword(
interpreter, "frame recognizer",
"Commands for editing and viewing frame recognizers.",
"frame recognizer [<sub-command-options>] ") {
- LoadSubCommand(
- "add",
- CommandObjectSP(new CommandObjectFrameRecognizerAdd(interpreter)));
+ LoadSubCommand("add", CommandObjectSP(new CommandObjectFrameRecognizerAdd(
+ interpreter)));
LoadSubCommand(
"clear",
CommandObjectSP(new CommandObjectFrameRecognizerClear(interpreter)));
LoadSubCommand(
"delete",
CommandObjectSP(new CommandObjectFrameRecognizerDelete(interpreter)));
- LoadSubCommand(
- "list",
- CommandObjectSP(new CommandObjectFrameRecognizerList(interpreter)));
- LoadSubCommand(
- "info",
- CommandObjectSP(new CommandObjectFrameRecognizerInfo(interpreter)));
+ LoadSubCommand("list", CommandObjectSP(new CommandObjectFrameRecognizerList(
+ interpreter)));
+ LoadSubCommand("info", CommandObjectSP(new CommandObjectFrameRecognizerInfo(
+ interpreter)));
}
~CommandObjectFrameRecognizer() override = default;
@@ -1093,9 +1081,10 @@ class CommandObjectFrameRecognizer : public CommandObjectMultiword {
CommandObjectMultiwordFrame::CommandObjectMultiwordFrame(
CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "frame", "Commands for selecting and "
- "examing the current "
- "thread's stack frames.",
+ : CommandObjectMultiword(interpreter, "frame",
+ "Commands for selecting and "
+ "examing the current "
+ "thread's stack frames.",
"frame <subcommand> [<subcommand-options>]") {
LoadSubCommand("diagnose",
CommandObjectSP(new CommandObjectFrameDiagnose(interpreter)));
@@ -1105,10 +1094,9 @@ CommandObjectMultiwordFrame::CommandObjectMultiwordFrame(
CommandObjectSP(new CommandObjectFrameSelect(interpreter)));
LoadSubCommand("variable",
CommandObjectSP(new CommandObjectFrameVariable(interpreter)));
-#ifndef LLDB_DISABLE_PYTHON
- LoadSubCommand(
- "recognizer",
- CommandObjectSP(new CommandObjectFrameRecognizer(interpreter)));
+#if LLDB_ENABLE_PYTHON
+ LoadSubCommand("recognizer", CommandObjectSP(new CommandObjectFrameRecognizer(
+ interpreter)));
#endif
}
diff --git a/lldb/source/Commands/CommandObjectFrame.h b/lldb/source/Commands/CommandObjectFrame.h
index 46a59f71733b..b2378f14290d 100644
--- a/lldb/source/Commands/CommandObjectFrame.h
+++ b/lldb/source/Commands/CommandObjectFrame.h
@@ -10,7 +10,6 @@
#define liblldb_CommandObjectFrame_h_
#include "lldb/Interpreter/CommandObjectMultiword.h"
-#include "lldb/Interpreter/Options.h"
namespace lldb_private {
diff --git a/lldb/source/Commands/CommandObjectGUI.cpp b/lldb/source/Commands/CommandObjectGUI.cpp
index fac2e9627783..67ddc68a169e 100644
--- a/lldb/source/Commands/CommandObjectGUI.cpp
+++ b/lldb/source/Commands/CommandObjectGUI.cpp
@@ -8,9 +8,10 @@
#include "CommandObjectGUI.h"
+#include "lldb/Core/IOHandlerCursesGUI.h"
+#include "lldb/Host/Config.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/lldb-private.h"
using namespace lldb;
using namespace lldb_private;
@@ -24,7 +25,7 @@ CommandObjectGUI::CommandObjectGUI(CommandInterpreter &interpreter)
CommandObjectGUI::~CommandObjectGUI() {}
bool CommandObjectGUI::DoExecute(Args &args, CommandReturnObject &result) {
-#ifndef LLDB_DISABLE_CURSES
+#if LLDB_ENABLE_CURSES
if (args.GetArgumentCount() == 0) {
Debugger &debugger = GetDebugger();
diff --git a/lldb/source/Commands/CommandObjectHelp.cpp b/lldb/source/Commands/CommandObjectHelp.cpp
index c02a583bf9df..6e908dc496a0 100644
--- a/lldb/source/Commands/CommandObjectHelp.cpp
+++ b/lldb/source/Commands/CommandObjectHelp.cpp
@@ -8,9 +8,7 @@
#include "CommandObjectHelp.h"
#include "lldb/Interpreter/CommandInterpreter.h"
-#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Interpreter/Options.h"
using namespace lldb;
using namespace lldb_private;
@@ -27,25 +25,27 @@ void CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
std::string command_str = command.str();
std::string prefix_str = prefix.str();
std::string subcommand_str = subcommand.str();
- const std::string &lookup_str = !subcommand_str.empty() ? subcommand_str : command_str;
+ const std::string &lookup_str =
+ !subcommand_str.empty() ? subcommand_str : command_str;
s->Printf("'%s' is not a known command.\n", command_str.c_str());
s->Printf("Try '%shelp' to see a current list of commands.\n",
prefix.str().c_str());
if (include_upropos) {
s->Printf("Try '%sapropos %s' for a list of related commands.\n",
- prefix_str.c_str(), lookup_str.c_str());
+ prefix_str.c_str(), lookup_str.c_str());
}
if (include_type_lookup) {
s->Printf("Try '%stype lookup %s' for information on types, methods, "
"functions, modules, etc.",
- prefix_str.c_str(), lookup_str.c_str());
+ prefix_str.c_str(), lookup_str.c_str());
}
}
CommandObjectHelp::CommandObjectHelp(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "help", "Show a list of all debugger "
- "commands, or give details "
- "about a specific command.",
+ : CommandObjectParsed(interpreter, "help",
+ "Show a list of all debugger "
+ "commands, or give details "
+ "about a specific command.",
"help [<cmd-name>]"),
m_options() {
CommandArgumentEntry arg;
diff --git a/lldb/source/Commands/CommandObjectLanguage.cpp b/lldb/source/Commands/CommandObjectLanguage.cpp
index 47c9e2a52023..35ce6e3193e8 100644
--- a/lldb/source/Commands/CommandObjectLanguage.cpp
+++ b/lldb/source/Commands/CommandObjectLanguage.cpp
@@ -8,12 +8,8 @@
#include "CommandObjectLanguage.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
-#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Target/Language.h"
#include "lldb/Target/LanguageRuntime.h"
using namespace lldb;
diff --git a/lldb/source/Commands/CommandObjectLanguage.h b/lldb/source/Commands/CommandObjectLanguage.h
index b86457c99af3..47079e219d03 100644
--- a/lldb/source/Commands/CommandObjectLanguage.h
+++ b/lldb/source/Commands/CommandObjectLanguage.h
@@ -9,10 +9,7 @@
#ifndef liblldb_CommandObjectLanguage_h_
#define liblldb_CommandObjectLanguage_h_
-
-
#include "lldb/Interpreter/CommandObjectMultiword.h"
-#include "lldb/lldb-types.h"
namespace lldb_private {
class CommandObjectLanguage : public CommandObjectMultiword {
diff --git a/lldb/source/Commands/CommandObjectLog.cpp b/lldb/source/Commands/CommandObjectLog.cpp
index 31a876c3430e..9bf0b30bc152 100644
--- a/lldb/source/Commands/CommandObjectLog.cpp
+++ b/lldb/source/Commands/CommandObjectLog.cpp
@@ -8,23 +8,13 @@
#include "CommandObjectLog.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/StreamFile.h"
#include "lldb/Host/OptionParser.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/Options.h"
-#include "lldb/Symbol/LineTable.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/SymbolFile.h"
-#include "lldb/Symbol/SymbolVendor.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/Target.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"
diff --git a/lldb/source/Commands/CommandObjectLog.h b/lldb/source/Commands/CommandObjectLog.h
index b2da900e21ed..eae41bf6b8d1 100644
--- a/lldb/source/Commands/CommandObjectLog.h
+++ b/lldb/source/Commands/CommandObjectLog.h
@@ -9,8 +9,6 @@
#ifndef liblldb_CommandObjectLog_h_
#define liblldb_CommandObjectLog_h_
-#include <map>
-#include <string>
#include "lldb/Interpreter/CommandObjectMultiword.h"
diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp
index 38bd3d179096..e497b5246b8d 100644
--- a/lldb/source/Commands/CommandObjectMemory.cpp
+++ b/lldb/source/Commands/CommandObjectMemory.cpp
@@ -7,15 +7,11 @@
//===----------------------------------------------------------------------===//
#include "CommandObjectMemory.h"
-#include "lldb/Core/Debugger.h"
#include "lldb/Core/DumpDataExtractor.h"
-#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/ValueObjectMemory.h"
-#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Host/OptionParser.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
@@ -38,7 +34,6 @@
#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/StreamString.h"
-#include "lldb/lldb-private.h"
#include <cinttypes>
#include <memory>
@@ -1440,8 +1435,7 @@ protected:
case eFormatBytes:
case eFormatHex:
case eFormatHexUppercase:
- case eFormatPointer:
- {
+ case eFormatPointer: {
// Decode hex bytes
// Be careful, getAsInteger with a radix of 16 rejects "0xab" so we
// have to special case that:
@@ -1597,13 +1591,14 @@ protected:
class CommandObjectMemoryHistory : public CommandObjectParsed {
public:
CommandObjectMemoryHistory(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "memory history", "Print recorded stack traces for "
- "allocation/deallocation events "
- "associated with an address.",
- nullptr,
- eCommandRequiresTarget | eCommandRequiresProcess |
- eCommandProcessMustBePaused | eCommandProcessMustBeLaunched) {
+ : CommandObjectParsed(interpreter, "memory history",
+ "Print recorded stack traces for "
+ "allocation/deallocation events "
+ "associated with an address.",
+ nullptr,
+ eCommandRequiresTarget | eCommandRequiresProcess |
+ eCommandProcessMustBePaused |
+ eCommandProcessMustBeLaunched) {
CommandArgumentEntry arg1;
CommandArgumentData addr_arg;
@@ -1730,15 +1725,12 @@ protected:
section_name = section_sp->GetName();
}
}
- result.AppendMessageWithFormat(
- "[0x%16.16" PRIx64 "-0x%16.16" PRIx64 ") %c%c%c%s%s%s%s\n",
+ result.AppendMessageWithFormatv(
+ "[{0:x16}-{1:x16}) {2:r}{3:w}{4:x}{5}{6}{7}{8}\n",
range_info.GetRange().GetRangeBase(),
- range_info.GetRange().GetRangeEnd(),
- range_info.GetReadable() ? 'r' : '-',
- range_info.GetWritable() ? 'w' : '-',
- range_info.GetExecutable() ? 'x' : '-',
- name ? " " : "", name.AsCString(""),
- section_name ? " " : "", section_name.AsCString(""));
+ range_info.GetRange().GetRangeEnd(), range_info.GetReadable(),
+ range_info.GetWritable(), range_info.GetExecutable(),
+ name ? " " : "", name, section_name ? " " : "", section_name);
m_prev_end_addr = range_info.GetRange().GetRangeEnd();
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
diff --git a/lldb/source/Commands/CommandObjectMultiword.cpp b/lldb/source/Commands/CommandObjectMultiword.cpp
index 03a3770d8df7..67225d3d6b8d 100644
--- a/lldb/source/Commands/CommandObjectMultiword.cpp
+++ b/lldb/source/Commands/CommandObjectMultiword.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "lldb/Interpreter/CommandObjectMultiword.h"
-#include "lldb/Core/Debugger.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/Options.h"
diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp
index fbd13aa37bda..10e6a4aa1793 100644
--- a/lldb/source/Commands/CommandObjectPlatform.cpp
+++ b/lldb/source/Commands/CommandObjectPlatform.cpp
@@ -6,7 +6,6 @@
//
//===----------------------------------------------------------------------===//
-#include <mutex>
#include "CommandObjectPlatform.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
@@ -22,10 +21,8 @@
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/Args.h"
-#include "lldb/Utility/DataExtractor.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/Threading.h"
using namespace lldb;
using namespace lldb_private;
@@ -1152,8 +1149,7 @@ protected:
class CommandOptions : public Options {
public:
CommandOptions()
- : Options(), match_info(), show_args(false), verbose(false) {
- }
+ : Options(), match_info(), show_args(false), verbose(false) {}
~CommandOptions() override = default;
@@ -1607,7 +1603,6 @@ public:
ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
m_options.NotifyOptionParsingStarting(&exe_ctx);
-
// Print out an usage syntax on an empty command line.
if (raw_command_line.empty()) {
result.GetOutputStream().Printf("%s\n", this->GetSyntax().str().c_str());
diff --git a/lldb/source/Commands/CommandObjectPlatform.h b/lldb/source/Commands/CommandObjectPlatform.h
index c94d2ea2cc4d..45e4a41c5b20 100644
--- a/lldb/source/Commands/CommandObjectPlatform.h
+++ b/lldb/source/Commands/CommandObjectPlatform.h
@@ -10,7 +10,6 @@
#define liblldb_CommandObjectPlatform_h_
#include "lldb/Interpreter/CommandObjectMultiword.h"
-#include "lldb/Interpreter/Options.h"
namespace lldb_private {
diff --git a/lldb/source/Commands/CommandObjectPlugin.cpp b/lldb/source/Commands/CommandObjectPlugin.cpp
index b70885061385..6fcb64f207b2 100644
--- a/lldb/source/Commands/CommandObjectPlugin.cpp
+++ b/lldb/source/Commands/CommandObjectPlugin.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "CommandObjectPlugin.h"
-#include "lldb/Host/Host.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
diff --git a/lldb/source/Commands/CommandObjectPlugin.h b/lldb/source/Commands/CommandObjectPlugin.h
index 0aabb1399407..94cea7db4111 100644
--- a/lldb/source/Commands/CommandObjectPlugin.h
+++ b/lldb/source/Commands/CommandObjectPlugin.h
@@ -9,10 +9,7 @@
#ifndef liblldb_CommandObjectPlugin_h_
#define liblldb_CommandObjectPlugin_h_
-
-
#include "lldb/Interpreter/CommandObjectMultiword.h"
-#include "lldb/lldb-types.h"
namespace lldb_private {
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index e5aa78afabb3..d825647728f8 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -12,7 +12,6 @@
#include "lldb/Breakpoint/BreakpointSite.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Host/Host.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -1014,10 +1013,10 @@ protected:
class CommandObjectProcessSignal : public CommandObjectParsed {
public:
CommandObjectProcessSignal(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "process signal",
- "Send a UNIX signal to the current target process.",
- nullptr, eCommandRequiresProcess |
- eCommandTryTargetAPILock) {
+ : CommandObjectParsed(
+ interpreter, "process signal",
+ "Send a UNIX signal to the current target process.", nullptr,
+ eCommandRequiresProcess | eCommandTryTargetAPILock) {
CommandArgumentEntry arg;
CommandArgumentData signal_arg;
@@ -1224,7 +1223,7 @@ public:
const uint32_t start_frame = 0;
const uint32_t num_frames = 1;
const uint32_t num_frames_with_source = 1;
- const bool stop_format = true;
+ const bool stop_format = true;
process->GetStatus(strm);
process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame,
num_frames, num_frames_with_source, stop_format);
diff --git a/lldb/source/Commands/CommandObjectRegister.cpp b/lldb/source/Commands/CommandObjectRegister.cpp
index 13266f8fce35..523b32a996b2 100644
--- a/lldb/source/Commands/CommandObjectRegister.cpp
+++ b/lldb/source/Commands/CommandObjectRegister.cpp
@@ -10,7 +10,6 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/DumpRegisterValue.h"
#include "lldb/Host/OptionParser.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionValueArray.h"
@@ -25,7 +24,6 @@
#include "lldb/Utility/Args.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/RegisterValue.h"
-#include "lldb/Utility/Scalar.h"
#include "llvm/Support/Errno.h"
using namespace lldb;
diff --git a/lldb/source/Commands/CommandObjectReproducer.cpp b/lldb/source/Commands/CommandObjectReproducer.cpp
index dc4579c20fc2..d15f622314d9 100644
--- a/lldb/source/Commands/CommandObjectReproducer.cpp
+++ b/lldb/source/Commands/CommandObjectReproducer.cpp
@@ -15,7 +15,8 @@
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
-#include "lldb/Interpreter/OptionGroupBoolean.h"
+
+#include <csignal>
using namespace lldb;
using namespace llvm;
@@ -68,7 +69,32 @@ static constexpr OptionEnumValues ReproducerProviderType() {
return OptionEnumValues(g_reproducer_provider_type);
}
-#define LLDB_OPTIONS_reproducer
+#define LLDB_OPTIONS_reproducer_dump
+#include "CommandOptions.inc"
+
+enum ReproducerCrashSignal {
+ eReproducerCrashSigill,
+ eReproducerCrashSigsegv,
+};
+
+static constexpr OptionEnumValueElement g_reproducer_signaltype[] = {
+ {
+ eReproducerCrashSigill,
+ "SIGILL",
+ "Illegal instruction",
+ },
+ {
+ eReproducerCrashSigsegv,
+ "SIGSEGV",
+ "Segmentation fault",
+ },
+};
+
+static constexpr OptionEnumValues ReproducerSignalType() {
+ return OptionEnumValues(g_reproducer_signaltype);
+}
+
+#define LLDB_OPTIONS_reproducer_xcrash
#include "CommandOptions.inc"
class CommandObjectReproducerGenerate : public CommandObjectParsed {
@@ -78,7 +104,7 @@ public:
interpreter, "reproducer generate",
"Generate reproducer on disk. When the debugger is in capture "
"mode, this command will output the reproducer to a directory on "
- "disk. In replay mode this command in a no-op.",
+ "disk and quit. In replay mode this command in a no-op.",
nullptr) {}
~CommandObjectReproducerGenerate() override = default;
@@ -95,7 +121,7 @@ protected:
if (auto generator = r.GetGenerator()) {
generator->Keep();
} else if (r.IsReplaying()) {
- // Make this operation a NOP in replay mode.
+ // Make this operation a NO-OP in replay mode.
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return result.Succeeded();
} else {
@@ -110,9 +136,94 @@ protected:
<< "Please have a look at the directory to assess if you're willing to "
"share the contained information.\n";
- result.SetStatus(eReturnStatusSuccessFinishResult);
+ m_interpreter.BroadcastEvent(
+ CommandInterpreter::eBroadcastBitQuitCommandReceived);
+ result.SetStatus(eReturnStatusQuit);
+ return result.Succeeded();
+ }
+};
+
+class CommandObjectReproducerXCrash : public CommandObjectParsed {
+public:
+ CommandObjectReproducerXCrash(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "reproducer xcrash",
+ "Intentionally force the debugger to crash in "
+ "order to trigger and test reproducer generation.",
+ nullptr) {}
+
+ ~CommandObjectReproducerXCrash() override = default;
+
+ Options *GetOptions() override { return &m_options; }
+
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options() {}
+
+ ~CommandOptions() override = default;
+
+ Status SetOptionValue(uint32_t option_idx, StringRef option_arg,
+ ExecutionContext *execution_context) override {
+ Status error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 's':
+ signal = (ReproducerCrashSignal)OptionArgParser::ToOptionEnum(
+ option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
+ if (!error.Success())
+ error.SetErrorStringWithFormat("unrecognized value for signal '%s'",
+ option_arg.str().c_str());
+ break;
+ default:
+ llvm_unreachable("Unimplemented option");
+ }
+
+ return error;
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ signal = eReproducerCrashSigsegv;
+ }
+
+ ArrayRef<OptionDefinition> GetDefinitions() override {
+ return makeArrayRef(g_reproducer_xcrash_options);
+ }
+
+ ReproducerCrashSignal signal = eReproducerCrashSigsegv;
+ };
+
+protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ if (!command.empty()) {
+ result.AppendErrorWithFormat("'%s' takes no arguments",
+ m_cmd_name.c_str());
+ return false;
+ }
+
+ auto &r = Reproducer::Instance();
+
+ if (!r.IsCapturing() && !r.IsReplaying()) {
+ result.SetError(
+ "forcing a crash is only supported when capturing a reproducer.");
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ return false;
+ }
+
+ switch (m_options.signal) {
+ case eReproducerCrashSigill:
+ std::raise(SIGILL);
+ break;
+ case eReproducerCrashSigsegv:
+ std::raise(SIGSEGV);
+ break;
+ }
+
+ result.SetStatus(eReturnStatusQuit);
return result.Succeeded();
}
+
+private:
+ CommandOptions m_options;
};
class CommandObjectReproducerStatus : public CommandObjectParsed {
@@ -120,7 +231,8 @@ public:
CommandObjectReproducerStatus(CommandInterpreter &interpreter)
: CommandObjectParsed(
interpreter, "reproducer status",
- "Show the current reproducer status. In capture mode the debugger "
+ "Show the current reproducer status. In capture mode the "
+ "debugger "
"is collecting all the information it needs to create a "
"reproducer. In replay mode the reproducer is replaying a "
"reproducer. When the reproducers are off, no data is collected "
@@ -206,7 +318,7 @@ public:
}
ArrayRef<OptionDefinition> GetDefinitions() override {
- return makeArrayRef(g_reproducer_options);
+ return makeArrayRef(g_reproducer_dump_options);
}
FileSpec file;
@@ -294,10 +406,9 @@ protected:
return true;
}
case eReproducerProviderCommands: {
- // Create a new command loader.
- std::unique_ptr<repro::CommandLoader> command_loader =
- repro::CommandLoader::Create(loader);
- if (!command_loader) {
+ std::unique_ptr<repro::MultiLoader<repro::CommandProvider>> multi_loader =
+ repro::MultiLoader<repro::CommandProvider>::Create(loader);
+ if (!multi_loader) {
SetError(result,
make_error<StringError>(llvm::inconvertibleErrorCode(),
"Unable to create command loader."));
@@ -305,9 +416,8 @@ protected:
}
// Iterate over the command files and dump them.
- while (true) {
- llvm::Optional<std::string> command_file =
- command_loader->GetNextFile();
+ llvm::Optional<std::string> command_file;
+ while ((command_file = multi_loader->GetNextFile())) {
if (!command_file)
break;
@@ -323,24 +433,29 @@ protected:
return true;
}
case eReproducerProviderGDB: {
- FileSpec gdb_file = loader->GetFile<ProcessGDBRemoteProvider::Info>();
- auto error_or_file = MemoryBuffer::getFile(gdb_file.GetPath());
- if (auto err = error_or_file.getError()) {
- SetError(result, errorCodeToError(err));
- return false;
- }
+ std::unique_ptr<repro::MultiLoader<repro::GDBRemoteProvider>>
+ multi_loader =
+ repro::MultiLoader<repro::GDBRemoteProvider>::Create(loader);
+ llvm::Optional<std::string> gdb_file;
+ while ((gdb_file = multi_loader->GetNextFile())) {
+ auto error_or_file = MemoryBuffer::getFile(*gdb_file);
+ if (auto err = error_or_file.getError()) {
+ SetError(result, errorCodeToError(err));
+ return false;
+ }
- std::vector<GDBRemotePacket> packets;
- yaml::Input yin((*error_or_file)->getBuffer());
- yin >> packets;
+ std::vector<GDBRemotePacket> packets;
+ yaml::Input yin((*error_or_file)->getBuffer());
+ yin >> packets;
- if (auto err = yin.error()) {
- SetError(result, errorCodeToError(err));
- return false;
- }
+ if (auto err = yin.error()) {
+ SetError(result, errorCodeToError(err));
+ return false;
+ }
- for (GDBRemotePacket &packet : packets) {
- packet.Dump(result.GetOutputStream());
+ for (GDBRemotePacket &packet : packets) {
+ packet.Dump(result.GetOutputStream());
+ }
}
result.SetStatus(eReturnStatusSuccessFinishResult);
@@ -363,7 +478,8 @@ CommandObjectReproducer::CommandObjectReproducer(
CommandInterpreter &interpreter)
: CommandObjectMultiword(
interpreter, "reproducer",
- "Commands for manipulating reproducers. Reproducers make it possible "
+ "Commands for manipulating reproducers. Reproducers make it "
+ "possible "
"to capture full debug sessions with all its dependencies. The "
"resulting reproducer is used to replay the debug session while "
"debugging the debugger.\n"
@@ -380,6 +496,8 @@ CommandObjectReproducer::CommandObjectReproducer(
new CommandObjectReproducerStatus(interpreter)));
LoadSubCommand("dump",
CommandObjectSP(new CommandObjectReproducerDump(interpreter)));
+ LoadSubCommand("xcrash", CommandObjectSP(
+ new CommandObjectReproducerXCrash(interpreter)));
}
CommandObjectReproducer::~CommandObjectReproducer() = default;
diff --git a/lldb/source/Commands/CommandObjectReproducer.h b/lldb/source/Commands/CommandObjectReproducer.h
index ad377241f814..8a85c21d6510 100644
--- a/lldb/source/Commands/CommandObjectReproducer.h
+++ b/lldb/source/Commands/CommandObjectReproducer.h
@@ -10,7 +10,6 @@
#define liblldb_CommandObjectReproducer_h_
#include "lldb/Interpreter/CommandObjectMultiword.h"
-#include "lldb/Interpreter/Options.h"
namespace lldb_private {
diff --git a/lldb/source/Commands/CommandObjectSettings.cpp b/lldb/source/Commands/CommandObjectSettings.cpp
index 248a04613d7a..95f79f45e22b 100644
--- a/lldb/source/Commands/CommandObjectSettings.cpp
+++ b/lldb/source/Commands/CommandObjectSettings.cpp
@@ -143,25 +143,24 @@ insert-before or insert-after.");
request, nullptr);
return;
}
- arg =
- request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex());
+ arg = request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex());
- if (!arg)
- return;
+ if (!arg)
+ return;
- // Complete option name
- if (arg[0] != '-')
- return;
+ // Complete option name
+ if (arg[0] != '-')
+ return;
- // Complete setting value
- const char *setting_var_name =
- request.GetParsedLine().GetArgumentAtIndex(setting_var_idx);
- Status error;
- lldb::OptionValueSP value_sp(GetDebugger().GetPropertyValue(
- &m_exe_ctx, setting_var_name, false, error));
- if (!value_sp)
- return;
- value_sp->AutoComplete(m_interpreter, request);
+ // Complete setting value
+ const char *setting_var_name =
+ request.GetParsedLine().GetArgumentAtIndex(setting_var_idx);
+ Status error;
+ lldb::OptionValueSP value_sp(GetDebugger().GetPropertyValue(
+ &m_exe_ctx, setting_var_name, false, error));
+ if (!value_sp)
+ return;
+ value_sp->AutoComplete(m_interpreter, request);
}
protected:
diff --git a/lldb/source/Commands/CommandObjectSettings.h b/lldb/source/Commands/CommandObjectSettings.h
index 730425953ea7..4db0ca1f83f8 100644
--- a/lldb/source/Commands/CommandObjectSettings.h
+++ b/lldb/source/Commands/CommandObjectSettings.h
@@ -9,9 +9,7 @@
#ifndef liblldb_CommandObjectSettings_h_
#define liblldb_CommandObjectSettings_h_
-#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
-#include "lldb/Interpreter/Options.h"
namespace lldb_private {
diff --git a/lldb/source/Commands/CommandObjectSource.cpp b/lldb/source/Commands/CommandObjectSource.cpp
index 78c8bc811926..19a554fb290a 100644
--- a/lldb/source/Commands/CommandObjectSource.cpp
+++ b/lldb/source/Commands/CommandObjectSource.cpp
@@ -14,18 +14,14 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/SourceManager.h"
#include "lldb/Host/OptionParser.h"
-#include "lldb/Interpreter/CommandCompletions.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
-#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
-#include "lldb/Target/TargetList.h"
#include "lldb/Utility/FileSpec.h"
using namespace lldb;
@@ -111,7 +107,7 @@ class CommandObjectSourceInfo : public CommandObjectParsed {
uint32_t start_line;
uint32_t end_line;
uint32_t num_lines;
- STLStringArray modules;
+ std::vector<std::string> modules;
};
public:
@@ -146,12 +142,6 @@ protected:
Target *target = m_exe_ctx.GetTargetPtr();
uint32_t num_matches = 0;
- bool has_path = false;
- if (file_spec) {
- assert(file_spec.GetFilename().AsCString());
- has_path = (file_spec.GetDirectory().AsCString() != nullptr);
- }
-
// Dump all the line entries for the file in the list.
ConstString last_module_file_name;
uint32_t num_scs = sc_list.GetSize();
@@ -168,9 +158,7 @@ protected:
if (module_list.GetSize() &&
module_list.GetIndexForModule(module) == LLDB_INVALID_INDEX32)
continue;
- if (file_spec &&
- !lldb_private::FileSpec::Equal(file_spec, line_entry.file,
- has_path))
+ if (!FileSpec::Match(file_spec, line_entry.file))
continue;
if (start_line > 0 && line_entry.line < start_line)
continue;
@@ -180,8 +168,7 @@ protected:
continue;
// Print a new header if the module changed.
- ConstString module_file_name =
- module->GetFileSpec().GetFilename();
+ ConstString module_file_name = module->GetFileSpec().GetFilename();
assert(module_file_name);
if (module_file_name != last_module_file_name) {
if (num_matches > 0)
@@ -227,8 +214,7 @@ protected:
// Dump all matching lines at or above start_line for the file in the
// CU.
ConstString file_spec_name = file_spec.GetFilename();
- ConstString module_file_name =
- module->GetFileSpec().GetFilename();
+ ConstString module_file_name = module->GetFileSpec().GetFilename();
bool cu_header_printed = false;
uint32_t line = start_line;
while (true) {
@@ -253,13 +239,13 @@ protected:
num_matches++;
if (num_lines > 0 && num_matches > num_lines)
break;
- assert(lldb_private::FileSpec::Equal(cu_file_spec, line_entry.file,
- has_path));
+ assert(cu_file_spec == line_entry.file);
if (!cu_header_printed) {
if (num_matches > 0)
strm << "\n\n";
strm << "Lines found for file " << file_spec_name
- << " in compilation unit " << cu->GetFilename() << " in `"
+ << " in compilation unit "
+ << cu->GetPrimaryFile().GetFilename() << " in `"
<< module_file_name << "\n";
cu_header_printed = true;
}
@@ -345,9 +331,8 @@ protected:
if (target->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) {
ModuleSP module_sp(so_addr.GetModule());
// Check to make sure this module is in our list.
- if (module_sp &&
- module_list.GetIndexForModule(module_sp.get()) !=
- LLDB_INVALID_INDEX32) {
+ if (module_sp && module_list.GetIndexForModule(module_sp.get()) !=
+ LLDB_INVALID_INDEX32) {
SymbolContext sc;
sc.Clear(true);
if (module_sp->ResolveSymbolContextForAddress(
@@ -401,8 +386,8 @@ protected:
// If we didn't find any functions with that name, try searching for
// symbols that line up exactly with function addresses.
SymbolContextList sc_list_symbols;
- module_list.FindFunctionSymbols(
- name, eFunctionNameTypeAuto, sc_list_symbols);
+ module_list.FindFunctionSymbols(name, eFunctionNameTypeAuto,
+ sc_list_symbols);
size_t num_symbol_matches = sc_list_symbols.GetSize();
for (size_t i = 0; i < num_symbol_matches; i++) {
SymbolContext sc;
@@ -712,7 +697,7 @@ class CommandObjectSourceList : public CommandObjectParsed {
lldb::addr_t address;
uint32_t start_line;
uint32_t num_lines;
- STLStringArray modules;
+ std::vector<std::string> modules;
bool show_bp_locs;
bool reverse;
};
@@ -875,7 +860,7 @@ protected:
// passed to the various ModuleList::Find* calls, which would either be a
// vector of string names or a ModuleSpecList.
void FindMatchingFunctions(Target *target, ConstString name,
- SymbolContextList &sc_list) {
+ SymbolContextList &sc_list) {
// Displaying the source for a symbol:
bool include_inlines = true;
bool include_symbols = false;
@@ -892,9 +877,9 @@ protected:
ModuleSpec module_spec(module_file_spec);
matching_modules.Clear();
target->GetImages().FindModules(module_spec, matching_modules);
- matching_modules.FindFunctions(
- name, eFunctionNameTypeAuto, include_symbols, include_inlines,
- sc_list);
+ matching_modules.FindFunctions(name, eFunctionNameTypeAuto,
+ include_symbols, include_inlines,
+ sc_list);
}
}
} else {
@@ -949,7 +934,7 @@ protected:
// symbols that line up exactly with function addresses.
SymbolContextList sc_list_symbols;
FindMatchingFunctionSymbols(target, name, sc_list_symbols);
- size_t num_symbol_matches =sc_list_symbols.GetSize();
+ size_t num_symbol_matches = sc_list_symbols.GetSize();
for (size_t i = 0; i < num_symbol_matches; i++) {
SymbolContext sc;
@@ -1081,7 +1066,8 @@ protected:
if (m_options.show_bp_locs) {
m_breakpoint_locations.Clear();
const bool show_inlines = true;
- m_breakpoint_locations.Reset(*sc.comp_unit, 0, show_inlines);
+ m_breakpoint_locations.Reset(sc.comp_unit->GetPrimaryFile(), 0,
+ show_inlines);
SearchFilterForUnconstrainedSearches target_search_filter(
target->shared_from_this());
target_search_filter.Search(m_breakpoint_locations);
@@ -1110,8 +1096,8 @@ protected:
? sc.line_entry.column
: 0;
target->GetSourceManager().DisplaySourceLinesWithLineNumbers(
- sc.comp_unit, sc.line_entry.line, column, lines_to_back_up,
- m_options.num_lines - lines_to_back_up, "->",
+ sc.comp_unit->GetPrimaryFile(), sc.line_entry.line, column,
+ lines_to_back_up, m_options.num_lines - lines_to_back_up, "->",
&result.GetOutputStream(), GetBreakpointLocations());
result.SetStatus(eReturnStatusSuccessFinishResult);
}
@@ -1194,18 +1180,18 @@ protected:
if (num_matches > 1) {
bool got_multiple = false;
- FileSpec *test_cu_spec = nullptr;
+ CompileUnit *test_cu = nullptr;
for (unsigned i = 0; i < num_matches; i++) {
SymbolContext sc;
sc_list.GetContextAtIndex(i, sc);
if (sc.comp_unit) {
- if (test_cu_spec) {
- if (test_cu_spec != static_cast<FileSpec *>(sc.comp_unit))
+ if (test_cu) {
+ if (test_cu != sc.comp_unit)
got_multiple = true;
break;
} else
- test_cu_spec = sc.comp_unit;
+ test_cu = sc.comp_unit;
}
}
if (got_multiple) {
@@ -1222,7 +1208,8 @@ protected:
if (sc.comp_unit) {
if (m_options.show_bp_locs) {
const bool show_inlines = true;
- m_breakpoint_locations.Reset(*sc.comp_unit, 0, show_inlines);
+ m_breakpoint_locations.Reset(sc.comp_unit->GetPrimaryFile(), 0,
+ show_inlines);
SearchFilterForUnconstrainedSearches target_search_filter(
target->shared_from_this());
target_search_filter.Search(m_breakpoint_locations);
@@ -1233,9 +1220,9 @@ protected:
m_options.num_lines = 10;
const uint32_t column = 0;
target->GetSourceManager().DisplaySourceLinesWithLineNumbers(
- sc.comp_unit, m_options.start_line, column,
- 0, m_options.num_lines,
- "", &result.GetOutputStream(), GetBreakpointLocations());
+ sc.comp_unit->GetPrimaryFile(), m_options.start_line, column, 0,
+ m_options.num_lines, "", &result.GetOutputStream(),
+ GetBreakpointLocations());
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
@@ -1265,10 +1252,11 @@ protected:
CommandObjectMultiwordSource::CommandObjectMultiwordSource(
CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "source", "Commands for examining "
- "source code described by "
- "debug information for the "
- "current target process.",
+ : CommandObjectMultiword(interpreter, "source",
+ "Commands for examining "
+ "source code described by "
+ "debug information for the "
+ "current target process.",
"source <subcommand> [<subcommand-options>]") {
LoadSubCommand("info",
CommandObjectSP(new CommandObjectSourceInfo(interpreter)));
diff --git a/lldb/source/Commands/CommandObjectSource.h b/lldb/source/Commands/CommandObjectSource.h
index d72122d55dc7..a4b8823a4fa9 100644
--- a/lldb/source/Commands/CommandObjectSource.h
+++ b/lldb/source/Commands/CommandObjectSource.h
@@ -10,8 +10,6 @@
#ifndef liblldb_CommandObjectSource_h_
#define liblldb_CommandObjectSource_h_
-#include "lldb/Core/STLUtils.h"
-#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
namespace lldb_private {
diff --git a/lldb/source/Commands/CommandObjectStats.cpp b/lldb/source/Commands/CommandObjectStats.cpp
index e3a1f9433662..eeec4a8d3e77 100644
--- a/lldb/source/Commands/CommandObjectStats.cpp
+++ b/lldb/source/Commands/CommandObjectStats.cpp
@@ -7,8 +7,6 @@
//===----------------------------------------------------------------------===//
#include "CommandObjectStats.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Target.h"
@@ -81,7 +79,8 @@ protected:
for (auto &stat : target.GetStatistics()) {
result.AppendMessageWithFormat(
"%s : %u\n",
- lldb_private::GetStatDescription(static_cast<lldb_private::StatisticKind>(i))
+ lldb_private::GetStatDescription(
+ static_cast<lldb_private::StatisticKind>(i))
.c_str(),
stat);
i += 1;
diff --git a/lldb/source/Commands/CommandObjectStats.h b/lldb/source/Commands/CommandObjectStats.h
index 27e9a6ff865a..593c4521e175 100644
--- a/lldb/source/Commands/CommandObjectStats.h
+++ b/lldb/source/Commands/CommandObjectStats.h
@@ -9,7 +9,6 @@
#ifndef liblldb_CommandObjectStats_h_
#define liblldb_CommandObjectStats_h_
-#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
namespace lldb_private {
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index abf7895a7384..8738e850c9f7 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -24,7 +24,6 @@
#include "lldb/Interpreter/OptionGroupBoolean.h"
#include "lldb/Interpreter/OptionGroupFile.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
-#include "lldb/Interpreter/OptionGroupPlatform.h"
#include "lldb/Interpreter/OptionGroupString.h"
#include "lldb/Interpreter/OptionGroupUInt64.h"
#include "lldb/Interpreter/OptionGroupUUID.h"
@@ -53,7 +52,6 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatAdapters.h"
-#include <cerrno>
using namespace lldb;
using namespace lldb_private;
@@ -78,7 +76,7 @@ static void DumpTargetInfo(uint32_t target_idx, Target *target,
uint32_t properties = 0;
if (target_arch.IsValid()) {
strm.Printf("%sarch=", properties++ > 0 ? ", " : " ( ");
- target_arch.DumpTriple(strm);
+ target_arch.DumpTriple(strm.AsRawOstream());
properties++;
}
PlatformSP platform_sp(target->GetPlatform());
@@ -107,11 +105,11 @@ static void DumpTargetInfo(uint32_t target_idx, Target *target,
const uint32_t start_frame = 0;
const uint32_t num_frames = 1;
const uint32_t num_frames_with_source = 1;
- const bool stop_format = false;
+ const bool stop_format = false;
process_sp->GetStatus(strm);
process_sp->GetThreadStatus(strm, only_threads_with_stop_reason,
- start_frame, num_frames,
- num_frames_with_source, stop_format);
+ start_frame, num_frames, num_frames_with_source,
+ stop_format);
}
}
@@ -398,8 +396,8 @@ protected:
debugger.GetTargetList().SetSelectedTarget(target_sp.get());
if (must_set_platform_path) {
ModuleSpec main_module_spec(file_spec);
- ModuleSP module_sp = target_sp->GetOrCreateModule(main_module_spec,
- true /* notify */);
+ ModuleSP module_sp =
+ target_sp->GetOrCreateModule(main_module_spec, true /* notify */);
if (module_sp)
module_sp->SetPlatformFileSpec(remote_file);
}
@@ -812,32 +810,28 @@ protected:
void DumpGlobalVariableList(const ExecutionContext &exe_ctx,
const SymbolContext &sc,
const VariableList &variable_list, Stream &s) {
- size_t count = variable_list.GetSize();
- if (count > 0) {
- if (sc.module_sp) {
- if (sc.comp_unit) {
- s.Printf("Global variables for %s in %s:\n",
- sc.comp_unit->GetPath().c_str(),
- sc.module_sp->GetFileSpec().GetPath().c_str());
- } else {
- s.Printf("Global variables for %s\n",
- sc.module_sp->GetFileSpec().GetPath().c_str());
- }
- } else if (sc.comp_unit) {
- s.Printf("Global variables for %s\n", sc.comp_unit->GetPath().c_str());
+ if (variable_list.Empty())
+ return;
+ if (sc.module_sp) {
+ if (sc.comp_unit) {
+ s.Format("Global variables for {0} in {1}:\n",
+ sc.comp_unit->GetPrimaryFile(), sc.module_sp->GetFileSpec());
+ } else {
+ s.Printf("Global variables for %s\n",
+ sc.module_sp->GetFileSpec().GetPath().c_str());
}
+ } else if (sc.comp_unit) {
+ s.Format("Global variables for {0}\n", sc.comp_unit->GetPrimaryFile());
+ }
- for (uint32_t i = 0; i < count; ++i) {
- VariableSP var_sp(variable_list.GetVariableAtIndex(i));
- if (var_sp) {
- ValueObjectSP valobj_sp(ValueObjectVariable::Create(
- exe_ctx.GetBestExecutionContextScope(), var_sp));
+ for (VariableSP var_sp : variable_list) {
+ if (!var_sp)
+ continue;
+ ValueObjectSP valobj_sp(ValueObjectVariable::Create(
+ exe_ctx.GetBestExecutionContextScope(), var_sp));
- if (valobj_sp)
- DumpValueObject(s, var_sp, valobj_sp,
- var_sp->GetName().GetCString());
- }
- }
+ if (valobj_sp)
+ DumpValueObject(s, var_sp, valobj_sp, var_sp->GetName().GetCString());
}
}
@@ -929,9 +923,9 @@ protected:
if (!success) {
if (frame) {
if (comp_unit)
- result.AppendErrorWithFormat(
- "no global variables in current compile unit: %s\n",
- comp_unit->GetPath().c_str());
+ result.AppendErrorWithFormatv(
+ "no global variables in current compile unit: {0}\n",
+ comp_unit->GetPrimaryFile());
else
result.AppendErrorWithFormat(
"no debug information for frame %u\n",
@@ -1295,7 +1289,7 @@ static void DumpModuleArchitecture(Stream &strm, Module *module,
StreamString arch_strm;
if (full_triple)
- module->GetArchitecture().DumpTriple(arch_strm);
+ module->GetArchitecture().DumpTriple(arch_strm.AsRawOstream());
else
arch_strm.PutCString(module->GetArchitecture().GetArchitectureName());
std::string arch_str = arch_strm.GetString();
@@ -1330,8 +1324,8 @@ static uint32_t DumpCompileUnitLineTable(CommandInterpreter &interpreter,
if (i > 0)
strm << "\n\n";
- strm << "Line table for " << *static_cast<FileSpec *>(sc.comp_unit)
- << " in `" << module->GetFileSpec().GetFilename() << "\n";
+ strm << "Line table for " << sc.comp_unit->GetPrimaryFile() << " in `"
+ << module->GetFileSpec().GetFilename() << "\n";
LineTable *line_table = sc.comp_unit->GetLineTable();
if (line_table)
line_table->GetDescription(
@@ -1353,7 +1347,7 @@ static void DumpFullpath(Stream &strm, const FileSpec *file_spec_ptr,
strm.Printf("%-*s", width, fullpath.c_str());
return;
} else {
- file_spec_ptr->Dump(&strm);
+ file_spec_ptr->Dump(strm.AsRawOstream());
return;
}
}
@@ -1420,12 +1414,13 @@ static size_t DumpModuleObjfileHeaders(Stream &strm, ModuleList &module_list) {
}
static void DumpModuleSymtab(CommandInterpreter &interpreter, Stream &strm,
- Module *module, SortOrder sort_order) {
+ Module *module, SortOrder sort_order,
+ Mangled::NamePreference name_preference) {
if (!module)
return;
if (Symtab *symtab = module->GetSymtab())
symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(),
- sort_order);
+ sort_order, name_preference);
}
static void DumpModuleSections(CommandInterpreter &interpreter, Stream &strm,
@@ -1970,6 +1965,11 @@ public:
const int short_option = m_getopt_table[option_idx].val;
switch (short_option) {
+ case 'm':
+ m_prefer_mangled.SetCurrentValue(true);
+ m_prefer_mangled.SetOptionWasSet();
+ break;
+
case 's':
m_sort_order = (SortOrder)OptionArgParser::ToOptionEnum(
option_arg, GetDefinitions()[option_idx].enum_values,
@@ -1984,6 +1984,7 @@ public:
void OptionParsingStarting(ExecutionContext *execution_context) override {
m_sort_order = eSortOrderNone;
+ m_prefer_mangled.Clear();
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@@ -1991,12 +1992,16 @@ public:
}
SortOrder m_sort_order;
+ OptionValueBoolean m_prefer_mangled = {false, false};
};
protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
Target *target = &GetSelectedTarget();
uint32_t num_dumped = 0;
+ Mangled::NamePreference name_preference =
+ (m_options.m_prefer_mangled ? Mangled::ePreferMangled
+ : Mangled::ePreferDemangled);
uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
result.GetOutputStream().SetAddressByteSize(addr_byte_size);
@@ -2022,7 +2027,7 @@ protected:
DumpModuleSymtab(
m_interpreter, result.GetOutputStream(),
target->GetImages().GetModulePointerAtIndexUnlocked(image_idx),
- m_options.m_sort_order);
+ m_options.m_sort_order, name_preference);
}
} else {
result.AppendError("the target has no associated executable images");
@@ -2050,7 +2055,7 @@ protected:
break;
num_dumped++;
DumpModuleSymtab(m_interpreter, result.GetOutputStream(), module,
- m_options.m_sort_order);
+ m_options.m_sort_order, name_preference);
}
}
} else
@@ -3139,18 +3144,17 @@ protected:
Address base_addr(objfile->GetBaseAddress());
if (base_addr.IsValid()) {
if (target && !target->GetSectionLoadList().IsEmpty()) {
- lldb::addr_t load_addr =
- base_addr.GetLoadAddress(target);
+ lldb::addr_t load_addr = base_addr.GetLoadAddress(target);
if (load_addr == LLDB_INVALID_ADDRESS) {
base_addr.Dump(&strm, target,
- Address::DumpStyleModuleWithFileAddress,
- Address::DumpStyleFileAddress);
+ Address::DumpStyleModuleWithFileAddress,
+ Address::DumpStyleFileAddress);
} else {
if (format_char == 'o') {
// Show the offset of slide for the image
- strm.Printf(
- "0x%*.*" PRIx64, addr_nibble_width, addr_nibble_width,
- load_addr - base_addr.GetFileAddress());
+ strm.Printf("0x%*.*" PRIx64, addr_nibble_width,
+ addr_nibble_width,
+ load_addr - base_addr.GetFileAddress());
} else {
// Show the load address of the image
strm.Printf("0x%*.*" PRIx64, addr_nibble_width,
@@ -3452,8 +3456,7 @@ protected:
}
UnwindPlanSP of_unwind_augmented_sp =
- func_unwinders_sp->GetObjectFileAugmentedUnwindPlan(*target,
- *thread);
+ func_unwinders_sp->GetObjectFileAugmentedUnwindPlan(*target, *thread);
if (of_unwind_augmented_sp) {
result.GetOutputStream().Printf("object file augmented UnwindPlan:\n");
of_unwind_augmented_sp->Dump(result.GetOutputStream(), thread.get(),
@@ -3751,7 +3754,7 @@ public:
break;
}
- return true;
+ return false;
}
bool LookupInModule(CommandInterpreter &interpreter, Module *module,
@@ -4035,169 +4038,165 @@ protected:
bool AddModuleSymbols(Target *target, ModuleSpec &module_spec, bool &flush,
CommandReturnObject &result) {
const FileSpec &symbol_fspec = module_spec.GetSymbolFileSpec();
- if (symbol_fspec) {
- char symfile_path[PATH_MAX];
- symbol_fspec.GetPath(symfile_path, sizeof(symfile_path));
+ if (!symbol_fspec) {
+ result.AppendError(
+ "one or more executable image paths must be specified");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
- if (!module_spec.GetUUID().IsValid()) {
- if (!module_spec.GetFileSpec() && !module_spec.GetPlatformFileSpec())
- module_spec.GetFileSpec().GetFilename() = symbol_fspec.GetFilename();
- }
- // We now have a module that represents a symbol file that can be used
- // for a module that might exist in the current target, so we need to
- // find that module in the target
- ModuleList matching_module_list;
-
- size_t num_matches = 0;
- // First extract all module specs from the symbol file
- lldb_private::ModuleSpecList symfile_module_specs;
- if (ObjectFile::GetModuleSpecifications(module_spec.GetSymbolFileSpec(),
- 0, 0, symfile_module_specs)) {
- // Now extract the module spec that matches the target architecture
- ModuleSpec target_arch_module_spec;
- ModuleSpec symfile_module_spec;
- target_arch_module_spec.GetArchitecture() = target->GetArchitecture();
- if (symfile_module_specs.FindMatchingModuleSpec(target_arch_module_spec,
- symfile_module_spec)) {
- // See if it has a UUID?
- if (symfile_module_spec.GetUUID().IsValid()) {
- // It has a UUID, look for this UUID in the target modules
- ModuleSpec symfile_uuid_module_spec;
- symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID();
- target->GetImages().FindModules(symfile_uuid_module_spec,
- matching_module_list);
- num_matches = matching_module_list.GetSize();
- }
+ char symfile_path[PATH_MAX];
+ symbol_fspec.GetPath(symfile_path, sizeof(symfile_path));
+
+ if (!module_spec.GetUUID().IsValid()) {
+ if (!module_spec.GetFileSpec() && !module_spec.GetPlatformFileSpec())
+ module_spec.GetFileSpec().GetFilename() = symbol_fspec.GetFilename();
+ }
+
+ // We now have a module that represents a symbol file that can be used
+ // for a module that might exist in the current target, so we need to
+ // find that module in the target
+ ModuleList matching_module_list;
+
+ size_t num_matches = 0;
+ // First extract all module specs from the symbol file
+ lldb_private::ModuleSpecList symfile_module_specs;
+ if (ObjectFile::GetModuleSpecifications(module_spec.GetSymbolFileSpec(),
+ 0, 0, symfile_module_specs)) {
+ // Now extract the module spec that matches the target architecture
+ ModuleSpec target_arch_module_spec;
+ ModuleSpec symfile_module_spec;
+ target_arch_module_spec.GetArchitecture() = target->GetArchitecture();
+ if (symfile_module_specs.FindMatchingModuleSpec(target_arch_module_spec,
+ symfile_module_spec)) {
+ // See if it has a UUID?
+ if (symfile_module_spec.GetUUID().IsValid()) {
+ // It has a UUID, look for this UUID in the target modules
+ ModuleSpec symfile_uuid_module_spec;
+ symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID();
+ target->GetImages().FindModules(symfile_uuid_module_spec,
+ matching_module_list);
+ num_matches = matching_module_list.GetSize();
}
+ }
- if (num_matches == 0) {
- // No matches yet, iterate through the module specs to find a UUID
- // value that we can match up to an image in our target
- const size_t num_symfile_module_specs =
- symfile_module_specs.GetSize();
- for (size_t i = 0; i < num_symfile_module_specs && num_matches == 0;
- ++i) {
- if (symfile_module_specs.GetModuleSpecAtIndex(
- i, symfile_module_spec)) {
- if (symfile_module_spec.GetUUID().IsValid()) {
- // It has a UUID, look for this UUID in the target modules
- ModuleSpec symfile_uuid_module_spec;
- symfile_uuid_module_spec.GetUUID() =
- symfile_module_spec.GetUUID();
- target->GetImages().FindModules(symfile_uuid_module_spec,
- matching_module_list);
- num_matches = matching_module_list.GetSize();
- }
+ if (num_matches == 0) {
+ // No matches yet, iterate through the module specs to find a UUID
+ // value that we can match up to an image in our target
+ const size_t num_symfile_module_specs =
+ symfile_module_specs.GetSize();
+ for (size_t i = 0; i < num_symfile_module_specs && num_matches == 0;
+ ++i) {
+ if (symfile_module_specs.GetModuleSpecAtIndex(
+ i, symfile_module_spec)) {
+ if (symfile_module_spec.GetUUID().IsValid()) {
+ // It has a UUID, look for this UUID in the target modules
+ ModuleSpec symfile_uuid_module_spec;
+ symfile_uuid_module_spec.GetUUID() =
+ symfile_module_spec.GetUUID();
+ target->GetImages().FindModules(symfile_uuid_module_spec,
+ matching_module_list);
+ num_matches = matching_module_list.GetSize();
}
}
}
}
+ }
- // Just try to match up the file by basename if we have no matches at
- // this point
- if (num_matches == 0) {
- target->GetImages().FindModules(module_spec, matching_module_list);
- num_matches = matching_module_list.GetSize();
- }
+ // Just try to match up the file by basename if we have no matches at
+ // this point
+ if (num_matches == 0) {
+ target->GetImages().FindModules(module_spec, matching_module_list);
+ num_matches = matching_module_list.GetSize();
+ }
- while (num_matches == 0) {
- ConstString filename_no_extension(
- module_spec.GetFileSpec().GetFileNameStrippingExtension());
- // Empty string returned, lets bail
- if (!filename_no_extension)
- break;
+ while (num_matches == 0) {
+ ConstString filename_no_extension(
+ module_spec.GetFileSpec().GetFileNameStrippingExtension());
+ // Empty string returned, let's bail
+ if (!filename_no_extension)
+ break;
- // Check if there was no extension to strip and the basename is the
- // same
- if (filename_no_extension == module_spec.GetFileSpec().GetFilename())
- break;
+ // Check if there was no extension to strip and the basename is the same
+ if (filename_no_extension == module_spec.GetFileSpec().GetFilename())
+ break;
- // Replace basename with one less extension
- module_spec.GetFileSpec().GetFilename() = filename_no_extension;
+ // Replace basename with one fewer extension
+ module_spec.GetFileSpec().GetFilename() = filename_no_extension;
+ target->GetImages().FindModules(module_spec, matching_module_list);
+ num_matches = matching_module_list.GetSize();
+ }
- target->GetImages().FindModules(module_spec, matching_module_list);
- num_matches = matching_module_list.GetSize();
- }
+ if (num_matches > 1) {
+ result.AppendErrorWithFormat("multiple modules match symbol file '%s', "
+ "use the --uuid option to resolve the "
+ "ambiguity.\n",
+ symfile_path);
+ } else if (num_matches == 1) {
+ ModuleSP module_sp(matching_module_list.GetModuleAtIndex(0));
+
+ // The module has not yet created its symbol vendor, we can just give
+ // the existing target module the symfile path to use for when it
+ // decides to create it!
+ module_sp->SetSymbolFileFileSpec(symbol_fspec);
+
+ SymbolFile *symbol_file =
+ module_sp->GetSymbolFile(true, &result.GetErrorStream());
+ if (symbol_file) {
+ ObjectFile *object_file = symbol_file->GetObjectFile();
+
+ if (object_file && object_file->GetFileSpec() == symbol_fspec) {
+ // Provide feedback that the symfile has been successfully added.
+ const FileSpec &module_fs = module_sp->GetFileSpec();
+ result.AppendMessageWithFormat(
+ "symbol file '%s' has been added to '%s'\n", symfile_path,
+ module_fs.GetPath().c_str());
- if (num_matches > 1) {
- result.AppendErrorWithFormat("multiple modules match symbol file '%s', "
- "use the --uuid option to resolve the "
- "ambiguity.\n",
- symfile_path);
- } else if (num_matches == 1) {
- ModuleSP module_sp(matching_module_list.GetModuleAtIndex(0));
-
- // The module has not yet created its symbol vendor, we can just give
- // the existing target module the symfile path to use for when it
- // decides to create it!
- module_sp->SetSymbolFileFileSpec(symbol_fspec);
-
- SymbolFile *symbol_file =
- module_sp->GetSymbolFile(true, &result.GetErrorStream());
- if (symbol_file) {
- ObjectFile *object_file = symbol_file->GetObjectFile();
-
- if (object_file && object_file->GetFileSpec() == symbol_fspec) {
- // Provide feedback that the symfile has been successfully added.
- const FileSpec &module_fs = module_sp->GetFileSpec();
- result.AppendMessageWithFormat(
- "symbol file '%s' has been added to '%s'\n", symfile_path,
- module_fs.GetPath().c_str());
-
- // Let clients know something changed in the module if it is
- // currently loaded
- ModuleList module_list;
- module_list.Append(module_sp);
- target->SymbolsDidLoad(module_list);
-
- // Make sure we load any scripting resources that may be embedded
- // in the debug info files in case the platform supports that.
- Status error;
- StreamString feedback_stream;
- module_sp->LoadScriptingResourceInTarget(target, error,
- &feedback_stream);
- if (error.Fail() && error.AsCString())
- result.AppendWarningWithFormat(
- "unable to load scripting data for module %s - error "
- "reported was %s",
- module_sp->GetFileSpec()
- .GetFileNameStrippingExtension()
- .GetCString(),
- error.AsCString());
- else if (feedback_stream.GetSize())
- result.AppendWarningWithFormat("%s", feedback_stream.GetData());
+ // Let clients know something changed in the module if it is
+ // currently loaded
+ ModuleList module_list;
+ module_list.Append(module_sp);
+ target->SymbolsDidLoad(module_list);
- flush = true;
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
+ // Make sure we load any scripting resources that may be embedded
+ // in the debug info files in case the platform supports that.
+ Status error;
+ StreamString feedback_stream;
+ module_sp->LoadScriptingResourceInTarget(target, error,
+ &feedback_stream);
+ if (error.Fail() && error.AsCString())
+ result.AppendWarningWithFormat(
+ "unable to load scripting data for module %s - error "
+ "reported was %s",
+ module_sp->GetFileSpec()
+ .GetFileNameStrippingExtension()
+ .GetCString(),
+ error.AsCString());
+ else if (feedback_stream.GetSize())
+ result.AppendWarningWithFormat("%s", feedback_stream.GetData());
+
+ flush = true;
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
}
- // Clear the symbol file spec if anything went wrong
- module_sp->SetSymbolFileFileSpec(FileSpec());
}
+ // Clear the symbol file spec if anything went wrong
+ module_sp->SetSymbolFileFileSpec(FileSpec());
+ }
- namespace fs = llvm::sys::fs;
- if (module_spec.GetUUID().IsValid()) {
- StreamString ss_symfile_uuid;
- module_spec.GetUUID().Dump(&ss_symfile_uuid);
- result.AppendErrorWithFormat(
- "symbol file '%s' (%s) does not match any existing module%s\n",
- symfile_path, ss_symfile_uuid.GetData(),
- !fs::is_regular_file(symbol_fspec.GetPath())
- ? "\n please specify the full path to the symbol file"
- : "");
- } else {
- result.AppendErrorWithFormat(
- "symbol file '%s' does not match any existing module%s\n",
- symfile_path,
- !fs::is_regular_file(symbol_fspec.GetPath())
- ? "\n please specify the full path to the symbol file"
- : "");
- }
- } else {
- result.AppendError(
- "one or more executable image paths must be specified");
+ namespace fs = llvm::sys::fs;
+ StreamString ss_symfile_uuid;
+ if (module_spec.GetUUID().IsValid()) {
+ ss_symfile_uuid << " (";
+ module_spec.GetUUID().Dump(&ss_symfile_uuid);
+ ss_symfile_uuid << ')';
}
+ result.AppendErrorWithFormat(
+ "symbol file '%s'%s does not match any existing module%s\n",
+ symfile_path, ss_symfile_uuid.GetData(),
+ !fs::is_regular_file(symbol_fspec.GetPath())
+ ? "\n please specify the full path to the symbol file"
+ : "");
result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4450,8 +4449,7 @@ public:
error.SetErrorStringWithFormat(
"invalid boolean value '%s' passed for -G option",
option_arg.str().c_str());
- }
- break;
+ } break;
case 'l':
if (option_arg.getAsInteger(0, m_line_start)) {
error.SetErrorStringWithFormat("invalid start line number: \"%s\"",
@@ -4655,48 +4653,43 @@ protected:
}
}
- if (specifier_up)
- new_hook_sp->SetSpecifier(specifier_up.release());
+ if (specifier_up)
+ new_hook_sp->SetSpecifier(specifier_up.release());
- // Next see if any of the thread options have been entered:
+ // Next see if any of the thread options have been entered:
- if (m_options.m_thread_specified) {
- ThreadSpec *thread_spec = new ThreadSpec();
+ if (m_options.m_thread_specified) {
+ ThreadSpec *thread_spec = new ThreadSpec();
- if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) {
- thread_spec->SetTID(m_options.m_thread_id);
- }
+ if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) {
+ thread_spec->SetTID(m_options.m_thread_id);
+ }
- if (m_options.m_thread_index != UINT32_MAX)
- thread_spec->SetIndex(m_options.m_thread_index);
+ if (m_options.m_thread_index != UINT32_MAX)
+ thread_spec->SetIndex(m_options.m_thread_index);
- if (!m_options.m_thread_name.empty())
- thread_spec->SetName(m_options.m_thread_name.c_str());
+ if (!m_options.m_thread_name.empty())
+ thread_spec->SetName(m_options.m_thread_name.c_str());
- if (!m_options.m_queue_name.empty())
- thread_spec->SetQueueName(m_options.m_queue_name.c_str());
+ if (!m_options.m_queue_name.empty())
+ thread_spec->SetQueueName(m_options.m_queue_name.c_str());
- new_hook_sp->SetThreadSpecifier(thread_spec);
- }
-
- new_hook_sp->SetAutoContinue(m_options.m_auto_continue);
- if (m_options.m_use_one_liner) {
- // Use one-liners.
- for (auto cmd : m_options.m_one_liner)
- new_hook_sp->GetCommandPointer()->AppendString(
- cmd.c_str());
- result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n",
- new_hook_sp->GetID());
- } else {
- m_stop_hook_sp = new_hook_sp;
- m_interpreter.GetLLDBCommandsFromIOHandler(
- "> ", // Prompt
- *this, // IOHandlerDelegate
- true, // Run IOHandler in async mode
- nullptr); // Baton for the "io_handler" that will be passed back
- // into our IOHandlerDelegate functions
- }
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ new_hook_sp->SetThreadSpecifier(thread_spec);
+ }
+
+ new_hook_sp->SetAutoContinue(m_options.m_auto_continue);
+ if (m_options.m_use_one_liner) {
+ // Use one-liners.
+ for (auto cmd : m_options.m_one_liner)
+ new_hook_sp->GetCommandPointer()->AppendString(cmd.c_str());
+ result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n",
+ new_hook_sp->GetID());
+ } else {
+ m_stop_hook_sp = new_hook_sp;
+ m_interpreter.GetLLDBCommandsFromIOHandler("> ", // Prompt
+ *this); // IOHandlerDelegate
+ }
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
return result.Succeeded();
}
@@ -4751,7 +4744,7 @@ protected:
}
}
}
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
return result.Succeeded();
}
};
@@ -4798,7 +4791,7 @@ protected:
}
}
}
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
return result.Succeeded();
}
diff --git a/lldb/source/Commands/CommandObjectTarget.h b/lldb/source/Commands/CommandObjectTarget.h
index 86d554c8a310..bf1dae6bfdc1 100644
--- a/lldb/source/Commands/CommandObjectTarget.h
+++ b/lldb/source/Commands/CommandObjectTarget.h
@@ -10,7 +10,6 @@
#define liblldb_CommandObjectTarget_h_
#include "lldb/Interpreter/CommandObjectMultiword.h"
-#include "lldb/Interpreter/Options.h"
namespace lldb_private {
diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp
index 8c5274553902..83c7cb50d142 100644
--- a/lldb/source/Commands/CommandObjectThread.cpp
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -8,9 +8,7 @@
#include "CommandObjectThread.h"
-#include "lldb/Core/SourceManager.h"
#include "lldb/Core/ValueObject.h"
-#include "lldb/Host/Host.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -29,11 +27,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanStepInRange.h"
-#include "lldb/Target/ThreadPlanStepInstruction.h"
-#include "lldb/Target/ThreadPlanStepOut.h"
-#include "lldb/Target/ThreadPlanStepRange.h"
#include "lldb/Utility/State.h"
-#include "lldb/lldb-private.h"
using namespace lldb;
using namespace lldb_private;
@@ -339,8 +333,7 @@ protected:
const bool stop_format = false;
if (ext_thread_sp->GetStatus(strm, m_options.m_start,
m_options.m_count,
- num_frames_with_source,
- stop_format)) {
+ num_frames_with_source, stop_format)) {
DoExtendedBacktrace(ext_thread_sp.get(), result);
}
}
@@ -393,7 +386,7 @@ static constexpr OptionEnumValueElement g_tri_running_mode[] = {
{eOnlyThisThread, "this-thread", "Run only this thread"},
{eAllThreads, "all-threads", "Run all threads"},
{eOnlyDuringStepping, "while-stepping",
- "Run only this thread while stepping"} };
+ "Run only this thread while stepping"}};
static constexpr OptionEnumValues TriRunningModes() {
return OptionEnumValues(g_tri_running_mode);
@@ -419,8 +412,8 @@ public:
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
ExecutionContext *execution_context) override {
Status error;
- const int short_option
- = g_thread_step_scope_options[option_idx].short_option;
+ const int short_option =
+ g_thread_step_scope_options[option_idx].short_option;
switch (short_option) {
case 'a': {
@@ -428,11 +421,10 @@ public:
bool avoid_no_debug =
OptionArgParser::ToBoolean(option_arg, true, &success);
if (!success)
- error.SetErrorStringWithFormat(
- "invalid boolean value for option '%c'", short_option);
+ error.SetErrorStringWithFormat("invalid boolean value for option '%c'",
+ short_option);
else {
- m_step_in_avoid_no_debug =
- avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
+ m_step_in_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
}
} break;
@@ -441,11 +433,10 @@ public:
bool avoid_no_debug =
OptionArgParser::ToBoolean(option_arg, true, &success);
if (!success)
- error.SetErrorStringWithFormat(
- "invalid boolean value for option '%c'", short_option);
+ error.SetErrorStringWithFormat("invalid boolean value for option '%c'",
+ short_option);
else {
- m_step_out_avoid_no_debug =
- avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
+ m_step_out_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
}
} break;
@@ -518,7 +509,6 @@ public:
class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed {
public:
-
CommandObjectThreadStepWithTypeAndScope(CommandInterpreter &interpreter,
const char *name, const char *help,
const char *syntax,
@@ -530,7 +520,7 @@ public:
eCommandProcessMustBeLaunched |
eCommandProcessMustBePaused),
m_step_type(step_type), m_step_scope(step_scope), m_options(),
- m_class_options("scripted step", 'C') {
+ m_class_options("scripted step") {
CommandArgumentEntry arg;
CommandArgumentData thread_id_arg;
@@ -544,9 +534,10 @@ public:
// Push the data for the first argument into the m_arguments vector.
m_arguments.push_back(arg);
-
+
if (step_type == eStepTypeScripted) {
- m_all_options.Append(&m_class_options, LLDB_OPT_SET_1, LLDB_OPT_SET_1);
+ m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
+ LLDB_OPT_SET_1);
}
m_all_options.Append(&m_options);
m_all_options.Finalize();
@@ -554,9 +545,7 @@ public:
~CommandObjectThreadStepWithTypeAndScope() override = default;
- Options *GetOptions() override {
- return &m_all_options;
- }
+ Options *GetOptions() override { return &m_all_options; }
protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
@@ -596,15 +585,15 @@ protected:
}
if (m_step_type == eStepTypeScripted) {
- if (m_class_options.GetClassName().empty()) {
+ if (m_class_options.GetName().empty()) {
result.AppendErrorWithFormat("empty class name for scripted step.");
result.SetStatus(eReturnStatusFailed);
return false;
} else if (!GetDebugger().GetScriptInterpreter()->CheckObjectExists(
- m_class_options.GetClassName().c_str())) {
+ m_class_options.GetName().c_str())) {
result.AppendErrorWithFormat(
"class for scripted step: \"%s\" does not exist.",
- m_class_options.GetClassName().c_str());
+ m_class_options.GetName().c_str());
result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -720,9 +709,9 @@ protected:
m_options.m_step_out_avoid_no_debug);
} else if (m_step_type == eStepTypeScripted) {
new_plan_sp = thread->QueueThreadPlanForStepScripted(
- abort_other_plans, m_class_options.GetClassName().c_str(),
- m_class_options.GetStructuredData(),
- bool_stop_other_threads, new_plan_status);
+ abort_other_plans, m_class_options.GetName().c_str(),
+ m_class_options.GetStructuredData(), bool_stop_other_threads,
+ new_plan_status);
} else {
result.AppendError("step type is not supported");
result.SetStatus(eReturnStatusFailed);
@@ -969,7 +958,7 @@ public:
static constexpr OptionEnumValueElement g_duo_running_mode[] = {
{eOnlyThisThread, "this-thread", "Run only this thread"},
- {eAllThreads, "all-threads", "Run all threads"} };
+ {eAllThreads, "all-threads", "Run all threads"}};
static constexpr OptionEnumValues DuoRunningModes() {
return OptionEnumValues(g_duo_running_mode);
@@ -1063,7 +1052,8 @@ public:
"Continue until a line number or address is reached by the "
"current or specified thread. Stops when returning from "
"the current function as a safety measure. "
- "The target line number(s) are given as arguments, and if more than one"
+ "The target line number(s) are given as arguments, and if more "
+ "than one"
" is provided, stepping will stop when the first one is hit.",
nullptr,
eCommandRequiresThread | eCommandTryTargetAPILock |
@@ -1197,7 +1187,7 @@ protected:
LineEntry line_entry;
const bool exact = false;
start_idx_ptr = sc.comp_unit->FindLineEntry(
- start_idx_ptr, line_number, sc.comp_unit, exact, &line_entry);
+ start_idx_ptr, line_number, nullptr, exact, &line_entry);
if (start_idx_ptr == UINT32_MAX)
break;
@@ -1430,9 +1420,10 @@ public:
CommandObjectThreadInfo(CommandInterpreter &interpreter)
: CommandObjectIterateOverThreads(
- interpreter, "thread info", "Show an extended summary of one or "
- "more threads. Defaults to the "
- "current thread.",
+ interpreter, "thread info",
+ "Show an extended summary of one or "
+ "more threads. Defaults to the "
+ "current thread.",
"thread info",
eCommandRequiresProcess | eCommandTryTargetAPILock |
eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
@@ -1474,7 +1465,7 @@ public:
// CommandObjectThreadException
class CommandObjectThreadException : public CommandObjectIterateOverThreads {
- public:
+public:
CommandObjectThreadException(CommandInterpreter &interpreter)
: CommandObjectIterateOverThreads(
interpreter, "thread exception",
@@ -2006,9 +1997,10 @@ public:
CommandObjectMultiwordThread::CommandObjectMultiwordThread(
CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "thread", "Commands for operating on "
- "one or more threads in "
- "the current process.",
+ : CommandObjectMultiword(interpreter, "thread",
+ "Commands for operating on "
+ "one or more threads in "
+ "the current process.",
"thread <subcommand> [<subcommand-options>]") {
LoadSubCommand("backtrace", CommandObjectSP(new CommandObjectThreadBacktrace(
interpreter)));
@@ -2026,9 +2018,8 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread(
CommandObjectSP(new CommandObjectThreadUntil(interpreter)));
LoadSubCommand("info",
CommandObjectSP(new CommandObjectThreadInfo(interpreter)));
- LoadSubCommand(
- "exception",
- CommandObjectSP(new CommandObjectThreadException(interpreter)));
+ LoadSubCommand("exception", CommandObjectSP(new CommandObjectThreadException(
+ interpreter)));
LoadSubCommand("step-in",
CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
interpreter, "thread step-in",
diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp
index 5e31fd5e8bce..87c107cfb943 100644
--- a/lldb/source/Commands/CommandObjectType.cpp
+++ b/lldb/source/Commands/CommandObjectType.cpp
@@ -11,6 +11,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/DataFormatters/DataVisualization.h"
+#include "lldb/Host/Config.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
@@ -23,20 +24,16 @@
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/Language.h"
-#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
-#include "lldb/Target/ThreadList.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/RegularExpression.h"
-#include "lldb/Utility/State.h"
#include "lldb/Utility/StringList.h"
#include "llvm/ADT/STLExtras.h"
#include <algorithm>
-#include <cctype>
#include <functional>
#include <memory>
@@ -162,7 +159,7 @@ public:
std::string &data) override {
StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
-#ifndef LLDB_DISABLE_PYTHON
+#if LLDB_ENABLE_PYTHON
ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
if (interpreter) {
StringList lines;
@@ -255,7 +252,7 @@ public:
"error: script interpreter missing, didn't add python command.\n");
error_sp->Flush();
}
-#endif // LLDB_DISABLE_PYTHON
+#endif
io_handler.SetIsDone(true);
}
@@ -394,7 +391,7 @@ protected:
std::string &data) override {
StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
-#ifndef LLDB_DISABLE_PYTHON
+#if LLDB_ENABLE_PYTHON
ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
if (interpreter) {
StringList lines;
@@ -474,7 +471,7 @@ protected:
error_sp->Flush();
}
-#endif // LLDB_DISABLE_PYTHON
+#endif
io_handler.SetIsDone(true);
}
@@ -1059,8 +1056,9 @@ protected:
bool any_printed = false;
- auto category_closure = [&result, &formatter_regex, &any_printed](
- const lldb::TypeCategoryImplSP &category) -> void {
+ auto category_closure =
+ [&result, &formatter_regex,
+ &any_printed](const lldb::TypeCategoryImplSP &category) -> void {
result.GetOutputStream().Printf(
"-----------------------\nCategory: %s%s\n-----------------------\n",
category->GetName(), category->IsEnabled() ? "" : " (disabled)");
@@ -1166,12 +1164,6 @@ public:
"Show a list of current formats.") {}
};
-#ifndef LLDB_DISABLE_PYTHON
-
-// CommandObjectTypeSummaryAdd
-
-#endif // LLDB_DISABLE_PYTHON
-
Status CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue(
uint32_t option_idx, llvm::StringRef option_arg,
ExecutionContext *execution_context) {
@@ -1254,7 +1246,7 @@ void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting(
m_category = "default";
}
-#ifndef LLDB_DISABLE_PYTHON
+#if LLDB_ENABLE_PYTHON
bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
Args &command, CommandReturnObject &result) {
@@ -1340,7 +1332,6 @@ bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
m_interpreter.GetPythonCommandsFromIOHandler(
" ", // Prompt
*this, // IOHandlerDelegate
- true, // Run IOHandler in async mode
options); // Baton for the "io_handler" that will be passed back into
// our IOHandlerDelegate functions
result.SetStatus(eReturnStatusSuccessFinishNoResult);
@@ -1379,7 +1370,7 @@ bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
return result.Succeeded();
}
-#endif // LLDB_DISABLE_PYTHON
+#endif
bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
Args &command, CommandReturnObject &result) {
@@ -1577,13 +1568,13 @@ bool CommandObjectTypeSummaryAdd::DoExecute(Args &command,
WarnOnPotentialUnquotedUnsignedType(command, result);
if (m_options.m_is_add_script) {
-#ifndef LLDB_DISABLE_PYTHON
+#if LLDB_ENABLE_PYTHON
return Execute_ScriptSummary(command, result);
#else
result.AppendError("python is disabled");
result.SetStatus(eReturnStatusFailed);
return false;
-#endif // LLDB_DISABLE_PYTHON
+#endif
}
return Execute_StringSummary(command, result);
@@ -2151,7 +2142,7 @@ public:
"Show a list of current filters.") {}
};
-#ifndef LLDB_DISABLE_PYTHON
+#if LLDB_ENABLE_PYTHON
// CommandObjectTypeSynthList
@@ -2164,7 +2155,7 @@ public:
"Show a list of current synthetic providers.") {}
};
-#endif // LLDB_DISABLE_PYTHON
+#endif
// CommandObjectTypeFilterDelete
@@ -2179,7 +2170,7 @@ public:
~CommandObjectTypeFilterDelete() override = default;
};
-#ifndef LLDB_DISABLE_PYTHON
+#if LLDB_ENABLE_PYTHON
// CommandObjectTypeSynthDelete
@@ -2195,7 +2186,7 @@ public:
~CommandObjectTypeSynthDelete() override = default;
};
-#endif // LLDB_DISABLE_PYTHON
+#endif
// CommandObjectTypeFilterClear
@@ -2208,7 +2199,7 @@ public:
"type filter clear", "Delete all existing filter.") {}
};
-#ifndef LLDB_DISABLE_PYTHON
+#if LLDB_ENABLE_PYTHON
// CommandObjectTypeSynthClear
class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear {
@@ -2240,7 +2231,6 @@ bool CommandObjectTypeSynthAdd::Execute_HandwritePython(
m_interpreter.GetPythonCommandsFromIOHandler(
" ", // Prompt
*this, // IOHandlerDelegate
- true, // Run IOHandler in async mode
options); // Baton for the "io_handler" that will be passed back into our
// IOHandlerDelegate functions
result.SetStatus(eReturnStatusSuccessFinishNoResult);
@@ -2343,9 +2333,9 @@ bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
type = eRegexSynth;
}
- if (category->AnyMatches(type_name, eFormatCategoryItemFilter |
- eFormatCategoryItemRegexFilter,
- false)) {
+ if (category->AnyMatches(
+ type_name, eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
+ false)) {
if (error)
error->SetErrorStringWithFormat("cannot add synthetic for type %s when "
"filter is defined in same category!",
@@ -2372,7 +2362,7 @@ bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
}
}
-#endif // LLDB_DISABLE_PYTHON
+#endif
#define LLDB_OPTIONS_type_filter_add
#include "CommandOptions.inc"
@@ -2468,9 +2458,9 @@ private:
type = eRegexFilter;
}
- if (category->AnyMatches(type_name, eFormatCategoryItemSynth |
- eFormatCategoryItemRegexSynth,
- false)) {
+ if (category->AnyMatches(
+ type_name, eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
+ false)) {
if (error)
error->SetErrorStringWithFormat("cannot add filter for type %s when "
"synthetic is defined in same "
@@ -2828,8 +2818,7 @@ public:
CommandObjectFormatterInfo(CommandInterpreter &interpreter,
const char *formatter_name,
DiscoveryFunction discovery_func)
- : CommandObjectRaw(interpreter, "", "", "",
- eCommandRequiresFrame),
+ : CommandObjectRaw(interpreter, "", "", "", eCommandRequiresFrame),
m_formatter_name(formatter_name ? formatter_name : ""),
m_discovery_function(discovery_func) {
StreamString name;
@@ -2923,7 +2912,7 @@ public:
~CommandObjectTypeFormat() override = default;
};
-#ifndef LLDB_DISABLE_PYTHON
+#if LLDB_ENABLE_PYTHON
class CommandObjectTypeSynth : public CommandObjectMultiword {
public:
@@ -2952,7 +2941,7 @@ public:
~CommandObjectTypeSynth() override = default;
};
-#endif // LLDB_DISABLE_PYTHON
+#endif
class CommandObjectTypeFilter : public CommandObjectMultiword {
public:
@@ -3038,10 +3027,10 @@ CommandObjectType::CommandObjectType(CommandInterpreter &interpreter)
CommandObjectSP(new CommandObjectTypeFormat(interpreter)));
LoadSubCommand("summary",
CommandObjectSP(new CommandObjectTypeSummary(interpreter)));
-#ifndef LLDB_DISABLE_PYTHON
+#if LLDB_ENABLE_PYTHON
LoadSubCommand("synthetic",
CommandObjectSP(new CommandObjectTypeSynth(interpreter)));
-#endif // LLDB_DISABLE_PYTHON
+#endif
LoadSubCommand("lookup",
CommandObjectSP(new CommandObjectTypeLookup(interpreter)));
}
diff --git a/lldb/source/Commands/CommandObjectType.h b/lldb/source/Commands/CommandObjectType.h
index ebb19039e503..938e481a6b87 100644
--- a/lldb/source/Commands/CommandObjectType.h
+++ b/lldb/source/Commands/CommandObjectType.h
@@ -9,11 +9,7 @@
#ifndef liblldb_CommandObjectType_h_
#define liblldb_CommandObjectType_h_
-
-
#include "lldb/Interpreter/CommandObjectMultiword.h"
-#include "lldb/Interpreter/Options.h"
-#include "lldb/lldb-types.h"
namespace lldb_private {
diff --git a/lldb/source/Commands/CommandObjectVersion.cpp b/lldb/source/Commands/CommandObjectVersion.cpp
index 904baf5b7d44..227d5d132d96 100644
--- a/lldb/source/Commands/CommandObjectVersion.cpp
+++ b/lldb/source/Commands/CommandObjectVersion.cpp
@@ -8,7 +8,6 @@
#include "CommandObjectVersion.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/lldb-private.h"
diff --git a/lldb/source/Commands/CommandObjectWatchpoint.cpp b/lldb/source/Commands/CommandObjectWatchpoint.cpp
index 44dfb29b19b5..c965d354f734 100644
--- a/lldb/source/Commands/CommandObjectWatchpoint.cpp
+++ b/lldb/source/Commands/CommandObjectWatchpoint.cpp
@@ -16,9 +16,7 @@
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Breakpoint/WatchpointList.h"
#include "lldb/Core/ValueObject.h"
-#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Host/OptionParser.h"
-#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Symbol/Variable.h"
@@ -417,6 +415,10 @@ protected:
};
// CommandObjectWatchpointDelete
+#define LLDB_OPTIONS_watchpoint_delete
+#include "CommandOptions.inc"
+
+// CommandObjectWatchpointDelete
#pragma mark Delete
class CommandObjectWatchpointDelete : public CommandObjectParsed {
@@ -425,7 +427,8 @@ public:
: CommandObjectParsed(interpreter, "watchpoint delete",
"Delete the specified watchpoint(s). If no "
"watchpoints are specified, delete them all.",
- nullptr, eCommandRequiresTarget) {
+ nullptr, eCommandRequiresTarget),
+ m_options() {
CommandArgumentEntry arg;
CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
eArgTypeWatchpointIDRange);
@@ -436,6 +439,41 @@ public:
~CommandObjectWatchpointDelete() override = default;
+ Options *GetOptions() override { return &m_options; }
+
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options(), m_force(false) {}
+
+ ~CommandOptions() override = default;
+
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override {
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 'f':
+ m_force = true;
+ break;
+ default:
+ llvm_unreachable("Unimplemented option");
+ }
+
+ return {};
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_force = false;
+ }
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+ return llvm::makeArrayRef(g_watchpoint_delete_options);
+ }
+
+ // Instance variables to hold the values for command options.
+ bool m_force;
+ };
+
protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
Target *target = &GetSelectedTarget();
@@ -455,8 +493,9 @@ protected:
return false;
}
- if (command.GetArgumentCount() == 0) {
- if (!m_interpreter.Confirm(
+ if (command.empty()) {
+ if (!m_options.m_force &&
+ !m_interpreter.Confirm(
"About to delete all watchpoints, do you want to do that?",
true)) {
result.AppendMessage("Operation cancelled...");
@@ -467,27 +506,31 @@ protected:
(uint64_t)num_watchpoints);
}
result.SetStatus(eReturnStatusSuccessFinishNoResult);
- } else {
- // Particular watchpoints selected; delete them.
- std::vector<uint32_t> wp_ids;
- if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
- target, command, wp_ids)) {
- result.AppendError("Invalid watchpoints specification.");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
+ return result.Succeeded();
+ }
- int count = 0;
- const size_t size = wp_ids.size();
- for (size_t i = 0; i < size; ++i)
- if (target->RemoveWatchpointByID(wp_ids[i]))
- ++count;
- result.AppendMessageWithFormat("%d watchpoints deleted.\n", count);
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ // Particular watchpoints selected; delete them.
+ std::vector<uint32_t> wp_ids;
+ if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command,
+ wp_ids)) {
+ result.AppendError("Invalid watchpoints specification.");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
}
+ int count = 0;
+ const size_t size = wp_ids.size();
+ for (size_t i = 0; i < size; ++i)
+ if (target->RemoveWatchpointByID(wp_ids[i]))
+ ++count;
+ result.AppendMessageWithFormat("%d watchpoints deleted.\n", count);
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+
return result.Succeeded();
}
+
+private:
+ CommandOptions m_options;
};
// CommandObjectWatchpointIgnore
diff --git a/lldb/source/Commands/CommandObjectWatchpoint.h b/lldb/source/Commands/CommandObjectWatchpoint.h
index f21796e6bc8d..4f4f80bbd620 100644
--- a/lldb/source/Commands/CommandObjectWatchpoint.h
+++ b/lldb/source/Commands/CommandObjectWatchpoint.h
@@ -9,10 +9,8 @@
#ifndef liblldb_CommandObjectWatchpoint_h_
#define liblldb_CommandObjectWatchpoint_h_
-
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/OptionGroupWatchpoint.h"
-#include "lldb/Interpreter/Options.h"
namespace lldb_private {
diff --git a/lldb/source/Commands/CommandObjectWatchpointCommand.cpp b/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
index 5683381efc85..1b83e885d27e 100644
--- a/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
+++ b/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
@@ -18,8 +18,6 @@
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Target/Target.h"
-#include "lldb/Target/Thread.h"
-#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
@@ -39,6 +37,11 @@ static constexpr OptionEnumValueElement g_script_option_enumeration[] = {
"Commands are in the Python language.",
},
{
+ eScriptLanguageLua,
+ "lua",
+ "Commands are in the Python language.",
+ },
+ {
eSortOrderByName,
"default-script",
"Commands are in the default scripting language.",
@@ -240,7 +243,6 @@ are no syntax errors may indicate that a function was declared but never called.
m_interpreter.GetLLDBCommandsFromIOHandler(
"> ", // Prompt
*this, // IOHandlerDelegate
- true, // Run IOHandler in async mode
wp_options); // Baton for the "io_handler" that will be passed back into
// our IOHandlerDelegate functions
}
@@ -333,8 +335,16 @@ are no syntax errors may indicate that a function was declared but never called.
option_arg, GetDefinitions()[option_idx].enum_values,
eScriptLanguageNone, error);
- m_use_script_language = (m_script_language == eScriptLanguagePython ||
- m_script_language == eScriptLanguageDefault);
+ switch (m_script_language) {
+ case eScriptLanguagePython:
+ case eScriptLanguageLua:
+ m_use_script_language = true;
+ break;
+ case eScriptLanguageNone:
+ case eScriptLanguageUnknown:
+ m_use_script_language = false;
+ break;
+ }
break;
case 'e': {
@@ -349,7 +359,6 @@ are no syntax errors may indicate that a function was declared but never called.
case 'F':
m_use_one_liner = false;
- m_use_script_language = true;
m_function_name.assign(option_arg);
break;
@@ -400,12 +409,11 @@ protected:
return false;
}
- if (!m_options.m_use_script_language &&
- !m_options.m_function_name.empty()) {
- result.AppendError("need to enable scripting to have a function run as a "
- "watchpoint command");
- result.SetStatus(eReturnStatusFailed);
- return false;
+ if (!m_options.m_function_name.empty()) {
+ if (!m_options.m_use_script_language) {
+ m_options.m_script_language = GetDebugger().GetScriptLanguage();
+ m_options.m_use_script_language = true;
+ }
}
std::vector<uint32_t> valid_wp_ids;
@@ -435,9 +443,11 @@ protected:
// to set or collect command callback. Otherwise, call the methods
// associated with this object.
if (m_options.m_use_script_language) {
+ ScriptInterpreter *script_interp = GetDebugger().GetScriptInterpreter(
+ /*can_create=*/true, m_options.m_script_language);
// Special handling for one-liner specified inline.
if (m_options.m_use_one_liner) {
- GetDebugger().GetScriptInterpreter()->SetWatchpointCommandCallback(
+ script_interp->SetWatchpointCommandCallback(
wp_options, m_options.m_one_liner.c_str());
}
// Special handling for using a Python function by name instead of
@@ -447,12 +457,11 @@ protected:
else if (!m_options.m_function_name.empty()) {
std::string oneliner(m_options.m_function_name);
oneliner += "(frame, wp, internal_dict)";
- GetDebugger().GetScriptInterpreter()->SetWatchpointCommandCallback(
+ script_interp->SetWatchpointCommandCallback(
wp_options, oneliner.c_str());
} else {
- GetDebugger()
- .GetScriptInterpreter()
- ->CollectDataForWatchpointCommandCallback(wp_options, result);
+ script_interp->CollectDataForWatchpointCommandCallback(wp_options,
+ result);
}
} else {
// Special handling for one-liner specified inline.
@@ -611,10 +620,10 @@ protected:
const Baton *baton = wp_options->GetBaton();
if (baton) {
result.GetOutputStream().Printf("Watchpoint %u:\n", cur_wp_id);
- result.GetOutputStream().IndentMore();
- baton->GetDescription(&result.GetOutputStream(),
- eDescriptionLevelFull);
- result.GetOutputStream().IndentLess();
+ baton->GetDescription(result.GetOutputStream().AsRawOstream(),
+ eDescriptionLevelFull,
+ result.GetOutputStream().GetIndentLevel() +
+ 2);
} else {
result.AppendMessageWithFormat(
"Watchpoint %u does not have an associated command.\n",
diff --git a/lldb/source/Commands/CommandObjectWatchpointCommand.h b/lldb/source/Commands/CommandObjectWatchpointCommand.h
index f2f15ef50b0f..6fbc9c741617 100644
--- a/lldb/source/Commands/CommandObjectWatchpointCommand.h
+++ b/lldb/source/Commands/CommandObjectWatchpointCommand.h
@@ -9,11 +9,7 @@
#ifndef liblldb_CommandObjectWatchpointCommand_h_
#define liblldb_CommandObjectWatchpointCommand_h_
-
-
#include "lldb/Interpreter/CommandObjectMultiword.h"
-#include "lldb/Interpreter/Options.h"
-#include "lldb/lldb-types.h"
namespace lldb_private {
diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td
index 87f5506c305f..850df133a429 100644
--- a/lldb/source/Commands/Options.td
+++ b/lldb/source/Commands/Options.td
@@ -4,6 +4,8 @@ let Command = "target modules dump symtab" in {
def tm_sort : Option<"sort", "s">, Group<1>,
Desc<"Supply a sort order when dumping the symbol table.">,
EnumArg<"SortOrder", "OptionEnumValues(g_sort_option_enumeration)">;
+ def tm_smn : Option<"show-mangled-names", "m">, Group<1>,
+ Desc<"Do not demangle symbol names before showing them.">;
}
let Command = "help" in {
@@ -268,10 +270,6 @@ let Command = "breakpoint command add" in {
EnumArg<"None", "ScriptOptionEnum()">,
Desc<"Specify the language for the commands - if none is specified, the "
"lldb command interpreter will be used.">;
- def breakpoint_add_python_function : Option<"python-function", "F">,
- Group<2>, Arg<"PythonFunction">,
- Desc<"Give the name of a Python function to run as command for this "
- "breakpoint. Be sure to give a module name if appropriate.">;
def breakpoint_add_dummy_breakpoints : Option<"dummy-breakpoints", "D">,
Desc<"Sets Dummy breakpoints - i.e. breakpoints set before a file is "
"provided, which prime new targets.">;
@@ -431,7 +429,7 @@ let Command = "log" in {
Desc<"Prepend the names of files and function that generate the logs.">;
}
-let Command = "reproducer" in {
+let Command = "reproducer dump" in {
def reproducer_provider : Option<"provider", "p">, Group<1>,
EnumArg<"None", "ReproducerProviderType()">,
Required, Desc<"The reproducer provider to dump.">;
@@ -440,6 +438,12 @@ let Command = "reproducer" in {
"provided, that reproducer is dumped.">;
}
+let Command = "reproducer xcrash" in {
+ def reproducer_signal : Option<"signal", "s">, Group<1>,
+ EnumArg<"None", "ReproducerSignalType()">,
+ Required, Desc<"The signal to crash the debugger.">;
+}
+
let Command = "memory read" in {
def memory_read_num_per_line : Option<"num-per-line", "l">, Group<1>,
Arg<"NumberPerLine">, Desc<"The number of items per line to display.">;
@@ -907,9 +911,6 @@ let Command = "thread step scope" in {
def thread_step_scope_step_in_target : Option<"step-in-target", "t">,
Group<1>, Arg<"FunctionName">, Desc<"The name of the directly called "
"function step in should stop at when stepping into.">;
- def thread_step_scope_python_class : Option<"python-class", "C">, Group<2>,
- Arg<"PythonClass">, Desc<"The name of the class that will manage this step "
- "- only supported for Scripted Step.">;
}
let Command = "thread until" in {
@@ -1125,3 +1126,8 @@ let Command = "watchpoint command add" in {
"to run as command for this watchpoint. Be sure to give a module name if "
"appropriate.">;
}
+
+let Command = "watchpoint delete" in {
+ def watchpoint_delete_force : Option<"force", "f">, Group<1>,
+ Desc<"Delete all watchpoints without querying for confirmation.">;
+}
diff --git a/lldb/source/Core/Address.cpp b/lldb/source/Core/Address.cpp
index a3912bef5a6e..b9a7b4a3894a 100644
--- a/lldb/source/Core/Address.cpp
+++ b/lldb/source/Core/Address.cpp
@@ -418,13 +418,13 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
section_sp->DumpName(s);
s->Printf(" + %" PRIu64, m_offset);
} else {
- s->Address(m_offset, addr_size);
+ DumpAddress(s->AsRawOstream(), m_offset, addr_size);
}
break;
case DumpStyleSectionPointerOffset:
s->Printf("(Section *)%p + ", static_cast<void *>(section_sp.get()));
- s->Address(m_offset, addr_size);
+ DumpAddress(s->AsRawOstream(), m_offset, addr_size);
break;
case DumpStyleModuleWithFileAddress:
@@ -444,7 +444,7 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
return false;
}
- s->Address(file_addr, addr_size);
+ DumpAddress(s->AsRawOstream(), file_addr, addr_size);
if (style == DumpStyleModuleWithFileAddress && section_sp)
s->PutChar(']');
} break;
@@ -472,7 +472,7 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
return false;
}
- s->Address(load_addr, addr_size);
+ DumpAddress(s->AsRawOstream(), load_addr, addr_size);
} break;
case DumpStyleResolvedDescription:
@@ -712,22 +712,20 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
[](Variable *) { return true; },
&variable_list);
- const size_t num_variables = variable_list.GetSize();
- for (size_t var_idx = 0; var_idx < num_variables; ++var_idx) {
- Variable *var = variable_list.GetVariableAtIndex(var_idx).get();
- if (var && var->LocationIsValidForAddress(*this)) {
+ for (const VariableSP &var_sp : variable_list) {
+ if (var_sp && var_sp->LocationIsValidForAddress(*this)) {
s->Indent();
s->Printf(" Variable: id = {0x%8.8" PRIx64 "}, name = \"%s\"",
- var->GetID(), var->GetName().GetCString());
- Type *type = var->GetType();
+ var_sp->GetID(), var_sp->GetName().GetCString());
+ Type *type = var_sp->GetType();
if (type)
s->Printf(", type = \"%s\"", type->GetName().GetCString());
else
s->PutCString(", type = <unknown>");
s->PutCString(", location = ");
- var->DumpLocationForAddress(s, *this);
+ var_sp->DumpLocationForAddress(s, *this);
s->PutCString(", decl = ");
- var->GetDeclaration().DumpStopContext(s, false);
+ var_sp->GetDeclaration().DumpStopContext(s, false);
s->EOL();
}
}
@@ -756,7 +754,8 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
if (dereferenced_addr.Dump(&strm, exe_scope,
DumpStyleResolvedDescription,
DumpStyleInvalid, addr_size)) {
- s->Address(dereferenced_load_addr, addr_size, " -> ", " ");
+ DumpAddress(s->AsRawOstream(), dereferenced_load_addr, addr_size,
+ " -> ", " ");
s->Write(strm.GetString().data(), strm.GetSize());
return true;
}
diff --git a/lldb/source/Core/AddressRange.cpp b/lldb/source/Core/AddressRange.cpp
index 71eec3c19607..83a1e54157d8 100644
--- a/lldb/source/Core/AddressRange.cpp
+++ b/lldb/source/Core/AddressRange.cpp
@@ -161,7 +161,8 @@ bool AddressRange::Dump(Stream *s, Target *target, Address::DumpStyle style,
s->PutChar('[');
m_base_addr.Dump(s, target, style, fallback_style);
s->PutChar('-');
- s->Address(m_base_addr.GetOffset() + GetByteSize(), addr_size);
+ DumpAddress(s->AsRawOstream(), m_base_addr.GetOffset() + GetByteSize(),
+ addr_size);
s->PutChar(')');
return true;
break;
@@ -185,7 +186,8 @@ bool AddressRange::Dump(Stream *s, Target *target, Address::DumpStyle style,
s->Printf("%s", module_sp->GetFileSpec().GetFilename().AsCString(
"<Unknown>"));
}
- s->AddressRange(vmaddr, vmaddr + GetByteSize(), addr_size);
+ DumpAddressRange(s->AsRawOstream(), vmaddr, vmaddr + GetByteSize(),
+ addr_size);
return true;
} else if (fallback_style != Address::DumpStyleInvalid) {
return Dump(s, target, fallback_style, Address::DumpStyleInvalid);
diff --git a/lldb/source/Core/AddressResolverFileLine.cpp b/lldb/source/Core/AddressResolverFileLine.cpp
index 4a14260c6c72..4122b5d3b747 100644
--- a/lldb/source/Core/AddressResolverFileLine.cpp
+++ b/lldb/source/Core/AddressResolverFileLine.cpp
@@ -40,14 +40,13 @@ Searcher::CallbackReturn
AddressResolverFileLine::SearchCallback(SearchFilter &filter,
SymbolContext &context, Address *addr) {
SymbolContextList sc_list;
- uint32_t sc_list_size;
CompileUnit *cu = context.comp_unit;
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
- sc_list_size =
- cu->ResolveSymbolContext(m_file_spec, m_line_number, m_inlines, false,
- eSymbolContextEverything, sc_list);
+ cu->ResolveSymbolContext(m_file_spec, m_line_number, m_inlines, false,
+ eSymbolContextEverything, sc_list);
+ uint32_t sc_list_size = sc_list.GetSize();
for (uint32_t i = 0; i < sc_list_size; i++) {
SymbolContext sc;
if (sc_list.GetContextAtIndex(i, sc)) {
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 18397d00dcaa..33f72a0896cb 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -708,8 +708,8 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
m_source_manager_up(), m_source_file_cache(),
m_command_interpreter_up(
std::make_unique<CommandInterpreter>(*this, false)),
- m_script_interpreter_sp(), m_input_reader_stack(), m_instance_name(),
- m_loaded_plugins(), m_event_handler_thread(), m_io_handler_thread(),
+ m_input_reader_stack(), m_instance_name(), m_loaded_plugins(),
+ m_event_handler_thread(), m_io_handler_thread(),
m_sync_broadcaster(nullptr, "lldb.debugger.sync"),
m_forward_listener_sp(), m_clear_once() {
char instance_cstr[256];
@@ -1198,17 +1198,21 @@ bool Debugger::EnableLog(llvm::StringRef channel,
error_stream);
}
-ScriptInterpreter *Debugger::GetScriptInterpreter(bool can_create) {
+ScriptInterpreter *
+Debugger::GetScriptInterpreter(bool can_create,
+ llvm::Optional<lldb::ScriptLanguage> language) {
std::lock_guard<std::recursive_mutex> locker(m_script_interpreter_mutex);
+ lldb::ScriptLanguage script_language =
+ language ? *language : GetScriptLanguage();
- if (!m_script_interpreter_sp) {
+ if (!m_script_interpreters[script_language]) {
if (!can_create)
return nullptr;
- m_script_interpreter_sp = PluginManager::GetScriptInterpreterForLanguage(
- GetScriptLanguage(), *this);
+ m_script_interpreters[script_language] =
+ PluginManager::GetScriptInterpreterForLanguage(script_language, *this);
}
- return m_script_interpreter_sp.get();
+ return m_script_interpreters[script_language].get();
}
SourceManager &Debugger::GetSourceManager() {
@@ -1452,7 +1456,7 @@ void Debugger::DefaultEventHandler() {
done = true;
} else if (event_type &
CommandInterpreter::eBroadcastBitAsynchronousErrorData) {
- const char *data = reinterpret_cast<const char *>(
+ const char *data = static_cast<const char *>(
EventDataBytes::GetBytesFromEvent(event_sp.get()));
if (data && data[0]) {
StreamSP error_sp(GetAsyncErrorStream());
@@ -1463,7 +1467,7 @@ void Debugger::DefaultEventHandler() {
}
} else if (event_type & CommandInterpreter::
eBroadcastBitAsynchronousOutputData) {
- const char *data = reinterpret_cast<const char *>(
+ const char *data = static_cast<const char *>(
EventDataBytes::GetBytesFromEvent(event_sp.get()));
if (data && data[0]) {
StreamSP output_sp(GetAsyncOutputStream());
diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp
index 89ae25cbad64..33172cc8868e 100644
--- a/lldb/source/Core/Disassembler.cpp
+++ b/lldb/source/Core/Disassembler.cpp
@@ -1101,15 +1101,22 @@ void InstructionList::Append(lldb::InstructionSP &inst_sp) {
uint32_t
InstructionList::GetIndexOfNextBranchInstruction(uint32_t start,
Target &target,
- bool ignore_calls) const {
+ bool ignore_calls,
+ bool *found_calls) const {
size_t num_instructions = m_instructions.size();
uint32_t next_branch = UINT32_MAX;
size_t i;
+
+ if (found_calls)
+ *found_calls = false;
for (i = start; i < num_instructions; i++) {
if (m_instructions[i]->DoesBranch()) {
- if (ignore_calls && m_instructions[i]->IsCall())
+ if (ignore_calls && m_instructions[i]->IsCall()) {
+ if (found_calls)
+ *found_calls = true;
continue;
+ }
next_branch = i;
break;
}
diff --git a/lldb/source/Core/DumpDataExtractor.cpp b/lldb/source/Core/DumpDataExtractor.cpp
index 12e98de2675c..b5e1071b72ae 100644
--- a/lldb/source/Core/DumpDataExtractor.cpp
+++ b/lldb/source/Core/DumpDataExtractor.cpp
@@ -467,9 +467,10 @@ lldb::offset_t lldb_private::DumpDataExtractor(
} break;
case eFormatPointer:
- s->Address(DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
- item_bit_offset),
- sizeof(addr_t));
+ DumpAddress(s->AsRawOstream(),
+ DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
+ item_bit_offset),
+ sizeof(addr_t));
break;
case eFormatComplexInteger: {
diff --git a/lldb/source/Core/FileLineResolver.cpp b/lldb/source/Core/FileLineResolver.cpp
index 01df295398a8..7d91d1a3e472 100644
--- a/lldb/source/Core/FileLineResolver.cpp
+++ b/lldb/source/Core/FileLineResolver.cpp
@@ -36,8 +36,8 @@ FileLineResolver::SearchCallback(SearchFilter &filter, SymbolContext &context,
Address *addr) {
CompileUnit *cu = context.comp_unit;
- if (m_inlines ||
- m_file_spec.Compare(*cu, m_file_spec, (bool)m_file_spec.GetDirectory())) {
+ if (m_inlines || m_file_spec.Compare(cu->GetPrimaryFile(), m_file_spec,
+ (bool)m_file_spec.GetDirectory())) {
uint32_t start_file_idx = 0;
uint32_t file_idx =
cu->GetSupportFiles().FindFileIndex(start_file_idx, m_file_spec, false);
diff --git a/lldb/source/Core/FileSpecList.cpp b/lldb/source/Core/FileSpecList.cpp
index 95133faf7502..6651324fa362 100644
--- a/lldb/source/Core/FileSpecList.cpp
+++ b/lldb/source/Core/FileSpecList.cpp
@@ -47,7 +47,7 @@ void FileSpecList::Clear() { m_files.clear(); }
void FileSpecList::Dump(Stream *s, const char *separator_cstr) const {
collection::const_iterator pos, end = m_files.end();
for (pos = m_files.begin(); pos != end; ++pos) {
- pos->Dump(s);
+ pos->Dump(s->AsRawOstream());
if (separator_cstr && ((pos + 1) != end))
s->PutCString(separator_cstr);
}
diff --git a/lldb/source/Core/FormatEntity.cpp b/lldb/source/Core/FormatEntity.cpp
index c90828f40989..7aa1eced34f3 100644
--- a/lldb/source/Core/FormatEntity.cpp
+++ b/lldb/source/Core/FormatEntity.cpp
@@ -125,6 +125,7 @@ static FormatEntity::Entry::Definition g_function_child_entries[] = {
ENTRY("name", FunctionName),
ENTRY("name-without-args", FunctionNameNoArgs),
ENTRY("name-with-args", FunctionNameWithArgs),
+ ENTRY("mangled-name", FunctionMangledName),
ENTRY("addr-offset", FunctionAddrOffset),
ENTRY("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete),
ENTRY("line-offset", FunctionLineOffset),
@@ -351,6 +352,7 @@ const char *FormatEntity::Entry::TypeToCString(Type t) {
ENUM_TO_CSTR(FunctionName);
ENUM_TO_CSTR(FunctionNameWithArgs);
ENUM_TO_CSTR(FunctionNameNoArgs);
+ ENUM_TO_CSTR(FunctionMangledName);
ENUM_TO_CSTR(FunctionAddrOffset);
ENUM_TO_CSTR(FunctionAddrOffsetConcrete);
ENUM_TO_CSTR(FunctionLineOffset);
@@ -414,9 +416,10 @@ static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc,
return false;
}
-static bool DumpAddress(Stream &s, const SymbolContext *sc,
- const ExecutionContext *exe_ctx, const Address &addr,
- bool print_file_addr_or_load_addr) {
+static bool DumpAddressAndContent(Stream &s, const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ const Address &addr,
+ bool print_file_addr_or_load_addr) {
Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
addr_t vaddr = LLDB_INVALID_ADDRESS;
if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
@@ -1145,9 +1148,10 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
case Entry::Type::AddressFile:
case Entry::Type::AddressLoad:
case Entry::Type::AddressLoadOrFile:
- return (addr != nullptr && addr->IsValid() &&
- DumpAddress(s, sc, exe_ctx, *addr,
- entry.type == Entry::Type::AddressLoadOrFile));
+ return (
+ addr != nullptr && addr->IsValid() &&
+ DumpAddressAndContent(s, sc, exe_ctx, *addr,
+ entry.type == Entry::Type::AddressLoadOrFile));
case Entry::Type::ProcessID:
if (exe_ctx) {
@@ -1376,8 +1380,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
if (sc) {
CompileUnit *cu = sc->comp_unit;
if (cu) {
- // CompileUnit is a FileSpec
- if (DumpFile(s, *cu, (FileKind)entry.number))
+ if (DumpFile(s, cu->GetPrimaryFile(), (FileKind)entry.number))
return true;
}
}
@@ -1416,7 +1419,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
if (frame) {
const Address &pc_addr = frame->GetFrameCodeAddress();
if (pc_addr.IsValid()) {
- if (DumpAddress(s, sc, exe_ctx, pc_addr, false))
+ if (DumpAddressAndContent(s, sc, exe_ctx, pc_addr, false))
return true;
}
}
@@ -1744,6 +1747,31 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
}
return false;
+ case Entry::Type::FunctionMangledName: {
+ const char *name = nullptr;
+ if (sc->symbol)
+ name = sc->symbol->GetMangled()
+ .GetName(sc->symbol->GetLanguage(), Mangled::ePreferMangled)
+ .AsCString();
+ else if (sc->function)
+ name = sc->function->GetMangled()
+ .GetName(sc->symbol->GetLanguage(), Mangled::ePreferMangled)
+ .AsCString();
+
+ if (!name)
+ return false;
+ s.PutCString(name);
+
+ if (sc->block->GetContainingInlinedBlock()) {
+ if (const InlineFunctionInfo *inline_info =
+ sc->block->GetInlinedFunctionInfo()) {
+ s.PutCString(" [inlined] ");
+ inline_info->GetName(sc->function->GetLanguage()).Dump(&s);
+ }
+ }
+ return true;
+ }
+
case Entry::Type::FunctionAddrOffset:
if (addr) {
if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false,
@@ -1828,7 +1856,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
if (entry.type == Entry::Type::LineEntryEndAddress)
addr.Slide(sc->line_entry.range.GetByteSize());
- if (DumpAddress(s, sc, exe_ctx, addr, false))
+ if (DumpAddressAndContent(s, sc, exe_ctx, addr, false))
return true;
}
return false;
@@ -2309,7 +2337,7 @@ bool FormatEntity::FormatFileSpec(const FileSpec &file_spec, Stream &s,
llvm::StringRef variable_name,
llvm::StringRef variable_format) {
if (variable_name.empty() || variable_name.equals(".fullpath")) {
- file_spec.Dump(&s);
+ file_spec.Dump(s.AsRawOstream());
return true;
} else if (variable_name.equals(".basename")) {
s.PutCString(file_spec.GetFilename().AsCString(""));
diff --git a/lldb/source/Core/IOHandler.cpp b/lldb/source/Core/IOHandler.cpp
index 46be29f6fbf9..4021a6d7f327 100644
--- a/lldb/source/Core/IOHandler.cpp
+++ b/lldb/source/Core/IOHandler.cpp
@@ -8,11 +8,6 @@
#include "lldb/Core/IOHandler.h"
-#ifndef LLDB_DISABLE_CURSES
-#include <curses.h>
-#include <panel.h>
-#endif
-
#if defined(__APPLE__)
#include <deque>
#endif
@@ -20,6 +15,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Host/Config.h"
#include "lldb/Host/File.h"
#include "lldb/Utility/Predicate.h"
#include "lldb/Utility/Status.h"
@@ -27,29 +23,11 @@
#include "lldb/Utility/StringList.h"
#include "lldb/lldb-forward.h"
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
#include "lldb/Host/Editline.h"
#endif
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
-#ifndef LLDB_DISABLE_CURSES
-#include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/ValueObject.h"
-#include "lldb/Core/ValueObjectRegister.h"
-#include "lldb/Symbol/Block.h"
-#include "lldb/Symbol/Function.h"
-#include "lldb/Symbol/Symbol.h"
-#include "lldb/Symbol/VariableList.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/RegisterContext.h"
-#include "lldb/Target/StackFrame.h"
-#include "lldb/Target/StopInfo.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Target/Thread.h"
-#include "lldb/Utility/State.h"
-#endif
-
#include "llvm/ADT/StringRef.h"
#ifdef _WIN32
@@ -74,7 +52,6 @@ using llvm::None;
using llvm::Optional;
using llvm::StringRef;
-
IOHandler::IOHandler(Debugger &debugger, IOHandler::Type type)
: IOHandler(debugger, type,
FileSP(), // Adopt STDIN from top input reader
@@ -257,7 +234,7 @@ IOHandlerEditline::IOHandlerEditline(
IOHandlerDelegate &delegate, repro::DataRecorder *data_recorder)
: IOHandler(debugger, type, input_sp, output_sp, error_sp, flags,
data_recorder),
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
m_editline_up(),
#endif
m_delegate(delegate), m_prompt(), m_continuation_prompt(),
@@ -267,7 +244,7 @@ IOHandlerEditline::IOHandlerEditline(
m_editing(false) {
SetPrompt(prompt);
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
bool use_editline = false;
use_editline = GetInputFILE() && GetOutputFILE() && GetErrorFILE() &&
@@ -295,7 +272,7 @@ IOHandlerEditline::IOHandlerEditline(
}
IOHandlerEditline::~IOHandlerEditline() {
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
m_editline_up.reset();
#endif
}
@@ -331,7 +308,7 @@ static Optional<std::string> SplitLineEOF(std::string &line_buffer) {
}
bool IOHandlerEditline::GetLine(std::string &line, bool &interrupted) {
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
if (m_editline_up) {
bool b = m_editline_up->GetLine(line, interrupted);
if (b && m_data_recorder)
@@ -425,7 +402,7 @@ bool IOHandlerEditline::GetLine(std::string &line, bool &interrupted) {
return (bool)got_line;
}
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
bool IOHandlerEditline::IsInputCompleteCallback(Editline *editline,
StringList &lines,
void *baton) {
@@ -452,14 +429,14 @@ void IOHandlerEditline::AutoCompleteCallback(CompletionRequest &request,
#endif
const char *IOHandlerEditline::GetPrompt() {
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
if (m_editline_up) {
return m_editline_up->GetPrompt();
} else {
#endif
if (m_prompt.empty())
return nullptr;
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
}
#endif
return m_prompt.c_str();
@@ -468,7 +445,7 @@ const char *IOHandlerEditline::GetPrompt() {
bool IOHandlerEditline::SetPrompt(llvm::StringRef prompt) {
m_prompt = prompt;
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
if (m_editline_up)
m_editline_up->SetPrompt(m_prompt.empty() ? nullptr : m_prompt.c_str());
#endif
@@ -483,7 +460,7 @@ const char *IOHandlerEditline::GetContinuationPrompt() {
void IOHandlerEditline::SetContinuationPrompt(llvm::StringRef prompt) {
m_continuation_prompt = prompt;
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
if (m_editline_up)
m_editline_up->SetContinuationPrompt(m_continuation_prompt.empty()
? nullptr
@@ -496,7 +473,7 @@ void IOHandlerEditline::SetBaseLineNumber(uint32_t line) {
}
uint32_t IOHandlerEditline::GetCurrentLineIndex() const {
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
if (m_editline_up)
return m_editline_up->GetCurrentLine();
#endif
@@ -507,7 +484,7 @@ bool IOHandlerEditline::GetLines(StringList &lines, bool &interrupted) {
m_current_lines_ptr = &lines;
bool success = false;
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
if (m_editline_up) {
return m_editline_up->GetLines(m_base_line_number, lines, interrupted);
} else {
@@ -537,7 +514,7 @@ bool IOHandlerEditline::GetLines(StringList &lines, bool &interrupted) {
}
}
success = lines.GetSize() > 0;
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
}
#endif
return success;
@@ -577,7 +554,7 @@ void IOHandlerEditline::Run() {
}
void IOHandlerEditline::Cancel() {
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
if (m_editline_up)
m_editline_up->Cancel();
#endif
@@ -588,7 +565,7 @@ bool IOHandlerEditline::Interrupt() {
if (m_delegate.IOHandlerInterrupt(*this))
return true;
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
if (m_editline_up)
return m_editline_up->Interrupt();
#endif
@@ -596,14 +573,14 @@ bool IOHandlerEditline::Interrupt() {
}
void IOHandlerEditline::GotEOF() {
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
if (m_editline_up)
m_editline_up->Interrupt();
#endif
}
void IOHandlerEditline::PrintAsync(Stream *stream, const char *s, size_t len) {
-#ifndef LLDB_DISABLE_LIBEDIT
+#if LLDB_ENABLE_LIBEDIT
if (m_editline_up)
m_editline_up->PrintAsync(stream, s, len);
else
@@ -631,3995 +608,3 @@ void IOHandlerEditline::PrintAsync(Stream *stream, const char *s, size_t len) {
#endif
}
}
-
-// we may want curses to be disabled for some builds for instance, windows
-#ifndef LLDB_DISABLE_CURSES
-
-#define KEY_RETURN 10
-#define KEY_ESCAPE 27
-
-namespace curses {
-class Menu;
-class MenuDelegate;
-class Window;
-class WindowDelegate;
-typedef std::shared_ptr<Menu> MenuSP;
-typedef std::shared_ptr<MenuDelegate> MenuDelegateSP;
-typedef std::shared_ptr<Window> WindowSP;
-typedef std::shared_ptr<WindowDelegate> WindowDelegateSP;
-typedef std::vector<MenuSP> Menus;
-typedef std::vector<WindowSP> Windows;
-typedef std::vector<WindowDelegateSP> WindowDelegates;
-
-#if 0
-type summary add -s "x=${var.x}, y=${var.y}" curses::Point
-type summary add -s "w=${var.width}, h=${var.height}" curses::Size
-type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
-#endif
-
-struct Point {
- int x;
- int y;
-
- Point(int _x = 0, int _y = 0) : x(_x), y(_y) {}
-
- void Clear() {
- x = 0;
- y = 0;
- }
-
- Point &operator+=(const Point &rhs) {
- x += rhs.x;
- y += rhs.y;
- return *this;
- }
-
- void Dump() { printf("(x=%i, y=%i)\n", x, y); }
-};
-
-bool operator==(const Point &lhs, const Point &rhs) {
- return lhs.x == rhs.x && lhs.y == rhs.y;
-}
-
-bool operator!=(const Point &lhs, const Point &rhs) {
- return lhs.x != rhs.x || lhs.y != rhs.y;
-}
-
-struct Size {
- int width;
- int height;
- Size(int w = 0, int h = 0) : width(w), height(h) {}
-
- void Clear() {
- width = 0;
- height = 0;
- }
-
- void Dump() { printf("(w=%i, h=%i)\n", width, height); }
-};
-
-bool operator==(const Size &lhs, const Size &rhs) {
- return lhs.width == rhs.width && lhs.height == rhs.height;
-}
-
-bool operator!=(const Size &lhs, const Size &rhs) {
- return lhs.width != rhs.width || lhs.height != rhs.height;
-}
-
-struct Rect {
- Point origin;
- Size size;
-
- Rect() : origin(), size() {}
-
- Rect(const Point &p, const Size &s) : origin(p), size(s) {}
-
- void Clear() {
- origin.Clear();
- size.Clear();
- }
-
- void Dump() {
- printf("(x=%i, y=%i), w=%i, h=%i)\n", origin.x, origin.y, size.width,
- size.height);
- }
-
- void Inset(int w, int h) {
- if (size.width > w * 2)
- size.width -= w * 2;
- origin.x += w;
-
- if (size.height > h * 2)
- size.height -= h * 2;
- origin.y += h;
- }
-
- // Return a status bar rectangle which is the last line of this rectangle.
- // This rectangle will be modified to not include the status bar area.
- Rect MakeStatusBar() {
- Rect status_bar;
- if (size.height > 1) {
- status_bar.origin.x = origin.x;
- status_bar.origin.y = size.height;
- status_bar.size.width = size.width;
- status_bar.size.height = 1;
- --size.height;
- }
- return status_bar;
- }
-
- // Return a menubar rectangle which is the first line of this rectangle. This
- // rectangle will be modified to not include the menubar area.
- Rect MakeMenuBar() {
- Rect menubar;
- if (size.height > 1) {
- menubar.origin.x = origin.x;
- menubar.origin.y = origin.y;
- menubar.size.width = size.width;
- menubar.size.height = 1;
- ++origin.y;
- --size.height;
- }
- return menubar;
- }
-
- void HorizontalSplitPercentage(float top_percentage, Rect &top,
- Rect &bottom) const {
- float top_height = top_percentage * size.height;
- HorizontalSplit(top_height, top, bottom);
- }
-
- void HorizontalSplit(int top_height, Rect &top, Rect &bottom) const {
- top = *this;
- if (top_height < size.height) {
- top.size.height = top_height;
- bottom.origin.x = origin.x;
- bottom.origin.y = origin.y + top.size.height;
- bottom.size.width = size.width;
- bottom.size.height = size.height - top.size.height;
- } else {
- bottom.Clear();
- }
- }
-
- void VerticalSplitPercentage(float left_percentage, Rect &left,
- Rect &right) const {
- float left_width = left_percentage * size.width;
- VerticalSplit(left_width, left, right);
- }
-
- void VerticalSplit(int left_width, Rect &left, Rect &right) const {
- left = *this;
- if (left_width < size.width) {
- left.size.width = left_width;
- right.origin.x = origin.x + left.size.width;
- right.origin.y = origin.y;
- right.size.width = size.width - left.size.width;
- right.size.height = size.height;
- } else {
- right.Clear();
- }
- }
-};
-
-bool operator==(const Rect &lhs, const Rect &rhs) {
- return lhs.origin == rhs.origin && lhs.size == rhs.size;
-}
-
-bool operator!=(const Rect &lhs, const Rect &rhs) {
- return lhs.origin != rhs.origin || lhs.size != rhs.size;
-}
-
-enum HandleCharResult {
- eKeyNotHandled = 0,
- eKeyHandled = 1,
- eQuitApplication = 2
-};
-
-enum class MenuActionResult {
- Handled,
- NotHandled,
- Quit // Exit all menus and quit
-};
-
-struct KeyHelp {
- int ch;
- const char *description;
-};
-
-class WindowDelegate {
-public:
- virtual ~WindowDelegate() = default;
-
- virtual bool WindowDelegateDraw(Window &window, bool force) {
- return false; // Drawing not handled
- }
-
- virtual HandleCharResult WindowDelegateHandleChar(Window &window, int key) {
- return eKeyNotHandled;
- }
-
- virtual const char *WindowDelegateGetHelpText() { return nullptr; }
-
- virtual KeyHelp *WindowDelegateGetKeyHelp() { return nullptr; }
-};
-
-class HelpDialogDelegate : public WindowDelegate {
-public:
- HelpDialogDelegate(const char *text, KeyHelp *key_help_array);
-
- ~HelpDialogDelegate() override;
-
- bool WindowDelegateDraw(Window &window, bool force) override;
-
- HandleCharResult WindowDelegateHandleChar(Window &window, int key) override;
-
- size_t GetNumLines() const { return m_text.GetSize(); }
-
- size_t GetMaxLineLength() const { return m_text.GetMaxStringLength(); }
-
-protected:
- StringList m_text;
- int m_first_visible_line;
-};
-
-class Window {
-public:
- Window(const char *name)
- : m_name(name), m_window(nullptr), m_panel(nullptr), m_parent(nullptr),
- m_subwindows(), m_delegate_sp(), m_curr_active_window_idx(UINT32_MAX),
- m_prev_active_window_idx(UINT32_MAX), m_delete(false),
- m_needs_update(true), m_can_activate(true), m_is_subwin(false) {}
-
- Window(const char *name, WINDOW *w, bool del = true)
- : m_name(name), m_window(nullptr), m_panel(nullptr), m_parent(nullptr),
- m_subwindows(), m_delegate_sp(), m_curr_active_window_idx(UINT32_MAX),
- m_prev_active_window_idx(UINT32_MAX), m_delete(del),
- m_needs_update(true), m_can_activate(true), m_is_subwin(false) {
- if (w)
- Reset(w);
- }
-
- Window(const char *name, const Rect &bounds)
- : m_name(name), m_window(nullptr), m_parent(nullptr), m_subwindows(),
- m_delegate_sp(), m_curr_active_window_idx(UINT32_MAX),
- m_prev_active_window_idx(UINT32_MAX), m_delete(true),
- m_needs_update(true), m_can_activate(true), m_is_subwin(false) {
- Reset(::newwin(bounds.size.height, bounds.size.width, bounds.origin.y,
- bounds.origin.y));
- }
-
- virtual ~Window() {
- RemoveSubWindows();
- Reset();
- }
-
- void Reset(WINDOW *w = nullptr, bool del = true) {
- if (m_window == w)
- return;
-
- if (m_panel) {
- ::del_panel(m_panel);
- m_panel = nullptr;
- }
- if (m_window && m_delete) {
- ::delwin(m_window);
- m_window = nullptr;
- m_delete = false;
- }
- if (w) {
- m_window = w;
- m_panel = ::new_panel(m_window);
- m_delete = del;
- }
- }
-
- void AttributeOn(attr_t attr) { ::wattron(m_window, attr); }
- void AttributeOff(attr_t attr) { ::wattroff(m_window, attr); }
- void Box(chtype v_char = ACS_VLINE, chtype h_char = ACS_HLINE) {
- ::box(m_window, v_char, h_char);
- }
- void Clear() { ::wclear(m_window); }
- void Erase() { ::werase(m_window); }
- Rect GetBounds() {
- return Rect(GetParentOrigin(), GetSize());
- } // Get the rectangle in our parent window
- int GetChar() { return ::wgetch(m_window); }
- int GetCursorX() { return getcurx(m_window); }
- int GetCursorY() { return getcury(m_window); }
- Rect GetFrame() {
- return Rect(Point(), GetSize());
- } // Get our rectangle in our own coordinate system
- Point GetParentOrigin() { return Point(GetParentX(), GetParentY()); }
- Size GetSize() { return Size(GetWidth(), GetHeight()); }
- int GetParentX() { return getparx(m_window); }
- int GetParentY() { return getpary(m_window); }
- int GetMaxX() { return getmaxx(m_window); }
- int GetMaxY() { return getmaxy(m_window); }
- int GetWidth() { return GetMaxX(); }
- int GetHeight() { return GetMaxY(); }
- void MoveCursor(int x, int y) { ::wmove(m_window, y, x); }
- void MoveWindow(int x, int y) { MoveWindow(Point(x, y)); }
- void Resize(int w, int h) { ::wresize(m_window, h, w); }
- void Resize(const Size &size) {
- ::wresize(m_window, size.height, size.width);
- }
- void PutChar(int ch) { ::waddch(m_window, ch); }
- void PutCString(const char *s, int len = -1) { ::waddnstr(m_window, s, len); }
- void SetBackground(int color_pair_idx) {
- ::wbkgd(m_window, COLOR_PAIR(color_pair_idx));
- }
-
- void PutCStringTruncated(const char *s, int right_pad) {
- int bytes_left = GetWidth() - GetCursorX();
- if (bytes_left > right_pad) {
- bytes_left -= right_pad;
- ::waddnstr(m_window, s, bytes_left);
- }
- }
-
- void MoveWindow(const Point &origin) {
- const bool moving_window = origin != GetParentOrigin();
- if (m_is_subwin && moving_window) {
- // Can't move subwindows, must delete and re-create
- Size size = GetSize();
- Reset(::subwin(m_parent->m_window, size.height, size.width, origin.y,
- origin.x),
- true);
- } else {
- ::mvwin(m_window, origin.y, origin.x);
- }
- }
-
- void SetBounds(const Rect &bounds) {
- const bool moving_window = bounds.origin != GetParentOrigin();
- if (m_is_subwin && moving_window) {
- // Can't move subwindows, must delete and re-create
- Reset(::subwin(m_parent->m_window, bounds.size.height, bounds.size.width,
- bounds.origin.y, bounds.origin.x),
- true);
- } else {
- if (moving_window)
- MoveWindow(bounds.origin);
- Resize(bounds.size);
- }
- }
-
- void Printf(const char *format, ...) __attribute__((format(printf, 2, 3))) {
- va_list args;
- va_start(args, format);
- vwprintw(m_window, format, args);
- va_end(args);
- }
-
- void Touch() {
- ::touchwin(m_window);
- if (m_parent)
- m_parent->Touch();
- }
-
- WindowSP CreateSubWindow(const char *name, const Rect &bounds,
- bool make_active) {
- auto get_window = [this, &bounds]() {
- return m_window
- ? ::subwin(m_window, bounds.size.height, bounds.size.width,
- bounds.origin.y, bounds.origin.x)
- : ::newwin(bounds.size.height, bounds.size.width,
- bounds.origin.y, bounds.origin.x);
- };
- WindowSP subwindow_sp = std::make_shared<Window>(name, get_window(), true);
- subwindow_sp->m_is_subwin = subwindow_sp.operator bool();
- subwindow_sp->m_parent = this;
- if (make_active) {
- m_prev_active_window_idx = m_curr_active_window_idx;
- m_curr_active_window_idx = m_subwindows.size();
- }
- m_subwindows.push_back(subwindow_sp);
- ::top_panel(subwindow_sp->m_panel);
- m_needs_update = true;
- return subwindow_sp;
- }
-
- bool RemoveSubWindow(Window *window) {
- Windows::iterator pos, end = m_subwindows.end();
- size_t i = 0;
- for (pos = m_subwindows.begin(); pos != end; ++pos, ++i) {
- if ((*pos).get() == window) {
- if (m_prev_active_window_idx == i)
- m_prev_active_window_idx = UINT32_MAX;
- else if (m_prev_active_window_idx != UINT32_MAX &&
- m_prev_active_window_idx > i)
- --m_prev_active_window_idx;
-
- if (m_curr_active_window_idx == i)
- m_curr_active_window_idx = UINT32_MAX;
- else if (m_curr_active_window_idx != UINT32_MAX &&
- m_curr_active_window_idx > i)
- --m_curr_active_window_idx;
- window->Erase();
- m_subwindows.erase(pos);
- m_needs_update = true;
- if (m_parent)
- m_parent->Touch();
- else
- ::touchwin(stdscr);
- return true;
- }
- }
- return false;
- }
-
- WindowSP FindSubWindow(const char *name) {
- Windows::iterator pos, end = m_subwindows.end();
- size_t i = 0;
- for (pos = m_subwindows.begin(); pos != end; ++pos, ++i) {
- if ((*pos)->m_name == name)
- return *pos;
- }
- return WindowSP();
- }
-
- void RemoveSubWindows() {
- m_curr_active_window_idx = UINT32_MAX;
- m_prev_active_window_idx = UINT32_MAX;
- for (Windows::iterator pos = m_subwindows.begin();
- pos != m_subwindows.end(); pos = m_subwindows.erase(pos)) {
- (*pos)->Erase();
- }
- if (m_parent)
- m_parent->Touch();
- else
- ::touchwin(stdscr);
- }
-
- WINDOW *get() { return m_window; }
-
- operator WINDOW *() { return m_window; }
-
- // Window drawing utilities
- void DrawTitleBox(const char *title, const char *bottom_message = nullptr) {
- attr_t attr = 0;
- if (IsActive())
- attr = A_BOLD | COLOR_PAIR(2);
- else
- attr = 0;
- if (attr)
- AttributeOn(attr);
-
- Box();
- MoveCursor(3, 0);
-
- if (title && title[0]) {
- PutChar('<');
- PutCString(title);
- PutChar('>');
- }
-
- if (bottom_message && bottom_message[0]) {
- int bottom_message_length = strlen(bottom_message);
- int x = GetWidth() - 3 - (bottom_message_length + 2);
-
- if (x > 0) {
- MoveCursor(x, GetHeight() - 1);
- PutChar('[');
- PutCString(bottom_message);
- PutChar(']');
- } else {
- MoveCursor(1, GetHeight() - 1);
- PutChar('[');
- PutCStringTruncated(bottom_message, 1);
- }
- }
- if (attr)
- AttributeOff(attr);
- }
-
- virtual void Draw(bool force) {
- if (m_delegate_sp && m_delegate_sp->WindowDelegateDraw(*this, force))
- return;
-
- for (auto &subwindow_sp : m_subwindows)
- subwindow_sp->Draw(force);
- }
-
- bool CreateHelpSubwindow() {
- if (m_delegate_sp) {
- const char *text = m_delegate_sp->WindowDelegateGetHelpText();
- KeyHelp *key_help = m_delegate_sp->WindowDelegateGetKeyHelp();
- if ((text && text[0]) || key_help) {
- std::unique_ptr<HelpDialogDelegate> help_delegate_up(
- new HelpDialogDelegate(text, key_help));
- const size_t num_lines = help_delegate_up->GetNumLines();
- const size_t max_length = help_delegate_up->GetMaxLineLength();
- Rect bounds = GetBounds();
- bounds.Inset(1, 1);
- if (max_length + 4 < static_cast<size_t>(bounds.size.width)) {
- bounds.origin.x += (bounds.size.width - max_length + 4) / 2;
- bounds.size.width = max_length + 4;
- } else {
- if (bounds.size.width > 100) {
- const int inset_w = bounds.size.width / 4;
- bounds.origin.x += inset_w;
- bounds.size.width -= 2 * inset_w;
- }
- }
-
- if (num_lines + 2 < static_cast<size_t>(bounds.size.height)) {
- bounds.origin.y += (bounds.size.height - num_lines + 2) / 2;
- bounds.size.height = num_lines + 2;
- } else {
- if (bounds.size.height > 100) {
- const int inset_h = bounds.size.height / 4;
- bounds.origin.y += inset_h;
- bounds.size.height -= 2 * inset_h;
- }
- }
- WindowSP help_window_sp;
- Window *parent_window = GetParent();
- if (parent_window)
- help_window_sp = parent_window->CreateSubWindow("Help", bounds, true);
- else
- help_window_sp = CreateSubWindow("Help", bounds, true);
- help_window_sp->SetDelegate(
- WindowDelegateSP(help_delegate_up.release()));
- return true;
- }
- }
- return false;
- }
-
- virtual HandleCharResult HandleChar(int key) {
- // Always check the active window first
- HandleCharResult result = eKeyNotHandled;
- WindowSP active_window_sp = GetActiveWindow();
- if (active_window_sp) {
- result = active_window_sp->HandleChar(key);
- if (result != eKeyNotHandled)
- return result;
- }
-
- if (m_delegate_sp) {
- result = m_delegate_sp->WindowDelegateHandleChar(*this, key);
- if (result != eKeyNotHandled)
- return result;
- }
-
- // Then check for any windows that want any keys that weren't handled. This
- // is typically only for a menubar. Make a copy of the subwindows in case
- // any HandleChar() functions muck with the subwindows. If we don't do
- // this, we can crash when iterating over the subwindows.
- Windows subwindows(m_subwindows);
- for (auto subwindow_sp : subwindows) {
- if (!subwindow_sp->m_can_activate) {
- HandleCharResult result = subwindow_sp->HandleChar(key);
- if (result != eKeyNotHandled)
- return result;
- }
- }
-
- return eKeyNotHandled;
- }
-
- WindowSP GetActiveWindow() {
- if (!m_subwindows.empty()) {
- if (m_curr_active_window_idx >= m_subwindows.size()) {
- if (m_prev_active_window_idx < m_subwindows.size()) {
- m_curr_active_window_idx = m_prev_active_window_idx;
- m_prev_active_window_idx = UINT32_MAX;
- } else if (IsActive()) {
- m_prev_active_window_idx = UINT32_MAX;
- m_curr_active_window_idx = UINT32_MAX;
-
- // Find first window that wants to be active if this window is active
- const size_t num_subwindows = m_subwindows.size();
- for (size_t i = 0; i < num_subwindows; ++i) {
- if (m_subwindows[i]->GetCanBeActive()) {
- m_curr_active_window_idx = i;
- break;
- }
- }
- }
- }
-
- if (m_curr_active_window_idx < m_subwindows.size())
- return m_subwindows[m_curr_active_window_idx];
- }
- return WindowSP();
- }
-
- bool GetCanBeActive() const { return m_can_activate; }
-
- void SetCanBeActive(bool b) { m_can_activate = b; }
-
- void SetDelegate(const WindowDelegateSP &delegate_sp) {
- m_delegate_sp = delegate_sp;
- }
-
- Window *GetParent() const { return m_parent; }
-
- bool IsActive() const {
- if (m_parent)
- return m_parent->GetActiveWindow().get() == this;
- else
- return true; // Top level window is always active
- }
-
- void SelectNextWindowAsActive() {
- // Move active focus to next window
- const size_t num_subwindows = m_subwindows.size();
- if (m_curr_active_window_idx == UINT32_MAX) {
- uint32_t idx = 0;
- for (auto subwindow_sp : m_subwindows) {
- if (subwindow_sp->GetCanBeActive()) {
- m_curr_active_window_idx = idx;
- break;
- }
- ++idx;
- }
- } else if (m_curr_active_window_idx + 1 < num_subwindows) {
- bool handled = false;
- m_prev_active_window_idx = m_curr_active_window_idx;
- for (size_t idx = m_curr_active_window_idx + 1; idx < num_subwindows;
- ++idx) {
- if (m_subwindows[idx]->GetCanBeActive()) {
- m_curr_active_window_idx = idx;
- handled = true;
- break;
- }
- }
- if (!handled) {
- for (size_t idx = 0; idx <= m_prev_active_window_idx; ++idx) {
- if (m_subwindows[idx]->GetCanBeActive()) {
- m_curr_active_window_idx = idx;
- break;
- }
- }
- }
- } else {
- m_prev_active_window_idx = m_curr_active_window_idx;
- for (size_t idx = 0; idx < num_subwindows; ++idx) {
- if (m_subwindows[idx]->GetCanBeActive()) {
- m_curr_active_window_idx = idx;
- break;
- }
- }
- }
- }
-
- const char *GetName() const { return m_name.c_str(); }
-
-protected:
- std::string m_name;
- WINDOW *m_window;
- PANEL *m_panel;
- Window *m_parent;
- Windows m_subwindows;
- WindowDelegateSP m_delegate_sp;
- uint32_t m_curr_active_window_idx;
- uint32_t m_prev_active_window_idx;
- bool m_delete;
- bool m_needs_update;
- bool m_can_activate;
- bool m_is_subwin;
-
-private:
- DISALLOW_COPY_AND_ASSIGN(Window);
-};
-
-class MenuDelegate {
-public:
- virtual ~MenuDelegate() = default;
-
- virtual MenuActionResult MenuDelegateAction(Menu &menu) = 0;
-};
-
-class Menu : public WindowDelegate {
-public:
- enum class Type { Invalid, Bar, Item, Separator };
-
- // Menubar or separator constructor
- Menu(Type type);
-
- // Menuitem constructor
- Menu(const char *name, const char *key_name, int key_value,
- uint64_t identifier);
-
- ~Menu() override = default;
-
- const MenuDelegateSP &GetDelegate() const { return m_delegate_sp; }
-
- void SetDelegate(const MenuDelegateSP &delegate_sp) {
- m_delegate_sp = delegate_sp;
- }
-
- void RecalculateNameLengths();
-
- void AddSubmenu(const MenuSP &menu_sp);
-
- int DrawAndRunMenu(Window &window);
-
- void DrawMenuTitle(Window &window, bool highlight);
-
- bool WindowDelegateDraw(Window &window, bool force) override;
-
- HandleCharResult WindowDelegateHandleChar(Window &window, int key) override;
-
- MenuActionResult ActionPrivate(Menu &menu) {
- MenuActionResult result = MenuActionResult::NotHandled;
- if (m_delegate_sp) {
- result = m_delegate_sp->MenuDelegateAction(menu);
- if (result != MenuActionResult::NotHandled)
- return result;
- } else if (m_parent) {
- result = m_parent->ActionPrivate(menu);
- if (result != MenuActionResult::NotHandled)
- return result;
- }
- return m_canned_result;
- }
-
- MenuActionResult Action() {
- // Call the recursive action so it can try to handle it with the menu
- // delegate, and if not, try our parent menu
- return ActionPrivate(*this);
- }
-
- void SetCannedResult(MenuActionResult result) { m_canned_result = result; }
-
- Menus &GetSubmenus() { return m_submenus; }
-
- const Menus &GetSubmenus() const { return m_submenus; }
-
- int GetSelectedSubmenuIndex() const { return m_selected; }
-
- void SetSelectedSubmenuIndex(int idx) { m_selected = idx; }
-
- Type GetType() const { return m_type; }
-
- int GetStartingColumn() const { return m_start_col; }
-
- void SetStartingColumn(int col) { m_start_col = col; }
-
- int GetKeyValue() const { return m_key_value; }
-
- std::string &GetName() { return m_name; }
-
- int GetDrawWidth() const {
- return m_max_submenu_name_length + m_max_submenu_key_name_length + 8;
- }
-
- uint64_t GetIdentifier() const { return m_identifier; }
-
- void SetIdentifier(uint64_t identifier) { m_identifier = identifier; }
-
-protected:
- std::string m_name;
- std::string m_key_name;
- uint64_t m_identifier;
- Type m_type;
- int m_key_value;
- int m_start_col;
- int m_max_submenu_name_length;
- int m_max_submenu_key_name_length;
- int m_selected;
- Menu *m_parent;
- Menus m_submenus;
- WindowSP m_menu_window_sp;
- MenuActionResult m_canned_result;
- MenuDelegateSP m_delegate_sp;
-};
-
-// Menubar or separator constructor
-Menu::Menu(Type type)
- : m_name(), m_key_name(), m_identifier(0), m_type(type), m_key_value(0),
- m_start_col(0), m_max_submenu_name_length(0),
- m_max_submenu_key_name_length(0), m_selected(0), m_parent(nullptr),
- m_submenus(), m_canned_result(MenuActionResult::NotHandled),
- m_delegate_sp() {}
-
-// Menuitem constructor
-Menu::Menu(const char *name, const char *key_name, int key_value,
- uint64_t identifier)
- : m_name(), m_key_name(), m_identifier(identifier), m_type(Type::Invalid),
- m_key_value(key_value), m_start_col(0), m_max_submenu_name_length(0),
- m_max_submenu_key_name_length(0), m_selected(0), m_parent(nullptr),
- m_submenus(), m_canned_result(MenuActionResult::NotHandled),
- m_delegate_sp() {
- if (name && name[0]) {
- m_name = name;
- m_type = Type::Item;
- if (key_name && key_name[0])
- m_key_name = key_name;
- } else {
- m_type = Type::Separator;
- }
-}
-
-void Menu::RecalculateNameLengths() {
- m_max_submenu_name_length = 0;
- m_max_submenu_key_name_length = 0;
- Menus &submenus = GetSubmenus();
- const size_t num_submenus = submenus.size();
- for (size_t i = 0; i < num_submenus; ++i) {
- Menu *submenu = submenus[i].get();
- if (static_cast<size_t>(m_max_submenu_name_length) < submenu->m_name.size())
- m_max_submenu_name_length = submenu->m_name.size();
- if (static_cast<size_t>(m_max_submenu_key_name_length) <
- submenu->m_key_name.size())
- m_max_submenu_key_name_length = submenu->m_key_name.size();
- }
-}
-
-void Menu::AddSubmenu(const MenuSP &menu_sp) {
- menu_sp->m_parent = this;
- if (static_cast<size_t>(m_max_submenu_name_length) < menu_sp->m_name.size())
- m_max_submenu_name_length = menu_sp->m_name.size();
- if (static_cast<size_t>(m_max_submenu_key_name_length) <
- menu_sp->m_key_name.size())
- m_max_submenu_key_name_length = menu_sp->m_key_name.size();
- m_submenus.push_back(menu_sp);
-}
-
-void Menu::DrawMenuTitle(Window &window, bool highlight) {
- if (m_type == Type::Separator) {
- window.MoveCursor(0, window.GetCursorY());
- window.PutChar(ACS_LTEE);
- int width = window.GetWidth();
- if (width > 2) {
- width -= 2;
- for (int i = 0; i < width; ++i)
- window.PutChar(ACS_HLINE);
- }
- window.PutChar(ACS_RTEE);
- } else {
- const int shortcut_key = m_key_value;
- bool underlined_shortcut = false;
- const attr_t hilgight_attr = A_REVERSE;
- if (highlight)
- window.AttributeOn(hilgight_attr);
- if (isprint(shortcut_key)) {
- size_t lower_pos = m_name.find(tolower(shortcut_key));
- size_t upper_pos = m_name.find(toupper(shortcut_key));
- const char *name = m_name.c_str();
- size_t pos = std::min<size_t>(lower_pos, upper_pos);
- if (pos != std::string::npos) {
- underlined_shortcut = true;
- if (pos > 0) {
- window.PutCString(name, pos);
- name += pos;
- }
- const attr_t shortcut_attr = A_UNDERLINE | A_BOLD;
- window.AttributeOn(shortcut_attr);
- window.PutChar(name[0]);
- window.AttributeOff(shortcut_attr);
- name++;
- if (name[0])
- window.PutCString(name);
- }
- }
-
- if (!underlined_shortcut) {
- window.PutCString(m_name.c_str());
- }
-
- if (highlight)
- window.AttributeOff(hilgight_attr);
-
- if (m_key_name.empty()) {
- if (!underlined_shortcut && isprint(m_key_value)) {
- window.AttributeOn(COLOR_PAIR(3));
- window.Printf(" (%c)", m_key_value);
- window.AttributeOff(COLOR_PAIR(3));
- }
- } else {
- window.AttributeOn(COLOR_PAIR(3));
- window.Printf(" (%s)", m_key_name.c_str());
- window.AttributeOff(COLOR_PAIR(3));
- }
- }
-}
-
-bool Menu::WindowDelegateDraw(Window &window, bool force) {
- Menus &submenus = GetSubmenus();
- const size_t num_submenus = submenus.size();
- const int selected_idx = GetSelectedSubmenuIndex();
- Menu::Type menu_type = GetType();
- switch (menu_type) {
- case Menu::Type::Bar: {
- window.SetBackground(2);
- window.MoveCursor(0, 0);
- for (size_t i = 0; i < num_submenus; ++i) {
- Menu *menu = submenus[i].get();
- if (i > 0)
- window.PutChar(' ');
- menu->SetStartingColumn(window.GetCursorX());
- window.PutCString("| ");
- menu->DrawMenuTitle(window, false);
- }
- window.PutCString(" |");
- } break;
-
- case Menu::Type::Item: {
- int y = 1;
- int x = 3;
- // Draw the menu
- int cursor_x = 0;
- int cursor_y = 0;
- window.Erase();
- window.SetBackground(2);
- window.Box();
- for (size_t i = 0; i < num_submenus; ++i) {
- const bool is_selected = (i == static_cast<size_t>(selected_idx));
- window.MoveCursor(x, y + i);
- if (is_selected) {
- // Remember where we want the cursor to be
- cursor_x = x - 1;
- cursor_y = y + i;
- }
- submenus[i]->DrawMenuTitle(window, is_selected);
- }
- window.MoveCursor(cursor_x, cursor_y);
- } break;
-
- default:
- case Menu::Type::Separator:
- break;
- }
- return true; // Drawing handled...
-}
-
-HandleCharResult Menu::WindowDelegateHandleChar(Window &window, int key) {
- HandleCharResult result = eKeyNotHandled;
-
- Menus &submenus = GetSubmenus();
- const size_t num_submenus = submenus.size();
- const int selected_idx = GetSelectedSubmenuIndex();
- Menu::Type menu_type = GetType();
- if (menu_type == Menu::Type::Bar) {
- MenuSP run_menu_sp;
- switch (key) {
- case KEY_DOWN:
- case KEY_UP:
- // Show last menu or first menu
- if (selected_idx < static_cast<int>(num_submenus))
- run_menu_sp = submenus[selected_idx];
- else if (!submenus.empty())
- run_menu_sp = submenus.front();
- result = eKeyHandled;
- break;
-
- case KEY_RIGHT:
- ++m_selected;
- if (m_selected >= static_cast<int>(num_submenus))
- m_selected = 0;
- if (m_selected < static_cast<int>(num_submenus))
- run_menu_sp = submenus[m_selected];
- else if (!submenus.empty())
- run_menu_sp = submenus.front();
- result = eKeyHandled;
- break;
-
- case KEY_LEFT:
- --m_selected;
- if (m_selected < 0)
- m_selected = num_submenus - 1;
- if (m_selected < static_cast<int>(num_submenus))
- run_menu_sp = submenus[m_selected];
- else if (!submenus.empty())
- run_menu_sp = submenus.front();
- result = eKeyHandled;
- break;
-
- default:
- for (size_t i = 0; i < num_submenus; ++i) {
- if (submenus[i]->GetKeyValue() == key) {
- SetSelectedSubmenuIndex(i);
- run_menu_sp = submenus[i];
- result = eKeyHandled;
- break;
- }
- }
- break;
- }
-
- if (run_menu_sp) {
- // Run the action on this menu in case we need to populate the menu with
- // dynamic content and also in case check marks, and any other menu
- // decorations need to be calculated
- if (run_menu_sp->Action() == MenuActionResult::Quit)
- return eQuitApplication;
-
- Rect menu_bounds;
- menu_bounds.origin.x = run_menu_sp->GetStartingColumn();
- menu_bounds.origin.y = 1;
- menu_bounds.size.width = run_menu_sp->GetDrawWidth();
- menu_bounds.size.height = run_menu_sp->GetSubmenus().size() + 2;
- if (m_menu_window_sp)
- window.GetParent()->RemoveSubWindow(m_menu_window_sp.get());
-
- m_menu_window_sp = window.GetParent()->CreateSubWindow(
- run_menu_sp->GetName().c_str(), menu_bounds, true);
- m_menu_window_sp->SetDelegate(run_menu_sp);
- }
- } else if (menu_type == Menu::Type::Item) {
- switch (key) {
- case KEY_DOWN:
- if (m_submenus.size() > 1) {
- const int start_select = m_selected;
- while (++m_selected != start_select) {
- if (static_cast<size_t>(m_selected) >= num_submenus)
- m_selected = 0;
- if (m_submenus[m_selected]->GetType() == Type::Separator)
- continue;
- else
- break;
- }
- return eKeyHandled;
- }
- break;
-
- case KEY_UP:
- if (m_submenus.size() > 1) {
- const int start_select = m_selected;
- while (--m_selected != start_select) {
- if (m_selected < static_cast<int>(0))
- m_selected = num_submenus - 1;
- if (m_submenus[m_selected]->GetType() == Type::Separator)
- continue;
- else
- break;
- }
- return eKeyHandled;
- }
- break;
-
- case KEY_RETURN:
- if (static_cast<size_t>(selected_idx) < num_submenus) {
- if (submenus[selected_idx]->Action() == MenuActionResult::Quit)
- return eQuitApplication;
- window.GetParent()->RemoveSubWindow(&window);
- return eKeyHandled;
- }
- break;
-
- case KEY_ESCAPE: // Beware: pressing escape key has 1 to 2 second delay in
- // case other chars are entered for escaped sequences
- window.GetParent()->RemoveSubWindow(&window);
- return eKeyHandled;
-
- default:
- for (size_t i = 0; i < num_submenus; ++i) {
- Menu *menu = submenus[i].get();
- if (menu->GetKeyValue() == key) {
- SetSelectedSubmenuIndex(i);
- window.GetParent()->RemoveSubWindow(&window);
- if (menu->Action() == MenuActionResult::Quit)
- return eQuitApplication;
- return eKeyHandled;
- }
- }
- break;
- }
- } else if (menu_type == Menu::Type::Separator) {
- }
- return result;
-}
-
-class Application {
-public:
- Application(FILE *in, FILE *out)
- : m_window_sp(), m_screen(nullptr), m_in(in), m_out(out) {}
-
- ~Application() {
- m_window_delegates.clear();
- m_window_sp.reset();
- if (m_screen) {
- ::delscreen(m_screen);
- m_screen = nullptr;
- }
- }
-
- void Initialize() {
- ::setlocale(LC_ALL, "");
- ::setlocale(LC_CTYPE, "");
- m_screen = ::newterm(nullptr, m_out, m_in);
- ::start_color();
- ::curs_set(0);
- ::noecho();
- ::keypad(stdscr, TRUE);
- }
-
- void Terminate() { ::endwin(); }
-
- void Run(Debugger &debugger) {
- bool done = false;
- int delay_in_tenths_of_a_second = 1;
-
- // Alas the threading model in curses is a bit lame so we need to resort to
- // polling every 0.5 seconds. We could poll for stdin ourselves and then
- // pass the keys down but then we need to translate all of the escape
- // sequences ourselves. So we resort to polling for input because we need
- // to receive async process events while in this loop.
-
- halfdelay(delay_in_tenths_of_a_second); // Poll using some number of tenths
- // of seconds seconds when calling
- // Window::GetChar()
-
- ListenerSP listener_sp(
- Listener::MakeListener("lldb.IOHandler.curses.Application"));
- ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
- ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
- ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
- debugger.EnableForwardEvents(listener_sp);
-
- bool update = true;
-#if defined(__APPLE__)
- std::deque<int> escape_chars;
-#endif
-
- while (!done) {
- if (update) {
- m_window_sp->Draw(false);
- // All windows should be calling Window::DeferredRefresh() instead of
- // Window::Refresh() so we can do a single update and avoid any screen
- // blinking
- update_panels();
-
- // Cursor hiding isn't working on MacOSX, so hide it in the top left
- // corner
- m_window_sp->MoveCursor(0, 0);
-
- doupdate();
- update = false;
- }
-
-#if defined(__APPLE__)
- // Terminal.app doesn't map its function keys correctly, F1-F4 default
- // to: \033OP, \033OQ, \033OR, \033OS, so lets take care of this here if
- // possible
- int ch;
- if (escape_chars.empty())
- ch = m_window_sp->GetChar();
- else {
- ch = escape_chars.front();
- escape_chars.pop_front();
- }
- if (ch == KEY_ESCAPE) {
- int ch2 = m_window_sp->GetChar();
- if (ch2 == 'O') {
- int ch3 = m_window_sp->GetChar();
- switch (ch3) {
- case 'P':
- ch = KEY_F(1);
- break;
- case 'Q':
- ch = KEY_F(2);
- break;
- case 'R':
- ch = KEY_F(3);
- break;
- case 'S':
- ch = KEY_F(4);
- break;
- default:
- escape_chars.push_back(ch2);
- if (ch3 != -1)
- escape_chars.push_back(ch3);
- break;
- }
- } else if (ch2 != -1)
- escape_chars.push_back(ch2);
- }
-#else
- int ch = m_window_sp->GetChar();
-
-#endif
- if (ch == -1) {
- if (feof(m_in) || ferror(m_in)) {
- done = true;
- } else {
- // Just a timeout from using halfdelay(), check for events
- EventSP event_sp;
- while (listener_sp->PeekAtNextEvent()) {
- listener_sp->GetEvent(event_sp, std::chrono::seconds(0));
-
- if (event_sp) {
- Broadcaster *broadcaster = event_sp->GetBroadcaster();
- if (broadcaster) {
- // uint32_t event_type = event_sp->GetType();
- ConstString broadcaster_class(
- broadcaster->GetBroadcasterClass());
- if (broadcaster_class == broadcaster_class_process) {
- debugger.GetCommandInterpreter().UpdateExecutionContext(
- nullptr);
- update = true;
- continue; // Don't get any key, just update our view
- }
- }
- }
- }
- }
- } else {
- HandleCharResult key_result = m_window_sp->HandleChar(ch);
- switch (key_result) {
- case eKeyHandled:
- debugger.GetCommandInterpreter().UpdateExecutionContext(nullptr);
- update = true;
- break;
- case eKeyNotHandled:
- break;
- case eQuitApplication:
- done = true;
- break;
- }
- }
- }
-
- debugger.CancelForwardEvents(listener_sp);
- }
-
- WindowSP &GetMainWindow() {
- if (!m_window_sp)
- m_window_sp = std::make_shared<Window>("main", stdscr, false);
- return m_window_sp;
- }
-
-protected:
- WindowSP m_window_sp;
- WindowDelegates m_window_delegates;
- SCREEN *m_screen;
- FILE *m_in;
- FILE *m_out;
-};
-
-} // namespace curses
-
-using namespace curses;
-
-struct Row {
- ValueObjectManager value;
- Row *parent;
- // The process stop ID when the children were calculated.
- uint32_t children_stop_id;
- int row_idx;
- int x;
- int y;
- bool might_have_children;
- bool expanded;
- bool calculated_children;
- std::vector<Row> children;
-
- Row(const ValueObjectSP &v, Row *p)
- : value(v, lldb::eDynamicDontRunTarget, true), parent(p), row_idx(0),
- x(1), y(1), might_have_children(v ? v->MightHaveChildren() : false),
- expanded(false), calculated_children(false), children() {}
-
- size_t GetDepth() const {
- if (parent)
- return 1 + parent->GetDepth();
- return 0;
- }
-
- void Expand() { expanded = true; }
-
- std::vector<Row> &GetChildren() {
- ProcessSP process_sp = value.GetProcessSP();
- auto stop_id = process_sp->GetStopID();
- if (process_sp && stop_id != children_stop_id) {
- children_stop_id = stop_id;
- calculated_children = false;
- }
- if (!calculated_children) {
- children.clear();
- calculated_children = true;
- ValueObjectSP valobj = value.GetSP();
- if (valobj) {
- const size_t num_children = valobj->GetNumChildren();
- for (size_t i = 0; i < num_children; ++i) {
- children.push_back(Row(valobj->GetChildAtIndex(i, true), this));
- }
- }
- }
- return children;
- }
-
- void Unexpand() {
- expanded = false;
- calculated_children = false;
- children.clear();
- }
-
- void DrawTree(Window &window) {
- if (parent)
- parent->DrawTreeForChild(window, this, 0);
-
- if (might_have_children) {
- // It we can get UTF8 characters to work we should try to use the
- // "symbol" UTF8 string below
- // const char *symbol = "";
- // if (row.expanded)
- // symbol = "\xe2\x96\xbd ";
- // else
- // symbol = "\xe2\x96\xb7 ";
- // window.PutCString (symbol);
-
- // The ACS_DARROW and ACS_RARROW don't look very nice they are just a 'v'
- // or '>' character...
- // if (expanded)
- // window.PutChar (ACS_DARROW);
- // else
- // window.PutChar (ACS_RARROW);
- // Since we can't find any good looking right arrow/down arrow symbols,
- // just use a diamond...
- window.PutChar(ACS_DIAMOND);
- window.PutChar(ACS_HLINE);
- }
- }
-
- void DrawTreeForChild(Window &window, Row *child, uint32_t reverse_depth) {
- if (parent)
- parent->DrawTreeForChild(window, this, reverse_depth + 1);
-
- if (&GetChildren().back() == child) {
- // Last child
- if (reverse_depth == 0) {
- window.PutChar(ACS_LLCORNER);
- window.PutChar(ACS_HLINE);
- } else {
- window.PutChar(' ');
- window.PutChar(' ');
- }
- } else {
- if (reverse_depth == 0) {
- window.PutChar(ACS_LTEE);
- window.PutChar(ACS_HLINE);
- } else {
- window.PutChar(ACS_VLINE);
- window.PutChar(' ');
- }
- }
- }
-};
-
-struct DisplayOptions {
- bool show_types;
-};
-
-class TreeItem;
-
-class TreeDelegate {
-public:
- TreeDelegate() = default;
- virtual ~TreeDelegate() = default;
-
- virtual void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) = 0;
- virtual void TreeDelegateGenerateChildren(TreeItem &item) = 0;
- virtual bool TreeDelegateItemSelected(
- TreeItem &item) = 0; // Return true if we need to update views
-};
-
-typedef std::shared_ptr<TreeDelegate> TreeDelegateSP;
-
-class TreeItem {
-public:
- TreeItem(TreeItem *parent, TreeDelegate &delegate, bool might_have_children)
- : m_parent(parent), m_delegate(delegate), m_user_data(nullptr),
- m_identifier(0), m_row_idx(-1), m_children(),
- m_might_have_children(might_have_children), m_is_expanded(false) {}
-
- TreeItem &operator=(const TreeItem &rhs) {
- if (this != &rhs) {
- m_parent = rhs.m_parent;
- m_delegate = rhs.m_delegate;
- m_user_data = rhs.m_user_data;
- m_identifier = rhs.m_identifier;
- m_row_idx = rhs.m_row_idx;
- m_children = rhs.m_children;
- m_might_have_children = rhs.m_might_have_children;
- m_is_expanded = rhs.m_is_expanded;
- }
- return *this;
- }
-
- size_t GetDepth() const {
- if (m_parent)
- return 1 + m_parent->GetDepth();
- return 0;
- }
-
- int GetRowIndex() const { return m_row_idx; }
-
- void ClearChildren() { m_children.clear(); }
-
- void Resize(size_t n, const TreeItem &t) { m_children.resize(n, t); }
-
- TreeItem &operator[](size_t i) { return m_children[i]; }
-
- void SetRowIndex(int row_idx) { m_row_idx = row_idx; }
-
- size_t GetNumChildren() {
- m_delegate.TreeDelegateGenerateChildren(*this);
- return m_children.size();
- }
-
- void ItemWasSelected() { m_delegate.TreeDelegateItemSelected(*this); }
-
- void CalculateRowIndexes(int &row_idx) {
- SetRowIndex(row_idx);
- ++row_idx;
-
- const bool expanded = IsExpanded();
-
- // The root item must calculate its children, or we must calculate the
- // number of children if the item is expanded
- if (m_parent == nullptr || expanded)
- GetNumChildren();
-
- for (auto &item : m_children) {
- if (expanded)
- item.CalculateRowIndexes(row_idx);
- else
- item.SetRowIndex(-1);
- }
- }
-
- TreeItem *GetParent() { return m_parent; }
-
- bool IsExpanded() const { return m_is_expanded; }
-
- void Expand() { m_is_expanded = true; }
-
- void Unexpand() { m_is_expanded = false; }
-
- bool Draw(Window &window, const int first_visible_row,
- const uint32_t selected_row_idx, int &row_idx, int &num_rows_left) {
- if (num_rows_left <= 0)
- return false;
-
- if (m_row_idx >= first_visible_row) {
- window.MoveCursor(2, row_idx + 1);
-
- if (m_parent)
- m_parent->DrawTreeForChild(window, this, 0);
-
- if (m_might_have_children) {
- // It we can get UTF8 characters to work we should try to use the
- // "symbol" UTF8 string below
- // const char *symbol = "";
- // if (row.expanded)
- // symbol = "\xe2\x96\xbd ";
- // else
- // symbol = "\xe2\x96\xb7 ";
- // window.PutCString (symbol);
-
- // The ACS_DARROW and ACS_RARROW don't look very nice they are just a
- // 'v' or '>' character...
- // if (expanded)
- // window.PutChar (ACS_DARROW);
- // else
- // window.PutChar (ACS_RARROW);
- // Since we can't find any good looking right arrow/down arrow symbols,
- // just use a diamond...
- window.PutChar(ACS_DIAMOND);
- window.PutChar(ACS_HLINE);
- }
- bool highlight = (selected_row_idx == static_cast<size_t>(m_row_idx)) &&
- window.IsActive();
-
- if (highlight)
- window.AttributeOn(A_REVERSE);
-
- m_delegate.TreeDelegateDrawTreeItem(*this, window);
-
- if (highlight)
- window.AttributeOff(A_REVERSE);
- ++row_idx;
- --num_rows_left;
- }
-
- if (num_rows_left <= 0)
- return false; // We are done drawing...
-
- if (IsExpanded()) {
- for (auto &item : m_children) {
- // If we displayed all the rows and item.Draw() returns false we are
- // done drawing and can exit this for loop
- if (!item.Draw(window, first_visible_row, selected_row_idx, row_idx,
- num_rows_left))
- break;
- }
- }
- return num_rows_left >= 0; // Return true if not done drawing yet
- }
-
- void DrawTreeForChild(Window &window, TreeItem *child,
- uint32_t reverse_depth) {
- if (m_parent)
- m_parent->DrawTreeForChild(window, this, reverse_depth + 1);
-
- if (&m_children.back() == child) {
- // Last child
- if (reverse_depth == 0) {
- window.PutChar(ACS_LLCORNER);
- window.PutChar(ACS_HLINE);
- } else {
- window.PutChar(' ');
- window.PutChar(' ');
- }
- } else {
- if (reverse_depth == 0) {
- window.PutChar(ACS_LTEE);
- window.PutChar(ACS_HLINE);
- } else {
- window.PutChar(ACS_VLINE);
- window.PutChar(' ');
- }
- }
- }
-
- TreeItem *GetItemForRowIndex(uint32_t row_idx) {
- if (static_cast<uint32_t>(m_row_idx) == row_idx)
- return this;
- if (m_children.empty())
- return nullptr;
- if (IsExpanded()) {
- for (auto &item : m_children) {
- TreeItem *selected_item_ptr = item.GetItemForRowIndex(row_idx);
- if (selected_item_ptr)
- return selected_item_ptr;
- }
- }
- return nullptr;
- }
-
- void *GetUserData() const { return m_user_data; }
-
- void SetUserData(void *user_data) { m_user_data = user_data; }
-
- uint64_t GetIdentifier() const { return m_identifier; }
-
- void SetIdentifier(uint64_t identifier) { m_identifier = identifier; }
-
- void SetMightHaveChildren(bool b) { m_might_have_children = b; }
-
-protected:
- TreeItem *m_parent;
- TreeDelegate &m_delegate;
- void *m_user_data;
- uint64_t m_identifier;
- int m_row_idx; // Zero based visible row index, -1 if not visible or for the
- // root item
- std::vector<TreeItem> m_children;
- bool m_might_have_children;
- bool m_is_expanded;
-};
-
-class TreeWindowDelegate : public WindowDelegate {
-public:
- TreeWindowDelegate(Debugger &debugger, const TreeDelegateSP &delegate_sp)
- : m_debugger(debugger), m_delegate_sp(delegate_sp),
- m_root(nullptr, *delegate_sp, true), m_selected_item(nullptr),
- m_num_rows(0), m_selected_row_idx(0), m_first_visible_row(0),
- m_min_x(0), m_min_y(0), m_max_x(0), m_max_y(0) {}
-
- int NumVisibleRows() const { return m_max_y - m_min_y; }
-
- bool WindowDelegateDraw(Window &window, bool force) override {
- ExecutionContext exe_ctx(
- m_debugger.GetCommandInterpreter().GetExecutionContext());
- Process *process = exe_ctx.GetProcessPtr();
-
- bool display_content = false;
- if (process) {
- StateType state = process->GetState();
- if (StateIsStoppedState(state, true)) {
- // We are stopped, so it is ok to
- display_content = true;
- } else if (StateIsRunningState(state)) {
- return true; // Don't do any updating when we are running
- }
- }
-
- m_min_x = 2;
- m_min_y = 1;
- m_max_x = window.GetWidth() - 1;
- m_max_y = window.GetHeight() - 1;
-
- window.Erase();
- window.DrawTitleBox(window.GetName());
-
- if (display_content) {
- const int num_visible_rows = NumVisibleRows();
- m_num_rows = 0;
- m_root.CalculateRowIndexes(m_num_rows);
-
- // If we unexpanded while having something selected our total number of
- // rows is less than the num visible rows, then make sure we show all the
- // rows by setting the first visible row accordingly.
- if (m_first_visible_row > 0 && m_num_rows < num_visible_rows)
- m_first_visible_row = 0;
-
- // Make sure the selected row is always visible
- if (m_selected_row_idx < m_first_visible_row)
- m_first_visible_row = m_selected_row_idx;
- else if (m_first_visible_row + num_visible_rows <= m_selected_row_idx)
- m_first_visible_row = m_selected_row_idx - num_visible_rows + 1;
-
- int row_idx = 0;
- int num_rows_left = num_visible_rows;
- m_root.Draw(window, m_first_visible_row, m_selected_row_idx, row_idx,
- num_rows_left);
- // Get the selected row
- m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
- } else {
- m_selected_item = nullptr;
- }
-
- return true; // Drawing handled
- }
-
- const char *WindowDelegateGetHelpText() override {
- return "Thread window keyboard shortcuts:";
- }
-
- KeyHelp *WindowDelegateGetKeyHelp() override {
- static curses::KeyHelp g_source_view_key_help[] = {
- {KEY_UP, "Select previous item"},
- {KEY_DOWN, "Select next item"},
- {KEY_RIGHT, "Expand the selected item"},
- {KEY_LEFT,
- "Unexpand the selected item or select parent if not expanded"},
- {KEY_PPAGE, "Page up"},
- {KEY_NPAGE, "Page down"},
- {'h', "Show help dialog"},
- {' ', "Toggle item expansion"},
- {',', "Page up"},
- {'.', "Page down"},
- {'\0', nullptr}};
- return g_source_view_key_help;
- }
-
- HandleCharResult WindowDelegateHandleChar(Window &window, int c) override {
- switch (c) {
- case ',':
- case KEY_PPAGE:
- // Page up key
- if (m_first_visible_row > 0) {
- if (m_first_visible_row > m_max_y)
- m_first_visible_row -= m_max_y;
- else
- m_first_visible_row = 0;
- m_selected_row_idx = m_first_visible_row;
- m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
- if (m_selected_item)
- m_selected_item->ItemWasSelected();
- }
- return eKeyHandled;
-
- case '.':
- case KEY_NPAGE:
- // Page down key
- if (m_num_rows > m_max_y) {
- if (m_first_visible_row + m_max_y < m_num_rows) {
- m_first_visible_row += m_max_y;
- m_selected_row_idx = m_first_visible_row;
- m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
- if (m_selected_item)
- m_selected_item->ItemWasSelected();
- }
- }
- return eKeyHandled;
-
- case KEY_UP:
- if (m_selected_row_idx > 0) {
- --m_selected_row_idx;
- m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
- if (m_selected_item)
- m_selected_item->ItemWasSelected();
- }
- return eKeyHandled;
-
- case KEY_DOWN:
- if (m_selected_row_idx + 1 < m_num_rows) {
- ++m_selected_row_idx;
- m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
- if (m_selected_item)
- m_selected_item->ItemWasSelected();
- }
- return eKeyHandled;
-
- case KEY_RIGHT:
- if (m_selected_item) {
- if (!m_selected_item->IsExpanded())
- m_selected_item->Expand();
- }
- return eKeyHandled;
-
- case KEY_LEFT:
- if (m_selected_item) {
- if (m_selected_item->IsExpanded())
- m_selected_item->Unexpand();
- else if (m_selected_item->GetParent()) {
- m_selected_row_idx = m_selected_item->GetParent()->GetRowIndex();
- m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
- if (m_selected_item)
- m_selected_item->ItemWasSelected();
- }
- }
- return eKeyHandled;
-
- case ' ':
- // Toggle expansion state when SPACE is pressed
- if (m_selected_item) {
- if (m_selected_item->IsExpanded())
- m_selected_item->Unexpand();
- else
- m_selected_item->Expand();
- }
- return eKeyHandled;
-
- case 'h':
- window.CreateHelpSubwindow();
- return eKeyHandled;
-
- default:
- break;
- }
- return eKeyNotHandled;
- }
-
-protected:
- Debugger &m_debugger;
- TreeDelegateSP m_delegate_sp;
- TreeItem m_root;
- TreeItem *m_selected_item;
- int m_num_rows;
- int m_selected_row_idx;
- int m_first_visible_row;
- int m_min_x;
- int m_min_y;
- int m_max_x;
- int m_max_y;
-};
-
-class FrameTreeDelegate : public TreeDelegate {
-public:
- FrameTreeDelegate() : TreeDelegate() {
- FormatEntity::Parse(
- "frame #${frame.index}: {${function.name}${function.pc-offset}}}",
- m_format);
- }
-
- ~FrameTreeDelegate() override = default;
-
- void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
- Thread *thread = (Thread *)item.GetUserData();
- if (thread) {
- const uint64_t frame_idx = item.GetIdentifier();
- StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_idx);
- if (frame_sp) {
- StreamString strm;
- const SymbolContext &sc =
- frame_sp->GetSymbolContext(eSymbolContextEverything);
- ExecutionContext exe_ctx(frame_sp);
- if (FormatEntity::Format(m_format, strm, &sc, &exe_ctx, nullptr,
- nullptr, false, false)) {
- int right_pad = 1;
- window.PutCStringTruncated(strm.GetString().str().c_str(), right_pad);
- }
- }
- }
- }
-
- void TreeDelegateGenerateChildren(TreeItem &item) override {
- // No children for frames yet...
- }
-
- bool TreeDelegateItemSelected(TreeItem &item) override {
- Thread *thread = (Thread *)item.GetUserData();
- if (thread) {
- thread->GetProcess()->GetThreadList().SetSelectedThreadByID(
- thread->GetID());
- const uint64_t frame_idx = item.GetIdentifier();
- thread->SetSelectedFrameByIndex(frame_idx);
- return true;
- }
- return false;
- }
-
-protected:
- FormatEntity::Entry m_format;
-};
-
-class ThreadTreeDelegate : public TreeDelegate {
-public:
- ThreadTreeDelegate(Debugger &debugger)
- : TreeDelegate(), m_debugger(debugger), m_tid(LLDB_INVALID_THREAD_ID),
- m_stop_id(UINT32_MAX) {
- FormatEntity::Parse("thread #${thread.index}: tid = ${thread.id}{, stop "
- "reason = ${thread.stop-reason}}",
- m_format);
- }
-
- ~ThreadTreeDelegate() override = default;
-
- ProcessSP GetProcess() {
- return m_debugger.GetCommandInterpreter()
- .GetExecutionContext()
- .GetProcessSP();
- }
-
- ThreadSP GetThread(const TreeItem &item) {
- ProcessSP process_sp = GetProcess();
- if (process_sp)
- return process_sp->GetThreadList().FindThreadByID(item.GetIdentifier());
- return ThreadSP();
- }
-
- void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
- ThreadSP thread_sp = GetThread(item);
- if (thread_sp) {
- StreamString strm;
- ExecutionContext exe_ctx(thread_sp);
- if (FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr,
- nullptr, false, false)) {
- int right_pad = 1;
- window.PutCStringTruncated(strm.GetString().str().c_str(), right_pad);
- }
- }
- }
-
- void TreeDelegateGenerateChildren(TreeItem &item) override {
- ProcessSP process_sp = GetProcess();
- if (process_sp && process_sp->IsAlive()) {
- StateType state = process_sp->GetState();
- if (StateIsStoppedState(state, true)) {
- ThreadSP thread_sp = GetThread(item);
- if (thread_sp) {
- if (m_stop_id == process_sp->GetStopID() &&
- thread_sp->GetID() == m_tid)
- return; // Children are already up to date
- if (!m_frame_delegate_sp) {
- // Always expand the thread item the first time we show it
- m_frame_delegate_sp = std::make_shared<FrameTreeDelegate>();
- }
-
- m_stop_id = process_sp->GetStopID();
- m_tid = thread_sp->GetID();
-
- TreeItem t(&item, *m_frame_delegate_sp, false);
- size_t num_frames = thread_sp->GetStackFrameCount();
- item.Resize(num_frames, t);
- for (size_t i = 0; i < num_frames; ++i) {
- item[i].SetUserData(thread_sp.get());
- item[i].SetIdentifier(i);
- }
- }
- return;
- }
- }
- item.ClearChildren();
- }
-
- bool TreeDelegateItemSelected(TreeItem &item) override {
- ProcessSP process_sp = GetProcess();
- if (process_sp && process_sp->IsAlive()) {
- StateType state = process_sp->GetState();
- if (StateIsStoppedState(state, true)) {
- ThreadSP thread_sp = GetThread(item);
- if (thread_sp) {
- ThreadList &thread_list = thread_sp->GetProcess()->GetThreadList();
- std::lock_guard<std::recursive_mutex> guard(thread_list.GetMutex());
- ThreadSP selected_thread_sp = thread_list.GetSelectedThread();
- if (selected_thread_sp->GetID() != thread_sp->GetID()) {
- thread_list.SetSelectedThreadByID(thread_sp->GetID());
- return true;
- }
- }
- }
- }
- return false;
- }
-
-protected:
- Debugger &m_debugger;
- std::shared_ptr<FrameTreeDelegate> m_frame_delegate_sp;
- lldb::user_id_t m_tid;
- uint32_t m_stop_id;
- FormatEntity::Entry m_format;
-};
-
-class ThreadsTreeDelegate : public TreeDelegate {
-public:
- ThreadsTreeDelegate(Debugger &debugger)
- : TreeDelegate(), m_thread_delegate_sp(), m_debugger(debugger),
- m_stop_id(UINT32_MAX) {
- FormatEntity::Parse("process ${process.id}{, name = ${process.name}}",
- m_format);
- }
-
- ~ThreadsTreeDelegate() override = default;
-
- ProcessSP GetProcess() {
- return m_debugger.GetCommandInterpreter()
- .GetExecutionContext()
- .GetProcessSP();
- }
-
- void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
- ProcessSP process_sp = GetProcess();
- if (process_sp && process_sp->IsAlive()) {
- StreamString strm;
- ExecutionContext exe_ctx(process_sp);
- if (FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr,
- nullptr, false, false)) {
- int right_pad = 1;
- window.PutCStringTruncated(strm.GetString().str().c_str(), right_pad);
- }
- }
- }
-
- void TreeDelegateGenerateChildren(TreeItem &item) override {
- ProcessSP process_sp = GetProcess();
- if (process_sp && process_sp->IsAlive()) {
- StateType state = process_sp->GetState();
- if (StateIsStoppedState(state, true)) {
- const uint32_t stop_id = process_sp->GetStopID();
- if (m_stop_id == stop_id)
- return; // Children are already up to date
-
- m_stop_id = stop_id;
-
- if (!m_thread_delegate_sp) {
- // Always expand the thread item the first time we show it
- // item.Expand();
- m_thread_delegate_sp =
- std::make_shared<ThreadTreeDelegate>(m_debugger);
- }
-
- TreeItem t(&item, *m_thread_delegate_sp, false);
- ThreadList &threads = process_sp->GetThreadList();
- std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
- size_t num_threads = threads.GetSize();
- item.Resize(num_threads, t);
- for (size_t i = 0; i < num_threads; ++i) {
- item[i].SetIdentifier(threads.GetThreadAtIndex(i)->GetID());
- item[i].SetMightHaveChildren(true);
- }
- return;
- }
- }
- item.ClearChildren();
- }
-
- bool TreeDelegateItemSelected(TreeItem &item) override { return false; }
-
-protected:
- std::shared_ptr<ThreadTreeDelegate> m_thread_delegate_sp;
- Debugger &m_debugger;
- uint32_t m_stop_id;
- FormatEntity::Entry m_format;
-};
-
-class ValueObjectListDelegate : public WindowDelegate {
-public:
- ValueObjectListDelegate()
- : m_rows(), m_selected_row(nullptr), m_selected_row_idx(0),
- m_first_visible_row(0), m_num_rows(0), m_max_x(0), m_max_y(0) {}
-
- ValueObjectListDelegate(ValueObjectList &valobj_list)
- : m_rows(), m_selected_row(nullptr), m_selected_row_idx(0),
- m_first_visible_row(0), m_num_rows(0), m_max_x(0), m_max_y(0) {
- SetValues(valobj_list);
- }
-
- ~ValueObjectListDelegate() override = default;
-
- void SetValues(ValueObjectList &valobj_list) {
- m_selected_row = nullptr;
- m_selected_row_idx = 0;
- m_first_visible_row = 0;
- m_num_rows = 0;
- m_rows.clear();
- for (auto &valobj_sp : valobj_list.GetObjects())
- m_rows.push_back(Row(valobj_sp, nullptr));
- }
-
- bool WindowDelegateDraw(Window &window, bool force) override {
- m_num_rows = 0;
- m_min_x = 2;
- m_min_y = 1;
- m_max_x = window.GetWidth() - 1;
- m_max_y = window.GetHeight() - 1;
-
- window.Erase();
- window.DrawTitleBox(window.GetName());
-
- const int num_visible_rows = NumVisibleRows();
- const int num_rows = CalculateTotalNumberRows(m_rows);
-
- // If we unexpanded while having something selected our total number of
- // rows is less than the num visible rows, then make sure we show all the
- // rows by setting the first visible row accordingly.
- if (m_first_visible_row > 0 && num_rows < num_visible_rows)
- m_first_visible_row = 0;
-
- // Make sure the selected row is always visible
- if (m_selected_row_idx < m_first_visible_row)
- m_first_visible_row = m_selected_row_idx;
- else if (m_first_visible_row + num_visible_rows <= m_selected_row_idx)
- m_first_visible_row = m_selected_row_idx - num_visible_rows + 1;
-
- DisplayRows(window, m_rows, g_options);
-
- // Get the selected row
- m_selected_row = GetRowForRowIndex(m_selected_row_idx);
- // Keep the cursor on the selected row so the highlight and the cursor are
- // always on the same line
- if (m_selected_row)
- window.MoveCursor(m_selected_row->x, m_selected_row->y);
-
- return true; // Drawing handled
- }
-
- KeyHelp *WindowDelegateGetKeyHelp() override {
- static curses::KeyHelp g_source_view_key_help[] = {
- {KEY_UP, "Select previous item"},
- {KEY_DOWN, "Select next item"},
- {KEY_RIGHT, "Expand selected item"},
- {KEY_LEFT, "Unexpand selected item or select parent if not expanded"},
- {KEY_PPAGE, "Page up"},
- {KEY_NPAGE, "Page down"},
- {'A', "Format as annotated address"},
- {'b', "Format as binary"},
- {'B', "Format as hex bytes with ASCII"},
- {'c', "Format as character"},
- {'d', "Format as a signed integer"},
- {'D', "Format selected value using the default format for the type"},
- {'f', "Format as float"},
- {'h', "Show help dialog"},
- {'i', "Format as instructions"},
- {'o', "Format as octal"},
- {'p', "Format as pointer"},
- {'s', "Format as C string"},
- {'t', "Toggle showing/hiding type names"},
- {'u', "Format as an unsigned integer"},
- {'x', "Format as hex"},
- {'X', "Format as uppercase hex"},
- {' ', "Toggle item expansion"},
- {',', "Page up"},
- {'.', "Page down"},
- {'\0', nullptr}};
- return g_source_view_key_help;
- }
-
- HandleCharResult WindowDelegateHandleChar(Window &window, int c) override {
- switch (c) {
- case 'x':
- case 'X':
- case 'o':
- case 's':
- case 'u':
- case 'd':
- case 'D':
- case 'i':
- case 'A':
- case 'p':
- case 'c':
- case 'b':
- case 'B':
- case 'f':
- // Change the format for the currently selected item
- if (m_selected_row) {
- auto valobj_sp = m_selected_row->value.GetSP();
- if (valobj_sp)
- valobj_sp->SetFormat(FormatForChar(c));
- }
- return eKeyHandled;
-
- case 't':
- // Toggle showing type names
- g_options.show_types = !g_options.show_types;
- return eKeyHandled;
-
- case ',':
- case KEY_PPAGE:
- // Page up key
- if (m_first_visible_row > 0) {
- if (static_cast<int>(m_first_visible_row) > m_max_y)
- m_first_visible_row -= m_max_y;
- else
- m_first_visible_row = 0;
- m_selected_row_idx = m_first_visible_row;
- }
- return eKeyHandled;
-
- case '.':
- case KEY_NPAGE:
- // Page down key
- if (m_num_rows > static_cast<size_t>(m_max_y)) {
- if (m_first_visible_row + m_max_y < m_num_rows) {
- m_first_visible_row += m_max_y;
- m_selected_row_idx = m_first_visible_row;
- }
- }
- return eKeyHandled;
-
- case KEY_UP:
- if (m_selected_row_idx > 0)
- --m_selected_row_idx;
- return eKeyHandled;
-
- case KEY_DOWN:
- if (m_selected_row_idx + 1 < m_num_rows)
- ++m_selected_row_idx;
- return eKeyHandled;
-
- case KEY_RIGHT:
- if (m_selected_row) {
- if (!m_selected_row->expanded)
- m_selected_row->Expand();
- }
- return eKeyHandled;
-
- case KEY_LEFT:
- if (m_selected_row) {
- if (m_selected_row->expanded)
- m_selected_row->Unexpand();
- else if (m_selected_row->parent)
- m_selected_row_idx = m_selected_row->parent->row_idx;
- }
- return eKeyHandled;
-
- case ' ':
- // Toggle expansion state when SPACE is pressed
- if (m_selected_row) {
- if (m_selected_row->expanded)
- m_selected_row->Unexpand();
- else
- m_selected_row->Expand();
- }
- return eKeyHandled;
-
- case 'h':
- window.CreateHelpSubwindow();
- return eKeyHandled;
-
- default:
- break;
- }
- return eKeyNotHandled;
- }
-
-protected:
- std::vector<Row> m_rows;
- Row *m_selected_row;
- uint32_t m_selected_row_idx;
- uint32_t m_first_visible_row;
- uint32_t m_num_rows;
- int m_min_x;
- int m_min_y;
- int m_max_x;
- int m_max_y;
-
- static Format FormatForChar(int c) {
- switch (c) {
- case 'x':
- return eFormatHex;
- case 'X':
- return eFormatHexUppercase;
- case 'o':
- return eFormatOctal;
- case 's':
- return eFormatCString;
- case 'u':
- return eFormatUnsigned;
- case 'd':
- return eFormatDecimal;
- case 'D':
- return eFormatDefault;
- case 'i':
- return eFormatInstruction;
- case 'A':
- return eFormatAddressInfo;
- case 'p':
- return eFormatPointer;
- case 'c':
- return eFormatChar;
- case 'b':
- return eFormatBinary;
- case 'B':
- return eFormatBytesWithASCII;
- case 'f':
- return eFormatFloat;
- }
- return eFormatDefault;
- }
-
- bool DisplayRowObject(Window &window, Row &row, DisplayOptions &options,
- bool highlight, bool last_child) {
- ValueObject *valobj = row.value.GetSP().get();
-
- if (valobj == nullptr)
- return false;
-
- const char *type_name =
- options.show_types ? valobj->GetTypeName().GetCString() : nullptr;
- const char *name = valobj->GetName().GetCString();
- const char *value = valobj->GetValueAsCString();
- const char *summary = valobj->GetSummaryAsCString();
-
- window.MoveCursor(row.x, row.y);
-
- row.DrawTree(window);
-
- if (highlight)
- window.AttributeOn(A_REVERSE);
-
- if (type_name && type_name[0])
- window.Printf("(%s) ", type_name);
-
- if (name && name[0])
- window.PutCString(name);
-
- attr_t changd_attr = 0;
- if (valobj->GetValueDidChange())
- changd_attr = COLOR_PAIR(5) | A_BOLD;
-
- if (value && value[0]) {
- window.PutCString(" = ");
- if (changd_attr)
- window.AttributeOn(changd_attr);
- window.PutCString(value);
- if (changd_attr)
- window.AttributeOff(changd_attr);
- }
-
- if (summary && summary[0]) {
- window.PutChar(' ');
- if (changd_attr)
- window.AttributeOn(changd_attr);
- window.PutCString(summary);
- if (changd_attr)
- window.AttributeOff(changd_attr);
- }
-
- if (highlight)
- window.AttributeOff(A_REVERSE);
-
- return true;
- }
-
- void DisplayRows(Window &window, std::vector<Row> &rows,
- DisplayOptions &options) {
- // > 0x25B7
- // \/ 0x25BD
-
- bool window_is_active = window.IsActive();
- for (auto &row : rows) {
- const bool last_child = row.parent && &rows[rows.size() - 1] == &row;
- // Save the row index in each Row structure
- row.row_idx = m_num_rows;
- if ((m_num_rows >= m_first_visible_row) &&
- ((m_num_rows - m_first_visible_row) <
- static_cast<size_t>(NumVisibleRows()))) {
- row.x = m_min_x;
- row.y = m_num_rows - m_first_visible_row + 1;
- if (DisplayRowObject(window, row, options,
- window_is_active &&
- m_num_rows == m_selected_row_idx,
- last_child)) {
- ++m_num_rows;
- } else {
- row.x = 0;
- row.y = 0;
- }
- } else {
- row.x = 0;
- row.y = 0;
- ++m_num_rows;
- }
-
- auto &children = row.GetChildren();
- if (row.expanded && !children.empty()) {
- DisplayRows(window, children, options);
- }
- }
- }
-
- int CalculateTotalNumberRows(std::vector<Row> &rows) {
- int row_count = 0;
- for (auto &row : rows) {
- ++row_count;
- if (row.expanded)
- row_count += CalculateTotalNumberRows(row.GetChildren());
- }
- return row_count;
- }
-
- static Row *GetRowForRowIndexImpl(std::vector<Row> &rows, size_t &row_index) {
- for (auto &row : rows) {
- if (row_index == 0)
- return &row;
- else {
- --row_index;
- auto &children = row.GetChildren();
- if (row.expanded && !children.empty()) {
- Row *result = GetRowForRowIndexImpl(children, row_index);
- if (result)
- return result;
- }
- }
- }
- return nullptr;
- }
-
- Row *GetRowForRowIndex(size_t row_index) {
- return GetRowForRowIndexImpl(m_rows, row_index);
- }
-
- int NumVisibleRows() const { return m_max_y - m_min_y; }
-
- static DisplayOptions g_options;
-};
-
-class FrameVariablesWindowDelegate : public ValueObjectListDelegate {
-public:
- FrameVariablesWindowDelegate(Debugger &debugger)
- : ValueObjectListDelegate(), m_debugger(debugger),
- m_frame_block(nullptr) {}
-
- ~FrameVariablesWindowDelegate() override = default;
-
- const char *WindowDelegateGetHelpText() override {
- return "Frame variable window keyboard shortcuts:";
- }
-
- bool WindowDelegateDraw(Window &window, bool force) override {
- ExecutionContext exe_ctx(
- m_debugger.GetCommandInterpreter().GetExecutionContext());
- Process *process = exe_ctx.GetProcessPtr();
- Block *frame_block = nullptr;
- StackFrame *frame = nullptr;
-
- if (process) {
- StateType state = process->GetState();
- if (StateIsStoppedState(state, true)) {
- frame = exe_ctx.GetFramePtr();
- if (frame)
- frame_block = frame->GetFrameBlock();
- } else if (StateIsRunningState(state)) {
- return true; // Don't do any updating when we are running
- }
- }
-
- ValueObjectList local_values;
- if (frame_block) {
- // Only update the variables if they have changed
- if (m_frame_block != frame_block) {
- m_frame_block = frame_block;
-
- VariableList *locals = frame->GetVariableList(true);
- if (locals) {
- const DynamicValueType use_dynamic = eDynamicDontRunTarget;
- const size_t num_locals = locals->GetSize();
- for (size_t i = 0; i < num_locals; ++i) {
- ValueObjectSP value_sp = frame->GetValueObjectForFrameVariable(
- locals->GetVariableAtIndex(i), use_dynamic);
- if (value_sp) {
- ValueObjectSP synthetic_value_sp = value_sp->GetSyntheticValue();
- if (synthetic_value_sp)
- local_values.Append(synthetic_value_sp);
- else
- local_values.Append(value_sp);
- }
- }
- // Update the values
- SetValues(local_values);
- }
- }
- } else {
- m_frame_block = nullptr;
- // Update the values with an empty list if there is no frame
- SetValues(local_values);
- }
-
- return ValueObjectListDelegate::WindowDelegateDraw(window, force);
- }
-
-protected:
- Debugger &m_debugger;
- Block *m_frame_block;
-};
-
-class RegistersWindowDelegate : public ValueObjectListDelegate {
-public:
- RegistersWindowDelegate(Debugger &debugger)
- : ValueObjectListDelegate(), m_debugger(debugger) {}
-
- ~RegistersWindowDelegate() override = default;
-
- const char *WindowDelegateGetHelpText() override {
- return "Register window keyboard shortcuts:";
- }
-
- bool WindowDelegateDraw(Window &window, bool force) override {
- ExecutionContext exe_ctx(
- m_debugger.GetCommandInterpreter().GetExecutionContext());
- StackFrame *frame = exe_ctx.GetFramePtr();
-
- ValueObjectList value_list;
- if (frame) {
- if (frame->GetStackID() != m_stack_id) {
- m_stack_id = frame->GetStackID();
- RegisterContextSP reg_ctx(frame->GetRegisterContext());
- if (reg_ctx) {
- const uint32_t num_sets = reg_ctx->GetRegisterSetCount();
- for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx) {
- value_list.Append(
- ValueObjectRegisterSet::Create(frame, reg_ctx, set_idx));
- }
- }
- SetValues(value_list);
- }
- } else {
- Process *process = exe_ctx.GetProcessPtr();
- if (process && process->IsAlive())
- return true; // Don't do any updating if we are running
- else {
- // Update the values with an empty list if there is no process or the
- // process isn't alive anymore
- SetValues(value_list);
- }
- }
- return ValueObjectListDelegate::WindowDelegateDraw(window, force);
- }
-
-protected:
- Debugger &m_debugger;
- StackID m_stack_id;
-};
-
-static const char *CursesKeyToCString(int ch) {
- static char g_desc[32];
- if (ch >= KEY_F0 && ch < KEY_F0 + 64) {
- snprintf(g_desc, sizeof(g_desc), "F%u", ch - KEY_F0);
- return g_desc;
- }
- switch (ch) {
- case KEY_DOWN:
- return "down";
- case KEY_UP:
- return "up";
- case KEY_LEFT:
- return "left";
- case KEY_RIGHT:
- return "right";
- case KEY_HOME:
- return "home";
- case KEY_BACKSPACE:
- return "backspace";
- case KEY_DL:
- return "delete-line";
- case KEY_IL:
- return "insert-line";
- case KEY_DC:
- return "delete-char";
- case KEY_IC:
- return "insert-char";
- case KEY_CLEAR:
- return "clear";
- case KEY_EOS:
- return "clear-to-eos";
- case KEY_EOL:
- return "clear-to-eol";
- case KEY_SF:
- return "scroll-forward";
- case KEY_SR:
- return "scroll-backward";
- case KEY_NPAGE:
- return "page-down";
- case KEY_PPAGE:
- return "page-up";
- case KEY_STAB:
- return "set-tab";
- case KEY_CTAB:
- return "clear-tab";
- case KEY_CATAB:
- return "clear-all-tabs";
- case KEY_ENTER:
- return "enter";
- case KEY_PRINT:
- return "print";
- case KEY_LL:
- return "lower-left key";
- case KEY_A1:
- return "upper left of keypad";
- case KEY_A3:
- return "upper right of keypad";
- case KEY_B2:
- return "center of keypad";
- case KEY_C1:
- return "lower left of keypad";
- case KEY_C3:
- return "lower right of keypad";
- case KEY_BTAB:
- return "back-tab key";
- case KEY_BEG:
- return "begin key";
- case KEY_CANCEL:
- return "cancel key";
- case KEY_CLOSE:
- return "close key";
- case KEY_COMMAND:
- return "command key";
- case KEY_COPY:
- return "copy key";
- case KEY_CREATE:
- return "create key";
- case KEY_END:
- return "end key";
- case KEY_EXIT:
- return "exit key";
- case KEY_FIND:
- return "find key";
- case KEY_HELP:
- return "help key";
- case KEY_MARK:
- return "mark key";
- case KEY_MESSAGE:
- return "message key";
- case KEY_MOVE:
- return "move key";
- case KEY_NEXT:
- return "next key";
- case KEY_OPEN:
- return "open key";
- case KEY_OPTIONS:
- return "options key";
- case KEY_PREVIOUS:
- return "previous key";
- case KEY_REDO:
- return "redo key";
- case KEY_REFERENCE:
- return "reference key";
- case KEY_REFRESH:
- return "refresh key";
- case KEY_REPLACE:
- return "replace key";
- case KEY_RESTART:
- return "restart key";
- case KEY_RESUME:
- return "resume key";
- case KEY_SAVE:
- return "save key";
- case KEY_SBEG:
- return "shifted begin key";
- case KEY_SCANCEL:
- return "shifted cancel key";
- case KEY_SCOMMAND:
- return "shifted command key";
- case KEY_SCOPY:
- return "shifted copy key";
- case KEY_SCREATE:
- return "shifted create key";
- case KEY_SDC:
- return "shifted delete-character key";
- case KEY_SDL:
- return "shifted delete-line key";
- case KEY_SELECT:
- return "select key";
- case KEY_SEND:
- return "shifted end key";
- case KEY_SEOL:
- return "shifted clear-to-end-of-line key";
- case KEY_SEXIT:
- return "shifted exit key";
- case KEY_SFIND:
- return "shifted find key";
- case KEY_SHELP:
- return "shifted help key";
- case KEY_SHOME:
- return "shifted home key";
- case KEY_SIC:
- return "shifted insert-character key";
- case KEY_SLEFT:
- return "shifted left-arrow key";
- case KEY_SMESSAGE:
- return "shifted message key";
- case KEY_SMOVE:
- return "shifted move key";
- case KEY_SNEXT:
- return "shifted next key";
- case KEY_SOPTIONS:
- return "shifted options key";
- case KEY_SPREVIOUS:
- return "shifted previous key";
- case KEY_SPRINT:
- return "shifted print key";
- case KEY_SREDO:
- return "shifted redo key";
- case KEY_SREPLACE:
- return "shifted replace key";
- case KEY_SRIGHT:
- return "shifted right-arrow key";
- case KEY_SRSUME:
- return "shifted resume key";
- case KEY_SSAVE:
- return "shifted save key";
- case KEY_SSUSPEND:
- return "shifted suspend key";
- case KEY_SUNDO:
- return "shifted undo key";
- case KEY_SUSPEND:
- return "suspend key";
- case KEY_UNDO:
- return "undo key";
- case KEY_MOUSE:
- return "Mouse event has occurred";
- case KEY_RESIZE:
- return "Terminal resize event";
-#ifdef KEY_EVENT
- case KEY_EVENT:
- return "We were interrupted by an event";
-#endif
- case KEY_RETURN:
- return "return";
- case ' ':
- return "space";
- case '\t':
- return "tab";
- case KEY_ESCAPE:
- return "escape";
- default:
- if (isprint(ch))
- snprintf(g_desc, sizeof(g_desc), "%c", ch);
- else
- snprintf(g_desc, sizeof(g_desc), "\\x%2.2x", ch);
- return g_desc;
- }
- return nullptr;
-}
-
-HelpDialogDelegate::HelpDialogDelegate(const char *text,
- KeyHelp *key_help_array)
- : m_text(), m_first_visible_line(0) {
- if (text && text[0]) {
- m_text.SplitIntoLines(text);
- m_text.AppendString("");
- }
- if (key_help_array) {
- for (KeyHelp *key = key_help_array; key->ch; ++key) {
- StreamString key_description;
- key_description.Printf("%10s - %s", CursesKeyToCString(key->ch),
- key->description);
- m_text.AppendString(key_description.GetString());
- }
- }
-}
-
-HelpDialogDelegate::~HelpDialogDelegate() = default;
-
-bool HelpDialogDelegate::WindowDelegateDraw(Window &window, bool force) {
- window.Erase();
- const int window_height = window.GetHeight();
- int x = 2;
- int y = 1;
- const int min_y = y;
- const int max_y = window_height - 1 - y;
- const size_t num_visible_lines = max_y - min_y + 1;
- const size_t num_lines = m_text.GetSize();
- const char *bottom_message;
- if (num_lines <= num_visible_lines)
- bottom_message = "Press any key to exit";
- else
- bottom_message = "Use arrows to scroll, any other key to exit";
- window.DrawTitleBox(window.GetName(), bottom_message);
- while (y <= max_y) {
- window.MoveCursor(x, y);
- window.PutCStringTruncated(
- m_text.GetStringAtIndex(m_first_visible_line + y - min_y), 1);
- ++y;
- }
- return true;
-}
-
-HandleCharResult HelpDialogDelegate::WindowDelegateHandleChar(Window &window,
- int key) {
- bool done = false;
- const size_t num_lines = m_text.GetSize();
- const size_t num_visible_lines = window.GetHeight() - 2;
-
- if (num_lines <= num_visible_lines) {
- done = true;
- // If we have all lines visible and don't need scrolling, then any key
- // press will cause us to exit
- } else {
- switch (key) {
- case KEY_UP:
- if (m_first_visible_line > 0)
- --m_first_visible_line;
- break;
-
- case KEY_DOWN:
- if (m_first_visible_line + num_visible_lines < num_lines)
- ++m_first_visible_line;
- break;
-
- case KEY_PPAGE:
- case ',':
- if (m_first_visible_line > 0) {
- if (static_cast<size_t>(m_first_visible_line) >= num_visible_lines)
- m_first_visible_line -= num_visible_lines;
- else
- m_first_visible_line = 0;
- }
- break;
-
- case KEY_NPAGE:
- case '.':
- if (m_first_visible_line + num_visible_lines < num_lines) {
- m_first_visible_line += num_visible_lines;
- if (static_cast<size_t>(m_first_visible_line) > num_lines)
- m_first_visible_line = num_lines - num_visible_lines;
- }
- break;
-
- default:
- done = true;
- break;
- }
- }
- if (done)
- window.GetParent()->RemoveSubWindow(&window);
- return eKeyHandled;
-}
-
-class ApplicationDelegate : public WindowDelegate, public MenuDelegate {
-public:
- enum {
- eMenuID_LLDB = 1,
- eMenuID_LLDBAbout,
- eMenuID_LLDBExit,
-
- eMenuID_Target,
- eMenuID_TargetCreate,
- eMenuID_TargetDelete,
-
- eMenuID_Process,
- eMenuID_ProcessAttach,
- eMenuID_ProcessDetach,
- eMenuID_ProcessLaunch,
- eMenuID_ProcessContinue,
- eMenuID_ProcessHalt,
- eMenuID_ProcessKill,
-
- eMenuID_Thread,
- eMenuID_ThreadStepIn,
- eMenuID_ThreadStepOver,
- eMenuID_ThreadStepOut,
-
- eMenuID_View,
- eMenuID_ViewBacktrace,
- eMenuID_ViewRegisters,
- eMenuID_ViewSource,
- eMenuID_ViewVariables,
-
- eMenuID_Help,
- eMenuID_HelpGUIHelp
- };
-
- ApplicationDelegate(Application &app, Debugger &debugger)
- : WindowDelegate(), MenuDelegate(), m_app(app), m_debugger(debugger) {}
-
- ~ApplicationDelegate() override = default;
-
- bool WindowDelegateDraw(Window &window, bool force) override {
- return false; // Drawing not handled, let standard window drawing happen
- }
-
- HandleCharResult WindowDelegateHandleChar(Window &window, int key) override {
- switch (key) {
- case '\t':
- window.SelectNextWindowAsActive();
- return eKeyHandled;
-
- case 'h':
- window.CreateHelpSubwindow();
- return eKeyHandled;
-
- case KEY_ESCAPE:
- return eQuitApplication;
-
- default:
- break;
- }
- return eKeyNotHandled;
- }
-
- const char *WindowDelegateGetHelpText() override {
- return "Welcome to the LLDB curses GUI.\n\n"
- "Press the TAB key to change the selected view.\n"
- "Each view has its own keyboard shortcuts, press 'h' to open a "
- "dialog to display them.\n\n"
- "Common key bindings for all views:";
- }
-
- KeyHelp *WindowDelegateGetKeyHelp() override {
- static curses::KeyHelp g_source_view_key_help[] = {
- {'\t', "Select next view"},
- {'h', "Show help dialog with view specific key bindings"},
- {',', "Page up"},
- {'.', "Page down"},
- {KEY_UP, "Select previous"},
- {KEY_DOWN, "Select next"},
- {KEY_LEFT, "Unexpand or select parent"},
- {KEY_RIGHT, "Expand"},
- {KEY_PPAGE, "Page up"},
- {KEY_NPAGE, "Page down"},
- {'\0', nullptr}};
- return g_source_view_key_help;
- }
-
- MenuActionResult MenuDelegateAction(Menu &menu) override {
- switch (menu.GetIdentifier()) {
- case eMenuID_ThreadStepIn: {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasThreadScope()) {
- Process *process = exe_ctx.GetProcessPtr();
- if (process && process->IsAlive() &&
- StateIsStoppedState(process->GetState(), true))
- exe_ctx.GetThreadRef().StepIn(true);
- }
- }
- return MenuActionResult::Handled;
-
- case eMenuID_ThreadStepOut: {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasThreadScope()) {
- Process *process = exe_ctx.GetProcessPtr();
- if (process && process->IsAlive() &&
- StateIsStoppedState(process->GetState(), true))
- exe_ctx.GetThreadRef().StepOut();
- }
- }
- return MenuActionResult::Handled;
-
- case eMenuID_ThreadStepOver: {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasThreadScope()) {
- Process *process = exe_ctx.GetProcessPtr();
- if (process && process->IsAlive() &&
- StateIsStoppedState(process->GetState(), true))
- exe_ctx.GetThreadRef().StepOver(true);
- }
- }
- return MenuActionResult::Handled;
-
- case eMenuID_ProcessContinue: {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasProcessScope()) {
- Process *process = exe_ctx.GetProcessPtr();
- if (process && process->IsAlive() &&
- StateIsStoppedState(process->GetState(), true))
- process->Resume();
- }
- }
- return MenuActionResult::Handled;
-
- case eMenuID_ProcessKill: {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasProcessScope()) {
- Process *process = exe_ctx.GetProcessPtr();
- if (process && process->IsAlive())
- process->Destroy(false);
- }
- }
- return MenuActionResult::Handled;
-
- case eMenuID_ProcessHalt: {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasProcessScope()) {
- Process *process = exe_ctx.GetProcessPtr();
- if (process && process->IsAlive())
- process->Halt();
- }
- }
- return MenuActionResult::Handled;
-
- case eMenuID_ProcessDetach: {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasProcessScope()) {
- Process *process = exe_ctx.GetProcessPtr();
- if (process && process->IsAlive())
- process->Detach(false);
- }
- }
- return MenuActionResult::Handled;
-
- case eMenuID_Process: {
- // Populate the menu with all of the threads if the process is stopped
- // when the Process menu gets selected and is about to display its
- // submenu.
- Menus &submenus = menu.GetSubmenus();
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- Process *process = exe_ctx.GetProcessPtr();
- if (process && process->IsAlive() &&
- StateIsStoppedState(process->GetState(), true)) {
- if (submenus.size() == 7)
- menu.AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
- else if (submenus.size() > 8)
- submenus.erase(submenus.begin() + 8, submenus.end());
-
- ThreadList &threads = process->GetThreadList();
- std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
- size_t num_threads = threads.GetSize();
- for (size_t i = 0; i < num_threads; ++i) {
- ThreadSP thread_sp = threads.GetThreadAtIndex(i);
- char menu_char = '\0';
- if (i < 9)
- menu_char = '1' + i;
- StreamString thread_menu_title;
- thread_menu_title.Printf("Thread %u", thread_sp->GetIndexID());
- const char *thread_name = thread_sp->GetName();
- if (thread_name && thread_name[0])
- thread_menu_title.Printf(" %s", thread_name);
- else {
- const char *queue_name = thread_sp->GetQueueName();
- if (queue_name && queue_name[0])
- thread_menu_title.Printf(" %s", queue_name);
- }
- menu.AddSubmenu(
- MenuSP(new Menu(thread_menu_title.GetString().str().c_str(),
- nullptr, menu_char, thread_sp->GetID())));
- }
- } else if (submenus.size() > 7) {
- // Remove the separator and any other thread submenu items that were
- // previously added
- submenus.erase(submenus.begin() + 7, submenus.end());
- }
- // Since we are adding and removing items we need to recalculate the name
- // lengths
- menu.RecalculateNameLengths();
- }
- return MenuActionResult::Handled;
-
- case eMenuID_ViewVariables: {
- WindowSP main_window_sp = m_app.GetMainWindow();
- WindowSP source_window_sp = main_window_sp->FindSubWindow("Source");
- WindowSP variables_window_sp = main_window_sp->FindSubWindow("Variables");
- WindowSP registers_window_sp = main_window_sp->FindSubWindow("Registers");
- const Rect source_bounds = source_window_sp->GetBounds();
-
- if (variables_window_sp) {
- const Rect variables_bounds = variables_window_sp->GetBounds();
-
- main_window_sp->RemoveSubWindow(variables_window_sp.get());
-
- if (registers_window_sp) {
- // We have a registers window, so give all the area back to the
- // registers window
- Rect registers_bounds = variables_bounds;
- registers_bounds.size.width = source_bounds.size.width;
- registers_window_sp->SetBounds(registers_bounds);
- } else {
- // We have no registers window showing so give the bottom area back
- // to the source view
- source_window_sp->Resize(source_bounds.size.width,
- source_bounds.size.height +
- variables_bounds.size.height);
- }
- } else {
- Rect new_variables_rect;
- if (registers_window_sp) {
- // We have a registers window so split the area of the registers
- // window into two columns where the left hand side will be the
- // variables and the right hand side will be the registers
- const Rect variables_bounds = registers_window_sp->GetBounds();
- Rect new_registers_rect;
- variables_bounds.VerticalSplitPercentage(0.50, new_variables_rect,
- new_registers_rect);
- registers_window_sp->SetBounds(new_registers_rect);
- } else {
- // No variables window, grab the bottom part of the source window
- Rect new_source_rect;
- source_bounds.HorizontalSplitPercentage(0.70, new_source_rect,
- new_variables_rect);
- source_window_sp->SetBounds(new_source_rect);
- }
- WindowSP new_window_sp = main_window_sp->CreateSubWindow(
- "Variables", new_variables_rect, false);
- new_window_sp->SetDelegate(
- WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger)));
- }
- touchwin(stdscr);
- }
- return MenuActionResult::Handled;
-
- case eMenuID_ViewRegisters: {
- WindowSP main_window_sp = m_app.GetMainWindow();
- WindowSP source_window_sp = main_window_sp->FindSubWindow("Source");
- WindowSP variables_window_sp = main_window_sp->FindSubWindow("Variables");
- WindowSP registers_window_sp = main_window_sp->FindSubWindow("Registers");
- const Rect source_bounds = source_window_sp->GetBounds();
-
- if (registers_window_sp) {
- if (variables_window_sp) {
- const Rect variables_bounds = variables_window_sp->GetBounds();
-
- // We have a variables window, so give all the area back to the
- // variables window
- variables_window_sp->Resize(variables_bounds.size.width +
- registers_window_sp->GetWidth(),
- variables_bounds.size.height);
- } else {
- // We have no variables window showing so give the bottom area back
- // to the source view
- source_window_sp->Resize(source_bounds.size.width,
- source_bounds.size.height +
- registers_window_sp->GetHeight());
- }
- main_window_sp->RemoveSubWindow(registers_window_sp.get());
- } else {
- Rect new_regs_rect;
- if (variables_window_sp) {
- // We have a variables window, split it into two columns where the
- // left hand side will be the variables and the right hand side will
- // be the registers
- const Rect variables_bounds = variables_window_sp->GetBounds();
- Rect new_vars_rect;
- variables_bounds.VerticalSplitPercentage(0.50, new_vars_rect,
- new_regs_rect);
- variables_window_sp->SetBounds(new_vars_rect);
- } else {
- // No registers window, grab the bottom part of the source window
- Rect new_source_rect;
- source_bounds.HorizontalSplitPercentage(0.70, new_source_rect,
- new_regs_rect);
- source_window_sp->SetBounds(new_source_rect);
- }
- WindowSP new_window_sp =
- main_window_sp->CreateSubWindow("Registers", new_regs_rect, false);
- new_window_sp->SetDelegate(
- WindowDelegateSP(new RegistersWindowDelegate(m_debugger)));
- }
- touchwin(stdscr);
- }
- return MenuActionResult::Handled;
-
- case eMenuID_HelpGUIHelp:
- m_app.GetMainWindow()->CreateHelpSubwindow();
- return MenuActionResult::Handled;
-
- default:
- break;
- }
-
- return MenuActionResult::NotHandled;
- }
-
-protected:
- Application &m_app;
- Debugger &m_debugger;
-};
-
-class StatusBarWindowDelegate : public WindowDelegate {
-public:
- StatusBarWindowDelegate(Debugger &debugger) : m_debugger(debugger) {
- FormatEntity::Parse("Thread: ${thread.id%tid}", m_format);
- }
-
- ~StatusBarWindowDelegate() override = default;
-
- bool WindowDelegateDraw(Window &window, bool force) override {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- Process *process = exe_ctx.GetProcessPtr();
- Thread *thread = exe_ctx.GetThreadPtr();
- StackFrame *frame = exe_ctx.GetFramePtr();
- window.Erase();
- window.SetBackground(2);
- window.MoveCursor(0, 0);
- if (process) {
- const StateType state = process->GetState();
- window.Printf("Process: %5" PRIu64 " %10s", process->GetID(),
- StateAsCString(state));
-
- if (StateIsStoppedState(state, true)) {
- StreamString strm;
- if (thread && FormatEntity::Format(m_format, strm, nullptr, &exe_ctx,
- nullptr, nullptr, false, false)) {
- window.MoveCursor(40, 0);
- window.PutCStringTruncated(strm.GetString().str().c_str(), 1);
- }
-
- window.MoveCursor(60, 0);
- if (frame)
- window.Printf("Frame: %3u PC = 0x%16.16" PRIx64,
- frame->GetFrameIndex(),
- frame->GetFrameCodeAddress().GetOpcodeLoadAddress(
- exe_ctx.GetTargetPtr()));
- } else if (state == eStateExited) {
- const char *exit_desc = process->GetExitDescription();
- const int exit_status = process->GetExitStatus();
- if (exit_desc && exit_desc[0])
- window.Printf(" with status = %i (%s)", exit_status, exit_desc);
- else
- window.Printf(" with status = %i", exit_status);
- }
- }
- return true;
- }
-
-protected:
- Debugger &m_debugger;
- FormatEntity::Entry m_format;
-};
-
-class SourceFileWindowDelegate : public WindowDelegate {
-public:
- SourceFileWindowDelegate(Debugger &debugger)
- : WindowDelegate(), m_debugger(debugger), m_sc(), m_file_sp(),
- m_disassembly_scope(nullptr), m_disassembly_sp(), m_disassembly_range(),
- m_title(), m_line_width(4), m_selected_line(0), m_pc_line(0),
- m_stop_id(0), m_frame_idx(UINT32_MAX), m_first_visible_line(0),
- m_min_x(0), m_min_y(0), m_max_x(0), m_max_y(0) {}
-
- ~SourceFileWindowDelegate() override = default;
-
- void Update(const SymbolContext &sc) { m_sc = sc; }
-
- uint32_t NumVisibleLines() const { return m_max_y - m_min_y; }
-
- const char *WindowDelegateGetHelpText() override {
- return "Source/Disassembly window keyboard shortcuts:";
- }
-
- KeyHelp *WindowDelegateGetKeyHelp() override {
- static curses::KeyHelp g_source_view_key_help[] = {
- {KEY_RETURN, "Run to selected line with one shot breakpoint"},
- {KEY_UP, "Select previous source line"},
- {KEY_DOWN, "Select next source line"},
- {KEY_PPAGE, "Page up"},
- {KEY_NPAGE, "Page down"},
- {'b', "Set breakpoint on selected source/disassembly line"},
- {'c', "Continue process"},
- {'d', "Detach and resume process"},
- {'D', "Detach with process suspended"},
- {'h', "Show help dialog"},
- {'k', "Kill process"},
- {'n', "Step over (source line)"},
- {'N', "Step over (single instruction)"},
- {'o', "Step out"},
- {'s', "Step in (source line)"},
- {'S', "Step in (single instruction)"},
- {',', "Page up"},
- {'.', "Page down"},
- {'\0', nullptr}};
- return g_source_view_key_help;
- }
-
- bool WindowDelegateDraw(Window &window, bool force) override {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- Process *process = exe_ctx.GetProcessPtr();
- Thread *thread = nullptr;
-
- bool update_location = false;
- if (process) {
- StateType state = process->GetState();
- if (StateIsStoppedState(state, true)) {
- // We are stopped, so it is ok to
- update_location = true;
- }
- }
-
- m_min_x = 1;
- m_min_y = 2;
- m_max_x = window.GetMaxX() - 1;
- m_max_y = window.GetMaxY() - 1;
-
- const uint32_t num_visible_lines = NumVisibleLines();
- StackFrameSP frame_sp;
- bool set_selected_line_to_pc = false;
-
- if (update_location) {
- const bool process_alive = process ? process->IsAlive() : false;
- bool thread_changed = false;
- if (process_alive) {
- thread = exe_ctx.GetThreadPtr();
- if (thread) {
- frame_sp = thread->GetSelectedFrame();
- auto tid = thread->GetID();
- thread_changed = tid != m_tid;
- m_tid = tid;
- } else {
- if (m_tid != LLDB_INVALID_THREAD_ID) {
- thread_changed = true;
- m_tid = LLDB_INVALID_THREAD_ID;
- }
- }
- }
- const uint32_t stop_id = process ? process->GetStopID() : 0;
- const bool stop_id_changed = stop_id != m_stop_id;
- bool frame_changed = false;
- m_stop_id = stop_id;
- m_title.Clear();
- if (frame_sp) {
- m_sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
- if (m_sc.module_sp) {
- m_title.Printf(
- "%s", m_sc.module_sp->GetFileSpec().GetFilename().GetCString());
- ConstString func_name = m_sc.GetFunctionName();
- if (func_name)
- m_title.Printf("`%s", func_name.GetCString());
- }
- const uint32_t frame_idx = frame_sp->GetFrameIndex();
- frame_changed = frame_idx != m_frame_idx;
- m_frame_idx = frame_idx;
- } else {
- m_sc.Clear(true);
- frame_changed = m_frame_idx != UINT32_MAX;
- m_frame_idx = UINT32_MAX;
- }
-
- const bool context_changed =
- thread_changed || frame_changed || stop_id_changed;
-
- if (process_alive) {
- if (m_sc.line_entry.IsValid()) {
- m_pc_line = m_sc.line_entry.line;
- if (m_pc_line != UINT32_MAX)
- --m_pc_line; // Convert to zero based line number...
- // Update the selected line if the stop ID changed...
- if (context_changed)
- m_selected_line = m_pc_line;
-
- if (m_file_sp && m_file_sp->FileSpecMatches(m_sc.line_entry.file)) {
- // Same file, nothing to do, we should either have the lines or not
- // (source file missing)
- if (m_selected_line >= static_cast<size_t>(m_first_visible_line)) {
- if (m_selected_line >= m_first_visible_line + num_visible_lines)
- m_first_visible_line = m_selected_line - 10;
- } else {
- if (m_selected_line > 10)
- m_first_visible_line = m_selected_line - 10;
- else
- m_first_visible_line = 0;
- }
- } else {
- // File changed, set selected line to the line with the PC
- m_selected_line = m_pc_line;
- m_file_sp =
- m_debugger.GetSourceManager().GetFile(m_sc.line_entry.file);
- if (m_file_sp) {
- const size_t num_lines = m_file_sp->GetNumLines();
- m_line_width = 1;
- for (size_t n = num_lines; n >= 10; n = n / 10)
- ++m_line_width;
-
- if (num_lines < num_visible_lines ||
- m_selected_line < num_visible_lines)
- m_first_visible_line = 0;
- else
- m_first_visible_line = m_selected_line - 10;
- }
- }
- } else {
- m_file_sp.reset();
- }
-
- if (!m_file_sp || m_file_sp->GetNumLines() == 0) {
- // Show disassembly
- bool prefer_file_cache = false;
- if (m_sc.function) {
- if (m_disassembly_scope != m_sc.function) {
- m_disassembly_scope = m_sc.function;
- m_disassembly_sp = m_sc.function->GetInstructions(
- exe_ctx, nullptr, prefer_file_cache);
- if (m_disassembly_sp) {
- set_selected_line_to_pc = true;
- m_disassembly_range = m_sc.function->GetAddressRange();
- } else {
- m_disassembly_range.Clear();
- }
- } else {
- set_selected_line_to_pc = context_changed;
- }
- } else if (m_sc.symbol) {
- if (m_disassembly_scope != m_sc.symbol) {
- m_disassembly_scope = m_sc.symbol;
- m_disassembly_sp = m_sc.symbol->GetInstructions(
- exe_ctx, nullptr, prefer_file_cache);
- if (m_disassembly_sp) {
- set_selected_line_to_pc = true;
- m_disassembly_range.GetBaseAddress() =
- m_sc.symbol->GetAddress();
- m_disassembly_range.SetByteSize(m_sc.symbol->GetByteSize());
- } else {
- m_disassembly_range.Clear();
- }
- } else {
- set_selected_line_to_pc = context_changed;
- }
- }
- }
- } else {
- m_pc_line = UINT32_MAX;
- }
- }
-
- const int window_width = window.GetWidth();
- window.Erase();
- window.DrawTitleBox("Sources");
- if (!m_title.GetString().empty()) {
- window.AttributeOn(A_REVERSE);
- window.MoveCursor(1, 1);
- window.PutChar(' ');
- window.PutCStringTruncated(m_title.GetString().str().c_str(), 1);
- int x = window.GetCursorX();
- if (x < window_width - 1) {
- window.Printf("%*s", window_width - x - 1, "");
- }
- window.AttributeOff(A_REVERSE);
- }
-
- Target *target = exe_ctx.GetTargetPtr();
- const size_t num_source_lines = GetNumSourceLines();
- if (num_source_lines > 0) {
- // Display source
- BreakpointLines bp_lines;
- if (target) {
- BreakpointList &bp_list = target->GetBreakpointList();
- const size_t num_bps = bp_list.GetSize();
- for (size_t bp_idx = 0; bp_idx < num_bps; ++bp_idx) {
- BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
- const size_t num_bps_locs = bp_sp->GetNumLocations();
- for (size_t bp_loc_idx = 0; bp_loc_idx < num_bps_locs; ++bp_loc_idx) {
- BreakpointLocationSP bp_loc_sp =
- bp_sp->GetLocationAtIndex(bp_loc_idx);
- LineEntry bp_loc_line_entry;
- if (bp_loc_sp->GetAddress().CalculateSymbolContextLineEntry(
- bp_loc_line_entry)) {
- if (m_file_sp->GetFileSpec() == bp_loc_line_entry.file) {
- bp_lines.insert(bp_loc_line_entry.line);
- }
- }
- }
- }
- }
-
- const attr_t selected_highlight_attr = A_REVERSE;
- const attr_t pc_highlight_attr = COLOR_PAIR(1);
-
- for (size_t i = 0; i < num_visible_lines; ++i) {
- const uint32_t curr_line = m_first_visible_line + i;
- if (curr_line < num_source_lines) {
- const int line_y = m_min_y + i;
- window.MoveCursor(1, line_y);
- const bool is_pc_line = curr_line == m_pc_line;
- const bool line_is_selected = m_selected_line == curr_line;
- // Highlight the line as the PC line first, then if the selected line
- // isn't the same as the PC line, highlight it differently
- attr_t highlight_attr = 0;
- attr_t bp_attr = 0;
- if (is_pc_line)
- highlight_attr = pc_highlight_attr;
- else if (line_is_selected)
- highlight_attr = selected_highlight_attr;
-
- if (bp_lines.find(curr_line + 1) != bp_lines.end())
- bp_attr = COLOR_PAIR(2);
-
- if (bp_attr)
- window.AttributeOn(bp_attr);
-
- window.Printf(" %*u ", m_line_width, curr_line + 1);
-
- if (bp_attr)
- window.AttributeOff(bp_attr);
-
- window.PutChar(ACS_VLINE);
- // Mark the line with the PC with a diamond
- if (is_pc_line)
- window.PutChar(ACS_DIAMOND);
- else
- window.PutChar(' ');
-
- if (highlight_attr)
- window.AttributeOn(highlight_attr);
- const uint32_t line_len =
- m_file_sp->GetLineLength(curr_line + 1, false);
- if (line_len > 0)
- window.PutCString(m_file_sp->PeekLineData(curr_line + 1), line_len);
-
- if (is_pc_line && frame_sp &&
- frame_sp->GetConcreteFrameIndex() == 0) {
- StopInfoSP stop_info_sp;
- if (thread)
- stop_info_sp = thread->GetStopInfo();
- if (stop_info_sp) {
- const char *stop_description = stop_info_sp->GetDescription();
- if (stop_description && stop_description[0]) {
- size_t stop_description_len = strlen(stop_description);
- int desc_x = window_width - stop_description_len - 16;
- window.Printf("%*s", desc_x - window.GetCursorX(), "");
- // window.MoveCursor(window_width - stop_description_len - 15,
- // line_y);
- window.Printf("<<< Thread %u: %s ", thread->GetIndexID(),
- stop_description);
- }
- } else {
- window.Printf("%*s", window_width - window.GetCursorX() - 1, "");
- }
- }
- if (highlight_attr)
- window.AttributeOff(highlight_attr);
- } else {
- break;
- }
- }
- } else {
- size_t num_disassembly_lines = GetNumDisassemblyLines();
- if (num_disassembly_lines > 0) {
- // Display disassembly
- BreakpointAddrs bp_file_addrs;
- Target *target = exe_ctx.GetTargetPtr();
- if (target) {
- BreakpointList &bp_list = target->GetBreakpointList();
- const size_t num_bps = bp_list.GetSize();
- for (size_t bp_idx = 0; bp_idx < num_bps; ++bp_idx) {
- BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
- const size_t num_bps_locs = bp_sp->GetNumLocations();
- for (size_t bp_loc_idx = 0; bp_loc_idx < num_bps_locs;
- ++bp_loc_idx) {
- BreakpointLocationSP bp_loc_sp =
- bp_sp->GetLocationAtIndex(bp_loc_idx);
- LineEntry bp_loc_line_entry;
- const lldb::addr_t file_addr =
- bp_loc_sp->GetAddress().GetFileAddress();
- if (file_addr != LLDB_INVALID_ADDRESS) {
- if (m_disassembly_range.ContainsFileAddress(file_addr))
- bp_file_addrs.insert(file_addr);
- }
- }
- }
- }
-
- const attr_t selected_highlight_attr = A_REVERSE;
- const attr_t pc_highlight_attr = COLOR_PAIR(1);
-
- StreamString strm;
-
- InstructionList &insts = m_disassembly_sp->GetInstructionList();
- Address pc_address;
-
- if (frame_sp)
- pc_address = frame_sp->GetFrameCodeAddress();
- const uint32_t pc_idx =
- pc_address.IsValid()
- ? insts.GetIndexOfInstructionAtAddress(pc_address)
- : UINT32_MAX;
- if (set_selected_line_to_pc) {
- m_selected_line = pc_idx;
- }
-
- const uint32_t non_visible_pc_offset = (num_visible_lines / 5);
- if (static_cast<size_t>(m_first_visible_line) >= num_disassembly_lines)
- m_first_visible_line = 0;
-
- if (pc_idx < num_disassembly_lines) {
- if (pc_idx < static_cast<uint32_t>(m_first_visible_line) ||
- pc_idx >= m_first_visible_line + num_visible_lines)
- m_first_visible_line = pc_idx - non_visible_pc_offset;
- }
-
- for (size_t i = 0; i < num_visible_lines; ++i) {
- const uint32_t inst_idx = m_first_visible_line + i;
- Instruction *inst = insts.GetInstructionAtIndex(inst_idx).get();
- if (!inst)
- break;
-
- const int line_y = m_min_y + i;
- window.MoveCursor(1, line_y);
- const bool is_pc_line = frame_sp && inst_idx == pc_idx;
- const bool line_is_selected = m_selected_line == inst_idx;
- // Highlight the line as the PC line first, then if the selected line
- // isn't the same as the PC line, highlight it differently
- attr_t highlight_attr = 0;
- attr_t bp_attr = 0;
- if (is_pc_line)
- highlight_attr = pc_highlight_attr;
- else if (line_is_selected)
- highlight_attr = selected_highlight_attr;
-
- if (bp_file_addrs.find(inst->GetAddress().GetFileAddress()) !=
- bp_file_addrs.end())
- bp_attr = COLOR_PAIR(2);
-
- if (bp_attr)
- window.AttributeOn(bp_attr);
-
- window.Printf(" 0x%16.16llx ",
- static_cast<unsigned long long>(
- inst->GetAddress().GetLoadAddress(target)));
-
- if (bp_attr)
- window.AttributeOff(bp_attr);
-
- window.PutChar(ACS_VLINE);
- // Mark the line with the PC with a diamond
- if (is_pc_line)
- window.PutChar(ACS_DIAMOND);
- else
- window.PutChar(' ');
-
- if (highlight_attr)
- window.AttributeOn(highlight_attr);
-
- const char *mnemonic = inst->GetMnemonic(&exe_ctx);
- const char *operands = inst->GetOperands(&exe_ctx);
- const char *comment = inst->GetComment(&exe_ctx);
-
- if (mnemonic != nullptr && mnemonic[0] == '\0')
- mnemonic = nullptr;
- if (operands != nullptr && operands[0] == '\0')
- operands = nullptr;
- if (comment != nullptr && comment[0] == '\0')
- comment = nullptr;
-
- strm.Clear();
-
- if (mnemonic != nullptr && operands != nullptr && comment != nullptr)
- strm.Printf("%-8s %-25s ; %s", mnemonic, operands, comment);
- else if (mnemonic != nullptr && operands != nullptr)
- strm.Printf("%-8s %s", mnemonic, operands);
- else if (mnemonic != nullptr)
- strm.Printf("%s", mnemonic);
-
- int right_pad = 1;
- window.PutCStringTruncated(strm.GetData(), right_pad);
-
- if (is_pc_line && frame_sp &&
- frame_sp->GetConcreteFrameIndex() == 0) {
- StopInfoSP stop_info_sp;
- if (thread)
- stop_info_sp = thread->GetStopInfo();
- if (stop_info_sp) {
- const char *stop_description = stop_info_sp->GetDescription();
- if (stop_description && stop_description[0]) {
- size_t stop_description_len = strlen(stop_description);
- int desc_x = window_width - stop_description_len - 16;
- window.Printf("%*s", desc_x - window.GetCursorX(), "");
- // window.MoveCursor(window_width - stop_description_len - 15,
- // line_y);
- window.Printf("<<< Thread %u: %s ", thread->GetIndexID(),
- stop_description);
- }
- } else {
- window.Printf("%*s", window_width - window.GetCursorX() - 1, "");
- }
- }
- if (highlight_attr)
- window.AttributeOff(highlight_attr);
- }
- }
- }
- return true; // Drawing handled
- }
-
- size_t GetNumLines() {
- size_t num_lines = GetNumSourceLines();
- if (num_lines == 0)
- num_lines = GetNumDisassemblyLines();
- return num_lines;
- }
-
- size_t GetNumSourceLines() const {
- if (m_file_sp)
- return m_file_sp->GetNumLines();
- return 0;
- }
-
- size_t GetNumDisassemblyLines() const {
- if (m_disassembly_sp)
- return m_disassembly_sp->GetInstructionList().GetSize();
- return 0;
- }
-
- HandleCharResult WindowDelegateHandleChar(Window &window, int c) override {
- const uint32_t num_visible_lines = NumVisibleLines();
- const size_t num_lines = GetNumLines();
-
- switch (c) {
- case ',':
- case KEY_PPAGE:
- // Page up key
- if (static_cast<uint32_t>(m_first_visible_line) > num_visible_lines)
- m_first_visible_line -= num_visible_lines;
- else
- m_first_visible_line = 0;
- m_selected_line = m_first_visible_line;
- return eKeyHandled;
-
- case '.':
- case KEY_NPAGE:
- // Page down key
- {
- if (m_first_visible_line + num_visible_lines < num_lines)
- m_first_visible_line += num_visible_lines;
- else if (num_lines < num_visible_lines)
- m_first_visible_line = 0;
- else
- m_first_visible_line = num_lines - num_visible_lines;
- m_selected_line = m_first_visible_line;
- }
- return eKeyHandled;
-
- case KEY_UP:
- if (m_selected_line > 0) {
- m_selected_line--;
- if (static_cast<size_t>(m_first_visible_line) > m_selected_line)
- m_first_visible_line = m_selected_line;
- }
- return eKeyHandled;
-
- case KEY_DOWN:
- if (m_selected_line + 1 < num_lines) {
- m_selected_line++;
- if (m_first_visible_line + num_visible_lines < m_selected_line)
- m_first_visible_line++;
- }
- return eKeyHandled;
-
- case '\r':
- case '\n':
- case KEY_ENTER:
- // Set a breakpoint and run to the line using a one shot breakpoint
- if (GetNumSourceLines() > 0) {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasProcessScope() && exe_ctx.GetProcessRef().IsAlive()) {
- BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
- nullptr, // Don't limit the breakpoint to certain modules
- m_file_sp->GetFileSpec(), // Source file
- m_selected_line +
- 1, // Source line number (m_selected_line is zero based)
- 0, // Unspecified column.
- 0, // No offset
- eLazyBoolCalculate, // Check inlines using global setting
- eLazyBoolCalculate, // Skip prologue using global setting,
- false, // internal
- false, // request_hardware
- eLazyBoolCalculate); // move_to_nearest_code
- // Make breakpoint one shot
- bp_sp->GetOptions()->SetOneShot(true);
- exe_ctx.GetProcessRef().Resume();
- }
- } else if (m_selected_line < GetNumDisassemblyLines()) {
- const Instruction *inst = m_disassembly_sp->GetInstructionList()
- .GetInstructionAtIndex(m_selected_line)
- .get();
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasTargetScope()) {
- Address addr = inst->GetAddress();
- BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
- addr, // lldb_private::Address
- false, // internal
- false); // request_hardware
- // Make breakpoint one shot
- bp_sp->GetOptions()->SetOneShot(true);
- exe_ctx.GetProcessRef().Resume();
- }
- }
- return eKeyHandled;
-
- case 'b': // 'b' == toggle breakpoint on currently selected line
- if (m_selected_line < GetNumSourceLines()) {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasTargetScope()) {
- BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
- nullptr, // Don't limit the breakpoint to certain modules
- m_file_sp->GetFileSpec(), // Source file
- m_selected_line +
- 1, // Source line number (m_selected_line is zero based)
- 0, // No column specified.
- 0, // No offset
- eLazyBoolCalculate, // Check inlines using global setting
- eLazyBoolCalculate, // Skip prologue using global setting,
- false, // internal
- false, // request_hardware
- eLazyBoolCalculate); // move_to_nearest_code
- }
- } else if (m_selected_line < GetNumDisassemblyLines()) {
- const Instruction *inst = m_disassembly_sp->GetInstructionList()
- .GetInstructionAtIndex(m_selected_line)
- .get();
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasTargetScope()) {
- Address addr = inst->GetAddress();
- BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
- addr, // lldb_private::Address
- false, // internal
- false); // request_hardware
- }
- }
- return eKeyHandled;
-
- case 'd': // 'd' == detach and let run
- case 'D': // 'D' == detach and keep stopped
- {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasProcessScope())
- exe_ctx.GetProcessRef().Detach(c == 'D');
- }
- return eKeyHandled;
-
- case 'k':
- // 'k' == kill
- {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasProcessScope())
- exe_ctx.GetProcessRef().Destroy(false);
- }
- return eKeyHandled;
-
- case 'c':
- // 'c' == continue
- {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasProcessScope())
- exe_ctx.GetProcessRef().Resume();
- }
- return eKeyHandled;
-
- case 'o':
- // 'o' == step out
- {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasThreadScope() &&
- StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) {
- exe_ctx.GetThreadRef().StepOut();
- }
- }
- return eKeyHandled;
-
- case 'n': // 'n' == step over
- case 'N': // 'N' == step over instruction
- {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasThreadScope() &&
- StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) {
- bool source_step = (c == 'n');
- exe_ctx.GetThreadRef().StepOver(source_step);
- }
- }
- return eKeyHandled;
-
- case 's': // 's' == step into
- case 'S': // 'S' == step into instruction
- {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasThreadScope() &&
- StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) {
- bool source_step = (c == 's');
- exe_ctx.GetThreadRef().StepIn(source_step);
- }
- }
- return eKeyHandled;
-
- case 'h':
- window.CreateHelpSubwindow();
- return eKeyHandled;
-
- default:
- break;
- }
- return eKeyNotHandled;
- }
-
-protected:
- typedef std::set<uint32_t> BreakpointLines;
- typedef std::set<lldb::addr_t> BreakpointAddrs;
-
- Debugger &m_debugger;
- SymbolContext m_sc;
- SourceManager::FileSP m_file_sp;
- SymbolContextScope *m_disassembly_scope;
- lldb::DisassemblerSP m_disassembly_sp;
- AddressRange m_disassembly_range;
- StreamString m_title;
- lldb::user_id_t m_tid;
- int m_line_width;
- uint32_t m_selected_line; // The selected line
- uint32_t m_pc_line; // The line with the PC
- uint32_t m_stop_id;
- uint32_t m_frame_idx;
- int m_first_visible_line;
- int m_min_x;
- int m_min_y;
- int m_max_x;
- int m_max_y;
-};
-
-DisplayOptions ValueObjectListDelegate::g_options = {true};
-
-IOHandlerCursesGUI::IOHandlerCursesGUI(Debugger &debugger)
- : IOHandler(debugger, IOHandler::Type::Curses) {}
-
-void IOHandlerCursesGUI::Activate() {
- IOHandler::Activate();
- if (!m_app_ap) {
- m_app_ap.reset(new Application(GetInputFILE(), GetOutputFILE()));
-
- // This is both a window and a menu delegate
- std::shared_ptr<ApplicationDelegate> app_delegate_sp(
- new ApplicationDelegate(*m_app_ap, m_debugger));
-
- MenuDelegateSP app_menu_delegate_sp =
- std::static_pointer_cast<MenuDelegate>(app_delegate_sp);
- MenuSP lldb_menu_sp(
- new Menu("LLDB", "F1", KEY_F(1), ApplicationDelegate::eMenuID_LLDB));
- MenuSP exit_menuitem_sp(
- new Menu("Exit", nullptr, 'x', ApplicationDelegate::eMenuID_LLDBExit));
- exit_menuitem_sp->SetCannedResult(MenuActionResult::Quit);
- lldb_menu_sp->AddSubmenu(MenuSP(new Menu(
- "About LLDB", nullptr, 'a', ApplicationDelegate::eMenuID_LLDBAbout)));
- lldb_menu_sp->AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
- lldb_menu_sp->AddSubmenu(exit_menuitem_sp);
-
- MenuSP target_menu_sp(new Menu("Target", "F2", KEY_F(2),
- ApplicationDelegate::eMenuID_Target));
- target_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Create", nullptr, 'c', ApplicationDelegate::eMenuID_TargetCreate)));
- target_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Delete", nullptr, 'd', ApplicationDelegate::eMenuID_TargetDelete)));
-
- MenuSP process_menu_sp(new Menu("Process", "F3", KEY_F(3),
- ApplicationDelegate::eMenuID_Process));
- process_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Attach", nullptr, 'a', ApplicationDelegate::eMenuID_ProcessAttach)));
- process_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Detach", nullptr, 'd', ApplicationDelegate::eMenuID_ProcessDetach)));
- process_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Launch", nullptr, 'l', ApplicationDelegate::eMenuID_ProcessLaunch)));
- process_menu_sp->AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
- process_menu_sp->AddSubmenu(
- MenuSP(new Menu("Continue", nullptr, 'c',
- ApplicationDelegate::eMenuID_ProcessContinue)));
- process_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Halt", nullptr, 'h', ApplicationDelegate::eMenuID_ProcessHalt)));
- process_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Kill", nullptr, 'k', ApplicationDelegate::eMenuID_ProcessKill)));
-
- MenuSP thread_menu_sp(new Menu("Thread", "F4", KEY_F(4),
- ApplicationDelegate::eMenuID_Thread));
- thread_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Step In", nullptr, 'i', ApplicationDelegate::eMenuID_ThreadStepIn)));
- thread_menu_sp->AddSubmenu(
- MenuSP(new Menu("Step Over", nullptr, 'v',
- ApplicationDelegate::eMenuID_ThreadStepOver)));
- thread_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Step Out", nullptr, 'o', ApplicationDelegate::eMenuID_ThreadStepOut)));
-
- MenuSP view_menu_sp(
- new Menu("View", "F5", KEY_F(5), ApplicationDelegate::eMenuID_View));
- view_menu_sp->AddSubmenu(
- MenuSP(new Menu("Backtrace", nullptr, 'b',
- ApplicationDelegate::eMenuID_ViewBacktrace)));
- view_menu_sp->AddSubmenu(
- MenuSP(new Menu("Registers", nullptr, 'r',
- ApplicationDelegate::eMenuID_ViewRegisters)));
- view_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Source", nullptr, 's', ApplicationDelegate::eMenuID_ViewSource)));
- view_menu_sp->AddSubmenu(
- MenuSP(new Menu("Variables", nullptr, 'v',
- ApplicationDelegate::eMenuID_ViewVariables)));
-
- MenuSP help_menu_sp(
- new Menu("Help", "F6", KEY_F(6), ApplicationDelegate::eMenuID_Help));
- help_menu_sp->AddSubmenu(MenuSP(new Menu(
- "GUI Help", nullptr, 'g', ApplicationDelegate::eMenuID_HelpGUIHelp)));
-
- m_app_ap->Initialize();
- WindowSP &main_window_sp = m_app_ap->GetMainWindow();
-
- MenuSP menubar_sp(new Menu(Menu::Type::Bar));
- menubar_sp->AddSubmenu(lldb_menu_sp);
- menubar_sp->AddSubmenu(target_menu_sp);
- menubar_sp->AddSubmenu(process_menu_sp);
- menubar_sp->AddSubmenu(thread_menu_sp);
- menubar_sp->AddSubmenu(view_menu_sp);
- menubar_sp->AddSubmenu(help_menu_sp);
- menubar_sp->SetDelegate(app_menu_delegate_sp);
-
- Rect content_bounds = main_window_sp->GetFrame();
- Rect menubar_bounds = content_bounds.MakeMenuBar();
- Rect status_bounds = content_bounds.MakeStatusBar();
- Rect source_bounds;
- Rect variables_bounds;
- Rect threads_bounds;
- Rect source_variables_bounds;
- content_bounds.VerticalSplitPercentage(0.80, source_variables_bounds,
- threads_bounds);
- source_variables_bounds.HorizontalSplitPercentage(0.70, source_bounds,
- variables_bounds);
-
- WindowSP menubar_window_sp =
- main_window_sp->CreateSubWindow("Menubar", menubar_bounds, false);
- // Let the menubar get keys if the active window doesn't handle the keys
- // that are typed so it can respond to menubar key presses.
- menubar_window_sp->SetCanBeActive(
- false); // Don't let the menubar become the active window
- menubar_window_sp->SetDelegate(menubar_sp);
-
- WindowSP source_window_sp(
- main_window_sp->CreateSubWindow("Source", source_bounds, true));
- WindowSP variables_window_sp(
- main_window_sp->CreateSubWindow("Variables", variables_bounds, false));
- WindowSP threads_window_sp(
- main_window_sp->CreateSubWindow("Threads", threads_bounds, false));
- WindowSP status_window_sp(
- main_window_sp->CreateSubWindow("Status", status_bounds, false));
- status_window_sp->SetCanBeActive(
- false); // Don't let the status bar become the active window
- main_window_sp->SetDelegate(
- std::static_pointer_cast<WindowDelegate>(app_delegate_sp));
- source_window_sp->SetDelegate(
- WindowDelegateSP(new SourceFileWindowDelegate(m_debugger)));
- variables_window_sp->SetDelegate(
- WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger)));
- TreeDelegateSP thread_delegate_sp(new ThreadsTreeDelegate(m_debugger));
- threads_window_sp->SetDelegate(WindowDelegateSP(
- new TreeWindowDelegate(m_debugger, thread_delegate_sp)));
- status_window_sp->SetDelegate(
- WindowDelegateSP(new StatusBarWindowDelegate(m_debugger)));
-
- // Show the main help window once the first time the curses GUI is launched
- static bool g_showed_help = false;
- if (!g_showed_help) {
- g_showed_help = true;
- main_window_sp->CreateHelpSubwindow();
- }
-
- init_pair(1, COLOR_WHITE, COLOR_BLUE);
- init_pair(2, COLOR_BLACK, COLOR_WHITE);
- init_pair(3, COLOR_MAGENTA, COLOR_WHITE);
- init_pair(4, COLOR_MAGENTA, COLOR_BLACK);
- init_pair(5, COLOR_RED, COLOR_BLACK);
- }
-}
-
-void IOHandlerCursesGUI::Deactivate() { m_app_ap->Terminate(); }
-
-void IOHandlerCursesGUI::Run() {
- m_app_ap->Run(m_debugger);
- SetIsDone(true);
-}
-
-IOHandlerCursesGUI::~IOHandlerCursesGUI() = default;
-
-void IOHandlerCursesGUI::Cancel() {}
-
-bool IOHandlerCursesGUI::Interrupt() { return false; }
-
-void IOHandlerCursesGUI::GotEOF() {}
-
-#endif // LLDB_DISABLE_CURSES
diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp
new file mode 100644
index 000000000000..1661b465efaf
--- /dev/null
+++ b/lldb/source/Core/IOHandlerCursesGUI.cpp
@@ -0,0 +1,4067 @@
+//===-- IOHandlerCursesGUI.cpp ----------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/IOHandlerCursesGUI.h"
+#include "lldb/Host/Config.h"
+
+#if LLDB_ENABLE_CURSES
+#include <curses.h>
+#include <panel.h>
+#endif
+
+#if defined(__APPLE__)
+#include <deque>
+#endif
+#include <string>
+
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Host/File.h"
+#include "lldb/Utility/Predicate.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/Utility/StreamString.h"
+#include "lldb/Utility/StringList.h"
+#include "lldb/lldb-forward.h"
+
+#include "lldb/Interpreter/CommandCompletions.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+
+#if LLDB_ENABLE_CURSES
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectRegister.h"
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Utility/State.h"
+#endif
+
+#include "llvm/ADT/StringRef.h"
+
+#ifdef _WIN32
+#include "lldb/Host/windows/windows.h"
+#endif
+
+#include <memory>
+#include <mutex>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <locale.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <type_traits>
+
+using namespace lldb;
+using namespace lldb_private;
+using llvm::None;
+using llvm::Optional;
+using llvm::StringRef;
+
+// we may want curses to be disabled for some builds for instance, windows
+#if LLDB_ENABLE_CURSES
+
+#define KEY_RETURN 10
+#define KEY_ESCAPE 27
+
+namespace curses {
+class Menu;
+class MenuDelegate;
+class Window;
+class WindowDelegate;
+typedef std::shared_ptr<Menu> MenuSP;
+typedef std::shared_ptr<MenuDelegate> MenuDelegateSP;
+typedef std::shared_ptr<Window> WindowSP;
+typedef std::shared_ptr<WindowDelegate> WindowDelegateSP;
+typedef std::vector<MenuSP> Menus;
+typedef std::vector<WindowSP> Windows;
+typedef std::vector<WindowDelegateSP> WindowDelegates;
+
+#if 0
+type summary add -s "x=${var.x}, y=${var.y}" curses::Point
+type summary add -s "w=${var.width}, h=${var.height}" curses::Size
+type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
+#endif
+
+struct Point {
+ int x;
+ int y;
+
+ Point(int _x = 0, int _y = 0) : x(_x), y(_y) {}
+
+ void Clear() {
+ x = 0;
+ y = 0;
+ }
+
+ Point &operator+=(const Point &rhs) {
+ x += rhs.x;
+ y += rhs.y;
+ return *this;
+ }
+
+ void Dump() { printf("(x=%i, y=%i)\n", x, y); }
+};
+
+bool operator==(const Point &lhs, const Point &rhs) {
+ return lhs.x == rhs.x && lhs.y == rhs.y;
+}
+
+bool operator!=(const Point &lhs, const Point &rhs) {
+ return lhs.x != rhs.x || lhs.y != rhs.y;
+}
+
+struct Size {
+ int width;
+ int height;
+ Size(int w = 0, int h = 0) : width(w), height(h) {}
+
+ void Clear() {
+ width = 0;
+ height = 0;
+ }
+
+ void Dump() { printf("(w=%i, h=%i)\n", width, height); }
+};
+
+bool operator==(const Size &lhs, const Size &rhs) {
+ return lhs.width == rhs.width && lhs.height == rhs.height;
+}
+
+bool operator!=(const Size &lhs, const Size &rhs) {
+ return lhs.width != rhs.width || lhs.height != rhs.height;
+}
+
+struct Rect {
+ Point origin;
+ Size size;
+
+ Rect() : origin(), size() {}
+
+ Rect(const Point &p, const Size &s) : origin(p), size(s) {}
+
+ void Clear() {
+ origin.Clear();
+ size.Clear();
+ }
+
+ void Dump() {
+ printf("(x=%i, y=%i), w=%i, h=%i)\n", origin.x, origin.y, size.width,
+ size.height);
+ }
+
+ void Inset(int w, int h) {
+ if (size.width > w * 2)
+ size.width -= w * 2;
+ origin.x += w;
+
+ if (size.height > h * 2)
+ size.height -= h * 2;
+ origin.y += h;
+ }
+
+ // Return a status bar rectangle which is the last line of this rectangle.
+ // This rectangle will be modified to not include the status bar area.
+ Rect MakeStatusBar() {
+ Rect status_bar;
+ if (size.height > 1) {
+ status_bar.origin.x = origin.x;
+ status_bar.origin.y = size.height;
+ status_bar.size.width = size.width;
+ status_bar.size.height = 1;
+ --size.height;
+ }
+ return status_bar;
+ }
+
+ // Return a menubar rectangle which is the first line of this rectangle. This
+ // rectangle will be modified to not include the menubar area.
+ Rect MakeMenuBar() {
+ Rect menubar;
+ if (size.height > 1) {
+ menubar.origin.x = origin.x;
+ menubar.origin.y = origin.y;
+ menubar.size.width = size.width;
+ menubar.size.height = 1;
+ ++origin.y;
+ --size.height;
+ }
+ return menubar;
+ }
+
+ void HorizontalSplitPercentage(float top_percentage, Rect &top,
+ Rect &bottom) const {
+ float top_height = top_percentage * size.height;
+ HorizontalSplit(top_height, top, bottom);
+ }
+
+ void HorizontalSplit(int top_height, Rect &top, Rect &bottom) const {
+ top = *this;
+ if (top_height < size.height) {
+ top.size.height = top_height;
+ bottom.origin.x = origin.x;
+ bottom.origin.y = origin.y + top.size.height;
+ bottom.size.width = size.width;
+ bottom.size.height = size.height - top.size.height;
+ } else {
+ bottom.Clear();
+ }
+ }
+
+ void VerticalSplitPercentage(float left_percentage, Rect &left,
+ Rect &right) const {
+ float left_width = left_percentage * size.width;
+ VerticalSplit(left_width, left, right);
+ }
+
+ void VerticalSplit(int left_width, Rect &left, Rect &right) const {
+ left = *this;
+ if (left_width < size.width) {
+ left.size.width = left_width;
+ right.origin.x = origin.x + left.size.width;
+ right.origin.y = origin.y;
+ right.size.width = size.width - left.size.width;
+ right.size.height = size.height;
+ } else {
+ right.Clear();
+ }
+ }
+};
+
+bool operator==(const Rect &lhs, const Rect &rhs) {
+ return lhs.origin == rhs.origin && lhs.size == rhs.size;
+}
+
+bool operator!=(const Rect &lhs, const Rect &rhs) {
+ return lhs.origin != rhs.origin || lhs.size != rhs.size;
+}
+
+enum HandleCharResult {
+ eKeyNotHandled = 0,
+ eKeyHandled = 1,
+ eQuitApplication = 2
+};
+
+enum class MenuActionResult {
+ Handled,
+ NotHandled,
+ Quit // Exit all menus and quit
+};
+
+struct KeyHelp {
+ int ch;
+ const char *description;
+};
+
+class WindowDelegate {
+public:
+ virtual ~WindowDelegate() = default;
+
+ virtual bool WindowDelegateDraw(Window &window, bool force) {
+ return false; // Drawing not handled
+ }
+
+ virtual HandleCharResult WindowDelegateHandleChar(Window &window, int key) {
+ return eKeyNotHandled;
+ }
+
+ virtual const char *WindowDelegateGetHelpText() { return nullptr; }
+
+ virtual KeyHelp *WindowDelegateGetKeyHelp() { return nullptr; }
+};
+
+class HelpDialogDelegate : public WindowDelegate {
+public:
+ HelpDialogDelegate(const char *text, KeyHelp *key_help_array);
+
+ ~HelpDialogDelegate() override;
+
+ bool WindowDelegateDraw(Window &window, bool force) override;
+
+ HandleCharResult WindowDelegateHandleChar(Window &window, int key) override;
+
+ size_t GetNumLines() const { return m_text.GetSize(); }
+
+ size_t GetMaxLineLength() const { return m_text.GetMaxStringLength(); }
+
+protected:
+ StringList m_text;
+ int m_first_visible_line;
+};
+
+class Window {
+public:
+ Window(const char *name)
+ : m_name(name), m_window(nullptr), m_panel(nullptr), m_parent(nullptr),
+ m_subwindows(), m_delegate_sp(), m_curr_active_window_idx(UINT32_MAX),
+ m_prev_active_window_idx(UINT32_MAX), m_delete(false),
+ m_needs_update(true), m_can_activate(true), m_is_subwin(false) {}
+
+ Window(const char *name, WINDOW *w, bool del = true)
+ : m_name(name), m_window(nullptr), m_panel(nullptr), m_parent(nullptr),
+ m_subwindows(), m_delegate_sp(), m_curr_active_window_idx(UINT32_MAX),
+ m_prev_active_window_idx(UINT32_MAX), m_delete(del),
+ m_needs_update(true), m_can_activate(true), m_is_subwin(false) {
+ if (w)
+ Reset(w);
+ }
+
+ Window(const char *name, const Rect &bounds)
+ : m_name(name), m_window(nullptr), m_parent(nullptr), m_subwindows(),
+ m_delegate_sp(), m_curr_active_window_idx(UINT32_MAX),
+ m_prev_active_window_idx(UINT32_MAX), m_delete(true),
+ m_needs_update(true), m_can_activate(true), m_is_subwin(false) {
+ Reset(::newwin(bounds.size.height, bounds.size.width, bounds.origin.y,
+ bounds.origin.y));
+ }
+
+ virtual ~Window() {
+ RemoveSubWindows();
+ Reset();
+ }
+
+ void Reset(WINDOW *w = nullptr, bool del = true) {
+ if (m_window == w)
+ return;
+
+ if (m_panel) {
+ ::del_panel(m_panel);
+ m_panel = nullptr;
+ }
+ if (m_window && m_delete) {
+ ::delwin(m_window);
+ m_window = nullptr;
+ m_delete = false;
+ }
+ if (w) {
+ m_window = w;
+ m_panel = ::new_panel(m_window);
+ m_delete = del;
+ }
+ }
+
+ void AttributeOn(attr_t attr) { ::wattron(m_window, attr); }
+ void AttributeOff(attr_t attr) { ::wattroff(m_window, attr); }
+ void Box(chtype v_char = ACS_VLINE, chtype h_char = ACS_HLINE) {
+ ::box(m_window, v_char, h_char);
+ }
+ void Clear() { ::wclear(m_window); }
+ void Erase() { ::werase(m_window); }
+ Rect GetBounds() {
+ return Rect(GetParentOrigin(), GetSize());
+ } // Get the rectangle in our parent window
+ int GetChar() { return ::wgetch(m_window); }
+ int GetCursorX() { return getcurx(m_window); }
+ int GetCursorY() { return getcury(m_window); }
+ Rect GetFrame() {
+ return Rect(Point(), GetSize());
+ } // Get our rectangle in our own coordinate system
+ Point GetParentOrigin() { return Point(GetParentX(), GetParentY()); }
+ Size GetSize() { return Size(GetWidth(), GetHeight()); }
+ int GetParentX() { return getparx(m_window); }
+ int GetParentY() { return getpary(m_window); }
+ int GetMaxX() { return getmaxx(m_window); }
+ int GetMaxY() { return getmaxy(m_window); }
+ int GetWidth() { return GetMaxX(); }
+ int GetHeight() { return GetMaxY(); }
+ void MoveCursor(int x, int y) { ::wmove(m_window, y, x); }
+ void MoveWindow(int x, int y) { MoveWindow(Point(x, y)); }
+ void Resize(int w, int h) { ::wresize(m_window, h, w); }
+ void Resize(const Size &size) {
+ ::wresize(m_window, size.height, size.width);
+ }
+ void PutChar(int ch) { ::waddch(m_window, ch); }
+ void PutCString(const char *s, int len = -1) { ::waddnstr(m_window, s, len); }
+ void SetBackground(int color_pair_idx) {
+ ::wbkgd(m_window, COLOR_PAIR(color_pair_idx));
+ }
+
+ void PutCStringTruncated(const char *s, int right_pad) {
+ int bytes_left = GetWidth() - GetCursorX();
+ if (bytes_left > right_pad) {
+ bytes_left -= right_pad;
+ ::waddnstr(m_window, s, bytes_left);
+ }
+ }
+
+ void MoveWindow(const Point &origin) {
+ const bool moving_window = origin != GetParentOrigin();
+ if (m_is_subwin && moving_window) {
+ // Can't move subwindows, must delete and re-create
+ Size size = GetSize();
+ Reset(::subwin(m_parent->m_window, size.height, size.width, origin.y,
+ origin.x),
+ true);
+ } else {
+ ::mvwin(m_window, origin.y, origin.x);
+ }
+ }
+
+ void SetBounds(const Rect &bounds) {
+ const bool moving_window = bounds.origin != GetParentOrigin();
+ if (m_is_subwin && moving_window) {
+ // Can't move subwindows, must delete and re-create
+ Reset(::subwin(m_parent->m_window, bounds.size.height, bounds.size.width,
+ bounds.origin.y, bounds.origin.x),
+ true);
+ } else {
+ if (moving_window)
+ MoveWindow(bounds.origin);
+ Resize(bounds.size);
+ }
+ }
+
+ void Printf(const char *format, ...) __attribute__((format(printf, 2, 3))) {
+ va_list args;
+ va_start(args, format);
+ vwprintw(m_window, format, args);
+ va_end(args);
+ }
+
+ void Touch() {
+ ::touchwin(m_window);
+ if (m_parent)
+ m_parent->Touch();
+ }
+
+ WindowSP CreateSubWindow(const char *name, const Rect &bounds,
+ bool make_active) {
+ auto get_window = [this, &bounds]() {
+ return m_window
+ ? ::subwin(m_window, bounds.size.height, bounds.size.width,
+ bounds.origin.y, bounds.origin.x)
+ : ::newwin(bounds.size.height, bounds.size.width,
+ bounds.origin.y, bounds.origin.x);
+ };
+ WindowSP subwindow_sp = std::make_shared<Window>(name, get_window(), true);
+ subwindow_sp->m_is_subwin = subwindow_sp.operator bool();
+ subwindow_sp->m_parent = this;
+ if (make_active) {
+ m_prev_active_window_idx = m_curr_active_window_idx;
+ m_curr_active_window_idx = m_subwindows.size();
+ }
+ m_subwindows.push_back(subwindow_sp);
+ ::top_panel(subwindow_sp->m_panel);
+ m_needs_update = true;
+ return subwindow_sp;
+ }
+
+ bool RemoveSubWindow(Window *window) {
+ Windows::iterator pos, end = m_subwindows.end();
+ size_t i = 0;
+ for (pos = m_subwindows.begin(); pos != end; ++pos, ++i) {
+ if ((*pos).get() == window) {
+ if (m_prev_active_window_idx == i)
+ m_prev_active_window_idx = UINT32_MAX;
+ else if (m_prev_active_window_idx != UINT32_MAX &&
+ m_prev_active_window_idx > i)
+ --m_prev_active_window_idx;
+
+ if (m_curr_active_window_idx == i)
+ m_curr_active_window_idx = UINT32_MAX;
+ else if (m_curr_active_window_idx != UINT32_MAX &&
+ m_curr_active_window_idx > i)
+ --m_curr_active_window_idx;
+ window->Erase();
+ m_subwindows.erase(pos);
+ m_needs_update = true;
+ if (m_parent)
+ m_parent->Touch();
+ else
+ ::touchwin(stdscr);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ WindowSP FindSubWindow(const char *name) {
+ Windows::iterator pos, end = m_subwindows.end();
+ size_t i = 0;
+ for (pos = m_subwindows.begin(); pos != end; ++pos, ++i) {
+ if ((*pos)->m_name == name)
+ return *pos;
+ }
+ return WindowSP();
+ }
+
+ void RemoveSubWindows() {
+ m_curr_active_window_idx = UINT32_MAX;
+ m_prev_active_window_idx = UINT32_MAX;
+ for (Windows::iterator pos = m_subwindows.begin();
+ pos != m_subwindows.end(); pos = m_subwindows.erase(pos)) {
+ (*pos)->Erase();
+ }
+ if (m_parent)
+ m_parent->Touch();
+ else
+ ::touchwin(stdscr);
+ }
+
+ WINDOW *get() { return m_window; }
+
+ operator WINDOW *() { return m_window; }
+
+ // Window drawing utilities
+ void DrawTitleBox(const char *title, const char *bottom_message = nullptr) {
+ attr_t attr = 0;
+ if (IsActive())
+ attr = A_BOLD | COLOR_PAIR(2);
+ else
+ attr = 0;
+ if (attr)
+ AttributeOn(attr);
+
+ Box();
+ MoveCursor(3, 0);
+
+ if (title && title[0]) {
+ PutChar('<');
+ PutCString(title);
+ PutChar('>');
+ }
+
+ if (bottom_message && bottom_message[0]) {
+ int bottom_message_length = strlen(bottom_message);
+ int x = GetWidth() - 3 - (bottom_message_length + 2);
+
+ if (x > 0) {
+ MoveCursor(x, GetHeight() - 1);
+ PutChar('[');
+ PutCString(bottom_message);
+ PutChar(']');
+ } else {
+ MoveCursor(1, GetHeight() - 1);
+ PutChar('[');
+ PutCStringTruncated(bottom_message, 1);
+ }
+ }
+ if (attr)
+ AttributeOff(attr);
+ }
+
+ virtual void Draw(bool force) {
+ if (m_delegate_sp && m_delegate_sp->WindowDelegateDraw(*this, force))
+ return;
+
+ for (auto &subwindow_sp : m_subwindows)
+ subwindow_sp->Draw(force);
+ }
+
+ bool CreateHelpSubwindow() {
+ if (m_delegate_sp) {
+ const char *text = m_delegate_sp->WindowDelegateGetHelpText();
+ KeyHelp *key_help = m_delegate_sp->WindowDelegateGetKeyHelp();
+ if ((text && text[0]) || key_help) {
+ std::unique_ptr<HelpDialogDelegate> help_delegate_up(
+ new HelpDialogDelegate(text, key_help));
+ const size_t num_lines = help_delegate_up->GetNumLines();
+ const size_t max_length = help_delegate_up->GetMaxLineLength();
+ Rect bounds = GetBounds();
+ bounds.Inset(1, 1);
+ if (max_length + 4 < static_cast<size_t>(bounds.size.width)) {
+ bounds.origin.x += (bounds.size.width - max_length + 4) / 2;
+ bounds.size.width = max_length + 4;
+ } else {
+ if (bounds.size.width > 100) {
+ const int inset_w = bounds.size.width / 4;
+ bounds.origin.x += inset_w;
+ bounds.size.width -= 2 * inset_w;
+ }
+ }
+
+ if (num_lines + 2 < static_cast<size_t>(bounds.size.height)) {
+ bounds.origin.y += (bounds.size.height - num_lines + 2) / 2;
+ bounds.size.height = num_lines + 2;
+ } else {
+ if (bounds.size.height > 100) {
+ const int inset_h = bounds.size.height / 4;
+ bounds.origin.y += inset_h;
+ bounds.size.height -= 2 * inset_h;
+ }
+ }
+ WindowSP help_window_sp;
+ Window *parent_window = GetParent();
+ if (parent_window)
+ help_window_sp = parent_window->CreateSubWindow("Help", bounds, true);
+ else
+ help_window_sp = CreateSubWindow("Help", bounds, true);
+ help_window_sp->SetDelegate(
+ WindowDelegateSP(help_delegate_up.release()));
+ return true;
+ }
+ }
+ return false;
+ }
+
+ virtual HandleCharResult HandleChar(int key) {
+ // Always check the active window first
+ HandleCharResult result = eKeyNotHandled;
+ WindowSP active_window_sp = GetActiveWindow();
+ if (active_window_sp) {
+ result = active_window_sp->HandleChar(key);
+ if (result != eKeyNotHandled)
+ return result;
+ }
+
+ if (m_delegate_sp) {
+ result = m_delegate_sp->WindowDelegateHandleChar(*this, key);
+ if (result != eKeyNotHandled)
+ return result;
+ }
+
+ // Then check for any windows that want any keys that weren't handled. This
+ // is typically only for a menubar. Make a copy of the subwindows in case
+ // any HandleChar() functions muck with the subwindows. If we don't do
+ // this, we can crash when iterating over the subwindows.
+ Windows subwindows(m_subwindows);
+ for (auto subwindow_sp : subwindows) {
+ if (!subwindow_sp->m_can_activate) {
+ HandleCharResult result = subwindow_sp->HandleChar(key);
+ if (result != eKeyNotHandled)
+ return result;
+ }
+ }
+
+ return eKeyNotHandled;
+ }
+
+ WindowSP GetActiveWindow() {
+ if (!m_subwindows.empty()) {
+ if (m_curr_active_window_idx >= m_subwindows.size()) {
+ if (m_prev_active_window_idx < m_subwindows.size()) {
+ m_curr_active_window_idx = m_prev_active_window_idx;
+ m_prev_active_window_idx = UINT32_MAX;
+ } else if (IsActive()) {
+ m_prev_active_window_idx = UINT32_MAX;
+ m_curr_active_window_idx = UINT32_MAX;
+
+ // Find first window that wants to be active if this window is active
+ const size_t num_subwindows = m_subwindows.size();
+ for (size_t i = 0; i < num_subwindows; ++i) {
+ if (m_subwindows[i]->GetCanBeActive()) {
+ m_curr_active_window_idx = i;
+ break;
+ }
+ }
+ }
+ }
+
+ if (m_curr_active_window_idx < m_subwindows.size())
+ return m_subwindows[m_curr_active_window_idx];
+ }
+ return WindowSP();
+ }
+
+ bool GetCanBeActive() const { return m_can_activate; }
+
+ void SetCanBeActive(bool b) { m_can_activate = b; }
+
+ void SetDelegate(const WindowDelegateSP &delegate_sp) {
+ m_delegate_sp = delegate_sp;
+ }
+
+ Window *GetParent() const { return m_parent; }
+
+ bool IsActive() const {
+ if (m_parent)
+ return m_parent->GetActiveWindow().get() == this;
+ else
+ return true; // Top level window is always active
+ }
+
+ void SelectNextWindowAsActive() {
+ // Move active focus to next window
+ const size_t num_subwindows = m_subwindows.size();
+ if (m_curr_active_window_idx == UINT32_MAX) {
+ uint32_t idx = 0;
+ for (auto subwindow_sp : m_subwindows) {
+ if (subwindow_sp->GetCanBeActive()) {
+ m_curr_active_window_idx = idx;
+ break;
+ }
+ ++idx;
+ }
+ } else if (m_curr_active_window_idx + 1 < num_subwindows) {
+ bool handled = false;
+ m_prev_active_window_idx = m_curr_active_window_idx;
+ for (size_t idx = m_curr_active_window_idx + 1; idx < num_subwindows;
+ ++idx) {
+ if (m_subwindows[idx]->GetCanBeActive()) {
+ m_curr_active_window_idx = idx;
+ handled = true;
+ break;
+ }
+ }
+ if (!handled) {
+ for (size_t idx = 0; idx <= m_prev_active_window_idx; ++idx) {
+ if (m_subwindows[idx]->GetCanBeActive()) {
+ m_curr_active_window_idx = idx;
+ break;
+ }
+ }
+ }
+ } else {
+ m_prev_active_window_idx = m_curr_active_window_idx;
+ for (size_t idx = 0; idx < num_subwindows; ++idx) {
+ if (m_subwindows[idx]->GetCanBeActive()) {
+ m_curr_active_window_idx = idx;
+ break;
+ }
+ }
+ }
+ }
+
+ const char *GetName() const { return m_name.c_str(); }
+
+protected:
+ std::string m_name;
+ WINDOW *m_window;
+ PANEL *m_panel;
+ Window *m_parent;
+ Windows m_subwindows;
+ WindowDelegateSP m_delegate_sp;
+ uint32_t m_curr_active_window_idx;
+ uint32_t m_prev_active_window_idx;
+ bool m_delete;
+ bool m_needs_update;
+ bool m_can_activate;
+ bool m_is_subwin;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(Window);
+};
+
+class MenuDelegate {
+public:
+ virtual ~MenuDelegate() = default;
+
+ virtual MenuActionResult MenuDelegateAction(Menu &menu) = 0;
+};
+
+class Menu : public WindowDelegate {
+public:
+ enum class Type { Invalid, Bar, Item, Separator };
+
+ // Menubar or separator constructor
+ Menu(Type type);
+
+ // Menuitem constructor
+ Menu(const char *name, const char *key_name, int key_value,
+ uint64_t identifier);
+
+ ~Menu() override = default;
+
+ const MenuDelegateSP &GetDelegate() const { return m_delegate_sp; }
+
+ void SetDelegate(const MenuDelegateSP &delegate_sp) {
+ m_delegate_sp = delegate_sp;
+ }
+
+ void RecalculateNameLengths();
+
+ void AddSubmenu(const MenuSP &menu_sp);
+
+ int DrawAndRunMenu(Window &window);
+
+ void DrawMenuTitle(Window &window, bool highlight);
+
+ bool WindowDelegateDraw(Window &window, bool force) override;
+
+ HandleCharResult WindowDelegateHandleChar(Window &window, int key) override;
+
+ MenuActionResult ActionPrivate(Menu &menu) {
+ MenuActionResult result = MenuActionResult::NotHandled;
+ if (m_delegate_sp) {
+ result = m_delegate_sp->MenuDelegateAction(menu);
+ if (result != MenuActionResult::NotHandled)
+ return result;
+ } else if (m_parent) {
+ result = m_parent->ActionPrivate(menu);
+ if (result != MenuActionResult::NotHandled)
+ return result;
+ }
+ return m_canned_result;
+ }
+
+ MenuActionResult Action() {
+ // Call the recursive action so it can try to handle it with the menu
+ // delegate, and if not, try our parent menu
+ return ActionPrivate(*this);
+ }
+
+ void SetCannedResult(MenuActionResult result) { m_canned_result = result; }
+
+ Menus &GetSubmenus() { return m_submenus; }
+
+ const Menus &GetSubmenus() const { return m_submenus; }
+
+ int GetSelectedSubmenuIndex() const { return m_selected; }
+
+ void SetSelectedSubmenuIndex(int idx) { m_selected = idx; }
+
+ Type GetType() const { return m_type; }
+
+ int GetStartingColumn() const { return m_start_col; }
+
+ void SetStartingColumn(int col) { m_start_col = col; }
+
+ int GetKeyValue() const { return m_key_value; }
+
+ std::string &GetName() { return m_name; }
+
+ int GetDrawWidth() const {
+ return m_max_submenu_name_length + m_max_submenu_key_name_length + 8;
+ }
+
+ uint64_t GetIdentifier() const { return m_identifier; }
+
+ void SetIdentifier(uint64_t identifier) { m_identifier = identifier; }
+
+protected:
+ std::string m_name;
+ std::string m_key_name;
+ uint64_t m_identifier;
+ Type m_type;
+ int m_key_value;
+ int m_start_col;
+ int m_max_submenu_name_length;
+ int m_max_submenu_key_name_length;
+ int m_selected;
+ Menu *m_parent;
+ Menus m_submenus;
+ WindowSP m_menu_window_sp;
+ MenuActionResult m_canned_result;
+ MenuDelegateSP m_delegate_sp;
+};
+
+// Menubar or separator constructor
+Menu::Menu(Type type)
+ : m_name(), m_key_name(), m_identifier(0), m_type(type), m_key_value(0),
+ m_start_col(0), m_max_submenu_name_length(0),
+ m_max_submenu_key_name_length(0), m_selected(0), m_parent(nullptr),
+ m_submenus(), m_canned_result(MenuActionResult::NotHandled),
+ m_delegate_sp() {}
+
+// Menuitem constructor
+Menu::Menu(const char *name, const char *key_name, int key_value,
+ uint64_t identifier)
+ : m_name(), m_key_name(), m_identifier(identifier), m_type(Type::Invalid),
+ m_key_value(key_value), m_start_col(0), m_max_submenu_name_length(0),
+ m_max_submenu_key_name_length(0), m_selected(0), m_parent(nullptr),
+ m_submenus(), m_canned_result(MenuActionResult::NotHandled),
+ m_delegate_sp() {
+ if (name && name[0]) {
+ m_name = name;
+ m_type = Type::Item;
+ if (key_name && key_name[0])
+ m_key_name = key_name;
+ } else {
+ m_type = Type::Separator;
+ }
+}
+
+void Menu::RecalculateNameLengths() {
+ m_max_submenu_name_length = 0;
+ m_max_submenu_key_name_length = 0;
+ Menus &submenus = GetSubmenus();
+ const size_t num_submenus = submenus.size();
+ for (size_t i = 0; i < num_submenus; ++i) {
+ Menu *submenu = submenus[i].get();
+ if (static_cast<size_t>(m_max_submenu_name_length) < submenu->m_name.size())
+ m_max_submenu_name_length = submenu->m_name.size();
+ if (static_cast<size_t>(m_max_submenu_key_name_length) <
+ submenu->m_key_name.size())
+ m_max_submenu_key_name_length = submenu->m_key_name.size();
+ }
+}
+
+void Menu::AddSubmenu(const MenuSP &menu_sp) {
+ menu_sp->m_parent = this;
+ if (static_cast<size_t>(m_max_submenu_name_length) < menu_sp->m_name.size())
+ m_max_submenu_name_length = menu_sp->m_name.size();
+ if (static_cast<size_t>(m_max_submenu_key_name_length) <
+ menu_sp->m_key_name.size())
+ m_max_submenu_key_name_length = menu_sp->m_key_name.size();
+ m_submenus.push_back(menu_sp);
+}
+
+void Menu::DrawMenuTitle(Window &window, bool highlight) {
+ if (m_type == Type::Separator) {
+ window.MoveCursor(0, window.GetCursorY());
+ window.PutChar(ACS_LTEE);
+ int width = window.GetWidth();
+ if (width > 2) {
+ width -= 2;
+ for (int i = 0; i < width; ++i)
+ window.PutChar(ACS_HLINE);
+ }
+ window.PutChar(ACS_RTEE);
+ } else {
+ const int shortcut_key = m_key_value;
+ bool underlined_shortcut = false;
+ const attr_t hilgight_attr = A_REVERSE;
+ if (highlight)
+ window.AttributeOn(hilgight_attr);
+ if (isprint(shortcut_key)) {
+ size_t lower_pos = m_name.find(tolower(shortcut_key));
+ size_t upper_pos = m_name.find(toupper(shortcut_key));
+ const char *name = m_name.c_str();
+ size_t pos = std::min<size_t>(lower_pos, upper_pos);
+ if (pos != std::string::npos) {
+ underlined_shortcut = true;
+ if (pos > 0) {
+ window.PutCString(name, pos);
+ name += pos;
+ }
+ const attr_t shortcut_attr = A_UNDERLINE | A_BOLD;
+ window.AttributeOn(shortcut_attr);
+ window.PutChar(name[0]);
+ window.AttributeOff(shortcut_attr);
+ name++;
+ if (name[0])
+ window.PutCString(name);
+ }
+ }
+
+ if (!underlined_shortcut) {
+ window.PutCString(m_name.c_str());
+ }
+
+ if (highlight)
+ window.AttributeOff(hilgight_attr);
+
+ if (m_key_name.empty()) {
+ if (!underlined_shortcut && isprint(m_key_value)) {
+ window.AttributeOn(COLOR_PAIR(3));
+ window.Printf(" (%c)", m_key_value);
+ window.AttributeOff(COLOR_PAIR(3));
+ }
+ } else {
+ window.AttributeOn(COLOR_PAIR(3));
+ window.Printf(" (%s)", m_key_name.c_str());
+ window.AttributeOff(COLOR_PAIR(3));
+ }
+ }
+}
+
+bool Menu::WindowDelegateDraw(Window &window, bool force) {
+ Menus &submenus = GetSubmenus();
+ const size_t num_submenus = submenus.size();
+ const int selected_idx = GetSelectedSubmenuIndex();
+ Menu::Type menu_type = GetType();
+ switch (menu_type) {
+ case Menu::Type::Bar: {
+ window.SetBackground(2);
+ window.MoveCursor(0, 0);
+ for (size_t i = 0; i < num_submenus; ++i) {
+ Menu *menu = submenus[i].get();
+ if (i > 0)
+ window.PutChar(' ');
+ menu->SetStartingColumn(window.GetCursorX());
+ window.PutCString("| ");
+ menu->DrawMenuTitle(window, false);
+ }
+ window.PutCString(" |");
+ } break;
+
+ case Menu::Type::Item: {
+ int y = 1;
+ int x = 3;
+ // Draw the menu
+ int cursor_x = 0;
+ int cursor_y = 0;
+ window.Erase();
+ window.SetBackground(2);
+ window.Box();
+ for (size_t i = 0; i < num_submenus; ++i) {
+ const bool is_selected = (i == static_cast<size_t>(selected_idx));
+ window.MoveCursor(x, y + i);
+ if (is_selected) {
+ // Remember where we want the cursor to be
+ cursor_x = x - 1;
+ cursor_y = y + i;
+ }
+ submenus[i]->DrawMenuTitle(window, is_selected);
+ }
+ window.MoveCursor(cursor_x, cursor_y);
+ } break;
+
+ default:
+ case Menu::Type::Separator:
+ break;
+ }
+ return true; // Drawing handled...
+}
+
+HandleCharResult Menu::WindowDelegateHandleChar(Window &window, int key) {
+ HandleCharResult result = eKeyNotHandled;
+
+ Menus &submenus = GetSubmenus();
+ const size_t num_submenus = submenus.size();
+ const int selected_idx = GetSelectedSubmenuIndex();
+ Menu::Type menu_type = GetType();
+ if (menu_type == Menu::Type::Bar) {
+ MenuSP run_menu_sp;
+ switch (key) {
+ case KEY_DOWN:
+ case KEY_UP:
+ // Show last menu or first menu
+ if (selected_idx < static_cast<int>(num_submenus))
+ run_menu_sp = submenus[selected_idx];
+ else if (!submenus.empty())
+ run_menu_sp = submenus.front();
+ result = eKeyHandled;
+ break;
+
+ case KEY_RIGHT:
+ ++m_selected;
+ if (m_selected >= static_cast<int>(num_submenus))
+ m_selected = 0;
+ if (m_selected < static_cast<int>(num_submenus))
+ run_menu_sp = submenus[m_selected];
+ else if (!submenus.empty())
+ run_menu_sp = submenus.front();
+ result = eKeyHandled;
+ break;
+
+ case KEY_LEFT:
+ --m_selected;
+ if (m_selected < 0)
+ m_selected = num_submenus - 1;
+ if (m_selected < static_cast<int>(num_submenus))
+ run_menu_sp = submenus[m_selected];
+ else if (!submenus.empty())
+ run_menu_sp = submenus.front();
+ result = eKeyHandled;
+ break;
+
+ default:
+ for (size_t i = 0; i < num_submenus; ++i) {
+ if (submenus[i]->GetKeyValue() == key) {
+ SetSelectedSubmenuIndex(i);
+ run_menu_sp = submenus[i];
+ result = eKeyHandled;
+ break;
+ }
+ }
+ break;
+ }
+
+ if (run_menu_sp) {
+ // Run the action on this menu in case we need to populate the menu with
+ // dynamic content and also in case check marks, and any other menu
+ // decorations need to be calculated
+ if (run_menu_sp->Action() == MenuActionResult::Quit)
+ return eQuitApplication;
+
+ Rect menu_bounds;
+ menu_bounds.origin.x = run_menu_sp->GetStartingColumn();
+ menu_bounds.origin.y = 1;
+ menu_bounds.size.width = run_menu_sp->GetDrawWidth();
+ menu_bounds.size.height = run_menu_sp->GetSubmenus().size() + 2;
+ if (m_menu_window_sp)
+ window.GetParent()->RemoveSubWindow(m_menu_window_sp.get());
+
+ m_menu_window_sp = window.GetParent()->CreateSubWindow(
+ run_menu_sp->GetName().c_str(), menu_bounds, true);
+ m_menu_window_sp->SetDelegate(run_menu_sp);
+ }
+ } else if (menu_type == Menu::Type::Item) {
+ switch (key) {
+ case KEY_DOWN:
+ if (m_submenus.size() > 1) {
+ const int start_select = m_selected;
+ while (++m_selected != start_select) {
+ if (static_cast<size_t>(m_selected) >= num_submenus)
+ m_selected = 0;
+ if (m_submenus[m_selected]->GetType() == Type::Separator)
+ continue;
+ else
+ break;
+ }
+ return eKeyHandled;
+ }
+ break;
+
+ case KEY_UP:
+ if (m_submenus.size() > 1) {
+ const int start_select = m_selected;
+ while (--m_selected != start_select) {
+ if (m_selected < static_cast<int>(0))
+ m_selected = num_submenus - 1;
+ if (m_submenus[m_selected]->GetType() == Type::Separator)
+ continue;
+ else
+ break;
+ }
+ return eKeyHandled;
+ }
+ break;
+
+ case KEY_RETURN:
+ if (static_cast<size_t>(selected_idx) < num_submenus) {
+ if (submenus[selected_idx]->Action() == MenuActionResult::Quit)
+ return eQuitApplication;
+ window.GetParent()->RemoveSubWindow(&window);
+ return eKeyHandled;
+ }
+ break;
+
+ case KEY_ESCAPE: // Beware: pressing escape key has 1 to 2 second delay in
+ // case other chars are entered for escaped sequences
+ window.GetParent()->RemoveSubWindow(&window);
+ return eKeyHandled;
+
+ default:
+ for (size_t i = 0; i < num_submenus; ++i) {
+ Menu *menu = submenus[i].get();
+ if (menu->GetKeyValue() == key) {
+ SetSelectedSubmenuIndex(i);
+ window.GetParent()->RemoveSubWindow(&window);
+ if (menu->Action() == MenuActionResult::Quit)
+ return eQuitApplication;
+ return eKeyHandled;
+ }
+ }
+ break;
+ }
+ } else if (menu_type == Menu::Type::Separator) {
+ }
+ return result;
+}
+
+class Application {
+public:
+ Application(FILE *in, FILE *out)
+ : m_window_sp(), m_screen(nullptr), m_in(in), m_out(out) {}
+
+ ~Application() {
+ m_window_delegates.clear();
+ m_window_sp.reset();
+ if (m_screen) {
+ ::delscreen(m_screen);
+ m_screen = nullptr;
+ }
+ }
+
+ void Initialize() {
+ ::setlocale(LC_ALL, "");
+ ::setlocale(LC_CTYPE, "");
+ m_screen = ::newterm(nullptr, m_out, m_in);
+ ::start_color();
+ ::curs_set(0);
+ ::noecho();
+ ::keypad(stdscr, TRUE);
+ }
+
+ void Terminate() { ::endwin(); }
+
+ void Run(Debugger &debugger) {
+ bool done = false;
+ int delay_in_tenths_of_a_second = 1;
+
+ // Alas the threading model in curses is a bit lame so we need to resort to
+ // polling every 0.5 seconds. We could poll for stdin ourselves and then
+ // pass the keys down but then we need to translate all of the escape
+ // sequences ourselves. So we resort to polling for input because we need
+ // to receive async process events while in this loop.
+
+ halfdelay(delay_in_tenths_of_a_second); // Poll using some number of tenths
+ // of seconds seconds when calling
+ // Window::GetChar()
+
+ ListenerSP listener_sp(
+ Listener::MakeListener("lldb.IOHandler.curses.Application"));
+ ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
+ ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
+ ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
+ debugger.EnableForwardEvents(listener_sp);
+
+ bool update = true;
+#if defined(__APPLE__)
+ std::deque<int> escape_chars;
+#endif
+
+ while (!done) {
+ if (update) {
+ m_window_sp->Draw(false);
+ // All windows should be calling Window::DeferredRefresh() instead of
+ // Window::Refresh() so we can do a single update and avoid any screen
+ // blinking
+ update_panels();
+
+ // Cursor hiding isn't working on MacOSX, so hide it in the top left
+ // corner
+ m_window_sp->MoveCursor(0, 0);
+
+ doupdate();
+ update = false;
+ }
+
+#if defined(__APPLE__)
+ // Terminal.app doesn't map its function keys correctly, F1-F4 default
+ // to: \033OP, \033OQ, \033OR, \033OS, so lets take care of this here if
+ // possible
+ int ch;
+ if (escape_chars.empty())
+ ch = m_window_sp->GetChar();
+ else {
+ ch = escape_chars.front();
+ escape_chars.pop_front();
+ }
+ if (ch == KEY_ESCAPE) {
+ int ch2 = m_window_sp->GetChar();
+ if (ch2 == 'O') {
+ int ch3 = m_window_sp->GetChar();
+ switch (ch3) {
+ case 'P':
+ ch = KEY_F(1);
+ break;
+ case 'Q':
+ ch = KEY_F(2);
+ break;
+ case 'R':
+ ch = KEY_F(3);
+ break;
+ case 'S':
+ ch = KEY_F(4);
+ break;
+ default:
+ escape_chars.push_back(ch2);
+ if (ch3 != -1)
+ escape_chars.push_back(ch3);
+ break;
+ }
+ } else if (ch2 != -1)
+ escape_chars.push_back(ch2);
+ }
+#else
+ int ch = m_window_sp->GetChar();
+
+#endif
+ if (ch == -1) {
+ if (feof(m_in) || ferror(m_in)) {
+ done = true;
+ } else {
+ // Just a timeout from using halfdelay(), check for events
+ EventSP event_sp;
+ while (listener_sp->PeekAtNextEvent()) {
+ listener_sp->GetEvent(event_sp, std::chrono::seconds(0));
+
+ if (event_sp) {
+ Broadcaster *broadcaster = event_sp->GetBroadcaster();
+ if (broadcaster) {
+ // uint32_t event_type = event_sp->GetType();
+ ConstString broadcaster_class(
+ broadcaster->GetBroadcasterClass());
+ if (broadcaster_class == broadcaster_class_process) {
+ debugger.GetCommandInterpreter().UpdateExecutionContext(
+ nullptr);
+ update = true;
+ continue; // Don't get any key, just update our view
+ }
+ }
+ }
+ }
+ }
+ } else {
+ HandleCharResult key_result = m_window_sp->HandleChar(ch);
+ switch (key_result) {
+ case eKeyHandled:
+ debugger.GetCommandInterpreter().UpdateExecutionContext(nullptr);
+ update = true;
+ break;
+ case eKeyNotHandled:
+ break;
+ case eQuitApplication:
+ done = true;
+ break;
+ }
+ }
+ }
+
+ debugger.CancelForwardEvents(listener_sp);
+ }
+
+ WindowSP &GetMainWindow() {
+ if (!m_window_sp)
+ m_window_sp = std::make_shared<Window>("main", stdscr, false);
+ return m_window_sp;
+ }
+
+protected:
+ WindowSP m_window_sp;
+ WindowDelegates m_window_delegates;
+ SCREEN *m_screen;
+ FILE *m_in;
+ FILE *m_out;
+};
+
+} // namespace curses
+
+using namespace curses;
+
+struct Row {
+ ValueObjectManager value;
+ Row *parent;
+ // The process stop ID when the children were calculated.
+ uint32_t children_stop_id;
+ int row_idx;
+ int x;
+ int y;
+ bool might_have_children;
+ bool expanded;
+ bool calculated_children;
+ std::vector<Row> children;
+
+ Row(const ValueObjectSP &v, Row *p)
+ : value(v, lldb::eDynamicDontRunTarget, true), parent(p), row_idx(0),
+ x(1), y(1), might_have_children(v ? v->MightHaveChildren() : false),
+ expanded(false), calculated_children(false), children() {}
+
+ size_t GetDepth() const {
+ if (parent)
+ return 1 + parent->GetDepth();
+ return 0;
+ }
+
+ void Expand() { expanded = true; }
+
+ std::vector<Row> &GetChildren() {
+ ProcessSP process_sp = value.GetProcessSP();
+ auto stop_id = process_sp->GetStopID();
+ if (process_sp && stop_id != children_stop_id) {
+ children_stop_id = stop_id;
+ calculated_children = false;
+ }
+ if (!calculated_children) {
+ children.clear();
+ calculated_children = true;
+ ValueObjectSP valobj = value.GetSP();
+ if (valobj) {
+ const size_t num_children = valobj->GetNumChildren();
+ for (size_t i = 0; i < num_children; ++i) {
+ children.push_back(Row(valobj->GetChildAtIndex(i, true), this));
+ }
+ }
+ }
+ return children;
+ }
+
+ void Unexpand() {
+ expanded = false;
+ calculated_children = false;
+ children.clear();
+ }
+
+ void DrawTree(Window &window) {
+ if (parent)
+ parent->DrawTreeForChild(window, this, 0);
+
+ if (might_have_children) {
+ // It we can get UTF8 characters to work we should try to use the
+ // "symbol" UTF8 string below
+ // const char *symbol = "";
+ // if (row.expanded)
+ // symbol = "\xe2\x96\xbd ";
+ // else
+ // symbol = "\xe2\x96\xb7 ";
+ // window.PutCString (symbol);
+
+ // The ACS_DARROW and ACS_RARROW don't look very nice they are just a 'v'
+ // or '>' character...
+ // if (expanded)
+ // window.PutChar (ACS_DARROW);
+ // else
+ // window.PutChar (ACS_RARROW);
+ // Since we can't find any good looking right arrow/down arrow symbols,
+ // just use a diamond...
+ window.PutChar(ACS_DIAMOND);
+ window.PutChar(ACS_HLINE);
+ }
+ }
+
+ void DrawTreeForChild(Window &window, Row *child, uint32_t reverse_depth) {
+ if (parent)
+ parent->DrawTreeForChild(window, this, reverse_depth + 1);
+
+ if (&GetChildren().back() == child) {
+ // Last child
+ if (reverse_depth == 0) {
+ window.PutChar(ACS_LLCORNER);
+ window.PutChar(ACS_HLINE);
+ } else {
+ window.PutChar(' ');
+ window.PutChar(' ');
+ }
+ } else {
+ if (reverse_depth == 0) {
+ window.PutChar(ACS_LTEE);
+ window.PutChar(ACS_HLINE);
+ } else {
+ window.PutChar(ACS_VLINE);
+ window.PutChar(' ');
+ }
+ }
+ }
+};
+
+struct DisplayOptions {
+ bool show_types;
+};
+
+class TreeItem;
+
+class TreeDelegate {
+public:
+ TreeDelegate() = default;
+ virtual ~TreeDelegate() = default;
+
+ virtual void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) = 0;
+ virtual void TreeDelegateGenerateChildren(TreeItem &item) = 0;
+ virtual bool TreeDelegateItemSelected(
+ TreeItem &item) = 0; // Return true if we need to update views
+};
+
+typedef std::shared_ptr<TreeDelegate> TreeDelegateSP;
+
+class TreeItem {
+public:
+ TreeItem(TreeItem *parent, TreeDelegate &delegate, bool might_have_children)
+ : m_parent(parent), m_delegate(delegate), m_user_data(nullptr),
+ m_identifier(0), m_row_idx(-1), m_children(),
+ m_might_have_children(might_have_children), m_is_expanded(false) {}
+
+ TreeItem &operator=(const TreeItem &rhs) {
+ if (this != &rhs) {
+ m_parent = rhs.m_parent;
+ m_delegate = rhs.m_delegate;
+ m_user_data = rhs.m_user_data;
+ m_identifier = rhs.m_identifier;
+ m_row_idx = rhs.m_row_idx;
+ m_children = rhs.m_children;
+ m_might_have_children = rhs.m_might_have_children;
+ m_is_expanded = rhs.m_is_expanded;
+ }
+ return *this;
+ }
+
+ TreeItem(const TreeItem &) = default;
+
+ size_t GetDepth() const {
+ if (m_parent)
+ return 1 + m_parent->GetDepth();
+ return 0;
+ }
+
+ int GetRowIndex() const { return m_row_idx; }
+
+ void ClearChildren() { m_children.clear(); }
+
+ void Resize(size_t n, const TreeItem &t) { m_children.resize(n, t); }
+
+ TreeItem &operator[](size_t i) { return m_children[i]; }
+
+ void SetRowIndex(int row_idx) { m_row_idx = row_idx; }
+
+ size_t GetNumChildren() {
+ m_delegate.TreeDelegateGenerateChildren(*this);
+ return m_children.size();
+ }
+
+ void ItemWasSelected() { m_delegate.TreeDelegateItemSelected(*this); }
+
+ void CalculateRowIndexes(int &row_idx) {
+ SetRowIndex(row_idx);
+ ++row_idx;
+
+ const bool expanded = IsExpanded();
+
+ // The root item must calculate its children, or we must calculate the
+ // number of children if the item is expanded
+ if (m_parent == nullptr || expanded)
+ GetNumChildren();
+
+ for (auto &item : m_children) {
+ if (expanded)
+ item.CalculateRowIndexes(row_idx);
+ else
+ item.SetRowIndex(-1);
+ }
+ }
+
+ TreeItem *GetParent() { return m_parent; }
+
+ bool IsExpanded() const { return m_is_expanded; }
+
+ void Expand() { m_is_expanded = true; }
+
+ void Unexpand() { m_is_expanded = false; }
+
+ bool Draw(Window &window, const int first_visible_row,
+ const uint32_t selected_row_idx, int &row_idx, int &num_rows_left) {
+ if (num_rows_left <= 0)
+ return false;
+
+ if (m_row_idx >= first_visible_row) {
+ window.MoveCursor(2, row_idx + 1);
+
+ if (m_parent)
+ m_parent->DrawTreeForChild(window, this, 0);
+
+ if (m_might_have_children) {
+ // It we can get UTF8 characters to work we should try to use the
+ // "symbol" UTF8 string below
+ // const char *symbol = "";
+ // if (row.expanded)
+ // symbol = "\xe2\x96\xbd ";
+ // else
+ // symbol = "\xe2\x96\xb7 ";
+ // window.PutCString (symbol);
+
+ // The ACS_DARROW and ACS_RARROW don't look very nice they are just a
+ // 'v' or '>' character...
+ // if (expanded)
+ // window.PutChar (ACS_DARROW);
+ // else
+ // window.PutChar (ACS_RARROW);
+ // Since we can't find any good looking right arrow/down arrow symbols,
+ // just use a diamond...
+ window.PutChar(ACS_DIAMOND);
+ window.PutChar(ACS_HLINE);
+ }
+ bool highlight = (selected_row_idx == static_cast<size_t>(m_row_idx)) &&
+ window.IsActive();
+
+ if (highlight)
+ window.AttributeOn(A_REVERSE);
+
+ m_delegate.TreeDelegateDrawTreeItem(*this, window);
+
+ if (highlight)
+ window.AttributeOff(A_REVERSE);
+ ++row_idx;
+ --num_rows_left;
+ }
+
+ if (num_rows_left <= 0)
+ return false; // We are done drawing...
+
+ if (IsExpanded()) {
+ for (auto &item : m_children) {
+ // If we displayed all the rows and item.Draw() returns false we are
+ // done drawing and can exit this for loop
+ if (!item.Draw(window, first_visible_row, selected_row_idx, row_idx,
+ num_rows_left))
+ break;
+ }
+ }
+ return num_rows_left >= 0; // Return true if not done drawing yet
+ }
+
+ void DrawTreeForChild(Window &window, TreeItem *child,
+ uint32_t reverse_depth) {
+ if (m_parent)
+ m_parent->DrawTreeForChild(window, this, reverse_depth + 1);
+
+ if (&m_children.back() == child) {
+ // Last child
+ if (reverse_depth == 0) {
+ window.PutChar(ACS_LLCORNER);
+ window.PutChar(ACS_HLINE);
+ } else {
+ window.PutChar(' ');
+ window.PutChar(' ');
+ }
+ } else {
+ if (reverse_depth == 0) {
+ window.PutChar(ACS_LTEE);
+ window.PutChar(ACS_HLINE);
+ } else {
+ window.PutChar(ACS_VLINE);
+ window.PutChar(' ');
+ }
+ }
+ }
+
+ TreeItem *GetItemForRowIndex(uint32_t row_idx) {
+ if (static_cast<uint32_t>(m_row_idx) == row_idx)
+ return this;
+ if (m_children.empty())
+ return nullptr;
+ if (IsExpanded()) {
+ for (auto &item : m_children) {
+ TreeItem *selected_item_ptr = item.GetItemForRowIndex(row_idx);
+ if (selected_item_ptr)
+ return selected_item_ptr;
+ }
+ }
+ return nullptr;
+ }
+
+ void *GetUserData() const { return m_user_data; }
+
+ void SetUserData(void *user_data) { m_user_data = user_data; }
+
+ uint64_t GetIdentifier() const { return m_identifier; }
+
+ void SetIdentifier(uint64_t identifier) { m_identifier = identifier; }
+
+ void SetMightHaveChildren(bool b) { m_might_have_children = b; }
+
+protected:
+ TreeItem *m_parent;
+ TreeDelegate &m_delegate;
+ void *m_user_data;
+ uint64_t m_identifier;
+ int m_row_idx; // Zero based visible row index, -1 if not visible or for the
+ // root item
+ std::vector<TreeItem> m_children;
+ bool m_might_have_children;
+ bool m_is_expanded;
+};
+
+class TreeWindowDelegate : public WindowDelegate {
+public:
+ TreeWindowDelegate(Debugger &debugger, const TreeDelegateSP &delegate_sp)
+ : m_debugger(debugger), m_delegate_sp(delegate_sp),
+ m_root(nullptr, *delegate_sp, true), m_selected_item(nullptr),
+ m_num_rows(0), m_selected_row_idx(0), m_first_visible_row(0),
+ m_min_x(0), m_min_y(0), m_max_x(0), m_max_y(0) {}
+
+ int NumVisibleRows() const { return m_max_y - m_min_y; }
+
+ bool WindowDelegateDraw(Window &window, bool force) override {
+ ExecutionContext exe_ctx(
+ m_debugger.GetCommandInterpreter().GetExecutionContext());
+ Process *process = exe_ctx.GetProcessPtr();
+
+ bool display_content = false;
+ if (process) {
+ StateType state = process->GetState();
+ if (StateIsStoppedState(state, true)) {
+ // We are stopped, so it is ok to
+ display_content = true;
+ } else if (StateIsRunningState(state)) {
+ return true; // Don't do any updating when we are running
+ }
+ }
+
+ m_min_x = 2;
+ m_min_y = 1;
+ m_max_x = window.GetWidth() - 1;
+ m_max_y = window.GetHeight() - 1;
+
+ window.Erase();
+ window.DrawTitleBox(window.GetName());
+
+ if (display_content) {
+ const int num_visible_rows = NumVisibleRows();
+ m_num_rows = 0;
+ m_root.CalculateRowIndexes(m_num_rows);
+
+ // If we unexpanded while having something selected our total number of
+ // rows is less than the num visible rows, then make sure we show all the
+ // rows by setting the first visible row accordingly.
+ if (m_first_visible_row > 0 && m_num_rows < num_visible_rows)
+ m_first_visible_row = 0;
+
+ // Make sure the selected row is always visible
+ if (m_selected_row_idx < m_first_visible_row)
+ m_first_visible_row = m_selected_row_idx;
+ else if (m_first_visible_row + num_visible_rows <= m_selected_row_idx)
+ m_first_visible_row = m_selected_row_idx - num_visible_rows + 1;
+
+ int row_idx = 0;
+ int num_rows_left = num_visible_rows;
+ m_root.Draw(window, m_first_visible_row, m_selected_row_idx, row_idx,
+ num_rows_left);
+ // Get the selected row
+ m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
+ } else {
+ m_selected_item = nullptr;
+ }
+
+ return true; // Drawing handled
+ }
+
+ const char *WindowDelegateGetHelpText() override {
+ return "Thread window keyboard shortcuts:";
+ }
+
+ KeyHelp *WindowDelegateGetKeyHelp() override {
+ static curses::KeyHelp g_source_view_key_help[] = {
+ {KEY_UP, "Select previous item"},
+ {KEY_DOWN, "Select next item"},
+ {KEY_RIGHT, "Expand the selected item"},
+ {KEY_LEFT,
+ "Unexpand the selected item or select parent if not expanded"},
+ {KEY_PPAGE, "Page up"},
+ {KEY_NPAGE, "Page down"},
+ {'h', "Show help dialog"},
+ {' ', "Toggle item expansion"},
+ {',', "Page up"},
+ {'.', "Page down"},
+ {'\0', nullptr}};
+ return g_source_view_key_help;
+ }
+
+ HandleCharResult WindowDelegateHandleChar(Window &window, int c) override {
+ switch (c) {
+ case ',':
+ case KEY_PPAGE:
+ // Page up key
+ if (m_first_visible_row > 0) {
+ if (m_first_visible_row > m_max_y)
+ m_first_visible_row -= m_max_y;
+ else
+ m_first_visible_row = 0;
+ m_selected_row_idx = m_first_visible_row;
+ m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
+ if (m_selected_item)
+ m_selected_item->ItemWasSelected();
+ }
+ return eKeyHandled;
+
+ case '.':
+ case KEY_NPAGE:
+ // Page down key
+ if (m_num_rows > m_max_y) {
+ if (m_first_visible_row + m_max_y < m_num_rows) {
+ m_first_visible_row += m_max_y;
+ m_selected_row_idx = m_first_visible_row;
+ m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
+ if (m_selected_item)
+ m_selected_item->ItemWasSelected();
+ }
+ }
+ return eKeyHandled;
+
+ case KEY_UP:
+ if (m_selected_row_idx > 0) {
+ --m_selected_row_idx;
+ m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
+ if (m_selected_item)
+ m_selected_item->ItemWasSelected();
+ }
+ return eKeyHandled;
+
+ case KEY_DOWN:
+ if (m_selected_row_idx + 1 < m_num_rows) {
+ ++m_selected_row_idx;
+ m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
+ if (m_selected_item)
+ m_selected_item->ItemWasSelected();
+ }
+ return eKeyHandled;
+
+ case KEY_RIGHT:
+ if (m_selected_item) {
+ if (!m_selected_item->IsExpanded())
+ m_selected_item->Expand();
+ }
+ return eKeyHandled;
+
+ case KEY_LEFT:
+ if (m_selected_item) {
+ if (m_selected_item->IsExpanded())
+ m_selected_item->Unexpand();
+ else if (m_selected_item->GetParent()) {
+ m_selected_row_idx = m_selected_item->GetParent()->GetRowIndex();
+ m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
+ if (m_selected_item)
+ m_selected_item->ItemWasSelected();
+ }
+ }
+ return eKeyHandled;
+
+ case ' ':
+ // Toggle expansion state when SPACE is pressed
+ if (m_selected_item) {
+ if (m_selected_item->IsExpanded())
+ m_selected_item->Unexpand();
+ else
+ m_selected_item->Expand();
+ }
+ return eKeyHandled;
+
+ case 'h':
+ window.CreateHelpSubwindow();
+ return eKeyHandled;
+
+ default:
+ break;
+ }
+ return eKeyNotHandled;
+ }
+
+protected:
+ Debugger &m_debugger;
+ TreeDelegateSP m_delegate_sp;
+ TreeItem m_root;
+ TreeItem *m_selected_item;
+ int m_num_rows;
+ int m_selected_row_idx;
+ int m_first_visible_row;
+ int m_min_x;
+ int m_min_y;
+ int m_max_x;
+ int m_max_y;
+};
+
+class FrameTreeDelegate : public TreeDelegate {
+public:
+ FrameTreeDelegate() : TreeDelegate() {
+ FormatEntity::Parse(
+ "frame #${frame.index}: {${function.name}${function.pc-offset}}}",
+ m_format);
+ }
+
+ ~FrameTreeDelegate() override = default;
+
+ void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
+ Thread *thread = (Thread *)item.GetUserData();
+ if (thread) {
+ const uint64_t frame_idx = item.GetIdentifier();
+ StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_idx);
+ if (frame_sp) {
+ StreamString strm;
+ const SymbolContext &sc =
+ frame_sp->GetSymbolContext(eSymbolContextEverything);
+ ExecutionContext exe_ctx(frame_sp);
+ if (FormatEntity::Format(m_format, strm, &sc, &exe_ctx, nullptr,
+ nullptr, false, false)) {
+ int right_pad = 1;
+ window.PutCStringTruncated(strm.GetString().str().c_str(), right_pad);
+ }
+ }
+ }
+ }
+
+ void TreeDelegateGenerateChildren(TreeItem &item) override {
+ // No children for frames yet...
+ }
+
+ bool TreeDelegateItemSelected(TreeItem &item) override {
+ Thread *thread = (Thread *)item.GetUserData();
+ if (thread) {
+ thread->GetProcess()->GetThreadList().SetSelectedThreadByID(
+ thread->GetID());
+ const uint64_t frame_idx = item.GetIdentifier();
+ thread->SetSelectedFrameByIndex(frame_idx);
+ return true;
+ }
+ return false;
+ }
+
+protected:
+ FormatEntity::Entry m_format;
+};
+
+class ThreadTreeDelegate : public TreeDelegate {
+public:
+ ThreadTreeDelegate(Debugger &debugger)
+ : TreeDelegate(), m_debugger(debugger), m_tid(LLDB_INVALID_THREAD_ID),
+ m_stop_id(UINT32_MAX) {
+ FormatEntity::Parse("thread #${thread.index}: tid = ${thread.id}{, stop "
+ "reason = ${thread.stop-reason}}",
+ m_format);
+ }
+
+ ~ThreadTreeDelegate() override = default;
+
+ ProcessSP GetProcess() {
+ return m_debugger.GetCommandInterpreter()
+ .GetExecutionContext()
+ .GetProcessSP();
+ }
+
+ ThreadSP GetThread(const TreeItem &item) {
+ ProcessSP process_sp = GetProcess();
+ if (process_sp)
+ return process_sp->GetThreadList().FindThreadByID(item.GetIdentifier());
+ return ThreadSP();
+ }
+
+ void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
+ ThreadSP thread_sp = GetThread(item);
+ if (thread_sp) {
+ StreamString strm;
+ ExecutionContext exe_ctx(thread_sp);
+ if (FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr,
+ nullptr, false, false)) {
+ int right_pad = 1;
+ window.PutCStringTruncated(strm.GetString().str().c_str(), right_pad);
+ }
+ }
+ }
+
+ void TreeDelegateGenerateChildren(TreeItem &item) override {
+ ProcessSP process_sp = GetProcess();
+ if (process_sp && process_sp->IsAlive()) {
+ StateType state = process_sp->GetState();
+ if (StateIsStoppedState(state, true)) {
+ ThreadSP thread_sp = GetThread(item);
+ if (thread_sp) {
+ if (m_stop_id == process_sp->GetStopID() &&
+ thread_sp->GetID() == m_tid)
+ return; // Children are already up to date
+ if (!m_frame_delegate_sp) {
+ // Always expand the thread item the first time we show it
+ m_frame_delegate_sp = std::make_shared<FrameTreeDelegate>();
+ }
+
+ m_stop_id = process_sp->GetStopID();
+ m_tid = thread_sp->GetID();
+
+ TreeItem t(&item, *m_frame_delegate_sp, false);
+ size_t num_frames = thread_sp->GetStackFrameCount();
+ item.Resize(num_frames, t);
+ for (size_t i = 0; i < num_frames; ++i) {
+ item[i].SetUserData(thread_sp.get());
+ item[i].SetIdentifier(i);
+ }
+ }
+ return;
+ }
+ }
+ item.ClearChildren();
+ }
+
+ bool TreeDelegateItemSelected(TreeItem &item) override {
+ ProcessSP process_sp = GetProcess();
+ if (process_sp && process_sp->IsAlive()) {
+ StateType state = process_sp->GetState();
+ if (StateIsStoppedState(state, true)) {
+ ThreadSP thread_sp = GetThread(item);
+ if (thread_sp) {
+ ThreadList &thread_list = thread_sp->GetProcess()->GetThreadList();
+ std::lock_guard<std::recursive_mutex> guard(thread_list.GetMutex());
+ ThreadSP selected_thread_sp = thread_list.GetSelectedThread();
+ if (selected_thread_sp->GetID() != thread_sp->GetID()) {
+ thread_list.SetSelectedThreadByID(thread_sp->GetID());
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+protected:
+ Debugger &m_debugger;
+ std::shared_ptr<FrameTreeDelegate> m_frame_delegate_sp;
+ lldb::user_id_t m_tid;
+ uint32_t m_stop_id;
+ FormatEntity::Entry m_format;
+};
+
+class ThreadsTreeDelegate : public TreeDelegate {
+public:
+ ThreadsTreeDelegate(Debugger &debugger)
+ : TreeDelegate(), m_thread_delegate_sp(), m_debugger(debugger),
+ m_stop_id(UINT32_MAX) {
+ FormatEntity::Parse("process ${process.id}{, name = ${process.name}}",
+ m_format);
+ }
+
+ ~ThreadsTreeDelegate() override = default;
+
+ ProcessSP GetProcess() {
+ return m_debugger.GetCommandInterpreter()
+ .GetExecutionContext()
+ .GetProcessSP();
+ }
+
+ void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
+ ProcessSP process_sp = GetProcess();
+ if (process_sp && process_sp->IsAlive()) {
+ StreamString strm;
+ ExecutionContext exe_ctx(process_sp);
+ if (FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr,
+ nullptr, false, false)) {
+ int right_pad = 1;
+ window.PutCStringTruncated(strm.GetString().str().c_str(), right_pad);
+ }
+ }
+ }
+
+ void TreeDelegateGenerateChildren(TreeItem &item) override {
+ ProcessSP process_sp = GetProcess();
+ if (process_sp && process_sp->IsAlive()) {
+ StateType state = process_sp->GetState();
+ if (StateIsStoppedState(state, true)) {
+ const uint32_t stop_id = process_sp->GetStopID();
+ if (m_stop_id == stop_id)
+ return; // Children are already up to date
+
+ m_stop_id = stop_id;
+
+ if (!m_thread_delegate_sp) {
+ // Always expand the thread item the first time we show it
+ // item.Expand();
+ m_thread_delegate_sp =
+ std::make_shared<ThreadTreeDelegate>(m_debugger);
+ }
+
+ TreeItem t(&item, *m_thread_delegate_sp, false);
+ ThreadList &threads = process_sp->GetThreadList();
+ std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
+ size_t num_threads = threads.GetSize();
+ item.Resize(num_threads, t);
+ for (size_t i = 0; i < num_threads; ++i) {
+ item[i].SetIdentifier(threads.GetThreadAtIndex(i)->GetID());
+ item[i].SetMightHaveChildren(true);
+ }
+ return;
+ }
+ }
+ item.ClearChildren();
+ }
+
+ bool TreeDelegateItemSelected(TreeItem &item) override { return false; }
+
+protected:
+ std::shared_ptr<ThreadTreeDelegate> m_thread_delegate_sp;
+ Debugger &m_debugger;
+ uint32_t m_stop_id;
+ FormatEntity::Entry m_format;
+};
+
+class ValueObjectListDelegate : public WindowDelegate {
+public:
+ ValueObjectListDelegate()
+ : m_rows(), m_selected_row(nullptr), m_selected_row_idx(0),
+ m_first_visible_row(0), m_num_rows(0), m_max_x(0), m_max_y(0) {}
+
+ ValueObjectListDelegate(ValueObjectList &valobj_list)
+ : m_rows(), m_selected_row(nullptr), m_selected_row_idx(0),
+ m_first_visible_row(0), m_num_rows(0), m_max_x(0), m_max_y(0) {
+ SetValues(valobj_list);
+ }
+
+ ~ValueObjectListDelegate() override = default;
+
+ void SetValues(ValueObjectList &valobj_list) {
+ m_selected_row = nullptr;
+ m_selected_row_idx = 0;
+ m_first_visible_row = 0;
+ m_num_rows = 0;
+ m_rows.clear();
+ for (auto &valobj_sp : valobj_list.GetObjects())
+ m_rows.push_back(Row(valobj_sp, nullptr));
+ }
+
+ bool WindowDelegateDraw(Window &window, bool force) override {
+ m_num_rows = 0;
+ m_min_x = 2;
+ m_min_y = 1;
+ m_max_x = window.GetWidth() - 1;
+ m_max_y = window.GetHeight() - 1;
+
+ window.Erase();
+ window.DrawTitleBox(window.GetName());
+
+ const int num_visible_rows = NumVisibleRows();
+ const int num_rows = CalculateTotalNumberRows(m_rows);
+
+ // If we unexpanded while having something selected our total number of
+ // rows is less than the num visible rows, then make sure we show all the
+ // rows by setting the first visible row accordingly.
+ if (m_first_visible_row > 0 && num_rows < num_visible_rows)
+ m_first_visible_row = 0;
+
+ // Make sure the selected row is always visible
+ if (m_selected_row_idx < m_first_visible_row)
+ m_first_visible_row = m_selected_row_idx;
+ else if (m_first_visible_row + num_visible_rows <= m_selected_row_idx)
+ m_first_visible_row = m_selected_row_idx - num_visible_rows + 1;
+
+ DisplayRows(window, m_rows, g_options);
+
+ // Get the selected row
+ m_selected_row = GetRowForRowIndex(m_selected_row_idx);
+ // Keep the cursor on the selected row so the highlight and the cursor are
+ // always on the same line
+ if (m_selected_row)
+ window.MoveCursor(m_selected_row->x, m_selected_row->y);
+
+ return true; // Drawing handled
+ }
+
+ KeyHelp *WindowDelegateGetKeyHelp() override {
+ static curses::KeyHelp g_source_view_key_help[] = {
+ {KEY_UP, "Select previous item"},
+ {KEY_DOWN, "Select next item"},
+ {KEY_RIGHT, "Expand selected item"},
+ {KEY_LEFT, "Unexpand selected item or select parent if not expanded"},
+ {KEY_PPAGE, "Page up"},
+ {KEY_NPAGE, "Page down"},
+ {'A', "Format as annotated address"},
+ {'b', "Format as binary"},
+ {'B', "Format as hex bytes with ASCII"},
+ {'c', "Format as character"},
+ {'d', "Format as a signed integer"},
+ {'D', "Format selected value using the default format for the type"},
+ {'f', "Format as float"},
+ {'h', "Show help dialog"},
+ {'i', "Format as instructions"},
+ {'o', "Format as octal"},
+ {'p', "Format as pointer"},
+ {'s', "Format as C string"},
+ {'t', "Toggle showing/hiding type names"},
+ {'u', "Format as an unsigned integer"},
+ {'x', "Format as hex"},
+ {'X', "Format as uppercase hex"},
+ {' ', "Toggle item expansion"},
+ {',', "Page up"},
+ {'.', "Page down"},
+ {'\0', nullptr}};
+ return g_source_view_key_help;
+ }
+
+ HandleCharResult WindowDelegateHandleChar(Window &window, int c) override {
+ switch (c) {
+ case 'x':
+ case 'X':
+ case 'o':
+ case 's':
+ case 'u':
+ case 'd':
+ case 'D':
+ case 'i':
+ case 'A':
+ case 'p':
+ case 'c':
+ case 'b':
+ case 'B':
+ case 'f':
+ // Change the format for the currently selected item
+ if (m_selected_row) {
+ auto valobj_sp = m_selected_row->value.GetSP();
+ if (valobj_sp)
+ valobj_sp->SetFormat(FormatForChar(c));
+ }
+ return eKeyHandled;
+
+ case 't':
+ // Toggle showing type names
+ g_options.show_types = !g_options.show_types;
+ return eKeyHandled;
+
+ case ',':
+ case KEY_PPAGE:
+ // Page up key
+ if (m_first_visible_row > 0) {
+ if (static_cast<int>(m_first_visible_row) > m_max_y)
+ m_first_visible_row -= m_max_y;
+ else
+ m_first_visible_row = 0;
+ m_selected_row_idx = m_first_visible_row;
+ }
+ return eKeyHandled;
+
+ case '.':
+ case KEY_NPAGE:
+ // Page down key
+ if (m_num_rows > static_cast<size_t>(m_max_y)) {
+ if (m_first_visible_row + m_max_y < m_num_rows) {
+ m_first_visible_row += m_max_y;
+ m_selected_row_idx = m_first_visible_row;
+ }
+ }
+ return eKeyHandled;
+
+ case KEY_UP:
+ if (m_selected_row_idx > 0)
+ --m_selected_row_idx;
+ return eKeyHandled;
+
+ case KEY_DOWN:
+ if (m_selected_row_idx + 1 < m_num_rows)
+ ++m_selected_row_idx;
+ return eKeyHandled;
+
+ case KEY_RIGHT:
+ if (m_selected_row) {
+ if (!m_selected_row->expanded)
+ m_selected_row->Expand();
+ }
+ return eKeyHandled;
+
+ case KEY_LEFT:
+ if (m_selected_row) {
+ if (m_selected_row->expanded)
+ m_selected_row->Unexpand();
+ else if (m_selected_row->parent)
+ m_selected_row_idx = m_selected_row->parent->row_idx;
+ }
+ return eKeyHandled;
+
+ case ' ':
+ // Toggle expansion state when SPACE is pressed
+ if (m_selected_row) {
+ if (m_selected_row->expanded)
+ m_selected_row->Unexpand();
+ else
+ m_selected_row->Expand();
+ }
+ return eKeyHandled;
+
+ case 'h':
+ window.CreateHelpSubwindow();
+ return eKeyHandled;
+
+ default:
+ break;
+ }
+ return eKeyNotHandled;
+ }
+
+protected:
+ std::vector<Row> m_rows;
+ Row *m_selected_row;
+ uint32_t m_selected_row_idx;
+ uint32_t m_first_visible_row;
+ uint32_t m_num_rows;
+ int m_min_x;
+ int m_min_y;
+ int m_max_x;
+ int m_max_y;
+
+ static Format FormatForChar(int c) {
+ switch (c) {
+ case 'x':
+ return eFormatHex;
+ case 'X':
+ return eFormatHexUppercase;
+ case 'o':
+ return eFormatOctal;
+ case 's':
+ return eFormatCString;
+ case 'u':
+ return eFormatUnsigned;
+ case 'd':
+ return eFormatDecimal;
+ case 'D':
+ return eFormatDefault;
+ case 'i':
+ return eFormatInstruction;
+ case 'A':
+ return eFormatAddressInfo;
+ case 'p':
+ return eFormatPointer;
+ case 'c':
+ return eFormatChar;
+ case 'b':
+ return eFormatBinary;
+ case 'B':
+ return eFormatBytesWithASCII;
+ case 'f':
+ return eFormatFloat;
+ }
+ return eFormatDefault;
+ }
+
+ bool DisplayRowObject(Window &window, Row &row, DisplayOptions &options,
+ bool highlight, bool last_child) {
+ ValueObject *valobj = row.value.GetSP().get();
+
+ if (valobj == nullptr)
+ return false;
+
+ const char *type_name =
+ options.show_types ? valobj->GetTypeName().GetCString() : nullptr;
+ const char *name = valobj->GetName().GetCString();
+ const char *value = valobj->GetValueAsCString();
+ const char *summary = valobj->GetSummaryAsCString();
+
+ window.MoveCursor(row.x, row.y);
+
+ row.DrawTree(window);
+
+ if (highlight)
+ window.AttributeOn(A_REVERSE);
+
+ if (type_name && type_name[0])
+ window.Printf("(%s) ", type_name);
+
+ if (name && name[0])
+ window.PutCString(name);
+
+ attr_t changd_attr = 0;
+ if (valobj->GetValueDidChange())
+ changd_attr = COLOR_PAIR(5) | A_BOLD;
+
+ if (value && value[0]) {
+ window.PutCString(" = ");
+ if (changd_attr)
+ window.AttributeOn(changd_attr);
+ window.PutCString(value);
+ if (changd_attr)
+ window.AttributeOff(changd_attr);
+ }
+
+ if (summary && summary[0]) {
+ window.PutChar(' ');
+ if (changd_attr)
+ window.AttributeOn(changd_attr);
+ window.PutCString(summary);
+ if (changd_attr)
+ window.AttributeOff(changd_attr);
+ }
+
+ if (highlight)
+ window.AttributeOff(A_REVERSE);
+
+ return true;
+ }
+
+ void DisplayRows(Window &window, std::vector<Row> &rows,
+ DisplayOptions &options) {
+ // > 0x25B7
+ // \/ 0x25BD
+
+ bool window_is_active = window.IsActive();
+ for (auto &row : rows) {
+ const bool last_child = row.parent && &rows[rows.size() - 1] == &row;
+ // Save the row index in each Row structure
+ row.row_idx = m_num_rows;
+ if ((m_num_rows >= m_first_visible_row) &&
+ ((m_num_rows - m_first_visible_row) <
+ static_cast<size_t>(NumVisibleRows()))) {
+ row.x = m_min_x;
+ row.y = m_num_rows - m_first_visible_row + 1;
+ if (DisplayRowObject(window, row, options,
+ window_is_active &&
+ m_num_rows == m_selected_row_idx,
+ last_child)) {
+ ++m_num_rows;
+ } else {
+ row.x = 0;
+ row.y = 0;
+ }
+ } else {
+ row.x = 0;
+ row.y = 0;
+ ++m_num_rows;
+ }
+
+ auto &children = row.GetChildren();
+ if (row.expanded && !children.empty()) {
+ DisplayRows(window, children, options);
+ }
+ }
+ }
+
+ int CalculateTotalNumberRows(std::vector<Row> &rows) {
+ int row_count = 0;
+ for (auto &row : rows) {
+ ++row_count;
+ if (row.expanded)
+ row_count += CalculateTotalNumberRows(row.GetChildren());
+ }
+ return row_count;
+ }
+
+ static Row *GetRowForRowIndexImpl(std::vector<Row> &rows, size_t &row_index) {
+ for (auto &row : rows) {
+ if (row_index == 0)
+ return &row;
+ else {
+ --row_index;
+ auto &children = row.GetChildren();
+ if (row.expanded && !children.empty()) {
+ Row *result = GetRowForRowIndexImpl(children, row_index);
+ if (result)
+ return result;
+ }
+ }
+ }
+ return nullptr;
+ }
+
+ Row *GetRowForRowIndex(size_t row_index) {
+ return GetRowForRowIndexImpl(m_rows, row_index);
+ }
+
+ int NumVisibleRows() const { return m_max_y - m_min_y; }
+
+ static DisplayOptions g_options;
+};
+
+class FrameVariablesWindowDelegate : public ValueObjectListDelegate {
+public:
+ FrameVariablesWindowDelegate(Debugger &debugger)
+ : ValueObjectListDelegate(), m_debugger(debugger),
+ m_frame_block(nullptr) {}
+
+ ~FrameVariablesWindowDelegate() override = default;
+
+ const char *WindowDelegateGetHelpText() override {
+ return "Frame variable window keyboard shortcuts:";
+ }
+
+ bool WindowDelegateDraw(Window &window, bool force) override {
+ ExecutionContext exe_ctx(
+ m_debugger.GetCommandInterpreter().GetExecutionContext());
+ Process *process = exe_ctx.GetProcessPtr();
+ Block *frame_block = nullptr;
+ StackFrame *frame = nullptr;
+
+ if (process) {
+ StateType state = process->GetState();
+ if (StateIsStoppedState(state, true)) {
+ frame = exe_ctx.GetFramePtr();
+ if (frame)
+ frame_block = frame->GetFrameBlock();
+ } else if (StateIsRunningState(state)) {
+ return true; // Don't do any updating when we are running
+ }
+ }
+
+ ValueObjectList local_values;
+ if (frame_block) {
+ // Only update the variables if they have changed
+ if (m_frame_block != frame_block) {
+ m_frame_block = frame_block;
+
+ VariableList *locals = frame->GetVariableList(true);
+ if (locals) {
+ const DynamicValueType use_dynamic = eDynamicDontRunTarget;
+ for (const VariableSP &local_sp : *locals) {
+ ValueObjectSP value_sp =
+ frame->GetValueObjectForFrameVariable(local_sp, use_dynamic);
+ if (value_sp) {
+ ValueObjectSP synthetic_value_sp = value_sp->GetSyntheticValue();
+ if (synthetic_value_sp)
+ local_values.Append(synthetic_value_sp);
+ else
+ local_values.Append(value_sp);
+ }
+ }
+ // Update the values
+ SetValues(local_values);
+ }
+ }
+ } else {
+ m_frame_block = nullptr;
+ // Update the values with an empty list if there is no frame
+ SetValues(local_values);
+ }
+
+ return ValueObjectListDelegate::WindowDelegateDraw(window, force);
+ }
+
+protected:
+ Debugger &m_debugger;
+ Block *m_frame_block;
+};
+
+class RegistersWindowDelegate : public ValueObjectListDelegate {
+public:
+ RegistersWindowDelegate(Debugger &debugger)
+ : ValueObjectListDelegate(), m_debugger(debugger) {}
+
+ ~RegistersWindowDelegate() override = default;
+
+ const char *WindowDelegateGetHelpText() override {
+ return "Register window keyboard shortcuts:";
+ }
+
+ bool WindowDelegateDraw(Window &window, bool force) override {
+ ExecutionContext exe_ctx(
+ m_debugger.GetCommandInterpreter().GetExecutionContext());
+ StackFrame *frame = exe_ctx.GetFramePtr();
+
+ ValueObjectList value_list;
+ if (frame) {
+ if (frame->GetStackID() != m_stack_id) {
+ m_stack_id = frame->GetStackID();
+ RegisterContextSP reg_ctx(frame->GetRegisterContext());
+ if (reg_ctx) {
+ const uint32_t num_sets = reg_ctx->GetRegisterSetCount();
+ for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx) {
+ value_list.Append(
+ ValueObjectRegisterSet::Create(frame, reg_ctx, set_idx));
+ }
+ }
+ SetValues(value_list);
+ }
+ } else {
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive())
+ return true; // Don't do any updating if we are running
+ else {
+ // Update the values with an empty list if there is no process or the
+ // process isn't alive anymore
+ SetValues(value_list);
+ }
+ }
+ return ValueObjectListDelegate::WindowDelegateDraw(window, force);
+ }
+
+protected:
+ Debugger &m_debugger;
+ StackID m_stack_id;
+};
+
+static const char *CursesKeyToCString(int ch) {
+ static char g_desc[32];
+ if (ch >= KEY_F0 && ch < KEY_F0 + 64) {
+ snprintf(g_desc, sizeof(g_desc), "F%u", ch - KEY_F0);
+ return g_desc;
+ }
+ switch (ch) {
+ case KEY_DOWN:
+ return "down";
+ case KEY_UP:
+ return "up";
+ case KEY_LEFT:
+ return "left";
+ case KEY_RIGHT:
+ return "right";
+ case KEY_HOME:
+ return "home";
+ case KEY_BACKSPACE:
+ return "backspace";
+ case KEY_DL:
+ return "delete-line";
+ case KEY_IL:
+ return "insert-line";
+ case KEY_DC:
+ return "delete-char";
+ case KEY_IC:
+ return "insert-char";
+ case KEY_CLEAR:
+ return "clear";
+ case KEY_EOS:
+ return "clear-to-eos";
+ case KEY_EOL:
+ return "clear-to-eol";
+ case KEY_SF:
+ return "scroll-forward";
+ case KEY_SR:
+ return "scroll-backward";
+ case KEY_NPAGE:
+ return "page-down";
+ case KEY_PPAGE:
+ return "page-up";
+ case KEY_STAB:
+ return "set-tab";
+ case KEY_CTAB:
+ return "clear-tab";
+ case KEY_CATAB:
+ return "clear-all-tabs";
+ case KEY_ENTER:
+ return "enter";
+ case KEY_PRINT:
+ return "print";
+ case KEY_LL:
+ return "lower-left key";
+ case KEY_A1:
+ return "upper left of keypad";
+ case KEY_A3:
+ return "upper right of keypad";
+ case KEY_B2:
+ return "center of keypad";
+ case KEY_C1:
+ return "lower left of keypad";
+ case KEY_C3:
+ return "lower right of keypad";
+ case KEY_BTAB:
+ return "back-tab key";
+ case KEY_BEG:
+ return "begin key";
+ case KEY_CANCEL:
+ return "cancel key";
+ case KEY_CLOSE:
+ return "close key";
+ case KEY_COMMAND:
+ return "command key";
+ case KEY_COPY:
+ return "copy key";
+ case KEY_CREATE:
+ return "create key";
+ case KEY_END:
+ return "end key";
+ case KEY_EXIT:
+ return "exit key";
+ case KEY_FIND:
+ return "find key";
+ case KEY_HELP:
+ return "help key";
+ case KEY_MARK:
+ return "mark key";
+ case KEY_MESSAGE:
+ return "message key";
+ case KEY_MOVE:
+ return "move key";
+ case KEY_NEXT:
+ return "next key";
+ case KEY_OPEN:
+ return "open key";
+ case KEY_OPTIONS:
+ return "options key";
+ case KEY_PREVIOUS:
+ return "previous key";
+ case KEY_REDO:
+ return "redo key";
+ case KEY_REFERENCE:
+ return "reference key";
+ case KEY_REFRESH:
+ return "refresh key";
+ case KEY_REPLACE:
+ return "replace key";
+ case KEY_RESTART:
+ return "restart key";
+ case KEY_RESUME:
+ return "resume key";
+ case KEY_SAVE:
+ return "save key";
+ case KEY_SBEG:
+ return "shifted begin key";
+ case KEY_SCANCEL:
+ return "shifted cancel key";
+ case KEY_SCOMMAND:
+ return "shifted command key";
+ case KEY_SCOPY:
+ return "shifted copy key";
+ case KEY_SCREATE:
+ return "shifted create key";
+ case KEY_SDC:
+ return "shifted delete-character key";
+ case KEY_SDL:
+ return "shifted delete-line key";
+ case KEY_SELECT:
+ return "select key";
+ case KEY_SEND:
+ return "shifted end key";
+ case KEY_SEOL:
+ return "shifted clear-to-end-of-line key";
+ case KEY_SEXIT:
+ return "shifted exit key";
+ case KEY_SFIND:
+ return "shifted find key";
+ case KEY_SHELP:
+ return "shifted help key";
+ case KEY_SHOME:
+ return "shifted home key";
+ case KEY_SIC:
+ return "shifted insert-character key";
+ case KEY_SLEFT:
+ return "shifted left-arrow key";
+ case KEY_SMESSAGE:
+ return "shifted message key";
+ case KEY_SMOVE:
+ return "shifted move key";
+ case KEY_SNEXT:
+ return "shifted next key";
+ case KEY_SOPTIONS:
+ return "shifted options key";
+ case KEY_SPREVIOUS:
+ return "shifted previous key";
+ case KEY_SPRINT:
+ return "shifted print key";
+ case KEY_SREDO:
+ return "shifted redo key";
+ case KEY_SREPLACE:
+ return "shifted replace key";
+ case KEY_SRIGHT:
+ return "shifted right-arrow key";
+ case KEY_SRSUME:
+ return "shifted resume key";
+ case KEY_SSAVE:
+ return "shifted save key";
+ case KEY_SSUSPEND:
+ return "shifted suspend key";
+ case KEY_SUNDO:
+ return "shifted undo key";
+ case KEY_SUSPEND:
+ return "suspend key";
+ case KEY_UNDO:
+ return "undo key";
+ case KEY_MOUSE:
+ return "Mouse event has occurred";
+ case KEY_RESIZE:
+ return "Terminal resize event";
+#ifdef KEY_EVENT
+ case KEY_EVENT:
+ return "We were interrupted by an event";
+#endif
+ case KEY_RETURN:
+ return "return";
+ case ' ':
+ return "space";
+ case '\t':
+ return "tab";
+ case KEY_ESCAPE:
+ return "escape";
+ default:
+ if (isprint(ch))
+ snprintf(g_desc, sizeof(g_desc), "%c", ch);
+ else
+ snprintf(g_desc, sizeof(g_desc), "\\x%2.2x", ch);
+ return g_desc;
+ }
+ return nullptr;
+}
+
+HelpDialogDelegate::HelpDialogDelegate(const char *text,
+ KeyHelp *key_help_array)
+ : m_text(), m_first_visible_line(0) {
+ if (text && text[0]) {
+ m_text.SplitIntoLines(text);
+ m_text.AppendString("");
+ }
+ if (key_help_array) {
+ for (KeyHelp *key = key_help_array; key->ch; ++key) {
+ StreamString key_description;
+ key_description.Printf("%10s - %s", CursesKeyToCString(key->ch),
+ key->description);
+ m_text.AppendString(key_description.GetString());
+ }
+ }
+}
+
+HelpDialogDelegate::~HelpDialogDelegate() = default;
+
+bool HelpDialogDelegate::WindowDelegateDraw(Window &window, bool force) {
+ window.Erase();
+ const int window_height = window.GetHeight();
+ int x = 2;
+ int y = 1;
+ const int min_y = y;
+ const int max_y = window_height - 1 - y;
+ const size_t num_visible_lines = max_y - min_y + 1;
+ const size_t num_lines = m_text.GetSize();
+ const char *bottom_message;
+ if (num_lines <= num_visible_lines)
+ bottom_message = "Press any key to exit";
+ else
+ bottom_message = "Use arrows to scroll, any other key to exit";
+ window.DrawTitleBox(window.GetName(), bottom_message);
+ while (y <= max_y) {
+ window.MoveCursor(x, y);
+ window.PutCStringTruncated(
+ m_text.GetStringAtIndex(m_first_visible_line + y - min_y), 1);
+ ++y;
+ }
+ return true;
+}
+
+HandleCharResult HelpDialogDelegate::WindowDelegateHandleChar(Window &window,
+ int key) {
+ bool done = false;
+ const size_t num_lines = m_text.GetSize();
+ const size_t num_visible_lines = window.GetHeight() - 2;
+
+ if (num_lines <= num_visible_lines) {
+ done = true;
+ // If we have all lines visible and don't need scrolling, then any key
+ // press will cause us to exit
+ } else {
+ switch (key) {
+ case KEY_UP:
+ if (m_first_visible_line > 0)
+ --m_first_visible_line;
+ break;
+
+ case KEY_DOWN:
+ if (m_first_visible_line + num_visible_lines < num_lines)
+ ++m_first_visible_line;
+ break;
+
+ case KEY_PPAGE:
+ case ',':
+ if (m_first_visible_line > 0) {
+ if (static_cast<size_t>(m_first_visible_line) >= num_visible_lines)
+ m_first_visible_line -= num_visible_lines;
+ else
+ m_first_visible_line = 0;
+ }
+ break;
+
+ case KEY_NPAGE:
+ case '.':
+ if (m_first_visible_line + num_visible_lines < num_lines) {
+ m_first_visible_line += num_visible_lines;
+ if (static_cast<size_t>(m_first_visible_line) > num_lines)
+ m_first_visible_line = num_lines - num_visible_lines;
+ }
+ break;
+
+ default:
+ done = true;
+ break;
+ }
+ }
+ if (done)
+ window.GetParent()->RemoveSubWindow(&window);
+ return eKeyHandled;
+}
+
+class ApplicationDelegate : public WindowDelegate, public MenuDelegate {
+public:
+ enum {
+ eMenuID_LLDB = 1,
+ eMenuID_LLDBAbout,
+ eMenuID_LLDBExit,
+
+ eMenuID_Target,
+ eMenuID_TargetCreate,
+ eMenuID_TargetDelete,
+
+ eMenuID_Process,
+ eMenuID_ProcessAttach,
+ eMenuID_ProcessDetach,
+ eMenuID_ProcessLaunch,
+ eMenuID_ProcessContinue,
+ eMenuID_ProcessHalt,
+ eMenuID_ProcessKill,
+
+ eMenuID_Thread,
+ eMenuID_ThreadStepIn,
+ eMenuID_ThreadStepOver,
+ eMenuID_ThreadStepOut,
+
+ eMenuID_View,
+ eMenuID_ViewBacktrace,
+ eMenuID_ViewRegisters,
+ eMenuID_ViewSource,
+ eMenuID_ViewVariables,
+
+ eMenuID_Help,
+ eMenuID_HelpGUIHelp
+ };
+
+ ApplicationDelegate(Application &app, Debugger &debugger)
+ : WindowDelegate(), MenuDelegate(), m_app(app), m_debugger(debugger) {}
+
+ ~ApplicationDelegate() override = default;
+
+ bool WindowDelegateDraw(Window &window, bool force) override {
+ return false; // Drawing not handled, let standard window drawing happen
+ }
+
+ HandleCharResult WindowDelegateHandleChar(Window &window, int key) override {
+ switch (key) {
+ case '\t':
+ window.SelectNextWindowAsActive();
+ return eKeyHandled;
+
+ case 'h':
+ window.CreateHelpSubwindow();
+ return eKeyHandled;
+
+ case KEY_ESCAPE:
+ return eQuitApplication;
+
+ default:
+ break;
+ }
+ return eKeyNotHandled;
+ }
+
+ const char *WindowDelegateGetHelpText() override {
+ return "Welcome to the LLDB curses GUI.\n\n"
+ "Press the TAB key to change the selected view.\n"
+ "Each view has its own keyboard shortcuts, press 'h' to open a "
+ "dialog to display them.\n\n"
+ "Common key bindings for all views:";
+ }
+
+ KeyHelp *WindowDelegateGetKeyHelp() override {
+ static curses::KeyHelp g_source_view_key_help[] = {
+ {'\t', "Select next view"},
+ {'h', "Show help dialog with view specific key bindings"},
+ {',', "Page up"},
+ {'.', "Page down"},
+ {KEY_UP, "Select previous"},
+ {KEY_DOWN, "Select next"},
+ {KEY_LEFT, "Unexpand or select parent"},
+ {KEY_RIGHT, "Expand"},
+ {KEY_PPAGE, "Page up"},
+ {KEY_NPAGE, "Page down"},
+ {'\0', nullptr}};
+ return g_source_view_key_help;
+ }
+
+ MenuActionResult MenuDelegateAction(Menu &menu) override {
+ switch (menu.GetIdentifier()) {
+ case eMenuID_ThreadStepIn: {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasThreadScope()) {
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive() &&
+ StateIsStoppedState(process->GetState(), true))
+ exe_ctx.GetThreadRef().StepIn(true);
+ }
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_ThreadStepOut: {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasThreadScope()) {
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive() &&
+ StateIsStoppedState(process->GetState(), true))
+ exe_ctx.GetThreadRef().StepOut();
+ }
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_ThreadStepOver: {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasThreadScope()) {
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive() &&
+ StateIsStoppedState(process->GetState(), true))
+ exe_ctx.GetThreadRef().StepOver(true);
+ }
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_ProcessContinue: {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasProcessScope()) {
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive() &&
+ StateIsStoppedState(process->GetState(), true))
+ process->Resume();
+ }
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_ProcessKill: {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasProcessScope()) {
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive())
+ process->Destroy(false);
+ }
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_ProcessHalt: {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasProcessScope()) {
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive())
+ process->Halt();
+ }
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_ProcessDetach: {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasProcessScope()) {
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive())
+ process->Detach(false);
+ }
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_Process: {
+ // Populate the menu with all of the threads if the process is stopped
+ // when the Process menu gets selected and is about to display its
+ // submenu.
+ Menus &submenus = menu.GetSubmenus();
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive() &&
+ StateIsStoppedState(process->GetState(), true)) {
+ if (submenus.size() == 7)
+ menu.AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
+ else if (submenus.size() > 8)
+ submenus.erase(submenus.begin() + 8, submenus.end());
+
+ ThreadList &threads = process->GetThreadList();
+ std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
+ size_t num_threads = threads.GetSize();
+ for (size_t i = 0; i < num_threads; ++i) {
+ ThreadSP thread_sp = threads.GetThreadAtIndex(i);
+ char menu_char = '\0';
+ if (i < 9)
+ menu_char = '1' + i;
+ StreamString thread_menu_title;
+ thread_menu_title.Printf("Thread %u", thread_sp->GetIndexID());
+ const char *thread_name = thread_sp->GetName();
+ if (thread_name && thread_name[0])
+ thread_menu_title.Printf(" %s", thread_name);
+ else {
+ const char *queue_name = thread_sp->GetQueueName();
+ if (queue_name && queue_name[0])
+ thread_menu_title.Printf(" %s", queue_name);
+ }
+ menu.AddSubmenu(
+ MenuSP(new Menu(thread_menu_title.GetString().str().c_str(),
+ nullptr, menu_char, thread_sp->GetID())));
+ }
+ } else if (submenus.size() > 7) {
+ // Remove the separator and any other thread submenu items that were
+ // previously added
+ submenus.erase(submenus.begin() + 7, submenus.end());
+ }
+ // Since we are adding and removing items we need to recalculate the name
+ // lengths
+ menu.RecalculateNameLengths();
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_ViewVariables: {
+ WindowSP main_window_sp = m_app.GetMainWindow();
+ WindowSP source_window_sp = main_window_sp->FindSubWindow("Source");
+ WindowSP variables_window_sp = main_window_sp->FindSubWindow("Variables");
+ WindowSP registers_window_sp = main_window_sp->FindSubWindow("Registers");
+ const Rect source_bounds = source_window_sp->GetBounds();
+
+ if (variables_window_sp) {
+ const Rect variables_bounds = variables_window_sp->GetBounds();
+
+ main_window_sp->RemoveSubWindow(variables_window_sp.get());
+
+ if (registers_window_sp) {
+ // We have a registers window, so give all the area back to the
+ // registers window
+ Rect registers_bounds = variables_bounds;
+ registers_bounds.size.width = source_bounds.size.width;
+ registers_window_sp->SetBounds(registers_bounds);
+ } else {
+ // We have no registers window showing so give the bottom area back
+ // to the source view
+ source_window_sp->Resize(source_bounds.size.width,
+ source_bounds.size.height +
+ variables_bounds.size.height);
+ }
+ } else {
+ Rect new_variables_rect;
+ if (registers_window_sp) {
+ // We have a registers window so split the area of the registers
+ // window into two columns where the left hand side will be the
+ // variables and the right hand side will be the registers
+ const Rect variables_bounds = registers_window_sp->GetBounds();
+ Rect new_registers_rect;
+ variables_bounds.VerticalSplitPercentage(0.50, new_variables_rect,
+ new_registers_rect);
+ registers_window_sp->SetBounds(new_registers_rect);
+ } else {
+ // No variables window, grab the bottom part of the source window
+ Rect new_source_rect;
+ source_bounds.HorizontalSplitPercentage(0.70, new_source_rect,
+ new_variables_rect);
+ source_window_sp->SetBounds(new_source_rect);
+ }
+ WindowSP new_window_sp = main_window_sp->CreateSubWindow(
+ "Variables", new_variables_rect, false);
+ new_window_sp->SetDelegate(
+ WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger)));
+ }
+ touchwin(stdscr);
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_ViewRegisters: {
+ WindowSP main_window_sp = m_app.GetMainWindow();
+ WindowSP source_window_sp = main_window_sp->FindSubWindow("Source");
+ WindowSP variables_window_sp = main_window_sp->FindSubWindow("Variables");
+ WindowSP registers_window_sp = main_window_sp->FindSubWindow("Registers");
+ const Rect source_bounds = source_window_sp->GetBounds();
+
+ if (registers_window_sp) {
+ if (variables_window_sp) {
+ const Rect variables_bounds = variables_window_sp->GetBounds();
+
+ // We have a variables window, so give all the area back to the
+ // variables window
+ variables_window_sp->Resize(variables_bounds.size.width +
+ registers_window_sp->GetWidth(),
+ variables_bounds.size.height);
+ } else {
+ // We have no variables window showing so give the bottom area back
+ // to the source view
+ source_window_sp->Resize(source_bounds.size.width,
+ source_bounds.size.height +
+ registers_window_sp->GetHeight());
+ }
+ main_window_sp->RemoveSubWindow(registers_window_sp.get());
+ } else {
+ Rect new_regs_rect;
+ if (variables_window_sp) {
+ // We have a variables window, split it into two columns where the
+ // left hand side will be the variables and the right hand side will
+ // be the registers
+ const Rect variables_bounds = variables_window_sp->GetBounds();
+ Rect new_vars_rect;
+ variables_bounds.VerticalSplitPercentage(0.50, new_vars_rect,
+ new_regs_rect);
+ variables_window_sp->SetBounds(new_vars_rect);
+ } else {
+ // No registers window, grab the bottom part of the source window
+ Rect new_source_rect;
+ source_bounds.HorizontalSplitPercentage(0.70, new_source_rect,
+ new_regs_rect);
+ source_window_sp->SetBounds(new_source_rect);
+ }
+ WindowSP new_window_sp =
+ main_window_sp->CreateSubWindow("Registers", new_regs_rect, false);
+ new_window_sp->SetDelegate(
+ WindowDelegateSP(new RegistersWindowDelegate(m_debugger)));
+ }
+ touchwin(stdscr);
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_HelpGUIHelp:
+ m_app.GetMainWindow()->CreateHelpSubwindow();
+ return MenuActionResult::Handled;
+
+ default:
+ break;
+ }
+
+ return MenuActionResult::NotHandled;
+ }
+
+protected:
+ Application &m_app;
+ Debugger &m_debugger;
+};
+
+class StatusBarWindowDelegate : public WindowDelegate {
+public:
+ StatusBarWindowDelegate(Debugger &debugger) : m_debugger(debugger) {
+ FormatEntity::Parse("Thread: ${thread.id%tid}", m_format);
+ }
+
+ ~StatusBarWindowDelegate() override = default;
+
+ bool WindowDelegateDraw(Window &window, bool force) override {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ Process *process = exe_ctx.GetProcessPtr();
+ Thread *thread = exe_ctx.GetThreadPtr();
+ StackFrame *frame = exe_ctx.GetFramePtr();
+ window.Erase();
+ window.SetBackground(2);
+ window.MoveCursor(0, 0);
+ if (process) {
+ const StateType state = process->GetState();
+ window.Printf("Process: %5" PRIu64 " %10s", process->GetID(),
+ StateAsCString(state));
+
+ if (StateIsStoppedState(state, true)) {
+ StreamString strm;
+ if (thread && FormatEntity::Format(m_format, strm, nullptr, &exe_ctx,
+ nullptr, nullptr, false, false)) {
+ window.MoveCursor(40, 0);
+ window.PutCStringTruncated(strm.GetString().str().c_str(), 1);
+ }
+
+ window.MoveCursor(60, 0);
+ if (frame)
+ window.Printf("Frame: %3u PC = 0x%16.16" PRIx64,
+ frame->GetFrameIndex(),
+ frame->GetFrameCodeAddress().GetOpcodeLoadAddress(
+ exe_ctx.GetTargetPtr()));
+ } else if (state == eStateExited) {
+ const char *exit_desc = process->GetExitDescription();
+ const int exit_status = process->GetExitStatus();
+ if (exit_desc && exit_desc[0])
+ window.Printf(" with status = %i (%s)", exit_status, exit_desc);
+ else
+ window.Printf(" with status = %i", exit_status);
+ }
+ }
+ return true;
+ }
+
+protected:
+ Debugger &m_debugger;
+ FormatEntity::Entry m_format;
+};
+
+class SourceFileWindowDelegate : public WindowDelegate {
+public:
+ SourceFileWindowDelegate(Debugger &debugger)
+ : WindowDelegate(), m_debugger(debugger), m_sc(), m_file_sp(),
+ m_disassembly_scope(nullptr), m_disassembly_sp(), m_disassembly_range(),
+ m_title(), m_line_width(4), m_selected_line(0), m_pc_line(0),
+ m_stop_id(0), m_frame_idx(UINT32_MAX), m_first_visible_line(0),
+ m_min_x(0), m_min_y(0), m_max_x(0), m_max_y(0) {}
+
+ ~SourceFileWindowDelegate() override = default;
+
+ void Update(const SymbolContext &sc) { m_sc = sc; }
+
+ uint32_t NumVisibleLines() const { return m_max_y - m_min_y; }
+
+ const char *WindowDelegateGetHelpText() override {
+ return "Source/Disassembly window keyboard shortcuts:";
+ }
+
+ KeyHelp *WindowDelegateGetKeyHelp() override {
+ static curses::KeyHelp g_source_view_key_help[] = {
+ {KEY_RETURN, "Run to selected line with one shot breakpoint"},
+ {KEY_UP, "Select previous source line"},
+ {KEY_DOWN, "Select next source line"},
+ {KEY_PPAGE, "Page up"},
+ {KEY_NPAGE, "Page down"},
+ {'b', "Set breakpoint on selected source/disassembly line"},
+ {'c', "Continue process"},
+ {'d', "Detach and resume process"},
+ {'D', "Detach with process suspended"},
+ {'h', "Show help dialog"},
+ {'k', "Kill process"},
+ {'n', "Step over (source line)"},
+ {'N', "Step over (single instruction)"},
+ {'o', "Step out"},
+ {'s', "Step in (source line)"},
+ {'S', "Step in (single instruction)"},
+ {',', "Page up"},
+ {'.', "Page down"},
+ {'\0', nullptr}};
+ return g_source_view_key_help;
+ }
+
+ bool WindowDelegateDraw(Window &window, bool force) override {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ Process *process = exe_ctx.GetProcessPtr();
+ Thread *thread = nullptr;
+
+ bool update_location = false;
+ if (process) {
+ StateType state = process->GetState();
+ if (StateIsStoppedState(state, true)) {
+ // We are stopped, so it is ok to
+ update_location = true;
+ }
+ }
+
+ m_min_x = 1;
+ m_min_y = 2;
+ m_max_x = window.GetMaxX() - 1;
+ m_max_y = window.GetMaxY() - 1;
+
+ const uint32_t num_visible_lines = NumVisibleLines();
+ StackFrameSP frame_sp;
+ bool set_selected_line_to_pc = false;
+
+ if (update_location) {
+ const bool process_alive = process ? process->IsAlive() : false;
+ bool thread_changed = false;
+ if (process_alive) {
+ thread = exe_ctx.GetThreadPtr();
+ if (thread) {
+ frame_sp = thread->GetSelectedFrame();
+ auto tid = thread->GetID();
+ thread_changed = tid != m_tid;
+ m_tid = tid;
+ } else {
+ if (m_tid != LLDB_INVALID_THREAD_ID) {
+ thread_changed = true;
+ m_tid = LLDB_INVALID_THREAD_ID;
+ }
+ }
+ }
+ const uint32_t stop_id = process ? process->GetStopID() : 0;
+ const bool stop_id_changed = stop_id != m_stop_id;
+ bool frame_changed = false;
+ m_stop_id = stop_id;
+ m_title.Clear();
+ if (frame_sp) {
+ m_sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
+ if (m_sc.module_sp) {
+ m_title.Printf(
+ "%s", m_sc.module_sp->GetFileSpec().GetFilename().GetCString());
+ ConstString func_name = m_sc.GetFunctionName();
+ if (func_name)
+ m_title.Printf("`%s", func_name.GetCString());
+ }
+ const uint32_t frame_idx = frame_sp->GetFrameIndex();
+ frame_changed = frame_idx != m_frame_idx;
+ m_frame_idx = frame_idx;
+ } else {
+ m_sc.Clear(true);
+ frame_changed = m_frame_idx != UINT32_MAX;
+ m_frame_idx = UINT32_MAX;
+ }
+
+ const bool context_changed =
+ thread_changed || frame_changed || stop_id_changed;
+
+ if (process_alive) {
+ if (m_sc.line_entry.IsValid()) {
+ m_pc_line = m_sc.line_entry.line;
+ if (m_pc_line != UINT32_MAX)
+ --m_pc_line; // Convert to zero based line number...
+ // Update the selected line if the stop ID changed...
+ if (context_changed)
+ m_selected_line = m_pc_line;
+
+ if (m_file_sp && m_file_sp->GetFileSpec() == m_sc.line_entry.file) {
+ // Same file, nothing to do, we should either have the lines or not
+ // (source file missing)
+ if (m_selected_line >= static_cast<size_t>(m_first_visible_line)) {
+ if (m_selected_line >= m_first_visible_line + num_visible_lines)
+ m_first_visible_line = m_selected_line - 10;
+ } else {
+ if (m_selected_line > 10)
+ m_first_visible_line = m_selected_line - 10;
+ else
+ m_first_visible_line = 0;
+ }
+ } else {
+ // File changed, set selected line to the line with the PC
+ m_selected_line = m_pc_line;
+ m_file_sp =
+ m_debugger.GetSourceManager().GetFile(m_sc.line_entry.file);
+ if (m_file_sp) {
+ const size_t num_lines = m_file_sp->GetNumLines();
+ m_line_width = 1;
+ for (size_t n = num_lines; n >= 10; n = n / 10)
+ ++m_line_width;
+
+ if (num_lines < num_visible_lines ||
+ m_selected_line < num_visible_lines)
+ m_first_visible_line = 0;
+ else
+ m_first_visible_line = m_selected_line - 10;
+ }
+ }
+ } else {
+ m_file_sp.reset();
+ }
+
+ if (!m_file_sp || m_file_sp->GetNumLines() == 0) {
+ // Show disassembly
+ bool prefer_file_cache = false;
+ if (m_sc.function) {
+ if (m_disassembly_scope != m_sc.function) {
+ m_disassembly_scope = m_sc.function;
+ m_disassembly_sp = m_sc.function->GetInstructions(
+ exe_ctx, nullptr, prefer_file_cache);
+ if (m_disassembly_sp) {
+ set_selected_line_to_pc = true;
+ m_disassembly_range = m_sc.function->GetAddressRange();
+ } else {
+ m_disassembly_range.Clear();
+ }
+ } else {
+ set_selected_line_to_pc = context_changed;
+ }
+ } else if (m_sc.symbol) {
+ if (m_disassembly_scope != m_sc.symbol) {
+ m_disassembly_scope = m_sc.symbol;
+ m_disassembly_sp = m_sc.symbol->GetInstructions(
+ exe_ctx, nullptr, prefer_file_cache);
+ if (m_disassembly_sp) {
+ set_selected_line_to_pc = true;
+ m_disassembly_range.GetBaseAddress() =
+ m_sc.symbol->GetAddress();
+ m_disassembly_range.SetByteSize(m_sc.symbol->GetByteSize());
+ } else {
+ m_disassembly_range.Clear();
+ }
+ } else {
+ set_selected_line_to_pc = context_changed;
+ }
+ }
+ }
+ } else {
+ m_pc_line = UINT32_MAX;
+ }
+ }
+
+ const int window_width = window.GetWidth();
+ window.Erase();
+ window.DrawTitleBox("Sources");
+ if (!m_title.GetString().empty()) {
+ window.AttributeOn(A_REVERSE);
+ window.MoveCursor(1, 1);
+ window.PutChar(' ');
+ window.PutCStringTruncated(m_title.GetString().str().c_str(), 1);
+ int x = window.GetCursorX();
+ if (x < window_width - 1) {
+ window.Printf("%*s", window_width - x - 1, "");
+ }
+ window.AttributeOff(A_REVERSE);
+ }
+
+ Target *target = exe_ctx.GetTargetPtr();
+ const size_t num_source_lines = GetNumSourceLines();
+ if (num_source_lines > 0) {
+ // Display source
+ BreakpointLines bp_lines;
+ if (target) {
+ BreakpointList &bp_list = target->GetBreakpointList();
+ const size_t num_bps = bp_list.GetSize();
+ for (size_t bp_idx = 0; bp_idx < num_bps; ++bp_idx) {
+ BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
+ const size_t num_bps_locs = bp_sp->GetNumLocations();
+ for (size_t bp_loc_idx = 0; bp_loc_idx < num_bps_locs; ++bp_loc_idx) {
+ BreakpointLocationSP bp_loc_sp =
+ bp_sp->GetLocationAtIndex(bp_loc_idx);
+ LineEntry bp_loc_line_entry;
+ if (bp_loc_sp->GetAddress().CalculateSymbolContextLineEntry(
+ bp_loc_line_entry)) {
+ if (m_file_sp->GetFileSpec() == bp_loc_line_entry.file) {
+ bp_lines.insert(bp_loc_line_entry.line);
+ }
+ }
+ }
+ }
+ }
+
+ const attr_t selected_highlight_attr = A_REVERSE;
+ const attr_t pc_highlight_attr = COLOR_PAIR(1);
+
+ for (size_t i = 0; i < num_visible_lines; ++i) {
+ const uint32_t curr_line = m_first_visible_line + i;
+ if (curr_line < num_source_lines) {
+ const int line_y = m_min_y + i;
+ window.MoveCursor(1, line_y);
+ const bool is_pc_line = curr_line == m_pc_line;
+ const bool line_is_selected = m_selected_line == curr_line;
+ // Highlight the line as the PC line first, then if the selected line
+ // isn't the same as the PC line, highlight it differently
+ attr_t highlight_attr = 0;
+ attr_t bp_attr = 0;
+ if (is_pc_line)
+ highlight_attr = pc_highlight_attr;
+ else if (line_is_selected)
+ highlight_attr = selected_highlight_attr;
+
+ if (bp_lines.find(curr_line + 1) != bp_lines.end())
+ bp_attr = COLOR_PAIR(2);
+
+ if (bp_attr)
+ window.AttributeOn(bp_attr);
+
+ window.Printf(" %*u ", m_line_width, curr_line + 1);
+
+ if (bp_attr)
+ window.AttributeOff(bp_attr);
+
+ window.PutChar(ACS_VLINE);
+ // Mark the line with the PC with a diamond
+ if (is_pc_line)
+ window.PutChar(ACS_DIAMOND);
+ else
+ window.PutChar(' ');
+
+ if (highlight_attr)
+ window.AttributeOn(highlight_attr);
+ const uint32_t line_len =
+ m_file_sp->GetLineLength(curr_line + 1, false);
+ if (line_len > 0)
+ window.PutCString(m_file_sp->PeekLineData(curr_line + 1), line_len);
+
+ if (is_pc_line && frame_sp &&
+ frame_sp->GetConcreteFrameIndex() == 0) {
+ StopInfoSP stop_info_sp;
+ if (thread)
+ stop_info_sp = thread->GetStopInfo();
+ if (stop_info_sp) {
+ const char *stop_description = stop_info_sp->GetDescription();
+ if (stop_description && stop_description[0]) {
+ size_t stop_description_len = strlen(stop_description);
+ int desc_x = window_width - stop_description_len - 16;
+ window.Printf("%*s", desc_x - window.GetCursorX(), "");
+ // window.MoveCursor(window_width - stop_description_len - 15,
+ // line_y);
+ window.Printf("<<< Thread %u: %s ", thread->GetIndexID(),
+ stop_description);
+ }
+ } else {
+ window.Printf("%*s", window_width - window.GetCursorX() - 1, "");
+ }
+ }
+ if (highlight_attr)
+ window.AttributeOff(highlight_attr);
+ } else {
+ break;
+ }
+ }
+ } else {
+ size_t num_disassembly_lines = GetNumDisassemblyLines();
+ if (num_disassembly_lines > 0) {
+ // Display disassembly
+ BreakpointAddrs bp_file_addrs;
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target) {
+ BreakpointList &bp_list = target->GetBreakpointList();
+ const size_t num_bps = bp_list.GetSize();
+ for (size_t bp_idx = 0; bp_idx < num_bps; ++bp_idx) {
+ BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
+ const size_t num_bps_locs = bp_sp->GetNumLocations();
+ for (size_t bp_loc_idx = 0; bp_loc_idx < num_bps_locs;
+ ++bp_loc_idx) {
+ BreakpointLocationSP bp_loc_sp =
+ bp_sp->GetLocationAtIndex(bp_loc_idx);
+ LineEntry bp_loc_line_entry;
+ const lldb::addr_t file_addr =
+ bp_loc_sp->GetAddress().GetFileAddress();
+ if (file_addr != LLDB_INVALID_ADDRESS) {
+ if (m_disassembly_range.ContainsFileAddress(file_addr))
+ bp_file_addrs.insert(file_addr);
+ }
+ }
+ }
+ }
+
+ const attr_t selected_highlight_attr = A_REVERSE;
+ const attr_t pc_highlight_attr = COLOR_PAIR(1);
+
+ StreamString strm;
+
+ InstructionList &insts = m_disassembly_sp->GetInstructionList();
+ Address pc_address;
+
+ if (frame_sp)
+ pc_address = frame_sp->GetFrameCodeAddress();
+ const uint32_t pc_idx =
+ pc_address.IsValid()
+ ? insts.GetIndexOfInstructionAtAddress(pc_address)
+ : UINT32_MAX;
+ if (set_selected_line_to_pc) {
+ m_selected_line = pc_idx;
+ }
+
+ const uint32_t non_visible_pc_offset = (num_visible_lines / 5);
+ if (static_cast<size_t>(m_first_visible_line) >= num_disassembly_lines)
+ m_first_visible_line = 0;
+
+ if (pc_idx < num_disassembly_lines) {
+ if (pc_idx < static_cast<uint32_t>(m_first_visible_line) ||
+ pc_idx >= m_first_visible_line + num_visible_lines)
+ m_first_visible_line = pc_idx - non_visible_pc_offset;
+ }
+
+ for (size_t i = 0; i < num_visible_lines; ++i) {
+ const uint32_t inst_idx = m_first_visible_line + i;
+ Instruction *inst = insts.GetInstructionAtIndex(inst_idx).get();
+ if (!inst)
+ break;
+
+ const int line_y = m_min_y + i;
+ window.MoveCursor(1, line_y);
+ const bool is_pc_line = frame_sp && inst_idx == pc_idx;
+ const bool line_is_selected = m_selected_line == inst_idx;
+ // Highlight the line as the PC line first, then if the selected line
+ // isn't the same as the PC line, highlight it differently
+ attr_t highlight_attr = 0;
+ attr_t bp_attr = 0;
+ if (is_pc_line)
+ highlight_attr = pc_highlight_attr;
+ else if (line_is_selected)
+ highlight_attr = selected_highlight_attr;
+
+ if (bp_file_addrs.find(inst->GetAddress().GetFileAddress()) !=
+ bp_file_addrs.end())
+ bp_attr = COLOR_PAIR(2);
+
+ if (bp_attr)
+ window.AttributeOn(bp_attr);
+
+ window.Printf(" 0x%16.16llx ",
+ static_cast<unsigned long long>(
+ inst->GetAddress().GetLoadAddress(target)));
+
+ if (bp_attr)
+ window.AttributeOff(bp_attr);
+
+ window.PutChar(ACS_VLINE);
+ // Mark the line with the PC with a diamond
+ if (is_pc_line)
+ window.PutChar(ACS_DIAMOND);
+ else
+ window.PutChar(' ');
+
+ if (highlight_attr)
+ window.AttributeOn(highlight_attr);
+
+ const char *mnemonic = inst->GetMnemonic(&exe_ctx);
+ const char *operands = inst->GetOperands(&exe_ctx);
+ const char *comment = inst->GetComment(&exe_ctx);
+
+ if (mnemonic != nullptr && mnemonic[0] == '\0')
+ mnemonic = nullptr;
+ if (operands != nullptr && operands[0] == '\0')
+ operands = nullptr;
+ if (comment != nullptr && comment[0] == '\0')
+ comment = nullptr;
+
+ strm.Clear();
+
+ if (mnemonic != nullptr && operands != nullptr && comment != nullptr)
+ strm.Printf("%-8s %-25s ; %s", mnemonic, operands, comment);
+ else if (mnemonic != nullptr && operands != nullptr)
+ strm.Printf("%-8s %s", mnemonic, operands);
+ else if (mnemonic != nullptr)
+ strm.Printf("%s", mnemonic);
+
+ int right_pad = 1;
+ window.PutCStringTruncated(strm.GetData(), right_pad);
+
+ if (is_pc_line && frame_sp &&
+ frame_sp->GetConcreteFrameIndex() == 0) {
+ StopInfoSP stop_info_sp;
+ if (thread)
+ stop_info_sp = thread->GetStopInfo();
+ if (stop_info_sp) {
+ const char *stop_description = stop_info_sp->GetDescription();
+ if (stop_description && stop_description[0]) {
+ size_t stop_description_len = strlen(stop_description);
+ int desc_x = window_width - stop_description_len - 16;
+ window.Printf("%*s", desc_x - window.GetCursorX(), "");
+ // window.MoveCursor(window_width - stop_description_len - 15,
+ // line_y);
+ window.Printf("<<< Thread %u: %s ", thread->GetIndexID(),
+ stop_description);
+ }
+ } else {
+ window.Printf("%*s", window_width - window.GetCursorX() - 1, "");
+ }
+ }
+ if (highlight_attr)
+ window.AttributeOff(highlight_attr);
+ }
+ }
+ }
+ return true; // Drawing handled
+ }
+
+ size_t GetNumLines() {
+ size_t num_lines = GetNumSourceLines();
+ if (num_lines == 0)
+ num_lines = GetNumDisassemblyLines();
+ return num_lines;
+ }
+
+ size_t GetNumSourceLines() const {
+ if (m_file_sp)
+ return m_file_sp->GetNumLines();
+ return 0;
+ }
+
+ size_t GetNumDisassemblyLines() const {
+ if (m_disassembly_sp)
+ return m_disassembly_sp->GetInstructionList().GetSize();
+ return 0;
+ }
+
+ HandleCharResult WindowDelegateHandleChar(Window &window, int c) override {
+ const uint32_t num_visible_lines = NumVisibleLines();
+ const size_t num_lines = GetNumLines();
+
+ switch (c) {
+ case ',':
+ case KEY_PPAGE:
+ // Page up key
+ if (static_cast<uint32_t>(m_first_visible_line) > num_visible_lines)
+ m_first_visible_line -= num_visible_lines;
+ else
+ m_first_visible_line = 0;
+ m_selected_line = m_first_visible_line;
+ return eKeyHandled;
+
+ case '.':
+ case KEY_NPAGE:
+ // Page down key
+ {
+ if (m_first_visible_line + num_visible_lines < num_lines)
+ m_first_visible_line += num_visible_lines;
+ else if (num_lines < num_visible_lines)
+ m_first_visible_line = 0;
+ else
+ m_first_visible_line = num_lines - num_visible_lines;
+ m_selected_line = m_first_visible_line;
+ }
+ return eKeyHandled;
+
+ case KEY_UP:
+ if (m_selected_line > 0) {
+ m_selected_line--;
+ if (static_cast<size_t>(m_first_visible_line) > m_selected_line)
+ m_first_visible_line = m_selected_line;
+ }
+ return eKeyHandled;
+
+ case KEY_DOWN:
+ if (m_selected_line + 1 < num_lines) {
+ m_selected_line++;
+ if (m_first_visible_line + num_visible_lines < m_selected_line)
+ m_first_visible_line++;
+ }
+ return eKeyHandled;
+
+ case '\r':
+ case '\n':
+ case KEY_ENTER:
+ // Set a breakpoint and run to the line using a one shot breakpoint
+ if (GetNumSourceLines() > 0) {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasProcessScope() && exe_ctx.GetProcessRef().IsAlive()) {
+ BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
+ nullptr, // Don't limit the breakpoint to certain modules
+ m_file_sp->GetFileSpec(), // Source file
+ m_selected_line +
+ 1, // Source line number (m_selected_line is zero based)
+ 0, // Unspecified column.
+ 0, // No offset
+ eLazyBoolCalculate, // Check inlines using global setting
+ eLazyBoolCalculate, // Skip prologue using global setting,
+ false, // internal
+ false, // request_hardware
+ eLazyBoolCalculate); // move_to_nearest_code
+ // Make breakpoint one shot
+ bp_sp->GetOptions()->SetOneShot(true);
+ exe_ctx.GetProcessRef().Resume();
+ }
+ } else if (m_selected_line < GetNumDisassemblyLines()) {
+ const Instruction *inst = m_disassembly_sp->GetInstructionList()
+ .GetInstructionAtIndex(m_selected_line)
+ .get();
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasTargetScope()) {
+ Address addr = inst->GetAddress();
+ BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
+ addr, // lldb_private::Address
+ false, // internal
+ false); // request_hardware
+ // Make breakpoint one shot
+ bp_sp->GetOptions()->SetOneShot(true);
+ exe_ctx.GetProcessRef().Resume();
+ }
+ }
+ return eKeyHandled;
+
+ case 'b': // 'b' == toggle breakpoint on currently selected line
+ if (m_selected_line < GetNumSourceLines()) {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasTargetScope()) {
+ BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
+ nullptr, // Don't limit the breakpoint to certain modules
+ m_file_sp->GetFileSpec(), // Source file
+ m_selected_line +
+ 1, // Source line number (m_selected_line is zero based)
+ 0, // No column specified.
+ 0, // No offset
+ eLazyBoolCalculate, // Check inlines using global setting
+ eLazyBoolCalculate, // Skip prologue using global setting,
+ false, // internal
+ false, // request_hardware
+ eLazyBoolCalculate); // move_to_nearest_code
+ }
+ } else if (m_selected_line < GetNumDisassemblyLines()) {
+ const Instruction *inst = m_disassembly_sp->GetInstructionList()
+ .GetInstructionAtIndex(m_selected_line)
+ .get();
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasTargetScope()) {
+ Address addr = inst->GetAddress();
+ BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
+ addr, // lldb_private::Address
+ false, // internal
+ false); // request_hardware
+ }
+ }
+ return eKeyHandled;
+
+ case 'd': // 'd' == detach and let run
+ case 'D': // 'D' == detach and keep stopped
+ {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasProcessScope())
+ exe_ctx.GetProcessRef().Detach(c == 'D');
+ }
+ return eKeyHandled;
+
+ case 'k':
+ // 'k' == kill
+ {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasProcessScope())
+ exe_ctx.GetProcessRef().Destroy(false);
+ }
+ return eKeyHandled;
+
+ case 'c':
+ // 'c' == continue
+ {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasProcessScope())
+ exe_ctx.GetProcessRef().Resume();
+ }
+ return eKeyHandled;
+
+ case 'o':
+ // 'o' == step out
+ {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasThreadScope() &&
+ StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) {
+ exe_ctx.GetThreadRef().StepOut();
+ }
+ }
+ return eKeyHandled;
+
+ case 'n': // 'n' == step over
+ case 'N': // 'N' == step over instruction
+ {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasThreadScope() &&
+ StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) {
+ bool source_step = (c == 'n');
+ exe_ctx.GetThreadRef().StepOver(source_step);
+ }
+ }
+ return eKeyHandled;
+
+ case 's': // 's' == step into
+ case 'S': // 'S' == step into instruction
+ {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasThreadScope() &&
+ StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) {
+ bool source_step = (c == 's');
+ exe_ctx.GetThreadRef().StepIn(source_step);
+ }
+ }
+ return eKeyHandled;
+
+ case 'h':
+ window.CreateHelpSubwindow();
+ return eKeyHandled;
+
+ default:
+ break;
+ }
+ return eKeyNotHandled;
+ }
+
+protected:
+ typedef std::set<uint32_t> BreakpointLines;
+ typedef std::set<lldb::addr_t> BreakpointAddrs;
+
+ Debugger &m_debugger;
+ SymbolContext m_sc;
+ SourceManager::FileSP m_file_sp;
+ SymbolContextScope *m_disassembly_scope;
+ lldb::DisassemblerSP m_disassembly_sp;
+ AddressRange m_disassembly_range;
+ StreamString m_title;
+ lldb::user_id_t m_tid;
+ int m_line_width;
+ uint32_t m_selected_line; // The selected line
+ uint32_t m_pc_line; // The line with the PC
+ uint32_t m_stop_id;
+ uint32_t m_frame_idx;
+ int m_first_visible_line;
+ int m_min_x;
+ int m_min_y;
+ int m_max_x;
+ int m_max_y;
+};
+
+DisplayOptions ValueObjectListDelegate::g_options = {true};
+
+IOHandlerCursesGUI::IOHandlerCursesGUI(Debugger &debugger)
+ : IOHandler(debugger, IOHandler::Type::Curses) {}
+
+void IOHandlerCursesGUI::Activate() {
+ IOHandler::Activate();
+ if (!m_app_ap) {
+ m_app_ap.reset(new Application(GetInputFILE(), GetOutputFILE()));
+
+ // This is both a window and a menu delegate
+ std::shared_ptr<ApplicationDelegate> app_delegate_sp(
+ new ApplicationDelegate(*m_app_ap, m_debugger));
+
+ MenuDelegateSP app_menu_delegate_sp =
+ std::static_pointer_cast<MenuDelegate>(app_delegate_sp);
+ MenuSP lldb_menu_sp(
+ new Menu("LLDB", "F1", KEY_F(1), ApplicationDelegate::eMenuID_LLDB));
+ MenuSP exit_menuitem_sp(
+ new Menu("Exit", nullptr, 'x', ApplicationDelegate::eMenuID_LLDBExit));
+ exit_menuitem_sp->SetCannedResult(MenuActionResult::Quit);
+ lldb_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "About LLDB", nullptr, 'a', ApplicationDelegate::eMenuID_LLDBAbout)));
+ lldb_menu_sp->AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
+ lldb_menu_sp->AddSubmenu(exit_menuitem_sp);
+
+ MenuSP target_menu_sp(new Menu("Target", "F2", KEY_F(2),
+ ApplicationDelegate::eMenuID_Target));
+ target_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Create", nullptr, 'c', ApplicationDelegate::eMenuID_TargetCreate)));
+ target_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Delete", nullptr, 'd', ApplicationDelegate::eMenuID_TargetDelete)));
+
+ MenuSP process_menu_sp(new Menu("Process", "F3", KEY_F(3),
+ ApplicationDelegate::eMenuID_Process));
+ process_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Attach", nullptr, 'a', ApplicationDelegate::eMenuID_ProcessAttach)));
+ process_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Detach", nullptr, 'd', ApplicationDelegate::eMenuID_ProcessDetach)));
+ process_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Launch", nullptr, 'l', ApplicationDelegate::eMenuID_ProcessLaunch)));
+ process_menu_sp->AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
+ process_menu_sp->AddSubmenu(
+ MenuSP(new Menu("Continue", nullptr, 'c',
+ ApplicationDelegate::eMenuID_ProcessContinue)));
+ process_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Halt", nullptr, 'h', ApplicationDelegate::eMenuID_ProcessHalt)));
+ process_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Kill", nullptr, 'k', ApplicationDelegate::eMenuID_ProcessKill)));
+
+ MenuSP thread_menu_sp(new Menu("Thread", "F4", KEY_F(4),
+ ApplicationDelegate::eMenuID_Thread));
+ thread_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Step In", nullptr, 'i', ApplicationDelegate::eMenuID_ThreadStepIn)));
+ thread_menu_sp->AddSubmenu(
+ MenuSP(new Menu("Step Over", nullptr, 'v',
+ ApplicationDelegate::eMenuID_ThreadStepOver)));
+ thread_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Step Out", nullptr, 'o', ApplicationDelegate::eMenuID_ThreadStepOut)));
+
+ MenuSP view_menu_sp(
+ new Menu("View", "F5", KEY_F(5), ApplicationDelegate::eMenuID_View));
+ view_menu_sp->AddSubmenu(
+ MenuSP(new Menu("Backtrace", nullptr, 'b',
+ ApplicationDelegate::eMenuID_ViewBacktrace)));
+ view_menu_sp->AddSubmenu(
+ MenuSP(new Menu("Registers", nullptr, 'r',
+ ApplicationDelegate::eMenuID_ViewRegisters)));
+ view_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Source", nullptr, 's', ApplicationDelegate::eMenuID_ViewSource)));
+ view_menu_sp->AddSubmenu(
+ MenuSP(new Menu("Variables", nullptr, 'v',
+ ApplicationDelegate::eMenuID_ViewVariables)));
+
+ MenuSP help_menu_sp(
+ new Menu("Help", "F6", KEY_F(6), ApplicationDelegate::eMenuID_Help));
+ help_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "GUI Help", nullptr, 'g', ApplicationDelegate::eMenuID_HelpGUIHelp)));
+
+ m_app_ap->Initialize();
+ WindowSP &main_window_sp = m_app_ap->GetMainWindow();
+
+ MenuSP menubar_sp(new Menu(Menu::Type::Bar));
+ menubar_sp->AddSubmenu(lldb_menu_sp);
+ menubar_sp->AddSubmenu(target_menu_sp);
+ menubar_sp->AddSubmenu(process_menu_sp);
+ menubar_sp->AddSubmenu(thread_menu_sp);
+ menubar_sp->AddSubmenu(view_menu_sp);
+ menubar_sp->AddSubmenu(help_menu_sp);
+ menubar_sp->SetDelegate(app_menu_delegate_sp);
+
+ Rect content_bounds = main_window_sp->GetFrame();
+ Rect menubar_bounds = content_bounds.MakeMenuBar();
+ Rect status_bounds = content_bounds.MakeStatusBar();
+ Rect source_bounds;
+ Rect variables_bounds;
+ Rect threads_bounds;
+ Rect source_variables_bounds;
+ content_bounds.VerticalSplitPercentage(0.80, source_variables_bounds,
+ threads_bounds);
+ source_variables_bounds.HorizontalSplitPercentage(0.70, source_bounds,
+ variables_bounds);
+
+ WindowSP menubar_window_sp =
+ main_window_sp->CreateSubWindow("Menubar", menubar_bounds, false);
+ // Let the menubar get keys if the active window doesn't handle the keys
+ // that are typed so it can respond to menubar key presses.
+ menubar_window_sp->SetCanBeActive(
+ false); // Don't let the menubar become the active window
+ menubar_window_sp->SetDelegate(menubar_sp);
+
+ WindowSP source_window_sp(
+ main_window_sp->CreateSubWindow("Source", source_bounds, true));
+ WindowSP variables_window_sp(
+ main_window_sp->CreateSubWindow("Variables", variables_bounds, false));
+ WindowSP threads_window_sp(
+ main_window_sp->CreateSubWindow("Threads", threads_bounds, false));
+ WindowSP status_window_sp(
+ main_window_sp->CreateSubWindow("Status", status_bounds, false));
+ status_window_sp->SetCanBeActive(
+ false); // Don't let the status bar become the active window
+ main_window_sp->SetDelegate(
+ std::static_pointer_cast<WindowDelegate>(app_delegate_sp));
+ source_window_sp->SetDelegate(
+ WindowDelegateSP(new SourceFileWindowDelegate(m_debugger)));
+ variables_window_sp->SetDelegate(
+ WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger)));
+ TreeDelegateSP thread_delegate_sp(new ThreadsTreeDelegate(m_debugger));
+ threads_window_sp->SetDelegate(WindowDelegateSP(
+ new TreeWindowDelegate(m_debugger, thread_delegate_sp)));
+ status_window_sp->SetDelegate(
+ WindowDelegateSP(new StatusBarWindowDelegate(m_debugger)));
+
+ // Show the main help window once the first time the curses GUI is launched
+ static bool g_showed_help = false;
+ if (!g_showed_help) {
+ g_showed_help = true;
+ main_window_sp->CreateHelpSubwindow();
+ }
+
+ init_pair(1, COLOR_WHITE, COLOR_BLUE);
+ init_pair(2, COLOR_BLACK, COLOR_WHITE);
+ init_pair(3, COLOR_MAGENTA, COLOR_WHITE);
+ init_pair(4, COLOR_MAGENTA, COLOR_BLACK);
+ init_pair(5, COLOR_RED, COLOR_BLACK);
+ }
+}
+
+void IOHandlerCursesGUI::Deactivate() { m_app_ap->Terminate(); }
+
+void IOHandlerCursesGUI::Run() {
+ m_app_ap->Run(m_debugger);
+ SetIsDone(true);
+}
+
+IOHandlerCursesGUI::~IOHandlerCursesGUI() = default;
+
+void IOHandlerCursesGUI::Cancel() {}
+
+bool IOHandlerCursesGUI::Interrupt() { return false; }
+
+void IOHandlerCursesGUI::GotEOF() {}
+
+#endif // LLDB_ENABLE_CURSES
diff --git a/lldb/source/Core/Mangled.cpp b/lldb/source/Core/Mangled.cpp
index b06656aa3fb7..15baffd212af 100644
--- a/lldb/source/Core/Mangled.cpp
+++ b/lldb/source/Core/Mangled.cpp
@@ -32,18 +32,8 @@
#include <string.h>
using namespace lldb_private;
-static inline Mangled::ManglingScheme cstring_mangling_scheme(const char *s) {
- if (s) {
- if (s[0] == '?')
- return Mangled::eManglingSchemeMSVC;
- if (s[0] == '_' && s[1] == 'Z')
- return Mangled::eManglingSchemeItanium;
- }
- return Mangled::eManglingSchemeNone;
-}
-
-static inline bool cstring_is_mangled(const char *s) {
- return cstring_mangling_scheme(s) != Mangled::eManglingSchemeNone;
+static inline bool cstring_is_mangled(llvm::StringRef s) {
+ return Mangled::GetManglingScheme(s) != Mangled::eManglingSchemeNone;
}
static ConstString
@@ -99,6 +89,23 @@ get_demangled_name_without_arguments(ConstString mangled,
#pragma mark Mangled
+Mangled::ManglingScheme Mangled::GetManglingScheme(llvm::StringRef const name) {
+ if (name.empty())
+ return Mangled::eManglingSchemeNone;
+
+ if (name.startswith("?"))
+ return Mangled::eManglingSchemeMSVC;
+
+ if (name.startswith("_Z"))
+ return Mangled::eManglingSchemeItanium;
+
+ // ___Z is a clang extension of block invocations
+ if (name.startswith("___Z"))
+ return Mangled::eManglingSchemeItanium;
+
+ return Mangled::eManglingSchemeNone;
+}
+
Mangled::Mangled(ConstString s) : m_mangled(), m_demangled() {
if (s)
SetValue(s);
@@ -159,7 +166,7 @@ void Mangled::SetValue(ConstString s, bool mangled) {
void Mangled::SetValue(ConstString name) {
if (name) {
- if (cstring_is_mangled(name.GetCString())) {
+ if (cstring_is_mangled(name.GetStringRef())) {
m_demangled.Clear();
m_mangled = name;
} else {
@@ -232,7 +239,7 @@ bool Mangled::DemangleWithRichManglingInfo(
assert(m_mangled);
// Check whether or not we are interested in this name at all.
- ManglingScheme scheme = cstring_mangling_scheme(m_mangled.GetCString());
+ ManglingScheme scheme = GetManglingScheme(m_mangled.GetStringRef());
if (skip_mangled_name && skip_mangled_name(m_mangled.GetStringRef(), scheme))
return false;
@@ -300,7 +307,7 @@ Mangled::GetDemangledName(lldb::LanguageType language) const {
// Don't bother running anything that isn't mangled
const char *mangled_name = m_mangled.GetCString();
- ManglingScheme mangling_scheme{cstring_mangling_scheme(mangled_name)};
+ ManglingScheme mangling_scheme = GetManglingScheme(m_mangled.GetStringRef());
if (mangling_scheme != eManglingSchemeNone &&
!m_mangled.GetMangledCounterpart(m_demangled)) {
// We didn't already mangle this name, demangle it and if all goes well
@@ -405,6 +412,7 @@ size_t Mangled::MemorySize() const {
// within those targets.
lldb::LanguageType Mangled::GuessLanguage() const {
ConstString mangled = GetMangledName();
+
if (mangled) {
const char *mangled_name = mangled.GetCString();
if (CPlusPlusLanguage::IsCPPMangledName(mangled_name))
diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index aef3f3e3b4b0..031892abdd24 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -613,11 +613,10 @@ void Module::FindCompileUnits(const FileSpec &path,
const size_t num_compile_units = GetNumCompileUnits();
SymbolContext sc;
sc.module_sp = shared_from_this();
- const bool compare_directory = (bool)path.GetDirectory();
for (size_t i = 0; i < num_compile_units; ++i) {
sc.comp_unit = GetCompileUnitAtIndex(i).get();
if (sc.comp_unit) {
- if (FileSpec::Equal(*sc.comp_unit, path, compare_directory))
+ if (FileSpec::Match(path, sc.comp_unit->GetPrimaryFile()))
sc_list.Append(sc);
}
}
@@ -1006,12 +1005,14 @@ void Module::FindTypes(
}
}
-void Module::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
- LanguageSet languages, TypeMap &types) {
+void Module::FindTypes(
+ llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
+ llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
+ TypeMap &types) {
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
if (SymbolFile *symbols = GetSymbolFile())
- symbols->FindTypes(pattern, languages, types);
+ symbols->FindTypes(pattern, languages, searched_symbol_files, types);
}
SymbolFile *Module::GetSymbolFile(bool can_create, Stream *feedback_strm) {
@@ -1058,34 +1059,35 @@ std::string Module::GetSpecificationDescription() const {
return spec;
}
-void Module::GetDescription(Stream *s, lldb::DescriptionLevel level) {
+void Module::GetDescription(llvm::raw_ostream &s,
+ lldb::DescriptionLevel level) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
if (level >= eDescriptionLevelFull) {
if (m_arch.IsValid())
- s->Printf("(%s) ", m_arch.GetArchitectureName());
+ s << llvm::formatv("({0}) ", m_arch.GetArchitectureName());
}
if (level == eDescriptionLevelBrief) {
const char *filename = m_file.GetFilename().GetCString();
if (filename)
- s->PutCString(filename);
+ s << filename;
} else {
char path[PATH_MAX];
if (m_file.GetPath(path, sizeof(path)))
- s->PutCString(path);
+ s << path;
}
const char *object_name = m_object_name.GetCString();
if (object_name)
- s->Printf("(%s)", object_name);
+ s << llvm::formatv("({0})", object_name);
}
void Module::ReportError(const char *format, ...) {
if (format && format[0]) {
StreamString strm;
strm.PutCString("error: ");
- GetDescription(&strm, lldb::eDescriptionLevelBrief);
+ GetDescription(strm.AsRawOstream(), lldb::eDescriptionLevelBrief);
strm.PutChar(' ');
va_list args;
va_start(args, format);
@@ -1116,7 +1118,7 @@ void Module::ReportErrorIfModifyDetected(const char *format, ...) {
if (format) {
StreamString strm;
strm.PutCString("error: the object file ");
- GetDescription(&strm, lldb::eDescriptionLevelFull);
+ GetDescription(strm.AsRawOstream(), lldb::eDescriptionLevelFull);
strm.PutCString(" has been modified\n");
va_list args;
@@ -1142,7 +1144,7 @@ void Module::ReportWarning(const char *format, ...) {
if (format && format[0]) {
StreamString strm;
strm.PutCString("warning: ");
- GetDescription(&strm, lldb::eDescriptionLevelFull);
+ GetDescription(strm.AsRawOstream(), lldb::eDescriptionLevelFull);
strm.PutChar(' ');
va_list args;
@@ -1163,7 +1165,7 @@ void Module::ReportWarning(const char *format, ...) {
void Module::LogMessage(Log *log, const char *format, ...) {
if (log != nullptr) {
StreamString log_message;
- GetDescription(&log_message, lldb::eDescriptionLevelFull);
+ GetDescription(log_message.AsRawOstream(), lldb::eDescriptionLevelFull);
log_message.PutCString(": ");
va_list args;
va_start(args, format);
@@ -1176,7 +1178,7 @@ void Module::LogMessage(Log *log, const char *format, ...) {
void Module::LogMessageVerboseBacktrace(Log *log, const char *format, ...) {
if (log != nullptr) {
StreamString log_message;
- GetDescription(&log_message, lldb::eDescriptionLevelFull);
+ GetDescription(log_message.AsRawOstream(), lldb::eDescriptionLevelFull);
log_message.PutCString(": ");
va_list args;
va_start(args, format);
@@ -1509,12 +1511,10 @@ bool Module::LoadScriptingResourceInTarget(Target *target, Status &error,
return false;
}
StreamString scripting_stream;
- scripting_fspec.Dump(&scripting_stream);
- const bool can_reload = true;
+ scripting_fspec.Dump(scripting_stream.AsRawOstream());
const bool init_lldb_globals = false;
bool did_load = script_interpreter->LoadScriptingModule(
- scripting_stream.GetData(), can_reload, init_lldb_globals,
- error);
+ scripting_stream.GetData(), init_lldb_globals, error);
if (!did_load)
return false;
}
@@ -1557,19 +1557,13 @@ bool Module::MatchesModuleSpec(const ModuleSpec &module_ref) {
}
const FileSpec &file_spec = module_ref.GetFileSpec();
- if (file_spec) {
- if (!FileSpec::Equal(file_spec, m_file, (bool)file_spec.GetDirectory()) &&
- !FileSpec::Equal(file_spec, m_platform_file,
- (bool)file_spec.GetDirectory()))
- return false;
- }
+ if (!FileSpec::Match(file_spec, m_file) &&
+ !FileSpec::Match(file_spec, m_platform_file))
+ return false;
const FileSpec &platform_file_spec = module_ref.GetPlatformFileSpec();
- if (platform_file_spec) {
- if (!FileSpec::Equal(platform_file_spec, GetPlatformFileSpec(),
- (bool)platform_file_spec.GetDirectory()))
- return false;
- }
+ if (!FileSpec::Match(platform_file_spec, GetPlatformFileSpec()))
+ return false;
const ArchSpec &arch = module_ref.GetArchitecture();
if (arch.IsValid()) {
diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp
index b0567a902fd7..07100bb81dca 100644
--- a/lldb/source/Core/ModuleList.cpp
+++ b/lldb/source/Core/ModuleList.cpp
@@ -752,9 +752,10 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_MODULES));
if (log != nullptr)
- LLDB_LOGF(log,
- "module changed: %p, removing from global module list",
- static_cast<void *>(module_sp.get()));
+ LLDB_LOGF(
+ log, "%p '%s' module changed: removing from global module list",
+ static_cast<void *>(module_sp.get()),
+ module_sp->GetFileSpec().GetFilename().GetCString());
shared_module_list.Remove(module_sp);
module_sp.reset();
diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp
index 80b64fb832fa..e8bfef724378 100644
--- a/lldb/source/Core/PluginManager.cpp
+++ b/lldb/source/Core/PluginManager.cpp
@@ -86,7 +86,7 @@ static void SetPluginInfo(const FileSpec &plugin_file_spec,
}
template <typename FPtrTy> static FPtrTy CastToFPtr(void *VPtr) {
- return reinterpret_cast<FPtrTy>(reinterpret_cast<intptr_t>(VPtr));
+ return reinterpret_cast<FPtrTy>(VPtr);
}
static FileSystem::EnumerateDirectoryResult
diff --git a/lldb/source/Core/SearchFilter.cpp b/lldb/source/Core/SearchFilter.cpp
index e02b4f66b58c..9902166be522 100644
--- a/lldb/source/Core/SearchFilter.cpp
+++ b/lldb/source/Core/SearchFilter.cpp
@@ -208,10 +208,12 @@ void SearchFilter::Search(Searcher &searcher) {
return;
empty_sc.target_sp = m_target_sp;
- if (searcher.GetDepth() == lldb::eSearchDepthTarget)
+ if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
searcher.SearchCallback(*this, empty_sc, nullptr);
- else
- DoModuleIteration(empty_sc, searcher);
+ return;
+ }
+
+ DoModuleIteration(empty_sc, searcher);
}
void SearchFilter::SearchInModuleList(Searcher &searcher, ModuleList &modules) {
@@ -221,20 +223,20 @@ void SearchFilter::SearchInModuleList(Searcher &searcher, ModuleList &modules) {
return;
empty_sc.target_sp = m_target_sp;
- if (searcher.GetDepth() == lldb::eSearchDepthTarget)
+ if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
searcher.SearchCallback(*this, empty_sc, nullptr);
- else {
- std::lock_guard<std::recursive_mutex> guard(modules.GetMutex());
- const size_t numModules = modules.GetSize();
-
- for (size_t i = 0; i < numModules; i++) {
- ModuleSP module_sp(modules.GetModuleAtIndexUnlocked(i));
- if (ModulePasses(module_sp)) {
- if (DoModuleIteration(module_sp, searcher) ==
- Searcher::eCallbackReturnStop)
- return;
- }
- }
+ return;
+ }
+
+ std::lock_guard<std::recursive_mutex> guard(modules.GetMutex());
+ const size_t numModules = modules.GetSize();
+
+ for (size_t i = 0; i < numModules; i++) {
+ ModuleSP module_sp(modules.GetModuleAtIndexUnlocked(i));
+ if (!ModulePasses(module_sp))
+ continue;
+ if (DoModuleIteration(module_sp, searcher) == Searcher::eCallbackReturnStop)
+ return;
}
}
@@ -248,45 +250,47 @@ SearchFilter::DoModuleIteration(const lldb::ModuleSP &module_sp,
Searcher::CallbackReturn
SearchFilter::DoModuleIteration(const SymbolContext &context,
Searcher &searcher) {
- if (searcher.GetDepth() >= lldb::eSearchDepthModule) {
- if (context.module_sp) {
- if (searcher.GetDepth() == lldb::eSearchDepthModule) {
- SymbolContext matchingContext(context.module_sp.get());
- searcher.SearchCallback(*this, matchingContext, nullptr);
- } else {
- return DoCUIteration(context.module_sp, context, searcher);
- }
+ if (searcher.GetDepth() < lldb::eSearchDepthModule)
+ return Searcher::eCallbackReturnContinue;
+
+ if (context.module_sp) {
+ if (searcher.GetDepth() != lldb::eSearchDepthModule)
+ return DoCUIteration(context.module_sp, context, searcher);
+
+ SymbolContext matchingContext(context.module_sp.get());
+ searcher.SearchCallback(*this, matchingContext, nullptr);
+ return Searcher::eCallbackReturnContinue;
+ }
+
+ const ModuleList &target_images = m_target_sp->GetImages();
+ std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex());
+
+ size_t n_modules = target_images.GetSize();
+ for (size_t i = 0; i < n_modules; i++) {
+ // If this is the last level supplied, then call the callback directly,
+ // otherwise descend.
+ ModuleSP module_sp(target_images.GetModuleAtIndexUnlocked(i));
+ if (!ModulePasses(module_sp))
+ continue;
+
+ if (searcher.GetDepth() == lldb::eSearchDepthModule) {
+ SymbolContext matchingContext(m_target_sp, module_sp);
+
+ Searcher::CallbackReturn shouldContinue =
+ searcher.SearchCallback(*this, matchingContext, nullptr);
+ if (shouldContinue == Searcher::eCallbackReturnStop ||
+ shouldContinue == Searcher::eCallbackReturnPop)
+ return shouldContinue;
} else {
- const ModuleList &target_images = m_target_sp->GetImages();
- std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex());
-
- size_t n_modules = target_images.GetSize();
- for (size_t i = 0; i < n_modules; i++) {
- // If this is the last level supplied, then call the callback directly,
- // otherwise descend.
- ModuleSP module_sp(target_images.GetModuleAtIndexUnlocked(i));
- if (!ModulePasses(module_sp))
- continue;
-
- if (searcher.GetDepth() == lldb::eSearchDepthModule) {
- SymbolContext matchingContext(m_target_sp, module_sp);
-
- Searcher::CallbackReturn shouldContinue =
- searcher.SearchCallback(*this, matchingContext, nullptr);
- if (shouldContinue == Searcher::eCallbackReturnStop ||
- shouldContinue == Searcher::eCallbackReturnPop)
- return shouldContinue;
- } else {
- Searcher::CallbackReturn shouldContinue =
- DoCUIteration(module_sp, context, searcher);
- if (shouldContinue == Searcher::eCallbackReturnStop)
- return shouldContinue;
- else if (shouldContinue == Searcher::eCallbackReturnPop)
- continue;
- }
- }
+ Searcher::CallbackReturn shouldContinue =
+ DoCUIteration(module_sp, context, searcher);
+ if (shouldContinue == Searcher::eCallbackReturnStop)
+ return shouldContinue;
+ else if (shouldContinue == Searcher::eCallbackReturnPop)
+ continue;
}
}
+
return Searcher::eCallbackReturnContinue;
}
@@ -294,56 +298,56 @@ Searcher::CallbackReturn
SearchFilter::DoCUIteration(const ModuleSP &module_sp,
const SymbolContext &context, Searcher &searcher) {
Searcher::CallbackReturn shouldContinue;
- if (context.comp_unit == nullptr) {
- const size_t num_comp_units = module_sp->GetNumCompileUnits();
- for (size_t i = 0; i < num_comp_units; i++) {
- CompUnitSP cu_sp(module_sp->GetCompileUnitAtIndex(i));
- if (cu_sp) {
- if (!CompUnitPasses(*(cu_sp.get())))
- continue;
-
- if (searcher.GetDepth() == lldb::eSearchDepthCompUnit) {
- SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get());
-
- shouldContinue =
- searcher.SearchCallback(*this, matchingContext, nullptr);
-
- if (shouldContinue == Searcher::eCallbackReturnPop)
- return Searcher::eCallbackReturnContinue;
- else if (shouldContinue == Searcher::eCallbackReturnStop)
- return shouldContinue;
- } else {
- // First make sure this compile unit's functions are parsed
- // since CompUnit::ForeachFunction only iterates over already
- // parsed functions.
- SymbolFile *sym_file = module_sp->GetSymbolFile();
- if (!sym_file)
- continue;
- if (!sym_file->ParseFunctions(*cu_sp))
- continue;
- // If we got any functions, use ForeachFunction to do the iteration.
- cu_sp->ForeachFunction([&](const FunctionSP &func_sp) {
- if (!FunctionPasses(*func_sp.get()))
- return false; // Didn't pass the filter, just keep going.
- if (searcher.GetDepth() == lldb::eSearchDepthFunction) {
- SymbolContext matchingContext(m_target_sp, module_sp,
- cu_sp.get(), func_sp.get());
- shouldContinue =
- searcher.SearchCallback(*this, matchingContext, nullptr);
- } else {
- shouldContinue = DoFunctionIteration(func_sp.get(), context,
- searcher);
- }
- return shouldContinue != Searcher::eCallbackReturnContinue;
- });
- }
- }
- }
- } else {
+ if (context.comp_unit != nullptr) {
if (CompUnitPasses(*context.comp_unit)) {
SymbolContext matchingContext(m_target_sp, module_sp, context.comp_unit);
return searcher.SearchCallback(*this, matchingContext, nullptr);
}
+ return Searcher::eCallbackReturnContinue;
+ }
+
+ const size_t num_comp_units = module_sp->GetNumCompileUnits();
+ for (size_t i = 0; i < num_comp_units; i++) {
+ CompUnitSP cu_sp(module_sp->GetCompileUnitAtIndex(i));
+ if (!cu_sp)
+ continue;
+ if (!CompUnitPasses(*(cu_sp.get())))
+ continue;
+
+ if (searcher.GetDepth() == lldb::eSearchDepthCompUnit) {
+ SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get());
+
+ shouldContinue = searcher.SearchCallback(*this, matchingContext, nullptr);
+
+ if (shouldContinue == Searcher::eCallbackReturnPop)
+ return Searcher::eCallbackReturnContinue;
+ else if (shouldContinue == Searcher::eCallbackReturnStop)
+ return shouldContinue;
+ continue;
+ }
+
+ // First make sure this compile unit's functions are parsed
+ // since CompUnit::ForeachFunction only iterates over already
+ // parsed functions.
+ SymbolFile *sym_file = module_sp->GetSymbolFile();
+ if (!sym_file)
+ continue;
+ if (!sym_file->ParseFunctions(*cu_sp))
+ continue;
+ // If we got any functions, use ForeachFunction to do the iteration.
+ cu_sp->ForeachFunction([&](const FunctionSP &func_sp) {
+ if (!FunctionPasses(*func_sp.get()))
+ return false; // Didn't pass the filter, just keep going.
+ if (searcher.GetDepth() == lldb::eSearchDepthFunction) {
+ SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get(),
+ func_sp.get());
+ shouldContinue =
+ searcher.SearchCallback(*this, matchingContext, nullptr);
+ } else {
+ shouldContinue = DoFunctionIteration(func_sp.get(), context, searcher);
+ }
+ return shouldContinue != Searcher::eCallbackReturnContinue;
+ });
}
return Searcher::eCallbackReturnContinue;
}
@@ -383,8 +387,7 @@ bool SearchFilterForUnconstrainedSearches::ModulePasses(
return true;
else if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_sp))
return false;
- else
- return true;
+ return true;
}
lldb::SearchFilterSP SearchFilterForUnconstrainedSearches::DoCopyForBreakpoint(
@@ -403,13 +406,11 @@ SearchFilterByModule::~SearchFilterByModule() = default;
bool SearchFilterByModule::ModulePasses(const ModuleSP &module_sp) {
return (module_sp &&
- FileSpec::Equal(module_sp->GetFileSpec(), m_module_spec, false));
+ FileSpec::Match(m_module_spec, module_sp->GetFileSpec()));
}
bool SearchFilterByModule::ModulePasses(const FileSpec &spec) {
- // Do a full match only if "spec" has a directory
- const bool full_match = (bool)spec.GetDirectory();
- return FileSpec::Equal(spec, m_module_spec, full_match);
+ return FileSpec::Match(m_module_spec, spec);
}
bool SearchFilterByModule::AddressPasses(Address &address) {
@@ -443,8 +444,7 @@ void SearchFilterByModule::Search(Searcher &searcher) {
const size_t num_modules = target_modules.GetSize();
for (size_t i = 0; i < num_modules; i++) {
Module *module = target_modules.GetModulePointerAtIndexUnlocked(i);
- const bool full_match = (bool)m_module_spec.GetDirectory();
- if (FileSpec::Equal(m_module_spec, module->GetFileSpec(), full_match)) {
+ if (FileSpec::Match(m_module_spec, module->GetFileSpec())) {
SymbolContext matchingContext(m_target_sp, module->shared_from_this());
Searcher::CallbackReturn shouldContinue;
@@ -523,13 +523,6 @@ SearchFilterByModuleList::SearchFilterByModuleList(
enum FilterTy filter_ty)
: SearchFilter(target_sp, filter_ty), m_module_spec_list(module_list) {}
-SearchFilterByModuleList &SearchFilterByModuleList::
-operator=(const SearchFilterByModuleList &rhs) {
- m_target_sp = rhs.m_target_sp;
- m_module_spec_list = rhs.m_module_spec_list;
- return *this;
-}
-
SearchFilterByModuleList::~SearchFilterByModuleList() = default;
bool SearchFilterByModuleList::ModulePasses(const ModuleSP &module_sp) {
@@ -580,15 +573,15 @@ void SearchFilterByModuleList::Search(Searcher &searcher) {
const size_t num_modules = target_modules.GetSize();
for (size_t i = 0; i < num_modules; i++) {
Module *module = target_modules.GetModulePointerAtIndexUnlocked(i);
- if (m_module_spec_list.FindFileIndex(0, module->GetFileSpec(), false) !=
- UINT32_MAX) {
- SymbolContext matchingContext(m_target_sp, module->shared_from_this());
- Searcher::CallbackReturn shouldContinue;
-
- shouldContinue = DoModuleIteration(matchingContext, searcher);
- if (shouldContinue == Searcher::eCallbackReturnStop)
- return;
- }
+ if (m_module_spec_list.FindFileIndex(0, module->GetFileSpec(), false) ==
+ UINT32_MAX)
+ continue;
+ SymbolContext matchingContext(m_target_sp, module->shared_from_this());
+ Searcher::CallbackReturn shouldContinue;
+
+ shouldContinue = DoModuleIteration(matchingContext, searcher);
+ if (shouldContinue == Searcher::eCallbackReturnStop)
+ return;
}
}
@@ -599,15 +592,16 @@ void SearchFilterByModuleList::GetDescription(Stream *s) {
s->PutCString(
m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString(
"<Unknown>"));
- } else {
- s->Printf(", modules(%" PRIu64 ") = ", (uint64_t)num_modules);
- for (size_t i = 0; i < num_modules; i++) {
- s->PutCString(
- m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString(
- "<Unknown>"));
- if (i != num_modules - 1)
- s->PutCString(", ");
- }
+ return;
+ }
+
+ s->Printf(", modules(%" PRIu64 ") = ", (uint64_t)num_modules);
+ for (size_t i = 0; i < num_modules; i++) {
+ s->PutCString(
+ m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString(
+ "<Unknown>"));
+ if (i != num_modules - 1)
+ s->PutCString(", ");
}
}
@@ -628,21 +622,22 @@ SearchFilterSP SearchFilterByModuleList::CreateFromStructuredData(
StructuredData::Array *modules_array;
bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
modules_array);
+
+ if (!success)
+ return std::make_shared<SearchFilterByModuleList>(target.shared_from_this(),
+ FileSpecList{});
FileSpecList modules;
- if (success) {
- size_t num_modules = modules_array->GetSize();
- for (size_t i = 0; i < num_modules; i++) {
- llvm::StringRef module;
- success = modules_array->GetItemAtIndexAsString(i, module);
- if (!success) {
- error.SetErrorStringWithFormat(
- "SFBM::CFSD: filter module item %zu not a string.", i);
- return nullptr;
- }
- modules.EmplaceBack(module);
+ size_t num_modules = modules_array->GetSize();
+ for (size_t i = 0; i < num_modules; i++) {
+ llvm::StringRef module;
+ success = modules_array->GetItemAtIndexAsString(i, module);
+ if (!success) {
+ error.SetErrorStringWithFormat(
+ "SFBM::CFSD: filter module item %zu not a string.", i);
+ return nullptr;
}
+ modules.EmplaceBack(module);
}
-
return std::make_shared<SearchFilterByModuleList>(target.shared_from_this(),
modules);
}
@@ -669,19 +664,6 @@ SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU(
FilterTy::ByModulesAndCU),
m_cu_spec_list(cu_list) {}
-SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU(
- const SearchFilterByModuleListAndCU &rhs) = default;
-
-SearchFilterByModuleListAndCU &SearchFilterByModuleListAndCU::
-operator=(const SearchFilterByModuleListAndCU &rhs) {
- if (&rhs != this) {
- m_target_sp = rhs.m_target_sp;
- m_module_spec_list = rhs.m_module_spec_list;
- m_cu_spec_list = rhs.m_cu_spec_list;
- }
- return *this;
-}
-
SearchFilterByModuleListAndCU::~SearchFilterByModuleListAndCU() = default;
lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData(
@@ -721,7 +703,7 @@ lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData(
success = cus_array->GetItemAtIndexAsString(i, cu);
if (!success) {
error.SetErrorStringWithFormat(
- "SFBM::CFSD: filter cu item %zu not a string.", i);
+ "SFBM::CFSD: filter CU item %zu not a string.", i);
return nullptr;
}
cus.EmplaceBack(cu);
@@ -746,8 +728,11 @@ bool SearchFilterByModuleListAndCU::AddressPasses(Address &address) {
if (m_cu_spec_list.GetSize() != 0)
return false; // Has no comp_unit so can't pass the file check.
}
- if (m_cu_spec_list.FindFileIndex(0, sym_ctx.comp_unit, false) == UINT32_MAX)
- return false; // Fails the file check
+ FileSpec cu_spec;
+ if (sym_ctx.comp_unit)
+ cu_spec = sym_ctx.comp_unit->GetPrimaryFile();
+ if (m_cu_spec_list.FindFileIndex(0, cu_spec, false) == UINT32_MAX)
+ return false; // Fails the file check
return SearchFilterByModuleList::ModulePasses(sym_ctx.module_sp);
}
@@ -756,17 +741,16 @@ bool SearchFilterByModuleListAndCU::CompUnitPasses(FileSpec &fileSpec) {
}
bool SearchFilterByModuleListAndCU::CompUnitPasses(CompileUnit &compUnit) {
- bool in_cu_list =
- m_cu_spec_list.FindFileIndex(0, compUnit, false) != UINT32_MAX;
- if (in_cu_list) {
- ModuleSP module_sp(compUnit.GetModule());
- if (module_sp) {
- bool module_passes = SearchFilterByModuleList::ModulePasses(module_sp);
- return module_passes;
- } else
- return true;
- } else
+ bool in_cu_list = m_cu_spec_list.FindFileIndex(0, compUnit.GetPrimaryFile(),
+ false) != UINT32_MAX;
+ if (!in_cu_list)
return false;
+
+ ModuleSP module_sp(compUnit.GetModule());
+ if (!module_sp)
+ return true;
+
+ return SearchFilterByModuleList::ModulePasses(module_sp);
}
void SearchFilterByModuleListAndCU::Search(Searcher &searcher) {
@@ -791,32 +775,34 @@ void SearchFilterByModuleListAndCU::Search(Searcher &searcher) {
bool no_modules_in_filter = m_module_spec_list.GetSize() == 0;
for (size_t i = 0; i < num_modules; i++) {
lldb::ModuleSP module_sp = target_images.GetModuleAtIndexUnlocked(i);
- if (no_modules_in_filter ||
- m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) !=
- UINT32_MAX) {
- SymbolContext matchingContext(m_target_sp, module_sp);
- Searcher::CallbackReturn shouldContinue;
+ if (!no_modules_in_filter &&
+ m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) ==
+ UINT32_MAX)
+ continue;
- if (searcher.GetDepth() == lldb::eSearchDepthModule) {
- shouldContinue = DoModuleIteration(matchingContext, searcher);
- if (shouldContinue == Searcher::eCallbackReturnStop)
- return;
- } else {
- const size_t num_cu = module_sp->GetNumCompileUnits();
- for (size_t cu_idx = 0; cu_idx < num_cu; cu_idx++) {
- CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(cu_idx);
- matchingContext.comp_unit = cu_sp.get();
- if (matchingContext.comp_unit) {
- if (m_cu_spec_list.FindFileIndex(0, *matchingContext.comp_unit,
- false) != UINT32_MAX) {
- shouldContinue =
- DoCUIteration(module_sp, matchingContext, searcher);
- if (shouldContinue == Searcher::eCallbackReturnStop)
- return;
- }
- }
- }
- }
+ SymbolContext matchingContext(m_target_sp, module_sp);
+ Searcher::CallbackReturn shouldContinue;
+
+ if (searcher.GetDepth() == lldb::eSearchDepthModule) {
+ shouldContinue = DoModuleIteration(matchingContext, searcher);
+ if (shouldContinue == Searcher::eCallbackReturnStop)
+ return;
+ continue;
+ }
+
+ const size_t num_cu = module_sp->GetNumCompileUnits();
+ for (size_t cu_idx = 0; cu_idx < num_cu; cu_idx++) {
+ CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(cu_idx);
+ matchingContext.comp_unit = cu_sp.get();
+ if (!matchingContext.comp_unit)
+ continue;
+ if (m_cu_spec_list.FindFileIndex(
+ 0, matchingContext.comp_unit->GetPrimaryFile(), false) ==
+ UINT32_MAX)
+ continue;
+ shouldContinue = DoCUIteration(module_sp, matchingContext, searcher);
+ if (shouldContinue == Searcher::eCallbackReturnStop)
+ return;
}
}
}
diff --git a/lldb/source/Core/Section.cpp b/lldb/source/Core/Section.cpp
index 7615dc1d65c7..1697f1f7a5d4 100644
--- a/lldb/source/Core/Section.cpp
+++ b/lldb/source/Core/Section.cpp
@@ -80,8 +80,12 @@ const char *Section::GetTypeAsCString() const {
return "dwarf-line-str";
case eSectionTypeDWARFDebugLoc:
return "dwarf-loc";
+ case eSectionTypeDWARFDebugLocDwo:
+ return "dwarf-loc-dwo";
case eSectionTypeDWARFDebugLocLists:
return "dwarf-loclists";
+ case eSectionTypeDWARFDebugLocListsDwo:
+ return "dwarf-loclists-dwo";
case eSectionTypeDWARFDebugMacInfo:
return "dwarf-macinfo";
case eSectionTypeDWARFDebugMacro:
@@ -94,6 +98,8 @@ const char *Section::GetTypeAsCString() const {
return "dwarf-ranges";
case eSectionTypeDWARFDebugRngLists:
return "dwarf-rnglists";
+ case eSectionTypeDWARFDebugRngListsDwo:
+ return "dwarf-rnglists-dwo";
case eSectionTypeDWARFDebugStr:
return "dwarf-str";
case eSectionTypeDWARFDebugStrDwo:
@@ -278,29 +284,6 @@ bool Section::ContainsFileAddress(addr_t vm_addr) const {
return false;
}
-int Section::Compare(const Section &a, const Section &b) {
- if (&a == &b)
- return 0;
-
- const ModuleSP a_module_sp = a.GetModule();
- const ModuleSP b_module_sp = b.GetModule();
- if (a_module_sp == b_module_sp) {
- user_id_t a_sect_uid = a.GetID();
- user_id_t b_sect_uid = b.GetID();
- if (a_sect_uid < b_sect_uid)
- return -1;
- if (a_sect_uid > b_sect_uid)
- return 1;
- return 0;
- } else {
- // The modules are different, just compare the module pointers
- if (a_module_sp.get() < b_module_sp.get())
- return -1;
- else
- return 1; // We already know the modules aren't equal
- }
-}
-
void Section::Dump(Stream *s, Target *target, uint32_t depth) const {
// s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
s->Indent();
@@ -321,7 +304,7 @@ void Section::Dump(Stream *s, Target *target, uint32_t depth) const {
}
VMRange range(addr, addr + m_byte_size);
- range.Dump(s, 0);
+ range.Dump(s->AsRawOstream(), 0);
}
s->Printf("%c %c%c%c 0x%8.8" PRIx64 " 0x%8.8" PRIx64 " 0x%8.8x ",
diff --git a/lldb/source/Core/SourceManager.cpp b/lldb/source/Core/SourceManager.cpp
index 42741e4ba4fe..8e0cc57f80c1 100644
--- a/lldb/source/Core/SourceManager.cpp
+++ b/lldb/source/Core/SourceManager.cpp
@@ -64,7 +64,8 @@ SourceManager::~SourceManager() {}
SourceManager::FileSP SourceManager::GetFile(const FileSpec &file_spec) {
bool same_as_previous =
- m_last_file_sp && m_last_file_sp->FileSpecMatches(file_spec);
+ m_last_file_sp &&
+ FileSpec::Match(file_spec, m_last_file_sp->GetFileSpec());
DebuggerSP debugger_sp(m_debugger_wp.lock());
FileSP file_sp;
@@ -399,24 +400,25 @@ void SourceManager::File::CommonInitializer(const FileSpec &file_spec,
if (num_matches != 0) {
if (num_matches > 1) {
SymbolContext sc;
- FileSpec *test_cu_spec = nullptr;
+ CompileUnit *test_cu = nullptr;
for (unsigned i = 0; i < num_matches; i++) {
sc_list.GetContextAtIndex(i, sc);
if (sc.comp_unit) {
- if (test_cu_spec) {
- if (test_cu_spec != static_cast<FileSpec *>(sc.comp_unit))
+ if (test_cu) {
+ if (test_cu != sc.comp_unit)
got_multiple = true;
break;
} else
- test_cu_spec = sc.comp_unit;
+ test_cu = sc.comp_unit;
}
}
}
if (!got_multiple) {
SymbolContext sc;
sc_list.GetContextAtIndex(0, sc);
- m_file_spec = sc.comp_unit;
+ if (sc.comp_unit)
+ m_file_spec = sc.comp_unit->GetPrimaryFile();
m_mod_time = FileSystem::Instance().GetModificationTime(m_file_spec);
}
}
@@ -601,10 +603,6 @@ void SourceManager::File::FindLinesMatchingRegex(
}
}
-bool SourceManager::File::FileSpecMatches(const FileSpec &file_spec) {
- return FileSpec::Equal(m_file_spec, file_spec, false);
-}
-
bool lldb_private::operator==(const SourceManager::File &lhs,
const SourceManager::File &rhs) {
if (lhs.m_file_spec != rhs.m_file_spec)
diff --git a/lldb/source/Core/StreamFile.cpp b/lldb/source/Core/StreamFile.cpp
index 2ddb39659d66..475c27ec4117 100644
--- a/lldb/source/Core/StreamFile.cpp
+++ b/lldb/source/Core/StreamFile.cpp
@@ -15,9 +15,6 @@
using namespace lldb;
using namespace lldb_private;
-// StreamFile constructor
-StreamFile::StreamFile() : Stream() { m_file_sp = std::make_shared<File>(); }
-
StreamFile::StreamFile(uint32_t flags, uint32_t addr_size, ByteOrder byte_order)
: Stream(flags, addr_size, byte_order) {
m_file_sp = std::make_shared<File>();
@@ -32,20 +29,6 @@ StreamFile::StreamFile(FILE *fh, bool transfer_ownership) : Stream() {
m_file_sp = std::make_shared<NativeFile>(fh, transfer_ownership);
}
-StreamFile::StreamFile(const char *path) : Stream() {
- auto file = FileSystem::Instance().Open(
- FileSpec(path), File::eOpenOptionWrite | File::eOpenOptionCanCreate |
- File::eOpenOptionCloseOnExec);
- if (file)
- m_file_sp = std::move(file.get());
- else {
- // TODO refactor this so the error gets popagated up instead of logged here.
- LLDB_LOG_ERROR(GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), file.takeError(),
- "Cannot open {1}: {0}", path);
- m_file_sp = std::make_shared<File>();
- }
-}
-
StreamFile::StreamFile(const char *path, File::OpenOptions options,
uint32_t permissions)
: Stream() {
diff --git a/lldb/source/Core/Value.cpp b/lldb/source/Core/Value.cpp
index 3124b9338b36..c70ab98dcdfa 100644
--- a/lldb/source/Core/Value.cpp
+++ b/lldb/source/Core/Value.cpp
@@ -322,6 +322,12 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
AddressType address_type = eAddressTypeFile;
Address file_so_addr;
const CompilerType &ast_type = GetCompilerType();
+ llvm::Optional<uint64_t> type_size = ast_type.GetByteSize(
+ exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr);
+ // Nothing to be done for a zero-sized type.
+ if (type_size && *type_size == 0)
+ return error;
+
switch (m_value_type) {
case eValueTypeVector:
if (ast_type.IsValid())
@@ -340,9 +346,8 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
uint32_t limit_byte_size = UINT32_MAX;
- if (llvm::Optional<uint64_t> size = ast_type.GetByteSize(
- exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr))
- limit_byte_size = *size;
+ if (type_size)
+ limit_byte_size = *type_size;
if (limit_byte_size <= m_value.GetByteSize()) {
if (m_value.GetData(data, limit_byte_size))
@@ -507,10 +512,10 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
return error;
}
- // If we got here, we need to read the value from memory
+ // If we got here, we need to read the value from memory.
size_t byte_size = GetValueByteSize(&error, exe_ctx);
- // Bail if we encountered any errors getting the byte size
+ // Bail if we encountered any errors getting the byte size.
if (error.Fail())
return error;
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index 74176eeace3a..1dd9a6cf62c3 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -22,9 +22,9 @@
#include "lldb/DataFormatters/StringPrinter.h"
#include "lldb/DataFormatters/TypeFormat.h"
#include "lldb/DataFormatters/TypeSummary.h"
-#include "lldb/DataFormatters/TypeValidator.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Expression/ExpressionVariable.h"
+#include "lldb/Host/Config.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/CompilerType.h"
@@ -82,13 +82,12 @@ ValueObject::ValueObject(ValueObject &parent)
m_parent(&parent), m_root(nullptr),
m_update_point(parent.GetUpdatePoint()), m_name(), m_data(), m_value(),
m_error(), m_value_str(), m_old_value_str(), m_location_str(),
- m_summary_str(), m_object_desc_str(), m_validation_result(),
- m_manager(parent.GetManager()), m_children(), m_synthetic_children(),
- m_dynamic_value(nullptr), m_synthetic_value(nullptr),
- m_deref_valobj(nullptr), m_format(eFormatDefault),
- m_last_format(eFormatDefault), m_last_format_mgr_revision(0),
- m_type_summary_sp(), m_type_format_sp(), m_synthetic_children_sp(),
- m_type_validator_sp(), m_user_id_of_forced_summary(),
+ m_summary_str(), m_object_desc_str(), m_manager(parent.GetManager()),
+ m_children(), m_synthetic_children(), m_dynamic_value(nullptr),
+ m_synthetic_value(nullptr), m_deref_valobj(nullptr),
+ m_format(eFormatDefault), m_last_format(eFormatDefault),
+ m_last_format_mgr_revision(0), m_type_summary_sp(), m_type_format_sp(),
+ m_synthetic_children_sp(), m_user_id_of_forced_summary(),
m_address_type_of_ptr_or_ref_children(eAddressTypeInvalid),
m_value_checksum(),
m_preferred_display_language(lldb::eLanguageTypeUnknown),
@@ -100,6 +99,8 @@ ValueObject::ValueObject(ValueObject &parent)
m_did_calculate_complete_objc_class_type(false),
m_is_synthetic_children_generated(
parent.m_is_synthetic_children_generated) {
+ m_data.SetByteOrder(parent.GetDataExtractor().GetByteOrder());
+ m_data.SetAddressByteSize(parent.GetDataExtractor().GetAddressByteSize());
m_manager->ManageObject(this);
}
@@ -110,12 +111,12 @@ ValueObject::ValueObject(ExecutionContextScope *exe_scope,
m_parent(nullptr), m_root(nullptr), m_update_point(exe_scope), m_name(),
m_data(), m_value(), m_error(), m_value_str(), m_old_value_str(),
m_location_str(), m_summary_str(), m_object_desc_str(),
- m_validation_result(), m_manager(), m_children(), m_synthetic_children(),
+ m_manager(), m_children(), m_synthetic_children(),
m_dynamic_value(nullptr), m_synthetic_value(nullptr),
m_deref_valobj(nullptr), m_format(eFormatDefault),
m_last_format(eFormatDefault), m_last_format_mgr_revision(0),
m_type_summary_sp(), m_type_format_sp(), m_synthetic_children_sp(),
- m_type_validator_sp(), m_user_id_of_forced_summary(),
+ m_user_id_of_forced_summary(),
m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type),
m_value_checksum(),
m_preferred_display_language(lldb::eLanguageTypeUnknown),
@@ -126,6 +127,14 @@ ValueObject::ValueObject(ExecutionContextScope *exe_scope,
m_is_getting_summary(false),
m_did_calculate_complete_objc_class_type(false),
m_is_synthetic_children_generated(false) {
+ if (exe_scope) {
+ TargetSP target_sp(exe_scope->CalculateTarget());
+ if (target_sp) {
+ const ArchSpec &arch = target_sp->GetArchitecture();
+ m_data.SetByteOrder(arch.GetByteOrder());
+ m_data.SetAddressByteSize(arch.GetAddressByteSize());
+ }
+ }
m_manager = new ValueObjectManager();
m_manager->ManageObject(this);
}
@@ -133,6 +142,58 @@ ValueObject::ValueObject(ExecutionContextScope *exe_scope,
// Destructor
ValueObject::~ValueObject() {}
+void ValueObject::UpdateChildrenAddressType() {
+ Value::ValueType value_type = m_value.GetValueType();
+ ExecutionContext exe_ctx(GetExecutionContextRef());
+ Process *process = exe_ctx.GetProcessPtr();
+ const bool process_is_alive = process && process->IsAlive();
+ const uint32_t type_info = GetCompilerType().GetTypeInfo();
+ const bool is_pointer_or_ref =
+ (type_info & (lldb::eTypeIsPointer | lldb::eTypeIsReference)) != 0;
+
+ switch (value_type) {
+ case Value::eValueTypeFileAddress:
+ // If this type is a pointer, then its children will be considered load
+ // addresses if the pointer or reference is dereferenced, but only if
+ // the process is alive.
+ //
+ // There could be global variables like in the following code:
+ // struct LinkedListNode { Foo* foo; LinkedListNode* next; };
+ // Foo g_foo1;
+ // Foo g_foo2;
+ // LinkedListNode g_second_node = { &g_foo2, NULL };
+ // LinkedListNode g_first_node = { &g_foo1, &g_second_node };
+ //
+ // When we aren't running, we should be able to look at these variables
+ // using the "target variable" command. Children of the "g_first_node"
+ // always will be of the same address type as the parent. But children
+ // of the "next" member of LinkedListNode will become load addresses if
+ // we have a live process, or remain a file address if it was a file
+ // address.
+ if (process_is_alive && is_pointer_or_ref)
+ SetAddressTypeOfChildren(eAddressTypeLoad);
+ else
+ SetAddressTypeOfChildren(eAddressTypeFile);
+ break;
+ case Value::eValueTypeHostAddress:
+ // Same as above for load addresses, except children of pointer or refs
+ // are always load addresses. Host addresses are used to store freeze
+ // dried variables. If this type is a struct, the entire struct
+ // contents will be copied into the heap of the
+ // LLDB process, but we do not currently follow any pointers.
+ if (is_pointer_or_ref)
+ SetAddressTypeOfChildren(eAddressTypeLoad);
+ else
+ SetAddressTypeOfChildren(eAddressTypeHost);
+ break;
+ case Value::eValueTypeLoadAddress:
+ case Value::eValueTypeScalar:
+ case Value::eValueTypeVector:
+ SetAddressTypeOfChildren(eAddressTypeLoad);
+ break;
+ }
+}
+
bool ValueObject::UpdateValueIfNeeded(bool update_format) {
bool did_change_formats = false;
@@ -195,6 +256,7 @@ bool ValueObject::UpdateValueIfNeeded(bool update_format) {
SetValueIsValid(success);
if (success) {
+ UpdateChildrenAddressType();
const uint64_t max_checksum_size = 128;
m_data.Checksum(m_value_checksum, max_checksum_size);
} else {
@@ -241,11 +303,10 @@ bool ValueObject::UpdateFormatsIfNeeded() {
SetValueFormat(DataVisualization::GetFormat(*this, eNoDynamicValues));
SetSummaryFormat(
DataVisualization::GetSummaryFormat(*this, GetDynamicValueType()));
-#ifndef LLDB_DISABLE_PYTHON
+#if LLDB_ENABLE_PYTHON
SetSyntheticChildren(
DataVisualization::GetSyntheticChildren(*this, GetDynamicValueType()));
#endif
- SetValidator(DataVisualization::GetValidator(*this, GetDynamicValueType()));
}
return any_change;
@@ -526,6 +587,10 @@ ValueObjectSP ValueObject::GetChildMemberWithName(ConstString name,
std::vector<uint32_t> child_indexes;
bool omit_empty_base_classes = true;
+
+ if (!GetCompilerType().IsValid())
+ return ValueObjectSP();
+
const size_t num_child_indexes =
GetCompilerType().GetIndexOfChildMemberWithName(
name.GetCString(), omit_empty_base_classes, child_indexes);
@@ -1037,23 +1102,6 @@ ValueObject::ReadPointedString(lldb::DataBufferSP &buffer_sp, Status &error,
return {total_bytes_read, was_capped};
}
-std::pair<TypeValidatorResult, std::string> ValueObject::GetValidationStatus() {
- if (!UpdateValueIfNeeded(true))
- return {TypeValidatorResult::Success,
- ""}; // not the validator's job to discuss update problems
-
- if (m_validation_result.hasValue())
- return m_validation_result.getValue();
-
- if (!m_type_validator_sp)
- return {TypeValidatorResult::Success, ""}; // no validator no failure
-
- auto outcome = m_type_validator_sp->FormatObject(this);
-
- return (m_validation_result = {outcome.m_result, outcome.m_message})
- .getValue();
-}
-
const char *ValueObject::GetObjectDescription() {
if (!UpdateValueIfNeeded(true))
return nullptr;
@@ -1970,15 +2018,14 @@ bool ValueObject::GetBaseClassPath(Stream &s) {
bool parent_had_base_class =
GetParent() && GetParent()->GetBaseClassPath(s);
CompilerType compiler_type = GetCompilerType();
- std::string cxx_class_name;
- bool this_had_base_class =
- ClangASTContext::GetCXXClassName(compiler_type, cxx_class_name);
- if (this_had_base_class) {
+ llvm::Optional<std::string> cxx_class_name =
+ ClangASTContext::GetCXXClassName(compiler_type);
+ if (cxx_class_name) {
if (parent_had_base_class)
s.PutCString("::");
- s.PutCString(cxx_class_name);
+ s.PutCString(cxx_class_name.getValue());
}
- return parent_had_base_class || this_had_base_class;
+ return parent_had_base_class || cxx_class_name;
}
return false;
}
@@ -3063,10 +3110,6 @@ void ValueObject::ClearUserVisibleData(uint32_t clear_mask) {
if (m_synthetic_value)
m_synthetic_value = nullptr;
}
-
- if ((clear_mask & eClearUserVisibleDataItemsValidator) ==
- eClearUserVisibleDataItemsValidator)
- m_validation_result.reset();
}
SymbolContextScope *ValueObject::GetSymbolContextScope() {
diff --git a/lldb/source/Core/ValueObjectSyntheticFilter.cpp b/lldb/source/Core/ValueObjectSyntheticFilter.cpp
index a6bf35eac70a..a30be1b08338 100644
--- a/lldb/source/Core/ValueObjectSyntheticFilter.cpp
+++ b/lldb/source/Core/ValueObjectSyntheticFilter.cpp
@@ -48,8 +48,9 @@ public:
ValueObjectSynthetic::ValueObjectSynthetic(ValueObject &parent,
lldb::SyntheticChildrenSP filter)
: ValueObject(parent), m_synth_sp(filter), m_children_byindex(),
- m_name_toindex(), m_synthetic_children_count(UINT32_MAX),
- m_synthetic_children_cache(), m_parent_type_name(parent.GetTypeName()),
+ m_name_toindex(), m_synthetic_children_cache(),
+ m_synthetic_children_count(UINT32_MAX),
+ m_parent_type_name(parent.GetTypeName()),
m_might_have_children(eLazyBoolCalculate),
m_provides_value(eLazyBoolCalculate) {
SetName(parent.GetName());
@@ -177,14 +178,20 @@ bool ValueObjectSynthetic::UpdateValue() {
"filter said caches are stale - clearing",
GetName().AsCString());
// filter said that cached values are stale
- m_children_byindex.Clear();
- m_name_toindex.Clear();
+ {
+ std::lock_guard<std::mutex> guard(m_child_mutex);
+ m_children_byindex.clear();
+ m_name_toindex.clear();
+ }
// usually, an object's value can change but this does not alter its
// children count for a synthetic VO that might indeed happen, so we need
// to tell the upper echelons that they need to come back to us asking for
// children
m_children_count_valid = false;
- m_synthetic_children_cache.Clear();
+ {
+ std::lock_guard<std::mutex> guard(m_child_mutex);
+ m_synthetic_children_cache.clear();
+ }
m_synthetic_children_count = UINT32_MAX;
m_might_have_children = eLazyBoolCalculate;
} else {
@@ -232,7 +239,16 @@ lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex(size_t idx,
UpdateValueIfNeeded();
ValueObject *valobj;
- if (!m_children_byindex.GetValueForKey(idx, valobj)) {
+ bool child_is_cached;
+ {
+ std::lock_guard<std::mutex> guard(m_child_mutex);
+ auto cached_child_it = m_children_byindex.find(idx);
+ child_is_cached = cached_child_it != m_children_byindex.end();
+ if (child_is_cached)
+ valobj = cached_child_it->second;
+ }
+
+ if (!child_is_cached) {
if (can_create && m_synth_filter_up != nullptr) {
LLDB_LOGF(log,
"[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at "
@@ -254,9 +270,12 @@ lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex(size_t idx,
if (!synth_guy)
return synth_guy;
- if (synth_guy->IsSyntheticChildrenGenerated())
- m_synthetic_children_cache.AppendObject(synth_guy);
- m_children_byindex.SetValueForKey(idx, synth_guy.get());
+ {
+ std::lock_guard<std::mutex> guard(m_child_mutex);
+ if (synth_guy->IsSyntheticChildrenGenerated())
+ m_synthetic_children_cache.push_back(synth_guy);
+ m_children_byindex[idx] = synth_guy.get();
+ }
synth_guy->SetPreferredDisplayLanguageIfNeeded(
GetPreferredDisplayLanguage());
return synth_guy;
@@ -297,13 +316,21 @@ size_t ValueObjectSynthetic::GetIndexOfChildWithName(ConstString name) {
UpdateValueIfNeeded();
uint32_t found_index = UINT32_MAX;
- bool did_find = m_name_toindex.GetValueForKey(name.GetCString(), found_index);
+ bool did_find;
+ {
+ std::lock_guard<std::mutex> guard(m_child_mutex);
+ auto name_to_index = m_name_toindex.find(name.GetCString());
+ did_find = name_to_index != m_name_toindex.end();
+ if (did_find)
+ found_index = name_to_index->second;
+ }
if (!did_find && m_synth_filter_up != nullptr) {
uint32_t index = m_synth_filter_up->GetIndexOfChildWithName(name);
if (index == UINT32_MAX)
return index;
- m_name_toindex.SetValueForKey(name.GetCString(), index);
+ std::lock_guard<std::mutex> guard(m_child_mutex);
+ m_name_toindex[name.GetCString()] = index;
return index;
} else if (!did_find && m_synth_filter_up == nullptr)
return UINT32_MAX;
diff --git a/lldb/source/Core/ValueObjectVariable.cpp b/lldb/source/Core/ValueObjectVariable.cpp
index 33f9d5410843..240ebe1fdff3 100644
--- a/lldb/source/Core/ValueObjectVariable.cpp
+++ b/lldb/source/Core/ValueObjectVariable.cpp
@@ -168,51 +168,6 @@ bool ValueObjectVariable::UpdateValue() {
Process *process = exe_ctx.GetProcessPtr();
const bool process_is_alive = process && process->IsAlive();
- const uint32_t type_info = compiler_type.GetTypeInfo();
- const bool is_pointer_or_ref =
- (type_info & (lldb::eTypeIsPointer | lldb::eTypeIsReference)) != 0;
-
- switch (value_type) {
- case Value::eValueTypeFileAddress:
- // If this type is a pointer, then its children will be considered load
- // addresses if the pointer or reference is dereferenced, but only if
- // the process is alive.
- //
- // There could be global variables like in the following code:
- // struct LinkedListNode { Foo* foo; LinkedListNode* next; };
- // Foo g_foo1;
- // Foo g_foo2;
- // LinkedListNode g_second_node = { &g_foo2, NULL };
- // LinkedListNode g_first_node = { &g_foo1, &g_second_node };
- //
- // When we aren't running, we should be able to look at these variables
- // using the "target variable" command. Children of the "g_first_node"
- // always will be of the same address type as the parent. But children
- // of the "next" member of LinkedListNode will become load addresses if
- // we have a live process, or remain what a file address if it what a
- // file address.
- if (process_is_alive && is_pointer_or_ref)
- SetAddressTypeOfChildren(eAddressTypeLoad);
- else
- SetAddressTypeOfChildren(eAddressTypeFile);
- break;
- case Value::eValueTypeHostAddress:
- // Same as above for load addresses, except children of pointer or refs
- // are always load addresses. Host addresses are used to store freeze
- // dried variables. If this type is a struct, the entire struct
- // contents will be copied into the heap of the
- // LLDB process, but we do not currently follow any pointers.
- if (is_pointer_or_ref)
- SetAddressTypeOfChildren(eAddressTypeLoad);
- else
- SetAddressTypeOfChildren(eAddressTypeHost);
- break;
- case Value::eValueTypeLoadAddress:
- case Value::eValueTypeScalar:
- case Value::eValueTypeVector:
- SetAddressTypeOfChildren(eAddressTypeLoad);
- break;
- }
switch (value_type) {
case Value::eValueTypeVector:
diff --git a/lldb/source/DataFormatters/DataVisualization.cpp b/lldb/source/DataFormatters/DataVisualization.cpp
index 08b3b34447bb..99c303c9f0b1 100644
--- a/lldb/source/DataFormatters/DataVisualization.cpp
+++ b/lldb/source/DataFormatters/DataVisualization.cpp
@@ -66,17 +66,6 @@ DataVisualization::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp) {
return GetFormatManager().GetSyntheticForType(type_sp);
}
-lldb::TypeValidatorImplSP
-DataVisualization::GetValidator(ValueObject &valobj,
- lldb::DynamicValueType use_dynamic) {
- return GetFormatManager().GetValidator(valobj, use_dynamic);
-}
-
-lldb::TypeValidatorImplSP
-DataVisualization::GetValidatorForType(lldb::TypeNameSpecifierImplSP type_sp) {
- return GetFormatManager().GetValidatorForType(type_sp);
-}
-
bool DataVisualization::AnyMatches(
ConstString type_name, TypeCategoryImpl::FormatCategoryItems items,
bool only_enabled, const char **matching_category,
@@ -122,8 +111,7 @@ void DataVisualization::Categories::Enable(ConstString category,
TypeCategoryMap::Position pos) {
if (GetFormatManager().GetCategory(category)->IsEnabled())
GetFormatManager().DisableCategory(category);
- GetFormatManager().EnableCategory(
- category, pos, std::initializer_list<lldb::LanguageType>());
+ GetFormatManager().EnableCategory(category, pos, {});
}
void DataVisualization::Categories::Enable(lldb::LanguageType lang_type) {
diff --git a/lldb/source/DataFormatters/FormatCache.cpp b/lldb/source/DataFormatters/FormatCache.cpp
index 7e328cb0dac8..231e7ed0c0a0 100644
--- a/lldb/source/DataFormatters/FormatCache.cpp
+++ b/lldb/source/DataFormatters/FormatCache.cpp
@@ -17,46 +17,7 @@ using namespace lldb_private;
FormatCache::Entry::Entry()
: m_format_cached(false), m_summary_cached(false),
- m_synthetic_cached(false), m_validator_cached(false), m_format_sp(),
- m_summary_sp(), m_synthetic_sp(), m_validator_sp() {}
-
-FormatCache::Entry::Entry(lldb::TypeFormatImplSP format_sp)
- : m_summary_cached(false), m_synthetic_cached(false),
- m_validator_cached(false), m_summary_sp(), m_synthetic_sp(),
- m_validator_sp() {
- SetFormat(format_sp);
-}
-
-FormatCache::Entry::Entry(lldb::TypeSummaryImplSP summary_sp)
- : m_format_cached(false), m_synthetic_cached(false),
- m_validator_cached(false), m_format_sp(), m_synthetic_sp(),
- m_validator_sp() {
- SetSummary(summary_sp);
-}
-
-FormatCache::Entry::Entry(lldb::SyntheticChildrenSP synthetic_sp)
- : m_format_cached(false), m_summary_cached(false),
- m_validator_cached(false), m_format_sp(), m_summary_sp(),
- m_validator_sp() {
- SetSynthetic(synthetic_sp);
-}
-
-FormatCache::Entry::Entry(lldb::TypeValidatorImplSP validator_sp)
- : m_format_cached(false), m_summary_cached(false),
- m_synthetic_cached(false), m_format_sp(), m_summary_sp(),
- m_synthetic_sp() {
- SetValidator(validator_sp);
-}
-
-FormatCache::Entry::Entry(lldb::TypeFormatImplSP format_sp,
- lldb::TypeSummaryImplSP summary_sp,
- lldb::SyntheticChildrenSP synthetic_sp,
- lldb::TypeValidatorImplSP validator_sp) {
- SetFormat(format_sp);
- SetSummary(summary_sp);
- SetSynthetic(synthetic_sp);
- SetValidator(validator_sp);
-}
+ m_synthetic_cached(false) {}
bool FormatCache::Entry::IsFormatCached() { return m_format_cached; }
@@ -64,42 +25,33 @@ bool FormatCache::Entry::IsSummaryCached() { return m_summary_cached; }
bool FormatCache::Entry::IsSyntheticCached() { return m_synthetic_cached; }
-bool FormatCache::Entry::IsValidatorCached() { return m_validator_cached; }
-
-lldb::TypeFormatImplSP FormatCache::Entry::GetFormat() { return m_format_sp; }
-
-lldb::TypeSummaryImplSP FormatCache::Entry::GetSummary() {
- return m_summary_sp;
+void FormatCache::Entry::Get(lldb::TypeFormatImplSP &retval) {
+ retval = m_format_sp;
}
-lldb::SyntheticChildrenSP FormatCache::Entry::GetSynthetic() {
- return m_synthetic_sp;
+void FormatCache::Entry::Get(lldb::TypeSummaryImplSP &retval) {
+ retval = m_summary_sp;
}
-lldb::TypeValidatorImplSP FormatCache::Entry::GetValidator() {
- return m_validator_sp;
+void FormatCache::Entry::Get(lldb::SyntheticChildrenSP &retval) {
+ retval = m_synthetic_sp;
}
-void FormatCache::Entry::SetFormat(lldb::TypeFormatImplSP format_sp) {
+void FormatCache::Entry::Set(lldb::TypeFormatImplSP format_sp) {
m_format_cached = true;
m_format_sp = format_sp;
}
-void FormatCache::Entry::SetSummary(lldb::TypeSummaryImplSP summary_sp) {
+void FormatCache::Entry::Set(lldb::TypeSummaryImplSP summary_sp) {
m_summary_cached = true;
m_summary_sp = summary_sp;
}
-void FormatCache::Entry::SetSynthetic(lldb::SyntheticChildrenSP synthetic_sp) {
+void FormatCache::Entry::Set(lldb::SyntheticChildrenSP synthetic_sp) {
m_synthetic_cached = true;
m_synthetic_sp = synthetic_sp;
}
-void FormatCache::Entry::SetValidator(lldb::TypeValidatorImplSP validator_sp) {
- m_validator_cached = true;
- m_validator_sp = validator_sp;
-}
-
FormatCache::FormatCache()
: m_map(), m_mutex()
#ifdef LLDB_CONFIGURATION_DEBUG
@@ -117,100 +69,60 @@ FormatCache::Entry &FormatCache::GetEntry(ConstString type) {
return m_map[type];
}
-bool FormatCache::GetFormat(ConstString type,
- lldb::TypeFormatImplSP &format_sp) {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- auto entry = GetEntry(type);
- if (entry.IsFormatCached()) {
-#ifdef LLDB_CONFIGURATION_DEBUG
- m_cache_hits++;
-#endif
- format_sp = entry.GetFormat();
- return true;
- }
-#ifdef LLDB_CONFIGURATION_DEBUG
- m_cache_misses++;
-#endif
- format_sp.reset();
- return false;
+template<> bool FormatCache::Entry::IsCached<lldb::TypeFormatImplSP>() {
+ return IsFormatCached();
}
-
-bool FormatCache::GetSummary(ConstString type,
- lldb::TypeSummaryImplSP &summary_sp) {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- auto entry = GetEntry(type);
- if (entry.IsSummaryCached()) {
-#ifdef LLDB_CONFIGURATION_DEBUG
- m_cache_hits++;
-#endif
- summary_sp = entry.GetSummary();
- return true;
- }
-#ifdef LLDB_CONFIGURATION_DEBUG
- m_cache_misses++;
-#endif
- summary_sp.reset();
- return false;
+template<> bool FormatCache::Entry::IsCached<lldb::TypeSummaryImplSP> () {
+ return IsSummaryCached();
}
-
-bool FormatCache::GetSynthetic(ConstString type,
- lldb::SyntheticChildrenSP &synthetic_sp) {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- auto entry = GetEntry(type);
- if (entry.IsSyntheticCached()) {
-#ifdef LLDB_CONFIGURATION_DEBUG
- m_cache_hits++;
-#endif
- synthetic_sp = entry.GetSynthetic();
- return true;
- }
-#ifdef LLDB_CONFIGURATION_DEBUG
- m_cache_misses++;
-#endif
- synthetic_sp.reset();
- return false;
+template<> bool FormatCache::Entry::IsCached<lldb::SyntheticChildrenSP>() {
+ return IsSyntheticCached();
}
-bool FormatCache::GetValidator(ConstString type,
- lldb::TypeValidatorImplSP &validator_sp) {
+template <typename ImplSP>
+bool FormatCache::Get(ConstString type, ImplSP &format_impl_sp) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
auto entry = GetEntry(type);
- if (entry.IsValidatorCached()) {
+ if (entry.IsCached<ImplSP>()) {
#ifdef LLDB_CONFIGURATION_DEBUG
m_cache_hits++;
#endif
- validator_sp = entry.GetValidator();
+ entry.Get(format_impl_sp);
return true;
}
#ifdef LLDB_CONFIGURATION_DEBUG
m_cache_misses++;
#endif
- validator_sp.reset();
+ format_impl_sp.reset();
return false;
}
-void FormatCache::SetFormat(ConstString type,
- lldb::TypeFormatImplSP &format_sp) {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- GetEntry(type).SetFormat(format_sp);
-}
+/// Explicit instantiations for the three types.
+/// \{
+template bool
+FormatCache::Get<lldb::TypeFormatImplSP>(ConstString, lldb::TypeFormatImplSP &);
+template bool
+FormatCache::Get<lldb::TypeSummaryImplSP>(ConstString,
+ lldb::TypeSummaryImplSP &);
+template bool
+FormatCache::Get<lldb::SyntheticChildrenSP>(ConstString,
+ lldb::SyntheticChildrenSP &);
+/// \}
-void FormatCache::SetSummary(ConstString type,
- lldb::TypeSummaryImplSP &summary_sp) {
+void FormatCache::Set(ConstString type, lldb::TypeFormatImplSP &format_sp) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- GetEntry(type).SetSummary(summary_sp);
+ GetEntry(type).Set(format_sp);
}
-void FormatCache::SetSynthetic(ConstString type,
- lldb::SyntheticChildrenSP &synthetic_sp) {
+void FormatCache::Set(ConstString type, lldb::TypeSummaryImplSP &summary_sp) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- GetEntry(type).SetSynthetic(synthetic_sp);
+ GetEntry(type).Set(summary_sp);
}
-void FormatCache::SetValidator(ConstString type,
- lldb::TypeValidatorImplSP &validator_sp) {
+void FormatCache::Set(ConstString type,
+ lldb::SyntheticChildrenSP &synthetic_sp) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- GetEntry(type).SetValidator(validator_sp);
+ GetEntry(type).Set(synthetic_sp);
}
void FormatCache::Clear() {
diff --git a/lldb/source/DataFormatters/FormatClasses.cpp b/lldb/source/DataFormatters/FormatClasses.cpp
index 271963b5f8f4..6a9279f54d64 100644
--- a/lldb/source/DataFormatters/FormatClasses.cpp
+++ b/lldb/source/DataFormatters/FormatClasses.cpp
@@ -24,7 +24,8 @@ FormattersMatchData::FormattersMatchData(ValueObject &valobj,
m_formatters_match_vector({}, false), m_type_for_cache(),
m_candidate_languages() {
m_type_for_cache = FormatManager::GetTypeForCache(valobj, use_dynamic);
- m_candidate_languages = FormatManager::GetCandidateLanguages(valobj);
+ m_candidate_languages =
+ FormatManager::GetCandidateLanguages(valobj.GetObjectRuntimeLanguage());
}
FormattersMatchVector FormattersMatchData::GetMatchesVector() {
diff --git a/lldb/source/DataFormatters/FormatManager.cpp b/lldb/source/DataFormatters/FormatManager.cpp
index 1eac372d79ec..d5db3ee75bf3 100644
--- a/lldb/source/DataFormatters/FormatManager.cpp
+++ b/lldb/source/DataFormatters/FormatManager.cpp
@@ -230,15 +230,38 @@ void FormatManager::GetPossibleMatches(
if (non_ptr_type.IsTypedefType()) {
CompilerType deffed_pointed_type =
non_ptr_type.GetTypedefedType().GetPointerType();
+ const bool stripped_typedef = true;
GetPossibleMatches(
valobj, deffed_pointed_type,
reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
use_dynamic, entries, did_strip_ptr, did_strip_ref,
- true); // this is not exactly the usual meaning of stripping typedefs
+ stripped_typedef); // this is not exactly the usual meaning of
+ // stripping typedefs
+ }
+ }
+
+ // For arrays with typedef-ed elements, we add a candidate with the typedef
+ // stripped.
+ uint64_t array_size;
+ if (compiler_type.IsArrayType(nullptr, &array_size, nullptr)) {
+ CompilerType element_type = compiler_type.GetArrayElementType();
+ if (element_type.IsTypedefType()) {
+ // Get the stripped element type and compute the stripped array type
+ // from it.
+ CompilerType deffed_array_type =
+ element_type.GetTypedefedType().GetArrayType(array_size);
+ const bool stripped_typedef = true;
+ GetPossibleMatches(
+ valobj, deffed_array_type,
+ reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
+ use_dynamic, entries, did_strip_ptr, did_strip_ref,
+ stripped_typedef); // this is not exactly the usual meaning of
+ // stripping typedefs
}
}
- for (lldb::LanguageType language_type : GetCandidateLanguages(valobj)) {
+ for (lldb::LanguageType language_type :
+ GetCandidateLanguages(valobj.GetObjectRuntimeLanguage())) {
if (Language *language = Language::FindPlugin(language_type)) {
for (ConstString candidate :
language->GetPossibleFormattersMatches(valobj, use_dynamic)) {
@@ -385,30 +408,6 @@ FormatManager::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp) {
return synth_chosen_sp;
}
-lldb::TypeValidatorImplSP
-FormatManager::GetValidatorForType(lldb::TypeNameSpecifierImplSP type_sp) {
- if (!type_sp)
- return lldb::TypeValidatorImplSP();
- lldb::TypeValidatorImplSP validator_chosen_sp;
- uint32_t num_categories = m_categories_map.GetCount();
- lldb::TypeCategoryImplSP category_sp;
- uint32_t prio_category = UINT32_MAX;
- for (uint32_t category_id = 0; category_id < num_categories; category_id++) {
- category_sp = GetCategoryAtIndex(category_id);
- if (!category_sp->IsEnabled())
- continue;
- lldb::TypeValidatorImplSP validator_current_sp(
- category_sp->GetValidatorForType(type_sp).get());
- if (validator_current_sp &&
- (validator_chosen_sp.get() == nullptr ||
- (prio_category > category_sp->GetEnabledPosition()))) {
- prio_category = category_sp->GetEnabledPosition();
- validator_chosen_sp = validator_current_sp;
- }
- }
- return validator_chosen_sp;
-}
-
void FormatManager::ForEachCategory(TypeCategoryMap::ForEachCallback callback) {
m_categories_map.ForEach(callback);
std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
@@ -579,12 +578,6 @@ ConstString FormatManager::GetTypeForCache(ValueObject &valobj,
}
std::vector<lldb::LanguageType>
-FormatManager::GetCandidateLanguages(ValueObject &valobj) {
- lldb::LanguageType lang_type = valobj.GetObjectRuntimeLanguage();
- return GetCandidateLanguages(lang_type);
-}
-
-std::vector<lldb::LanguageType>
FormatManager::GetCandidateLanguages(lldb::LanguageType lang_type) {
switch (lang_type) {
case lldb::eLanguageTypeC:
@@ -599,6 +592,7 @@ FormatManager::GetCandidateLanguages(lldb::LanguageType lang_type) {
default:
return {lang_type};
}
+ llvm_unreachable("Fully covered switch");
}
LanguageCategory *
@@ -614,302 +608,93 @@ FormatManager::GetCategoryForLanguage(lldb::LanguageType lang_type) {
return lang_category;
}
-lldb::TypeFormatImplSP
-FormatManager::GetHardcodedFormat(FormattersMatchData &match_data) {
- TypeFormatImplSP retval_sp;
-
+template <typename ImplSP>
+ImplSP FormatManager::GetHardcoded(FormattersMatchData &match_data) {
+ ImplSP retval_sp;
for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
if (lang_category->GetHardcoded(*this, match_data, retval_sp))
- break;
+ return retval_sp;
}
}
-
return retval_sp;
}
-lldb::TypeFormatImplSP
-FormatManager::GetFormat(ValueObject &valobj,
- lldb::DynamicValueType use_dynamic) {
+template <typename ImplSP>
+ImplSP FormatManager::Get(ValueObject &valobj,
+ lldb::DynamicValueType use_dynamic) {
FormattersMatchData match_data(valobj, use_dynamic);
+ if (ImplSP retval_sp = GetCached<ImplSP>(match_data))
+ return retval_sp;
- TypeFormatImplSP retval;
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
- if (match_data.GetTypeForCache()) {
- LLDB_LOGF(log,
- "\n\n[FormatManager::GetFormat] Looking into cache for type %s",
- match_data.GetTypeForCache().AsCString("<invalid>"));
- if (m_format_cache.GetFormat(match_data.GetTypeForCache(), retval)) {
- if (log) {
- LLDB_LOGF(
- log, "[FormatManager::GetFormat] Cache search success. Returning.");
- LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
- m_format_cache.GetCacheHits(),
- m_format_cache.GetCacheMisses());
- }
- return retval;
- }
- LLDB_LOGF(
- log,
- "[FormatManager::GetFormat] Cache search failed. Going normal route");
- }
-
- retval = m_categories_map.GetFormat(match_data);
- if (!retval) {
- LLDB_LOGF(log,
- "[FormatManager::GetFormat] Search failed. Giving language a "
- "chance.");
- for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
- if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
- if (lang_category->Get(match_data, retval))
- break;
- }
- }
- if (retval) {
- LLDB_LOGF(
- log,
- "[FormatManager::GetFormat] Language search success. Returning.");
- return retval;
- }
- }
- if (!retval) {
- LLDB_LOGF(log, "[FormatManager::GetFormat] Search failed. Giving hardcoded "
- "a chance.");
- retval = GetHardcodedFormat(match_data);
- }
-
- if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) {
- LLDB_LOGF(log, "[FormatManager::GetFormat] Caching %p for type %s",
- static_cast<void *>(retval.get()),
- match_data.GetTypeForCache().AsCString("<invalid>"));
- m_format_cache.SetFormat(match_data.GetTypeForCache(), retval);
- }
- LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
- m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
- return retval;
-}
-
-lldb::TypeSummaryImplSP
-FormatManager::GetHardcodedSummaryFormat(FormattersMatchData &match_data) {
- TypeSummaryImplSP retval_sp;
+ LLDB_LOGF(log, "[%s] Search failed. Giving language a chance.", __FUNCTION__);
for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
- if (lang_category->GetHardcoded(*this, match_data, retval_sp))
- break;
+ ImplSP retval_sp;
+ if (lang_category->Get(match_data, retval_sp))
+ if (retval_sp) {
+ LLDB_LOGF(log, "[%s] Language search success. Returning.",
+ __FUNCTION__);
+ return retval_sp;
+ }
}
}
- return retval_sp;
+ LLDB_LOGF(log, "[%s] Search failed. Giving hardcoded a chance.",
+ __FUNCTION__);
+ return GetHardcoded<ImplSP>(match_data);
}
-lldb::TypeSummaryImplSP
-FormatManager::GetSummaryFormat(ValueObject &valobj,
- lldb::DynamicValueType use_dynamic) {
- FormattersMatchData match_data(valobj, use_dynamic);
-
- TypeSummaryImplSP retval;
+template <typename ImplSP>
+ImplSP FormatManager::GetCached(FormattersMatchData &match_data) {
+ ImplSP retval_sp;
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
if (match_data.GetTypeForCache()) {
- LLDB_LOGF(log,
- "\n\n[FormatManager::GetSummaryFormat] Looking into cache "
- "for type %s",
+ LLDB_LOGF(log, "\n\n[%s] Looking into cache for type %s", __FUNCTION__,
match_data.GetTypeForCache().AsCString("<invalid>"));
- if (m_format_cache.GetSummary(match_data.GetTypeForCache(), retval)) {
+ if (m_format_cache.Get(match_data.GetTypeForCache(), retval_sp)) {
if (log) {
- LLDB_LOGF(log,
- "[FormatManager::GetSummaryFormat] Cache search success. "
- "Returning.");
+ LLDB_LOGF(log, "[%s] Cache search success. Returning.", __FUNCTION__);
LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
m_format_cache.GetCacheHits(),
m_format_cache.GetCacheMisses());
}
- return retval;
+ return retval_sp;
}
- LLDB_LOGF(log, "[FormatManager::GetSummaryFormat] Cache search failed. "
- "Going normal route");
+ LLDB_LOGF(log, "[%s] Cache search failed. Going normal route",
+ __FUNCTION__);
}
- retval = m_categories_map.GetSummaryFormat(match_data);
- if (!retval) {
- LLDB_LOGF(log, "[FormatManager::GetSummaryFormat] Search failed. Giving "
- "language a chance.");
- for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
- if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
- if (lang_category->Get(match_data, retval))
- break;
- }
- }
- if (retval) {
- LLDB_LOGF(log, "[FormatManager::GetSummaryFormat] Language search "
- "success. Returning.");
- return retval;
- }
- }
- if (!retval) {
- LLDB_LOGF(log, "[FormatManager::GetSummaryFormat] Search failed. Giving "
- "hardcoded a chance.");
- retval = GetHardcodedSummaryFormat(match_data);
- }
-
- if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) {
- LLDB_LOGF(log, "[FormatManager::GetSummaryFormat] Caching %p for type %s",
- static_cast<void *>(retval.get()),
+ m_categories_map.Get(match_data, retval_sp);
+ if (match_data.GetTypeForCache() && (!retval_sp || !retval_sp->NonCacheable())) {
+ LLDB_LOGF(log, "[%s] Caching %p for type %s", __FUNCTION__,
+ static_cast<void *>(retval_sp.get()),
match_data.GetTypeForCache().AsCString("<invalid>"));
- m_format_cache.SetSummary(match_data.GetTypeForCache(), retval);
+ m_format_cache.Set(match_data.GetTypeForCache(), retval_sp);
}
LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
- return retval;
+ return retval_sp;
}
-lldb::SyntheticChildrenSP
-FormatManager::GetHardcodedSyntheticChildren(FormattersMatchData &match_data) {
- SyntheticChildrenSP retval_sp;
-
- for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
- if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
- if (lang_category->GetHardcoded(*this, match_data, retval_sp))
- break;
- }
- }
+lldb::TypeFormatImplSP
+FormatManager::GetFormat(ValueObject &valobj,
+ lldb::DynamicValueType use_dynamic) {
+ return Get<lldb::TypeFormatImplSP>(valobj, use_dynamic);
+}
- return retval_sp;
+lldb::TypeSummaryImplSP
+FormatManager::GetSummaryFormat(ValueObject &valobj,
+ lldb::DynamicValueType use_dynamic) {
+ return Get<lldb::TypeSummaryImplSP>(valobj, use_dynamic);
}
lldb::SyntheticChildrenSP
FormatManager::GetSyntheticChildren(ValueObject &valobj,
lldb::DynamicValueType use_dynamic) {
- FormattersMatchData match_data(valobj, use_dynamic);
-
- SyntheticChildrenSP retval;
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
- if (match_data.GetTypeForCache()) {
- LLDB_LOGF(log,
- "\n\n[FormatManager::GetSyntheticChildren] Looking into "
- "cache for type %s",
- match_data.GetTypeForCache().AsCString("<invalid>"));
- if (m_format_cache.GetSynthetic(match_data.GetTypeForCache(), retval)) {
- if (log) {
- LLDB_LOGF(log, "[FormatManager::GetSyntheticChildren] Cache search "
- "success. Returning.");
- LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
- m_format_cache.GetCacheHits(),
- m_format_cache.GetCacheMisses());
- }
- return retval;
- }
- LLDB_LOGF(log, "[FormatManager::GetSyntheticChildren] Cache search failed. "
- "Going normal route");
- }
-
- retval = m_categories_map.GetSyntheticChildren(match_data);
- if (!retval) {
- LLDB_LOGF(log,
- "[FormatManager::GetSyntheticChildren] Search failed. Giving "
- "language a chance.");
- for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
- if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
- if (lang_category->Get(match_data, retval))
- break;
- }
- }
- if (retval) {
- LLDB_LOGF(log, "[FormatManager::GetSyntheticChildren] Language search "
- "success. Returning.");
- return retval;
- }
- }
- if (!retval) {
- LLDB_LOGF(log,
- "[FormatManager::GetSyntheticChildren] Search failed. Giving "
- "hardcoded a chance.");
- retval = GetHardcodedSyntheticChildren(match_data);
- }
-
- if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) {
- LLDB_LOGF(log,
- "[FormatManager::GetSyntheticChildren] Caching %p for type %s",
- static_cast<void *>(retval.get()),
- match_data.GetTypeForCache().AsCString("<invalid>"));
- m_format_cache.SetSynthetic(match_data.GetTypeForCache(), retval);
- }
- LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
- m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
- return retval;
-}
-
-lldb::TypeValidatorImplSP
-FormatManager::GetValidator(ValueObject &valobj,
- lldb::DynamicValueType use_dynamic) {
- FormattersMatchData match_data(valobj, use_dynamic);
-
- TypeValidatorImplSP retval;
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
- if (match_data.GetTypeForCache()) {
- LLDB_LOGF(
- log, "\n\n[FormatManager::GetValidator] Looking into cache for type %s",
- match_data.GetTypeForCache().AsCString("<invalid>"));
- if (m_format_cache.GetValidator(match_data.GetTypeForCache(), retval)) {
- if (log) {
- LLDB_LOGF(
- log,
- "[FormatManager::GetValidator] Cache search success. Returning.");
- LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
- m_format_cache.GetCacheHits(),
- m_format_cache.GetCacheMisses());
- }
- return retval;
- }
- LLDB_LOGF(log, "[FormatManager::GetValidator] Cache search failed. Going "
- "normal route");
- }
-
- retval = m_categories_map.GetValidator(match_data);
- if (!retval) {
- LLDB_LOGF(log, "[FormatManager::GetValidator] Search failed. Giving "
- "language a chance.");
- for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
- if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
- if (lang_category->Get(match_data, retval))
- break;
- }
- }
- if (retval) {
- LLDB_LOGF(log, "[FormatManager::GetValidator] Language search success. "
- "Returning.");
- return retval;
- }
- }
- if (!retval) {
- LLDB_LOGF(log, "[FormatManager::GetValidator] Search failed. Giving "
- "hardcoded a chance.");
- retval = GetHardcodedValidator(match_data);
- }
-
- if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) {
- LLDB_LOGF(log, "[FormatManager::GetValidator] Caching %p for type %s",
- static_cast<void *>(retval.get()),
- match_data.GetTypeForCache().AsCString("<invalid>"));
- m_format_cache.SetValidator(match_data.GetTypeForCache(), retval);
- }
- LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
- m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
- return retval;
-}
-
-lldb::TypeValidatorImplSP
-FormatManager::GetHardcodedValidator(FormattersMatchData &match_data) {
- TypeValidatorImplSP retval_sp;
-
- for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
- if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
- if (lang_category->GetHardcoded(*this, match_data, retval_sp))
- break;
- }
- }
-
- return retval_sp;
+ return Get<lldb::SyntheticChildrenSP>(valobj, use_dynamic);
}
FormatManager::FormatManager()
diff --git a/lldb/source/DataFormatters/LanguageCategory.cpp b/lldb/source/DataFormatters/LanguageCategory.cpp
index 969b02556548..e18ec0feaa8b 100644
--- a/lldb/source/DataFormatters/LanguageCategory.cpp
+++ b/lldb/source/DataFormatters/LanguageCategory.cpp
@@ -14,7 +14,6 @@
#include "lldb/DataFormatters/TypeFormat.h"
#include "lldb/DataFormatters/TypeSummary.h"
#include "lldb/DataFormatters/TypeSynthetic.h"
-#include "lldb/DataFormatters/TypeValidator.h"
#include "lldb/Target/Language.h"
using namespace lldb;
@@ -22,20 +21,19 @@ using namespace lldb_private;
LanguageCategory::LanguageCategory(lldb::LanguageType lang_type)
: m_category_sp(), m_hardcoded_formats(), m_hardcoded_summaries(),
- m_hardcoded_synthetics(), m_hardcoded_validators(), m_format_cache(),
- m_enabled(false) {
+ m_hardcoded_synthetics(), m_format_cache(), m_enabled(false) {
if (Language *language_plugin = Language::FindPlugin(lang_type)) {
m_category_sp = language_plugin->GetFormatters();
m_hardcoded_formats = language_plugin->GetHardcodedFormats();
m_hardcoded_summaries = language_plugin->GetHardcodedSummaries();
m_hardcoded_synthetics = language_plugin->GetHardcodedSynthetics();
- m_hardcoded_validators = language_plugin->GetHardcodedValidators();
}
Enable();
}
+template<typename ImplSP>
bool LanguageCategory::Get(FormattersMatchData &match_data,
- lldb::TypeFormatImplSP &format_sp) {
+ ImplSP &retval_sp) {
if (!m_category_sp)
return false;
@@ -43,168 +41,76 @@ bool LanguageCategory::Get(FormattersMatchData &match_data,
return false;
if (match_data.GetTypeForCache()) {
- if (m_format_cache.GetFormat(match_data.GetTypeForCache(), format_sp))
- return format_sp.get() != nullptr;
+ if (m_format_cache.Get(match_data.GetTypeForCache(), retval_sp))
+ return (bool)retval_sp;
}
ValueObject &valobj(match_data.GetValueObject());
- bool result =
- m_category_sp->Get(valobj, match_data.GetMatchesVector(), format_sp);
+ bool result = m_category_sp->Get(valobj.GetObjectRuntimeLanguage(),
+ match_data.GetMatchesVector(), retval_sp);
if (match_data.GetTypeForCache() &&
- (!format_sp || !format_sp->NonCacheable())) {
- m_format_cache.SetFormat(match_data.GetTypeForCache(), format_sp);
+ (!retval_sp || !retval_sp->NonCacheable())) {
+ m_format_cache.Set(match_data.GetTypeForCache(), retval_sp);
}
return result;
}
-bool LanguageCategory::Get(FormattersMatchData &match_data,
- lldb::TypeSummaryImplSP &format_sp) {
- if (!m_category_sp)
- return false;
-
- if (!IsEnabled())
- return false;
-
- if (match_data.GetTypeForCache()) {
- if (m_format_cache.GetSummary(match_data.GetTypeForCache(), format_sp))
- return format_sp.get() != nullptr;
- }
-
- ValueObject &valobj(match_data.GetValueObject());
- bool result =
- m_category_sp->Get(valobj, match_data.GetMatchesVector(), format_sp);
- if (match_data.GetTypeForCache() &&
- (!format_sp || !format_sp->NonCacheable())) {
- m_format_cache.SetSummary(match_data.GetTypeForCache(), format_sp);
- }
- return result;
+/// Explicit instantiations for the three types.
+/// \{
+template bool
+LanguageCategory::Get<lldb::TypeFormatImplSP>(FormattersMatchData &,
+ lldb::TypeFormatImplSP &);
+template bool
+LanguageCategory::Get<lldb::TypeSummaryImplSP>(FormattersMatchData &,
+ lldb::TypeSummaryImplSP &);
+template bool
+LanguageCategory::Get<lldb::SyntheticChildrenSP>(FormattersMatchData &,
+ lldb::SyntheticChildrenSP &);
+/// \}
+
+template <>
+auto &LanguageCategory::GetHardcodedFinder<lldb::TypeFormatImplSP>() {
+ return m_hardcoded_formats;
}
-bool LanguageCategory::Get(FormattersMatchData &match_data,
- lldb::SyntheticChildrenSP &format_sp) {
- if (!m_category_sp)
- return false;
-
- if (!IsEnabled())
- return false;
-
- if (match_data.GetTypeForCache()) {
- if (m_format_cache.GetSynthetic(match_data.GetTypeForCache(), format_sp))
- return format_sp.get() != nullptr;
- }
-
- ValueObject &valobj(match_data.GetValueObject());
- bool result =
- m_category_sp->Get(valobj, match_data.GetMatchesVector(), format_sp);
- if (match_data.GetTypeForCache() &&
- (!format_sp || !format_sp->NonCacheable())) {
- m_format_cache.SetSynthetic(match_data.GetTypeForCache(), format_sp);
- }
- return result;
+template <>
+auto &LanguageCategory::GetHardcodedFinder<lldb::TypeSummaryImplSP>() {
+ return m_hardcoded_summaries;
}
-bool LanguageCategory::Get(FormattersMatchData &match_data,
- lldb::TypeValidatorImplSP &format_sp) {
- if (!m_category_sp)
- return false;
-
- if (!IsEnabled())
- return false;
-
- if (match_data.GetTypeForCache()) {
- if (m_format_cache.GetValidator(match_data.GetTypeForCache(), format_sp))
- return format_sp.get() != nullptr;
- }
-
- ValueObject &valobj(match_data.GetValueObject());
- bool result =
- m_category_sp->Get(valobj, match_data.GetMatchesVector(), format_sp);
- if (match_data.GetTypeForCache() &&
- (!format_sp || !format_sp->NonCacheable())) {
- m_format_cache.SetValidator(match_data.GetTypeForCache(), format_sp);
- }
- return result;
+template <>
+auto &LanguageCategory::GetHardcodedFinder<lldb::SyntheticChildrenSP>() {
+ return m_hardcoded_synthetics;
}
+template <typename ImplSP>
bool LanguageCategory::GetHardcoded(FormatManager &fmt_mgr,
FormattersMatchData &match_data,
- lldb::TypeFormatImplSP &format_sp) {
+ ImplSP &retval_sp) {
if (!IsEnabled())
return false;
ValueObject &valobj(match_data.GetValueObject());
lldb::DynamicValueType use_dynamic(match_data.GetDynamicValueType());
- for (auto &candidate : m_hardcoded_formats) {
- if ((format_sp = candidate(valobj, use_dynamic, fmt_mgr)))
+ for (auto &candidate : GetHardcodedFinder<ImplSP>()) {
+ if (auto result = candidate(valobj, use_dynamic, fmt_mgr)) {
+ retval_sp = result;
break;
+ }
}
- if (match_data.GetTypeForCache() &&
- (!format_sp || !format_sp->NonCacheable())) {
- m_format_cache.SetFormat(match_data.GetTypeForCache(), format_sp);
- }
- return format_sp.get() != nullptr;
-}
-
-bool LanguageCategory::GetHardcoded(FormatManager &fmt_mgr,
- FormattersMatchData &match_data,
- lldb::TypeSummaryImplSP &format_sp) {
- if (!IsEnabled())
- return false;
-
- ValueObject &valobj(match_data.GetValueObject());
- lldb::DynamicValueType use_dynamic(match_data.GetDynamicValueType());
-
- for (auto &candidate : m_hardcoded_summaries) {
- if ((format_sp = candidate(valobj, use_dynamic, fmt_mgr)))
- break;
- }
- if (match_data.GetTypeForCache() &&
- (!format_sp || !format_sp->NonCacheable())) {
- m_format_cache.SetSummary(match_data.GetTypeForCache(), format_sp);
- }
- return format_sp.get() != nullptr;
-}
-
-bool LanguageCategory::GetHardcoded(FormatManager &fmt_mgr,
- FormattersMatchData &match_data,
- lldb::SyntheticChildrenSP &format_sp) {
- if (!IsEnabled())
- return false;
-
- ValueObject &valobj(match_data.GetValueObject());
- lldb::DynamicValueType use_dynamic(match_data.GetDynamicValueType());
-
- for (auto &candidate : m_hardcoded_synthetics) {
- if ((format_sp = candidate(valobj, use_dynamic, fmt_mgr)))
- break;
- }
- if (match_data.GetTypeForCache() &&
- (!format_sp || !format_sp->NonCacheable())) {
- m_format_cache.SetSynthetic(match_data.GetTypeForCache(), format_sp);
- }
- return format_sp.get() != nullptr;
+ return (bool)retval_sp;
}
-bool LanguageCategory::GetHardcoded(FormatManager &fmt_mgr,
- FormattersMatchData &match_data,
- lldb::TypeValidatorImplSP &format_sp) {
- if (!IsEnabled())
- return false;
-
- ValueObject &valobj(match_data.GetValueObject());
- lldb::DynamicValueType use_dynamic(match_data.GetDynamicValueType());
-
- for (auto &candidate : m_hardcoded_validators) {
- if ((format_sp = candidate(valobj, use_dynamic, fmt_mgr)))
- break;
- }
- if (match_data.GetTypeForCache() &&
- (!format_sp || !format_sp->NonCacheable())) {
- m_format_cache.SetValidator(match_data.GetTypeForCache(), format_sp);
- }
- return format_sp.get() != nullptr;
-}
+/// Explicit instantiations for the three types.
+/// \{
+template bool LanguageCategory::GetHardcoded<lldb::TypeFormatImplSP>(
+ FormatManager &, FormattersMatchData &, lldb::TypeFormatImplSP &);
+template bool LanguageCategory::GetHardcoded<lldb::TypeSummaryImplSP>(
+ FormatManager &, FormattersMatchData &, lldb::TypeSummaryImplSP &);
+template bool LanguageCategory::GetHardcoded<lldb::SyntheticChildrenSP>(
+ FormatManager &, FormattersMatchData &, lldb::SyntheticChildrenSP &);
+/// \}
lldb::TypeCategoryImplSP LanguageCategory::GetCategory() const {
return m_category_sp;
diff --git a/lldb/source/DataFormatters/TypeCategory.cpp b/lldb/source/DataFormatters/TypeCategory.cpp
index fed2dfb3c7c5..85699691f52b 100644
--- a/lldb/source/DataFormatters/TypeCategory.cpp
+++ b/lldb/source/DataFormatters/TypeCategory.cpp
@@ -13,18 +13,13 @@
using namespace lldb;
using namespace lldb_private;
-TypeCategoryImpl::TypeCategoryImpl(
- IFormatChangeListener *clist, ConstString name,
- std::initializer_list<lldb::LanguageType> langs)
+TypeCategoryImpl::TypeCategoryImpl(IFormatChangeListener *clist,
+ ConstString name)
: m_format_cont("format", "regex-format", clist),
m_summary_cont("summary", "regex-summary", clist),
m_filter_cont("filter", "regex-filter", clist),
- m_synth_cont("synth", "regex-synth", clist),
- m_validator_cont("validator", "regex-validator", clist), m_enabled(false),
- m_change_listener(clist), m_mutex(), m_name(name), m_languages() {
- for (const lldb::LanguageType lang : langs)
- AddLanguage(lang);
-}
+ m_synth_cont("synth", "regex-synth", clist), m_enabled(false),
+ m_change_listener(clist), m_mutex(), m_name(name), m_languages() {}
static bool IsApplicable(lldb::LanguageType category_lang,
lldb::LanguageType valobj_lang) {
@@ -64,11 +59,10 @@ static bool IsApplicable(lldb::LanguageType category_lang,
}
}
-bool TypeCategoryImpl::IsApplicable(ValueObject &valobj) {
- lldb::LanguageType valobj_lang = valobj.GetObjectRuntimeLanguage();
+bool TypeCategoryImpl::IsApplicable(lldb::LanguageType lang) {
for (size_t idx = 0; idx < GetNumLanguages(); idx++) {
const lldb::LanguageType category_lang = GetLanguageAtIndex(idx);
- if (::IsApplicable(category_lang, valobj_lang))
+ if (::IsApplicable(category_lang, lang))
return true;
}
return false;
@@ -90,16 +84,10 @@ void TypeCategoryImpl::AddLanguage(lldb::LanguageType lang) {
m_languages.push_back(lang);
}
-bool TypeCategoryImpl::HasLanguage(lldb::LanguageType lang) {
- const auto iter = std::find(m_languages.begin(), m_languages.end(), lang),
- end = m_languages.end();
- return (iter != end);
-}
-
-bool TypeCategoryImpl::Get(ValueObject &valobj,
+bool TypeCategoryImpl::Get(lldb::LanguageType lang,
const FormattersMatchVector &candidates,
lldb::TypeFormatImplSP &entry, uint32_t *reason) {
- if (!IsEnabled() || !IsApplicable(valobj))
+ if (!IsEnabled() || !IsApplicable(lang))
return false;
if (GetTypeFormatsContainer()->Get(candidates, entry, reason))
return true;
@@ -109,10 +97,10 @@ bool TypeCategoryImpl::Get(ValueObject &valobj,
return regex;
}
-bool TypeCategoryImpl::Get(ValueObject &valobj,
+bool TypeCategoryImpl::Get(lldb::LanguageType lang,
const FormattersMatchVector &candidates,
lldb::TypeSummaryImplSP &entry, uint32_t *reason) {
- if (!IsEnabled() || !IsApplicable(valobj))
+ if (!IsEnabled() || !IsApplicable(lang))
return false;
if (GetTypeSummariesContainer()->Get(candidates, entry, reason))
return true;
@@ -122,10 +110,10 @@ bool TypeCategoryImpl::Get(ValueObject &valobj,
return regex;
}
-bool TypeCategoryImpl::Get(ValueObject &valobj,
+bool TypeCategoryImpl::Get(lldb::LanguageType lang,
const FormattersMatchVector &candidates,
lldb::SyntheticChildrenSP &entry, uint32_t *reason) {
- if (!IsEnabled() || !IsApplicable(valobj))
+ if (!IsEnabled() || !IsApplicable(lang))
return false;
TypeFilterImpl::SharedPointer filter_sp;
uint32_t reason_filter = 0;
@@ -169,20 +157,6 @@ bool TypeCategoryImpl::Get(ValueObject &valobj,
return false;
}
-bool TypeCategoryImpl::Get(ValueObject &valobj,
- const FormattersMatchVector &candidates,
- lldb::TypeValidatorImplSP &entry, uint32_t *reason) {
- if (!IsEnabled())
- return false;
- if (GetTypeValidatorsContainer()->Get(candidates, entry, reason))
- return true;
- bool regex =
- GetRegexTypeValidatorsContainer()->Get(candidates, entry, reason);
- if (regex && reason)
- *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
- return regex;
-}
-
void TypeCategoryImpl::Clear(FormatCategoryItems items) {
if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue)
GetTypeFormatsContainer()->Clear();
@@ -205,12 +179,6 @@ void TypeCategoryImpl::Clear(FormatCategoryItems items) {
GetTypeSyntheticsContainer()->Clear();
if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth)
GetRegexTypeSyntheticsContainer()->Clear();
-
- if ((items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator)
- GetTypeValidatorsContainer()->Clear();
- if ((items & eFormatCategoryItemRegexValidator) ==
- eFormatCategoryItemRegexValidator)
- GetRegexTypeValidatorsContainer()->Clear();
}
bool TypeCategoryImpl::Delete(ConstString name, FormatCategoryItems items) {
@@ -238,12 +206,6 @@ bool TypeCategoryImpl::Delete(ConstString name, FormatCategoryItems items) {
if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth)
success = GetRegexTypeSyntheticsContainer()->Delete(name) || success;
- if ((items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator)
- success = GetTypeValidatorsContainer()->Delete(name) || success;
- if ((items & eFormatCategoryItemRegexValidator) ==
- eFormatCategoryItemRegexValidator)
- success = GetRegexTypeValidatorsContainer()->Delete(name) || success;
-
return success;
}
@@ -272,12 +234,6 @@ uint32_t TypeCategoryImpl::GetCount(FormatCategoryItems items) {
if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth)
count += GetRegexTypeSyntheticsContainer()->GetCount();
- if ((items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator)
- count += GetTypeValidatorsContainer()->GetCount();
- if ((items & eFormatCategoryItemRegexValidator) ==
- eFormatCategoryItemRegexValidator)
- count += GetRegexTypeValidatorsContainer()->GetCount();
-
return count;
}
@@ -292,7 +248,6 @@ bool TypeCategoryImpl::AnyMatches(ConstString type_name,
lldb::TypeSummaryImplSP summary_sp;
TypeFilterImpl::SharedPointer filter_sp;
ScriptedSyntheticChildren::SharedPointer synth_sp;
- TypeValidatorImpl::SharedPointer validator_sp;
if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue) {
if (GetTypeFormatsContainer()->Get(type_name, format_sp)) {
@@ -374,26 +329,6 @@ bool TypeCategoryImpl::AnyMatches(ConstString type_name,
}
}
- if ((items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator) {
- if (GetTypeValidatorsContainer()->Get(type_name, validator_sp)) {
- if (matching_category)
- *matching_category = m_name.GetCString();
- if (matching_type)
- *matching_type = eFormatCategoryItemValidator;
- return true;
- }
- }
- if ((items & eFormatCategoryItemRegexValidator) ==
- eFormatCategoryItemRegexValidator) {
- if (GetRegexTypeValidatorsContainer()->Get(type_name, validator_sp)) {
- if (matching_category)
- *matching_category = m_name.GetCString();
- if (matching_type)
- *matching_type = eFormatCategoryItemRegexValidator;
- return true;
- }
- }
-
return false;
}
@@ -461,22 +396,6 @@ TypeCategoryImpl::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp) {
return retval;
}
-TypeCategoryImpl::ValidatorContainer::MapValueType
-TypeCategoryImpl::GetValidatorForType(lldb::TypeNameSpecifierImplSP type_sp) {
- ValidatorContainer::MapValueType retval;
-
- if (type_sp) {
- if (type_sp->IsRegex())
- GetRegexTypeValidatorsContainer()->GetExact(
- ConstString(type_sp->GetName()), retval);
- else
- GetTypeValidatorsContainer()->GetExact(ConstString(type_sp->GetName()),
- retval);
- }
-
- return retval;
-}
-
lldb::TypeNameSpecifierImplSP
TypeCategoryImpl::GetTypeNameSpecifierForSummaryAtIndex(size_t index) {
if (index < GetTypeSummariesContainer()->GetCount())
@@ -549,24 +468,6 @@ TypeCategoryImpl::GetTypeNameSpecifierForSyntheticAtIndex(size_t index) {
index - GetTypeSyntheticsContainer()->GetCount());
}
-TypeCategoryImpl::ValidatorContainer::MapValueType
-TypeCategoryImpl::GetValidatorAtIndex(size_t index) {
- if (index < GetTypeValidatorsContainer()->GetCount())
- return GetTypeValidatorsContainer()->GetAtIndex(index);
- else
- return GetRegexTypeValidatorsContainer()->GetAtIndex(
- index - GetTypeValidatorsContainer()->GetCount());
-}
-
-lldb::TypeNameSpecifierImplSP
-TypeCategoryImpl::GetTypeNameSpecifierForValidatorAtIndex(size_t index) {
- if (index < GetTypeValidatorsContainer()->GetCount())
- return GetTypeValidatorsContainer()->GetTypeNameSpecifierAtIndex(index);
- else
- return GetRegexTypeValidatorsContainer()->GetTypeNameSpecifierAtIndex(
- index - GetTypeValidatorsContainer()->GetCount());
-}
-
void TypeCategoryImpl::Enable(bool value, uint32_t position) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
if ((m_enabled = value))
diff --git a/lldb/source/DataFormatters/TypeCategoryMap.cpp b/lldb/source/DataFormatters/TypeCategoryMap.cpp
index b1075e9878d8..ac515154299a 100644
--- a/lldb/source/DataFormatters/TypeCategoryMap.cpp
+++ b/lldb/source/DataFormatters/TypeCategoryMap.cpp
@@ -169,8 +169,8 @@ bool TypeCategoryMap::AnyMatches(
return false;
}
-lldb::TypeFormatImplSP
-TypeCategoryMap::GetFormat(FormattersMatchData &match_data) {
+template <typename ImplSP>
+void TypeCategoryMap::Get(FormattersMatchData &match_data, ImplSP &retval) {
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
uint32_t reason_why;
@@ -182,8 +182,8 @@ TypeCategoryMap::GetFormat(FormattersMatchData &match_data) {
for (auto match : match_data.GetMatchesVector()) {
LLDB_LOGF(
log,
- "[CategoryMap::GetFormat] candidate match = %s %s %s %s reason = "
- "%" PRIu32,
+ "[%s] candidate match = %s %s %s %s reason = %" PRIu32,
+ __FUNCTION__,
match.GetTypeName().GetCString(),
match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
match.DidStripReference() ? "strip-reference" : "no-strip-reference",
@@ -194,140 +194,31 @@ TypeCategoryMap::GetFormat(FormattersMatchData &match_data) {
for (begin = m_active_categories.begin(); begin != end; begin++) {
lldb::TypeCategoryImplSP category_sp = *begin;
- lldb::TypeFormatImplSP current_format;
- LLDB_LOGF(log, "[TypeCategoryMap::GetFormat] Trying to use category %s",
+ ImplSP current_format;
+ LLDB_LOGF(log, "[%s] Trying to use category %s", __FUNCTION__,
category_sp->GetName());
- if (!category_sp->Get(match_data.GetValueObject(),
- match_data.GetMatchesVector(), current_format,
- &reason_why))
+ if (!category_sp->Get(
+ match_data.GetValueObject().GetObjectRuntimeLanguage(),
+ match_data.GetMatchesVector(), current_format, &reason_why))
continue;
- return current_format;
- }
- LLDB_LOGF(log,
- "[TypeCategoryMap::GetFormat] nothing found - returning empty SP");
- return lldb::TypeFormatImplSP();
-}
-
-lldb::TypeSummaryImplSP
-TypeCategoryMap::GetSummaryFormat(FormattersMatchData &match_data) {
- std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
-
- uint32_t reason_why;
- ActiveCategoriesIterator begin, end = m_active_categories.end();
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
-
- if (log) {
- for (auto match : match_data.GetMatchesVector()) {
- LLDB_LOGF(
- log,
- "[CategoryMap::GetSummaryFormat] candidate match = %s %s %s %s "
- "reason = %" PRIu32,
- match.GetTypeName().GetCString(),
- match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
- match.DidStripReference() ? "strip-reference" : "no-strip-reference",
- match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
- match.GetReason());
- }
+ retval = std::move(current_format);
+ return;
}
-
- for (begin = m_active_categories.begin(); begin != end; begin++) {
- lldb::TypeCategoryImplSP category_sp = *begin;
- lldb::TypeSummaryImplSP current_format;
- LLDB_LOGF(log, "[CategoryMap::GetSummaryFormat] Trying to use category %s",
- category_sp->GetName());
- if (!category_sp->Get(match_data.GetValueObject(),
- match_data.GetMatchesVector(), current_format,
- &reason_why))
- continue;
- return current_format;
- }
- LLDB_LOGF(
- log,
- "[CategoryMap::GetSummaryFormat] nothing found - returning empty SP");
- return lldb::TypeSummaryImplSP();
+ LLDB_LOGF(log, "[%s] nothing found - returning empty SP", __FUNCTION__);
}
-lldb::SyntheticChildrenSP
-TypeCategoryMap::GetSyntheticChildren(FormattersMatchData &match_data) {
- std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
-
- uint32_t reason_why;
-
- ActiveCategoriesIterator begin, end = m_active_categories.end();
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
-
- if (log) {
- for (auto match : match_data.GetMatchesVector()) {
- LLDB_LOGF(
- log,
- "[CategoryMap::GetSyntheticChildren] candidate match = %s %s %s %s "
- "reason = %" PRIu32,
- match.GetTypeName().GetCString(),
- match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
- match.DidStripReference() ? "strip-reference" : "no-strip-reference",
- match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
- match.GetReason());
- }
- }
-
- for (begin = m_active_categories.begin(); begin != end; begin++) {
- lldb::TypeCategoryImplSP category_sp = *begin;
- lldb::SyntheticChildrenSP current_format;
- LLDB_LOGF(log,
- "[CategoryMap::GetSyntheticChildren] Trying to use category %s",
- category_sp->GetName());
- if (!category_sp->Get(match_data.GetValueObject(),
- match_data.GetMatchesVector(), current_format,
- &reason_why))
- continue;
- return current_format;
- }
- LLDB_LOGF(log,
- "[CategoryMap::GetSyntheticChildren] nothing found - returning "
- "empty SP");
- return lldb::SyntheticChildrenSP();
-}
-
-lldb::TypeValidatorImplSP
-TypeCategoryMap::GetValidator(FormattersMatchData &match_data) {
- std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
-
- uint32_t reason_why;
- ActiveCategoriesIterator begin, end = m_active_categories.end();
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
-
- if (log) {
- for (auto match : match_data.GetMatchesVector()) {
- LLDB_LOGF(
- log,
- "[CategoryMap::GetValidator] candidate match = %s %s %s %s reason = "
- "%" PRIu32,
- match.GetTypeName().GetCString(),
- match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
- match.DidStripReference() ? "strip-reference" : "no-strip-reference",
- match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
- match.GetReason());
- }
- }
-
- for (begin = m_active_categories.begin(); begin != end; begin++) {
- lldb::TypeCategoryImplSP category_sp = *begin;
- lldb::TypeValidatorImplSP current_format;
- LLDB_LOGF(log, "[CategoryMap::GetValidator] Trying to use category %s",
- category_sp->GetName());
- if (!category_sp->Get(match_data.GetValueObject(),
- match_data.GetMatchesVector(), current_format,
- &reason_why))
- continue;
- return current_format;
- }
- LLDB_LOGF(log,
- "[CategoryMap::GetValidator] nothing found - returning empty SP");
- return lldb::TypeValidatorImplSP();
-}
+/// Explicit instantiations for the three types.
+/// \{
+template void
+TypeCategoryMap::Get<lldb::TypeFormatImplSP>(FormattersMatchData &match_data,
+ lldb::TypeFormatImplSP &retval);
+template void
+TypeCategoryMap::Get<lldb::TypeSummaryImplSP>(FormattersMatchData &match_data,
+ lldb::TypeSummaryImplSP &retval);
+template void TypeCategoryMap::Get<lldb::SyntheticChildrenSP>(
+ FormattersMatchData &match_data, lldb::SyntheticChildrenSP &retval);
+/// \}
void TypeCategoryMap::ForEach(ForEachCallback callback) {
if (callback) {
diff --git a/lldb/source/DataFormatters/TypeValidator.cpp b/lldb/source/DataFormatters/TypeValidator.cpp
deleted file mode 100644
index 5ce24cacfb55..000000000000
--- a/lldb/source/DataFormatters/TypeValidator.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-//===-- TypeValidator.cpp ---------------------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-
-
-
-#include "lldb/DataFormatters/TypeValidator.h"
-#include "lldb/Utility/StreamString.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-TypeValidatorImpl::TypeValidatorImpl(const Flags &flags)
- : m_flags(flags), m_my_revision(0) {}
-
-TypeValidatorImpl::~TypeValidatorImpl() {}
-
-TypeValidatorImpl::ValidationResult TypeValidatorImpl::Success() {
- return ValidationResult{TypeValidatorResult::Success, ""};
-}
-
-TypeValidatorImpl::ValidationResult
-TypeValidatorImpl::Failure(std::string message) {
- return ValidationResult{TypeValidatorResult::Failure, message};
-}
-
-TypeValidatorImpl_CXX::TypeValidatorImpl_CXX(
- ValidatorFunction f, std::string d, const TypeValidatorImpl::Flags &flags)
- : TypeValidatorImpl(flags), m_description(d), m_validator_function(f) {}
-
-TypeValidatorImpl_CXX::~TypeValidatorImpl_CXX() {}
-
-TypeValidatorImpl::ValidationResult
-TypeValidatorImpl_CXX::FormatObject(ValueObject *valobj) const {
- if (!valobj)
- return Success(); // I guess there's nothing wrong with a null valueobject..
-
- return m_validator_function(valobj);
-}
-
-std::string TypeValidatorImpl_CXX::GetDescription() {
- StreamString sstr;
- sstr.Printf("%s%s%s%s", m_description.c_str(),
- Cascades() ? "" : " (not cascading)",
- SkipsPointers() ? " (skip pointers)" : "",
- SkipsReferences() ? " (skip references)" : "");
- return sstr.GetString();
-}
diff --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
index fa43c677a194..466cf398ec24 100644
--- a/lldb/source/DataFormatters/ValueObjectPrinter.cpp
+++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
@@ -75,8 +75,6 @@ bool ValueObjectPrinter::PrintValueObject() {
return false;
if (ShouldPrintValueObject()) {
- PrintValidationMarkerIfNeeded();
-
PrintLocationIfNeeded();
m_stream->Indent();
@@ -94,8 +92,6 @@ bool ValueObjectPrinter::PrintValueObject() {
else
m_stream->EOL();
- PrintValidationErrorIfNeeded();
-
return true;
}
@@ -790,37 +786,3 @@ void ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed,
} else
m_stream->EOL();
}
-
-bool ValueObjectPrinter::ShouldPrintValidation() {
- return m_options.m_run_validator;
-}
-
-bool ValueObjectPrinter::PrintValidationMarkerIfNeeded() {
- if (!ShouldPrintValidation())
- return false;
-
- m_validation = m_valobj->GetValidationStatus();
-
- if (TypeValidatorResult::Failure == m_validation.first) {
- m_stream->Printf("! ");
- return true;
- }
-
- return false;
-}
-
-bool ValueObjectPrinter::PrintValidationErrorIfNeeded() {
- if (!ShouldPrintValidation())
- return false;
-
- if (TypeValidatorResult::Success == m_validation.first)
- return false;
-
- if (m_validation.second.empty())
- m_validation.second.assign("unknown error");
-
- m_stream->Printf(" ! validation error: %s", m_validation.second.c_str());
- m_stream->EOL();
-
- return true;
-}
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 3789d9147737..69c84640ef93 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -47,22 +47,23 @@ ReadAddressFromDebugAddrSection(const DWARFUnit *dwarf_cu,
uint32_t index_size = dwarf_cu->GetAddressByteSize();
dw_offset_t addr_base = dwarf_cu->GetAddrBase();
lldb::offset_t offset = addr_base + index * index_size;
- return dwarf_cu->GetSymbolFileDWARF()
- .GetDWARFContext()
- .getOrLoadAddrData()
- .GetMaxU64(&offset, index_size);
+ const DWARFDataExtractor &data =
+ dwarf_cu->GetSymbolFileDWARF().GetDWARFContext().getOrLoadAddrData();
+ if (data.ValidOffsetForDataOfSize(offset, index_size))
+ return data.GetMaxU64_unchecked(&offset, index_size);
+ return LLDB_INVALID_ADDRESS;
}
// DWARFExpression constructor
DWARFExpression::DWARFExpression()
: m_module_wp(), m_data(), m_dwarf_cu(nullptr),
- m_reg_kind(eRegisterKindDWARF), m_loclist_slide(LLDB_INVALID_ADDRESS) {}
+ m_reg_kind(eRegisterKindDWARF) {}
DWARFExpression::DWARFExpression(lldb::ModuleSP module_sp,
const DataExtractor &data,
const DWARFUnit *dwarf_cu)
: m_module_wp(), m_data(data), m_dwarf_cu(dwarf_cu),
- m_reg_kind(eRegisterKindDWARF), m_loclist_slide(LLDB_INVALID_ADDRESS) {
+ m_reg_kind(eRegisterKindDWARF) {
if (module_sp)
m_module_wp = module_sp;
}
@@ -84,18 +85,18 @@ void DWARFExpression::UpdateValue(uint64_t const_value,
m_data.SetAddressByteSize(addr_byte_size);
}
-void DWARFExpression::DumpLocation(Stream *s, lldb::offset_t offset,
- lldb::offset_t length,
+void DWARFExpression::DumpLocation(Stream *s, const DataExtractor &data,
lldb::DescriptionLevel level,
ABI *abi) const {
- llvm::DWARFExpression(DataExtractor(m_data, offset, length).GetAsLLVM(),
- llvm::dwarf::DWARF_VERSION, m_data.GetAddressByteSize())
+ llvm::DWARFExpression(data.GetAsLLVM(), llvm::dwarf::DWARF_VERSION,
+ data.GetAddressByteSize())
.print(s->AsRawOstream(), abi ? &abi->GetMCRegisterInfo() : nullptr,
nullptr);
}
-void DWARFExpression::SetLocationListSlide(addr_t slide) {
- m_loclist_slide = slide;
+void DWARFExpression::SetLocationListAddresses(addr_t cu_file_addr,
+ addr_t func_file_addr) {
+ m_loclist_addresses = LoclistAddresses{cu_file_addr, func_file_addr};
}
int DWARFExpression::GetRegisterKind() { return m_reg_kind; }
@@ -105,7 +106,26 @@ void DWARFExpression::SetRegisterKind(RegisterKind reg_kind) {
}
bool DWARFExpression::IsLocationList() const {
- return m_loclist_slide != LLDB_INVALID_ADDRESS;
+ return bool(m_loclist_addresses);
+}
+
+namespace {
+/// Implement enough of the DWARFObject interface in order to be able to call
+/// DWARFLocationTable::dumpLocationList. We don't have access to a real
+/// DWARFObject here because DWARFExpression is used in non-DWARF scenarios too.
+class DummyDWARFObject final: public llvm::DWARFObject {
+public:
+ DummyDWARFObject(bool IsLittleEndian) : IsLittleEndian(IsLittleEndian) {}
+
+ bool isLittleEndian() const override { return IsLittleEndian; }
+
+ llvm::Optional<llvm::RelocAddrEntry> find(const llvm::DWARFSection &Sec,
+ uint64_t Pos) const override {
+ return llvm::None;
+ }
+private:
+ bool IsLittleEndian;
+};
}
void DWARFExpression::GetDescription(Stream *s, lldb::DescriptionLevel level,
@@ -114,47 +134,19 @@ void DWARFExpression::GetDescription(Stream *s, lldb::DescriptionLevel level,
if (IsLocationList()) {
// We have a location list
lldb::offset_t offset = 0;
- uint32_t count = 0;
- addr_t curr_base_addr = location_list_base_addr;
- while (m_data.ValidOffset(offset)) {
- addr_t begin_addr_offset = LLDB_INVALID_ADDRESS;
- addr_t end_addr_offset = LLDB_INVALID_ADDRESS;
- if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset,
- begin_addr_offset, end_addr_offset))
- break;
+ std::unique_ptr<llvm::DWARFLocationTable> loctable_up =
+ m_dwarf_cu->GetLocationTable(m_data);
- if (begin_addr_offset == 0 && end_addr_offset == 0)
- break;
+ llvm::MCRegisterInfo *MRI = abi ? &abi->GetMCRegisterInfo() : nullptr;
- if (begin_addr_offset < end_addr_offset) {
- if (count > 0)
- s->PutCString(", ");
- VMRange addr_range(curr_base_addr + begin_addr_offset,
- curr_base_addr + end_addr_offset);
- addr_range.Dump(s, 0, 8);
- s->PutChar('{');
- lldb::offset_t location_length = m_data.GetU16(&offset);
- DumpLocation(s, offset, location_length, level, abi);
- s->PutChar('}');
- offset += location_length;
- } else {
- if ((m_data.GetAddressByteSize() == 4 &&
- (begin_addr_offset == UINT32_MAX)) ||
- (m_data.GetAddressByteSize() == 8 &&
- (begin_addr_offset == UINT64_MAX))) {
- curr_base_addr = end_addr_offset + location_list_base_addr;
- // We have a new base address
- if (count > 0)
- s->PutCString(", ");
- *s << "base_addr = " << end_addr_offset;
- }
- }
-
- count++;
- }
+ loctable_up->dumpLocationList(
+ &offset, s->AsRawOstream(),
+ llvm::object::SectionedAddress{m_loclist_addresses->cu_file_addr}, MRI,
+ DummyDWARFObject(m_data.GetByteOrder() == eByteOrderLittle), nullptr,
+ llvm::DIDumpOptions(), s->GetIndentLevel() + 2);
} else {
// We have a normal location that contains DW_OP location opcodes
- DumpLocation(s, 0, m_data.GetByteSize(), level, abi);
+ DumpLocation(s, m_data, level, abi);
}
}
@@ -477,7 +469,7 @@ bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) {
m_data.GetByteOrder(), addr_byte_size);
// Replace the address in the new buffer
- if (encoder.PutMaxU64(offset, addr_byte_size, file_addr) == UINT32_MAX)
+ if (encoder.PutUnsigned(offset, addr_byte_size, file_addr) == UINT32_MAX)
return false;
// All went well, so now we can reset the data using a shared pointer to
@@ -583,8 +575,8 @@ bool DWARFExpression::LinkThreadLocalStorage(
if (linked_file_addr == LLDB_INVALID_ADDRESS)
return false;
// Replace the address in the new buffer
- if (encoder.PutMaxU64(const_offset, const_byte_size,
- linked_file_addr) == UINT32_MAX)
+ if (encoder.PutUnsigned(const_offset, const_byte_size,
+ linked_file_addr) == UINT32_MAX)
return false;
}
break;
@@ -614,102 +606,29 @@ bool DWARFExpression::LinkThreadLocalStorage(
return true;
}
-bool DWARFExpression::LocationListContainsAddress(
- lldb::addr_t loclist_base_addr, lldb::addr_t addr) const {
- if (addr == LLDB_INVALID_ADDRESS)
+bool DWARFExpression::LocationListContainsAddress(addr_t func_load_addr,
+ lldb::addr_t addr) const {
+ if (func_load_addr == LLDB_INVALID_ADDRESS || addr == LLDB_INVALID_ADDRESS)
return false;
- if (IsLocationList()) {
- lldb::offset_t offset = 0;
-
- if (loclist_base_addr == LLDB_INVALID_ADDRESS)
- return false;
-
- while (m_data.ValidOffset(offset)) {
- // We need to figure out what the value is for the location.
- addr_t lo_pc = LLDB_INVALID_ADDRESS;
- addr_t hi_pc = LLDB_INVALID_ADDRESS;
- if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc,
- hi_pc))
- break;
-
- if (lo_pc == 0 && hi_pc == 0)
- break;
-
- if ((m_data.GetAddressByteSize() == 4 && (lo_pc == UINT32_MAX)) ||
- (m_data.GetAddressByteSize() == 8 && (lo_pc == UINT64_MAX))) {
- loclist_base_addr = hi_pc + m_loclist_slide;
- continue;
- }
- lo_pc += loclist_base_addr - m_loclist_slide;
- hi_pc += loclist_base_addr - m_loclist_slide;
-
- if (lo_pc <= addr && addr < hi_pc)
- return true;
+ if (!IsLocationList())
+ return false;
- offset += m_data.GetU16(&offset);
- }
- }
- return false;
+ return GetLocationExpression(func_load_addr, addr) != llvm::None;
}
-bool DWARFExpression::GetLocation(addr_t base_addr, addr_t pc,
- lldb::offset_t &offset,
- lldb::offset_t &length) {
- offset = 0;
+bool DWARFExpression::DumpLocationForAddress(Stream *s,
+ lldb::DescriptionLevel level,
+ addr_t func_load_addr,
+ addr_t address, ABI *abi) {
if (!IsLocationList()) {
- length = m_data.GetByteSize();
+ DumpLocation(s, m_data, level, abi);
return true;
}
-
- if (base_addr != LLDB_INVALID_ADDRESS && pc != LLDB_INVALID_ADDRESS) {
- addr_t curr_base_addr = base_addr;
-
- while (m_data.ValidOffset(offset)) {
- // We need to figure out what the value is for the location.
- addr_t lo_pc = LLDB_INVALID_ADDRESS;
- addr_t hi_pc = LLDB_INVALID_ADDRESS;
- if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc,
- hi_pc))
- break;
-
- if (lo_pc == 0 && hi_pc == 0)
- break;
-
- if ((m_data.GetAddressByteSize() == 4 && (lo_pc == UINT32_MAX)) ||
- (m_data.GetAddressByteSize() == 8 && (lo_pc == UINT64_MAX))) {
- curr_base_addr = hi_pc + m_loclist_slide;
- continue;
- }
-
- lo_pc += curr_base_addr - m_loclist_slide;
- hi_pc += curr_base_addr - m_loclist_slide;
-
- length = m_data.GetU16(&offset);
-
- if (length > 0 && lo_pc <= pc && pc < hi_pc)
- return true;
-
- offset += length;
- }
- }
- offset = LLDB_INVALID_OFFSET;
- length = 0;
- return false;
-}
-
-bool DWARFExpression::DumpLocationForAddress(Stream *s,
- lldb::DescriptionLevel level,
- addr_t base_addr, addr_t address,
- ABI *abi) {
- lldb::offset_t offset = 0;
- lldb::offset_t length = 0;
-
- if (GetLocation(base_addr, address, offset, length)) {
- if (length > 0) {
- DumpLocation(s, offset, length, level, abi);
- return true;
- }
+ if (llvm::Optional<DataExtractor> expr =
+ GetLocationExpression(func_load_addr, address)) {
+ DumpLocation(s, *expr, level, abi);
+ return true;
}
return false;
}
@@ -830,6 +749,8 @@ static bool Evaluate_DW_OP_entry_value(std::vector<Value> &stack,
CallEdge *call_edge = nullptr;
ModuleList &modlist = target.GetImages();
+ ExecutionContext parent_exe_ctx = *exe_ctx;
+ parent_exe_ctx.SetFrameSP(parent_frame);
if (!parent_frame->IsArtificial()) {
// If the parent frame is not artificial, the current activation may be
// produced by an ambiguous tail call. In this case, refuse to proceed.
@@ -841,7 +762,7 @@ static bool Evaluate_DW_OP_entry_value(std::vector<Value> &stack,
return_pc, parent_func->GetName());
return false;
}
- Function *callee_func = call_edge->GetCallee(modlist);
+ Function *callee_func = call_edge->GetCallee(modlist, parent_exe_ctx);
if (callee_func != current_func) {
LLDB_LOG(log, "Evaluate_DW_OP_entry_value: ambiguous call sequence, "
"can't find real parent frame");
@@ -851,9 +772,9 @@ static bool Evaluate_DW_OP_entry_value(std::vector<Value> &stack,
// The StackFrameList solver machinery has deduced that an unambiguous tail
// call sequence that produced the current activation. The first edge in
// the parent that points to the current function must be valid.
- for (CallEdge &edge : parent_func->GetTailCallingEdges()) {
- if (edge.GetCallee(modlist) == current_func) {
- call_edge = &edge;
+ for (auto &edge : parent_func->GetTailCallingEdges()) {
+ if (edge->GetCallee(modlist, parent_exe_ctx) == current_func) {
+ call_edge = edge.get();
break;
}
}
@@ -907,8 +828,6 @@ static bool Evaluate_DW_OP_entry_value(std::vector<Value> &stack,
// TODO: Add support for DW_OP_push_object_address within a DW_OP_entry_value
// subexpresion whenever llvm does.
Value result;
- ExecutionContext parent_exe_ctx = *exe_ctx;
- parent_exe_ctx.SetFrameSP(parent_frame);
const DWARFExpression &param_expr = matched_param->LocationInCaller;
if (!param_expr.Evaluate(&parent_exe_ctx,
parent_frame->GetRegisterContext().get(),
@@ -936,14 +855,13 @@ bool DWARFExpression::Evaluate(ExecutionContextScope *exe_scope,
bool DWARFExpression::Evaluate(ExecutionContext *exe_ctx,
RegisterContext *reg_ctx,
- lldb::addr_t loclist_base_load_addr,
+ lldb::addr_t func_load_addr,
const Value *initial_value_ptr,
const Value *object_address_ptr, Value &result,
Status *error_ptr) const {
ModuleSP module_sp = m_module_wp.lock();
if (IsLocationList()) {
- lldb::offset_t offset = 0;
addr_t pc;
StackFrame *frame = nullptr;
if (reg_ctx)
@@ -958,45 +876,18 @@ bool DWARFExpression::Evaluate(ExecutionContext *exe_ctx,
pc = reg_ctx_sp->GetPC();
}
- if (loclist_base_load_addr != LLDB_INVALID_ADDRESS) {
+ if (func_load_addr != LLDB_INVALID_ADDRESS) {
if (pc == LLDB_INVALID_ADDRESS) {
if (error_ptr)
error_ptr->SetErrorString("Invalid PC in frame.");
return false;
}
- addr_t curr_loclist_base_load_addr = loclist_base_load_addr;
-
- while (m_data.ValidOffset(offset)) {
- // We need to figure out what the value is for the location.
- addr_t lo_pc = LLDB_INVALID_ADDRESS;
- addr_t hi_pc = LLDB_INVALID_ADDRESS;
- if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset,
- lo_pc, hi_pc))
- break;
-
- if (lo_pc == 0 && hi_pc == 0)
- break;
-
- if ((m_data.GetAddressByteSize() == 4 &&
- (lo_pc == UINT32_MAX)) ||
- (m_data.GetAddressByteSize() == 8 &&
- (lo_pc == UINT64_MAX))) {
- curr_loclist_base_load_addr = hi_pc + m_loclist_slide;
- continue;
- }
- lo_pc += curr_loclist_base_load_addr - m_loclist_slide;
- hi_pc += curr_loclist_base_load_addr - m_loclist_slide;
-
- uint16_t length = m_data.GetU16(&offset);
-
- if (length > 0 && lo_pc <= pc && pc < hi_pc) {
- return DWARFExpression::Evaluate(
- exe_ctx, reg_ctx, module_sp,
- DataExtractor(m_data, offset, length), m_dwarf_cu, m_reg_kind,
- initial_value_ptr, object_address_ptr, result, error_ptr);
- }
- offset += length;
+ if (llvm::Optional<DataExtractor> expr =
+ GetLocationExpression(func_load_addr, pc)) {
+ return DWARFExpression::Evaluate(
+ exe_ctx, reg_ctx, module_sp, *expr, m_dwarf_cu, m_reg_kind,
+ initial_value_ptr, object_address_ptr, result, error_ptr);
}
}
if (error_ptr)
@@ -2655,62 +2546,6 @@ bool DWARFExpression::Evaluate(
return true; // Return true on success
}
-bool DWARFExpression::AddressRangeForLocationListEntry(
- const DWARFUnit *dwarf_cu, const DataExtractor &debug_loc_data,
- lldb::offset_t *offset_ptr, lldb::addr_t &low_pc, lldb::addr_t &high_pc) {
- if (!debug_loc_data.ValidOffset(*offset_ptr))
- return false;
-
- DWARFExpression::LocationListFormat format =
- dwarf_cu->GetSymbolFileDWARF().GetLocationListFormat();
- switch (format) {
- case NonLocationList:
- return false;
- case RegularLocationList:
- low_pc = debug_loc_data.GetAddress(offset_ptr);
- high_pc = debug_loc_data.GetAddress(offset_ptr);
- return true;
- case SplitDwarfLocationList:
- case LocLists:
- switch (debug_loc_data.GetU8(offset_ptr)) {
- case DW_LLE_end_of_list:
- return false;
- case DW_LLE_startx_endx: {
- uint64_t index = debug_loc_data.GetULEB128(offset_ptr);
- low_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index);
- index = debug_loc_data.GetULEB128(offset_ptr);
- high_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index);
- return true;
- }
- case DW_LLE_startx_length: {
- uint64_t index = debug_loc_data.GetULEB128(offset_ptr);
- low_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index);
- uint64_t length = (format == LocLists)
- ? debug_loc_data.GetULEB128(offset_ptr)
- : debug_loc_data.GetU32(offset_ptr);
- high_pc = low_pc + length;
- return true;
- }
- case DW_LLE_start_length: {
- low_pc = debug_loc_data.GetAddress(offset_ptr);
- high_pc = low_pc + debug_loc_data.GetULEB128(offset_ptr);
- return true;
- }
- case DW_LLE_start_end: {
- low_pc = debug_loc_data.GetAddress(offset_ptr);
- high_pc = debug_loc_data.GetAddress(offset_ptr);
- return true;
- }
- default:
- // Not supported entry type
- lldbassert(false && "Not supported location list type");
- return false;
- }
- }
- assert(false && "Not supported location list type");
- return false;
-}
-
static bool print_dwarf_exp_op(Stream &s, const DataExtractor &data,
lldb::offset_t *offset_ptr, int address_size,
int dwarf_ref_size) {
@@ -2929,8 +2764,9 @@ void DWARFExpression::PrintDWARFLocationList(
s.PutCString("\n ");
s.Indent();
if (cu)
- s.AddressRange(start_addr + base_addr, end_addr + base_addr,
- cu->GetAddressByteSize(), nullptr, ": ");
+ DumpAddressRange(s.AsRawOstream(), start_addr + base_addr,
+ end_addr + base_addr, cu->GetAddressByteSize(), nullptr,
+ ": ");
uint32_t loc_length = debug_loc_data.GetU16(&offset);
DataExtractor locationData(debug_loc_data, offset, loc_length);
@@ -2939,56 +2775,87 @@ void DWARFExpression::PrintDWARFLocationList(
}
}
-bool DWARFExpression::GetOpAndEndOffsets(StackFrame &frame,
- lldb::offset_t &op_offset,
- lldb::offset_t &end_offset) {
- SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction);
- if (!sc.function) {
- return false;
- }
-
- addr_t loclist_base_file_addr =
- sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
- if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) {
- return false;
- }
-
- addr_t pc_file_addr = frame.GetFrameCodeAddress().GetFileAddress();
- lldb::offset_t opcodes_offset, opcodes_length;
- if (!GetLocation(loclist_base_file_addr, pc_file_addr, opcodes_offset,
- opcodes_length)) {
- return false;
- }
-
- if (opcodes_length == 0) {
- return false;
- }
+static DataExtractor ToDataExtractor(const llvm::DWARFLocationExpression &loc,
+ ByteOrder byte_order, uint32_t addr_size) {
+ auto buffer_sp =
+ std::make_shared<DataBufferHeap>(loc.Expr.data(), loc.Expr.size());
+ return DataExtractor(buffer_sp, byte_order, addr_size);
+}
- op_offset = opcodes_offset;
- end_offset = opcodes_offset + opcodes_length;
- return true;
+llvm::Optional<DataExtractor>
+DWARFExpression::GetLocationExpression(addr_t load_function_start,
+ addr_t addr) const {
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
+
+ std::unique_ptr<llvm::DWARFLocationTable> loctable_up =
+ m_dwarf_cu->GetLocationTable(m_data);
+ llvm::Optional<DataExtractor> result;
+ uint64_t offset = 0;
+ auto lookup_addr =
+ [&](uint32_t index) -> llvm::Optional<llvm::object::SectionedAddress> {
+ addr_t address = ReadAddressFromDebugAddrSection(m_dwarf_cu, index);
+ if (address == LLDB_INVALID_ADDRESS)
+ return llvm::None;
+ return llvm::object::SectionedAddress{address};
+ };
+ auto process_list = [&](llvm::Expected<llvm::DWARFLocationExpression> loc) {
+ if (!loc) {
+ LLDB_LOG_ERROR(log, loc.takeError(), "{0}");
+ return true;
+ }
+ if (loc->Range) {
+ // This relocates low_pc and high_pc by adding the difference between the
+ // function file address, and the actual address it is loaded in memory.
+ addr_t slide = load_function_start - m_loclist_addresses->func_file_addr;
+ loc->Range->LowPC += slide;
+ loc->Range->HighPC += slide;
+
+ if (loc->Range->LowPC <= addr && addr < loc->Range->HighPC)
+ result = ToDataExtractor(*loc, m_data.GetByteOrder(),
+ m_data.GetAddressByteSize());
+ }
+ return !result;
+ };
+ llvm::Error E = loctable_up->visitAbsoluteLocationList(
+ offset, llvm::object::SectionedAddress{m_loclist_addresses->cu_file_addr},
+ lookup_addr, process_list);
+ if (E)
+ LLDB_LOG_ERROR(log, std::move(E), "{0}");
+ return result;
}
bool DWARFExpression::MatchesOperand(StackFrame &frame,
const Instruction::Operand &operand) {
using namespace OperandMatchers;
- lldb::offset_t op_offset;
- lldb::offset_t end_offset;
- if (!GetOpAndEndOffsets(frame, op_offset, end_offset)) {
- return false;
- }
-
- if (!m_data.ValidOffset(op_offset) || op_offset >= end_offset) {
- return false;
- }
-
RegisterContextSP reg_ctx_sp = frame.GetRegisterContext();
if (!reg_ctx_sp) {
return false;
}
- DataExtractor opcodes = m_data;
+ DataExtractor opcodes;
+ if (IsLocationList()) {
+ SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction);
+ if (!sc.function)
+ return false;
+
+ addr_t load_function_start =
+ sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
+ if (load_function_start == LLDB_INVALID_ADDRESS)
+ return false;
+
+ addr_t pc = frame.GetFrameCodeAddress().GetLoadAddress(
+ frame.CalculateTarget().get());
+
+ if (llvm::Optional<DataExtractor> expr = GetLocationExpression(load_function_start, pc))
+ opcodes = std::move(*expr);
+ else
+ return false;
+ } else
+ opcodes = m_data;
+
+
+ lldb::offset_t op_offset = 0;
uint8_t opcode = opcodes.GetU8(&op_offset);
if (opcode == DW_OP_fbreg) {
diff --git a/lldb/source/Expression/Expression.cpp b/lldb/source/Expression/Expression.cpp
index 8e1ef6958cc7..71369d0b9eec 100644
--- a/lldb/source/Expression/Expression.cpp
+++ b/lldb/source/Expression/Expression.cpp
@@ -12,18 +12,16 @@
using namespace lldb_private;
-Expression::Expression(Target &target, ExpressionKind kind)
- : m_kind(kind),
- m_target_wp(target.shared_from_this()),
+Expression::Expression(Target &target)
+ : m_target_wp(target.shared_from_this()),
m_jit_start_addr(LLDB_INVALID_ADDRESS),
m_jit_end_addr(LLDB_INVALID_ADDRESS) {
// Can't make any kind of expression without a target.
assert(m_target_wp.lock());
}
-Expression::Expression(ExecutionContextScope &exe_scope, ExpressionKind kind)
- : m_kind(kind),
- m_target_wp(exe_scope.CalculateTarget()),
+Expression::Expression(ExecutionContextScope &exe_scope)
+ : m_target_wp(exe_scope.CalculateTarget()),
m_jit_start_addr(LLDB_INVALID_ADDRESS),
m_jit_end_addr(LLDB_INVALID_ADDRESS) {
assert(m_target_wp.lock());
diff --git a/lldb/source/Expression/FunctionCaller.cpp b/lldb/source/Expression/FunctionCaller.cpp
index 203cfff63d80..dc80c8169d7d 100644
--- a/lldb/source/Expression/FunctionCaller.cpp
+++ b/lldb/source/Expression/FunctionCaller.cpp
@@ -29,14 +29,16 @@
using namespace lldb_private;
+char FunctionCaller::ID;
+
// FunctionCaller constructor
FunctionCaller::FunctionCaller(ExecutionContextScope &exe_scope,
const CompilerType &return_type,
const Address &functionAddress,
const ValueList &arg_value_list,
const char *name)
- : Expression(exe_scope, eKindFunctionCaller), m_execution_unit_sp(),
- m_parser(), m_jit_module_wp(), m_name(name ? name : "<unknown>"),
+ : Expression(exe_scope), m_execution_unit_sp(), m_parser(),
+ m_jit_module_wp(), m_name(name ? name : "<unknown>"),
m_function_ptr(nullptr), m_function_addr(functionAddress),
m_function_return_type(return_type),
m_wrapper_function_name("__lldb_caller_function"),
diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp
index b10628e10cc5..e033b90cfd8b 100644
--- a/lldb/source/Expression/IRExecutionUnit.cpp
+++ b/lldb/source/Expression/IRExecutionUnit.cpp
@@ -348,7 +348,7 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr,
return;
}
m_jitted_functions.push_back(JittedFunction(
- function.getName().str().c_str(), external, (lldb::addr_t)fun_ptr));
+ function.getName().str().c_str(), external, reinterpret_cast<uintptr_t>(fun_ptr)));
}
CommitAllocations(process_sp);
@@ -728,8 +728,6 @@ void IRExecutionUnit::CollectCandidateCPlusPlusNames(
if (best_alternate_mangled_name) {
CPP_specs.push_back(best_alternate_mangled_name);
}
-
- CPP_specs.push_back(SearchSpec(demangled, lldb::eFunctionNameTypeFull));
}
}
@@ -977,30 +975,49 @@ IRExecutionUnit::FindSymbol(lldb_private::ConstString name, bool &missing_weak)
void IRExecutionUnit::GetStaticInitializers(
std::vector<lldb::addr_t> &static_initializers) {
- if (llvm::GlobalVariable *global_ctors =
- m_module->getNamedGlobal("llvm.global_ctors")) {
- if (llvm::ConstantArray *ctor_array = llvm::dyn_cast<llvm::ConstantArray>(
- global_ctors->getInitializer())) {
- for (llvm::Use &ctor_use : ctor_array->operands()) {
- if (llvm::ConstantStruct *ctor_struct =
- llvm::dyn_cast<llvm::ConstantStruct>(ctor_use)) {
- lldbassert(ctor_struct->getNumOperands() ==
- 3); // this is standardized
- if (llvm::Function *ctor_function =
- llvm::dyn_cast<llvm::Function>(ctor_struct->getOperand(1))) {
- ConstString ctor_function_name_cs(ctor_function->getName().str());
-
- for (JittedFunction &jitted_function : m_jitted_functions) {
- if (ctor_function_name_cs == jitted_function.m_name) {
- if (jitted_function.m_remote_addr != LLDB_INVALID_ADDRESS) {
- static_initializers.push_back(jitted_function.m_remote_addr);
- }
- break;
- }
- }
- }
- }
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ llvm::GlobalVariable *global_ctors =
+ m_module->getNamedGlobal("llvm.global_ctors");
+ if (!global_ctors) {
+ LLDB_LOG(log, "Couldn't find llvm.global_ctors.");
+ return;
+ }
+ auto *ctor_array =
+ llvm::dyn_cast<llvm::ConstantArray>(global_ctors->getInitializer());
+ if (!ctor_array) {
+ LLDB_LOG(log, "llvm.global_ctors not a ConstantArray.");
+ return;
+ }
+
+ for (llvm::Use &ctor_use : ctor_array->operands()) {
+ auto *ctor_struct = llvm::dyn_cast<llvm::ConstantStruct>(ctor_use);
+ if (!ctor_struct)
+ continue;
+ // this is standardized
+ lldbassert(ctor_struct->getNumOperands() == 3);
+ auto *ctor_function =
+ llvm::dyn_cast<llvm::Function>(ctor_struct->getOperand(1));
+ if (!ctor_function) {
+ LLDB_LOG(log, "global_ctor doesn't contain an llvm::Function");
+ continue;
+ }
+
+ ConstString ctor_function_name(ctor_function->getName().str());
+ LLDB_LOG(log, "Looking for callable jitted function with name {0}.",
+ ctor_function_name);
+
+ for (JittedFunction &jitted_function : m_jitted_functions) {
+ if (ctor_function_name != jitted_function.m_name)
+ continue;
+ if (jitted_function.m_remote_addr == LLDB_INVALID_ADDRESS) {
+ LLDB_LOG(log, "Found jitted function with invalid address.");
+ continue;
}
+ static_initializers.push_back(jitted_function.m_remote_addr);
+ LLDB_LOG(log, "Calling function at address {0:x}.",
+ jitted_function.m_remote_addr);
+ break;
}
}
}
diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp
index 856c9a0244fb..b2e4be5e40fd 100644
--- a/lldb/source/Expression/IRInterpreter.cpp
+++ b/lldb/source/Expression/IRInterpreter.cpp
@@ -490,10 +490,8 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
bool saw_function_with_body = false;
-
- for (Module::iterator fi = module.begin(), fe = module.end(); fi != fe;
- ++fi) {
- if (fi->begin() != fi->end()) {
+ for (Function &f : module) {
+ if (f.begin() != f.end()) {
if (saw_function_with_body) {
LLDB_LOGF(log, "More than one function in the module has a body");
error.SetErrorToGenericError();
@@ -504,13 +502,11 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
}
}
- for (Function::iterator bbi = function.begin(), bbe = function.end();
- bbi != bbe; ++bbi) {
- for (BasicBlock::iterator ii = bbi->begin(), ie = bbi->end(); ii != ie;
- ++ii) {
- switch (ii->getOpcode()) {
+ for (BasicBlock &bb : function) {
+ for (Instruction &ii : bb) {
+ switch (ii.getOpcode()) {
default: {
- LLDB_LOGF(log, "Unsupported instruction: %s", PrintValue(&*ii).c_str());
+ LLDB_LOGF(log, "Unsupported instruction: %s", PrintValue(&ii).c_str());
error.SetErrorToGenericError();
error.SetErrorString(unsupported_opcode_error);
return false;
@@ -522,7 +518,7 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
case Instruction::PHI:
break;
case Instruction::Call: {
- CallInst *call_inst = dyn_cast<CallInst>(ii);
+ CallInst *call_inst = dyn_cast<CallInst>(&ii);
if (!call_inst) {
error.SetErrorToGenericError();
@@ -532,7 +528,7 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
if (!CanIgnoreCall(call_inst) && !support_function_calls) {
LLDB_LOGF(log, "Unsupported instruction: %s",
- PrintValue(&*ii).c_str());
+ PrintValue(&ii).c_str());
error.SetErrorToGenericError();
error.SetErrorString(unsupported_opcode_error);
return false;
@@ -541,7 +537,7 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
case Instruction::GetElementPtr:
break;
case Instruction::ICmp: {
- ICmpInst *icmp_inst = dyn_cast<ICmpInst>(ii);
+ ICmpInst *icmp_inst = dyn_cast<ICmpInst>(&ii);
if (!icmp_inst) {
error.SetErrorToGenericError();
@@ -552,7 +548,7 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
switch (icmp_inst->getPredicate()) {
default: {
LLDB_LOGF(log, "Unsupported ICmp predicate: %s",
- PrintValue(&*ii).c_str());
+ PrintValue(&ii).c_str());
error.SetErrorToGenericError();
error.SetErrorString(unsupported_opcode_error);
@@ -594,8 +590,8 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
break;
}
- for (int oi = 0, oe = ii->getNumOperands(); oi != oe; ++oi) {
- Value *operand = ii->getOperand(oi);
+ for (unsigned oi = 0, oe = ii.getNumOperands(); oi != oe; ++oi) {
+ Value *operand = ii.getOperand(oi);
Type *operand_type = operand->getType();
switch (operand_type->getTypeID()) {
@@ -804,15 +800,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
}
} break;
case Instruction::Alloca: {
- const AllocaInst *alloca_inst = dyn_cast<AllocaInst>(inst);
-
- if (!alloca_inst) {
- LLDB_LOGF(log, "getOpcode() returns Alloca, but instruction is not an "
- "AllocaInst");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
+ const AllocaInst *alloca_inst = cast<AllocaInst>(inst);
if (alloca_inst->isArrayAllocation()) {
LLDB_LOGF(log,
@@ -875,16 +863,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
} break;
case Instruction::BitCast:
case Instruction::ZExt: {
- const CastInst *cast_inst = dyn_cast<CastInst>(inst);
-
- if (!cast_inst) {
- LLDB_LOGF(
- log, "getOpcode() returns %s, but instruction is not a BitCastInst",
- cast_inst->getOpcodeName());
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
+ const CastInst *cast_inst = cast<CastInst>(inst);
Value *source = cast_inst->getOperand(0);
@@ -900,16 +879,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
frame.AssignValue(inst, S, module);
} break;
case Instruction::SExt: {
- const CastInst *cast_inst = dyn_cast<CastInst>(inst);
-
- if (!cast_inst) {
- LLDB_LOGF(
- log, "getOpcode() returns %s, but instruction is not a BitCastInst",
- cast_inst->getOpcodeName());
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
+ const CastInst *cast_inst = cast<CastInst>(inst);
Value *source = cast_inst->getOperand(0);
@@ -929,15 +899,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
frame.AssignValue(inst, S_signextend, module);
} break;
case Instruction::Br: {
- const BranchInst *br_inst = dyn_cast<BranchInst>(inst);
-
- if (!br_inst) {
- LLDB_LOGF(
- log, "getOpcode() returns Br, but instruction is not a BranchInst");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
+ const BranchInst *br_inst = cast<BranchInst>(inst);
if (br_inst->isConditional()) {
Value *condition = br_inst->getCondition();
@@ -971,15 +933,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
}
continue;
case Instruction::PHI: {
- const PHINode *phi_inst = dyn_cast<PHINode>(inst);
-
- if (!phi_inst) {
- LLDB_LOGF(log,
- "getOpcode() returns PHI, but instruction is not a PHINode");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
+ const PHINode *phi_inst = cast<PHINode>(inst);
if (!frame.m_prev_bb) {
LLDB_LOGF(log,
"Encountered PHI node without having jumped from another "
@@ -1006,15 +960,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
}
} break;
case Instruction::GetElementPtr: {
- const GetElementPtrInst *gep_inst = dyn_cast<GetElementPtrInst>(inst);
-
- if (!gep_inst) {
- LLDB_LOGF(log, "getOpcode() returns GetElementPtr, but instruction is "
- "not a GetElementPtrInst");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
+ const GetElementPtrInst *gep_inst = cast<GetElementPtrInst>(inst);
const Value *pointer_operand = gep_inst->getPointerOperand();
Type *src_elem_ty = gep_inst->getSourceElementType();
@@ -1076,16 +1022,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
}
} break;
case Instruction::ICmp: {
- const ICmpInst *icmp_inst = dyn_cast<ICmpInst>(inst);
-
- if (!icmp_inst) {
- LLDB_LOGF(
- log,
- "getOpcode() returns ICmp, but instruction is not an ICmpInst");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
+ const ICmpInst *icmp_inst = cast<ICmpInst>(inst);
CmpInst::Predicate predicate = icmp_inst->getPredicate();
@@ -1172,16 +1109,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
}
} break;
case Instruction::IntToPtr: {
- const IntToPtrInst *int_to_ptr_inst = dyn_cast<IntToPtrInst>(inst);
-
- if (!int_to_ptr_inst) {
- LLDB_LOGF(log,
- "getOpcode() returns IntToPtr, but instruction is not an "
- "IntToPtrInst");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
+ const IntToPtrInst *int_to_ptr_inst = cast<IntToPtrInst>(inst);
Value *src_operand = int_to_ptr_inst->getOperand(0);
@@ -1203,16 +1131,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
}
} break;
case Instruction::PtrToInt: {
- const PtrToIntInst *ptr_to_int_inst = dyn_cast<PtrToIntInst>(inst);
-
- if (!ptr_to_int_inst) {
- LLDB_LOGF(log,
- "getOpcode() returns PtrToInt, but instruction is not an "
- "PtrToIntInst");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
+ const PtrToIntInst *ptr_to_int_inst = cast<PtrToIntInst>(inst);
Value *src_operand = ptr_to_int_inst->getOperand(0);
@@ -1234,16 +1153,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
}
} break;
case Instruction::Trunc: {
- const TruncInst *trunc_inst = dyn_cast<TruncInst>(inst);
-
- if (!trunc_inst) {
- LLDB_LOGF(
- log,
- "getOpcode() returns Trunc, but instruction is not a TruncInst");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
+ const TruncInst *trunc_inst = cast<TruncInst>(inst);
Value *src_operand = trunc_inst->getOperand(0);
@@ -1265,15 +1175,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
}
} break;
case Instruction::Load: {
- const LoadInst *load_inst = dyn_cast<LoadInst>(inst);
-
- if (!load_inst) {
- LLDB_LOGF(
- log, "getOpcode() returns Load, but instruction is not a LoadInst");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
+ const LoadInst *load_inst = cast<LoadInst>(inst);
// The semantics of Load are:
// Create a region D that will contain the loaded data
@@ -1355,16 +1257,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
return true;
}
case Instruction::Store: {
- const StoreInst *store_inst = dyn_cast<StoreInst>(inst);
-
- if (!store_inst) {
- LLDB_LOGF(
- log,
- "getOpcode() returns Store, but instruction is not a StoreInst");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
+ const StoreInst *store_inst = cast<StoreInst>(inst);
// The semantics of Store are:
// Resolve the region D containing the data to be stored
@@ -1440,16 +1333,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
}
} break;
case Instruction::Call: {
- const CallInst *call_inst = dyn_cast<CallInst>(inst);
-
- if (!call_inst) {
- LLDB_LOGF(log,
- "getOpcode() returns %s, but instruction is not a CallInst",
- inst->getOpcodeName());
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
+ const CallInst *call_inst = cast<CallInst>(inst);
if (CanIgnoreCall(call_inst))
break;
diff --git a/lldb/source/Expression/IRMemoryMap.cpp b/lldb/source/Expression/IRMemoryMap.cpp
index 5fdf452bf94e..02a875ec833b 100644
--- a/lldb/source/Expression/IRMemoryMap.cpp
+++ b/lldb/source/Expression/IRMemoryMap.cpp
@@ -328,9 +328,9 @@ lldb::addr_t IRMemoryMap::Malloc(size_t size, uint8_t alignment,
case eAllocationPolicyMirror:
process_sp = m_process_wp.lock();
LLDB_LOGF(log,
- "IRMemoryMap::%s process_sp=0x%" PRIx64
+ "IRMemoryMap::%s process_sp=0x%" PRIxPTR
", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s",
- __FUNCTION__, (lldb::addr_t)process_sp.get(),
+ __FUNCTION__, reinterpret_cast<uintptr_t>(process_sp.get()),
process_sp && process_sp->CanJIT() ? "true" : "false",
process_sp && process_sp->IsAlive() ? "true" : "false");
if (process_sp && process_sp->CanJIT() && process_sp->IsAlive()) {
@@ -577,9 +577,9 @@ void IRMemoryMap::WriteMemory(lldb::addr_t process_address,
if (lldb_private::Log *log =
lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
LLDB_LOGF(log,
- "IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64
+ "IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIxPTR
", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
- (uint64_t)process_address, (uint64_t)bytes, (uint64_t)size,
+ (uint64_t)process_address, reinterpret_cast<uintptr_t>(bytes), (uint64_t)size,
(uint64_t)allocation.m_process_start,
(uint64_t)allocation.m_process_start +
(uint64_t)allocation.m_size);
@@ -708,9 +708,9 @@ void IRMemoryMap::ReadMemory(uint8_t *bytes, lldb::addr_t process_address,
if (lldb_private::Log *log =
lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
LLDB_LOGF(log,
- "IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64
+ "IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIxPTR
", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
- (uint64_t)process_address, (uint64_t)bytes, (uint64_t)size,
+ (uint64_t)process_address, reinterpret_cast<uintptr_t>(bytes), (uint64_t)size,
(uint64_t)allocation.m_process_start,
(uint64_t)allocation.m_process_start +
(uint64_t)allocation.m_size);
diff --git a/lldb/source/Expression/LLVMUserExpression.cpp b/lldb/source/Expression/LLVMUserExpression.cpp
index 99e0c11df420..1fc878bbd616 100644
--- a/lldb/source/Expression/LLVMUserExpression.cpp
+++ b/lldb/source/Expression/LLVMUserExpression.cpp
@@ -35,20 +35,20 @@
using namespace lldb_private;
+char LLVMUserExpression::ID;
+
LLVMUserExpression::LLVMUserExpression(ExecutionContextScope &exe_scope,
llvm::StringRef expr,
llvm::StringRef prefix,
lldb::LanguageType language,
ResultType desired_type,
- const EvaluateExpressionOptions &options,
- ExpressionKind kind)
- : UserExpression(exe_scope, expr, prefix, language, desired_type, options,
- kind),
+ const EvaluateExpressionOptions &options)
+ : UserExpression(exe_scope, expr, prefix, language, desired_type, options),
m_stack_frame_bottom(LLDB_INVALID_ADDRESS),
m_stack_frame_top(LLDB_INVALID_ADDRESS), m_allow_cxx(false),
m_allow_objc(false), m_transformed_text(), m_execution_unit_sp(),
- m_materializer_up(), m_jit_module_wp(),
- m_can_interpret(false), m_materialized_address(LLDB_INVALID_ADDRESS) {}
+ m_materializer_up(), m_jit_module_wp(), m_can_interpret(false),
+ m_materialized_address(LLDB_INVALID_ADDRESS) {}
LLVMUserExpression::~LLVMUserExpression() {
if (m_target) {
@@ -70,174 +70,172 @@ LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager,
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS |
LIBLLDB_LOG_STEP));
- if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) {
- lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
+ if (m_jit_start_addr == LLDB_INVALID_ADDRESS && !m_can_interpret) {
+ diagnostic_manager.PutString(
+ eDiagnosticSeverityError,
+ "Expression can't be run, because there is no JIT compiled function");
+ return lldb::eExpressionSetupError;
+ }
- if (!PrepareToExecuteJITExpression(diagnostic_manager, exe_ctx,
- struct_address)) {
- diagnostic_manager.Printf(
+ lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
+
+ if (!PrepareToExecuteJITExpression(diagnostic_manager, exe_ctx,
+ struct_address)) {
+ diagnostic_manager.Printf(
+ eDiagnosticSeverityError,
+ "errored out in %s, couldn't PrepareToExecuteJITExpression",
+ __FUNCTION__);
+ return lldb::eExpressionSetupError;
+ }
+
+ lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
+ lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;
+
+ if (m_can_interpret) {
+ llvm::Module *module = m_execution_unit_sp->GetModule();
+ llvm::Function *function = m_execution_unit_sp->GetFunction();
+
+ if (!module || !function) {
+ diagnostic_manager.PutString(
eDiagnosticSeverityError,
- "errored out in %s, couldn't PrepareToExecuteJITExpression",
- __FUNCTION__);
+ "supposed to interpret, but nothing is there");
return lldb::eExpressionSetupError;
}
- lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
- lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;
+ Status interpreter_error;
- if (m_can_interpret) {
- llvm::Module *module = m_execution_unit_sp->GetModule();
- llvm::Function *function = m_execution_unit_sp->GetFunction();
+ std::vector<lldb::addr_t> args;
- if (!module || !function) {
- diagnostic_manager.PutString(
- eDiagnosticSeverityError,
- "supposed to interpret, but nothing is there");
- return lldb::eExpressionSetupError;
- }
+ if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) {
+ diagnostic_manager.Printf(eDiagnosticSeverityError,
+ "errored out in %s, couldn't AddArguments",
+ __FUNCTION__);
+ return lldb::eExpressionSetupError;
+ }
- Status interpreter_error;
+ function_stack_bottom = m_stack_frame_bottom;
+ function_stack_top = m_stack_frame_top;
- std::vector<lldb::addr_t> args;
+ IRInterpreter::Interpret(*module, *function, args, *m_execution_unit_sp,
+ interpreter_error, function_stack_bottom,
+ function_stack_top, exe_ctx);
- if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) {
- diagnostic_manager.Printf(eDiagnosticSeverityError,
- "errored out in %s, couldn't AddArguments",
- __FUNCTION__);
- return lldb::eExpressionSetupError;
- }
+ if (!interpreter_error.Success()) {
+ diagnostic_manager.Printf(eDiagnosticSeverityError,
+ "supposed to interpret, but failed: %s",
+ interpreter_error.AsCString());
+ return lldb::eExpressionDiscarded;
+ }
+ } else {
+ if (!exe_ctx.HasThreadScope()) {
+ diagnostic_manager.Printf(eDiagnosticSeverityError,
+ "%s called with no thread selected",
+ __FUNCTION__);
+ return lldb::eExpressionSetupError;
+ }
- function_stack_bottom = m_stack_frame_bottom;
- function_stack_top = m_stack_frame_top;
+ Address wrapper_address(m_jit_start_addr);
- IRInterpreter::Interpret(*module, *function, args, *m_execution_unit_sp,
- interpreter_error, function_stack_bottom,
- function_stack_top, exe_ctx);
+ std::vector<lldb::addr_t> args;
- if (!interpreter_error.Success()) {
- diagnostic_manager.Printf(eDiagnosticSeverityError,
- "supposed to interpret, but failed: %s",
- interpreter_error.AsCString());
- return lldb::eExpressionDiscarded;
- }
- } else {
- if (!exe_ctx.HasThreadScope()) {
- diagnostic_manager.Printf(eDiagnosticSeverityError,
- "%s called with no thread selected",
- __FUNCTION__);
- return lldb::eExpressionSetupError;
- }
+ if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) {
+ diagnostic_manager.Printf(eDiagnosticSeverityError,
+ "errored out in %s, couldn't AddArguments",
+ __FUNCTION__);
+ return lldb::eExpressionSetupError;
+ }
- Address wrapper_address(m_jit_start_addr);
+ lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression(
+ exe_ctx.GetThreadRef(), wrapper_address, args, options,
+ shared_ptr_to_me));
- std::vector<lldb::addr_t> args;
+ StreamString ss;
+ if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) {
+ diagnostic_manager.PutString(eDiagnosticSeverityError, ss.GetString());
+ return lldb::eExpressionSetupError;
+ }
- if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) {
- diagnostic_manager.Printf(eDiagnosticSeverityError,
- "errored out in %s, couldn't AddArguments",
- __FUNCTION__);
- return lldb::eExpressionSetupError;
- }
+ ThreadPlanCallUserExpression *user_expression_plan =
+ static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());
- lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression(
- exe_ctx.GetThreadRef(), wrapper_address, args, options,
- shared_ptr_to_me));
+ lldb::addr_t function_stack_pointer =
+ user_expression_plan->GetFunctionStackPointer();
- StreamString ss;
- if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) {
- diagnostic_manager.PutString(eDiagnosticSeverityError, ss.GetString());
- return lldb::eExpressionSetupError;
- }
+ function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
+ function_stack_top = function_stack_pointer;
+
+ LLDB_LOGF(log,
+ "-- [UserExpression::Execute] Execution of expression begins --");
+
+ if (exe_ctx.GetProcessPtr())
+ exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
+
+ lldb::ExpressionResults execution_result =
+ exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options,
+ diagnostic_manager);
+
+ if (exe_ctx.GetProcessPtr())
+ exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
- ThreadPlanCallUserExpression *user_expression_plan =
- static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());
-
- lldb::addr_t function_stack_pointer =
- user_expression_plan->GetFunctionStackPointer();
-
- function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
- function_stack_top = function_stack_pointer;
-
- LLDB_LOGF(
- log,
- "-- [UserExpression::Execute] Execution of expression begins --");
-
- if (exe_ctx.GetProcessPtr())
- exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
-
- lldb::ExpressionResults execution_result =
- exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options,
- diagnostic_manager);
-
- if (exe_ctx.GetProcessPtr())
- exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
-
- LLDB_LOGF(log, "-- [UserExpression::Execute] Execution of expression "
- "completed --");
-
- if (execution_result == lldb::eExpressionInterrupted ||
- execution_result == lldb::eExpressionHitBreakpoint) {
- const char *error_desc = nullptr;
-
- if (call_plan_sp) {
- lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
- if (real_stop_info_sp)
- error_desc = real_stop_info_sp->GetDescription();
- }
- if (error_desc)
- diagnostic_manager.Printf(eDiagnosticSeverityError,
- "Execution was interrupted, reason: %s.",
- error_desc);
- else
- diagnostic_manager.PutString(eDiagnosticSeverityError,
- "Execution was interrupted.");
-
- if ((execution_result == lldb::eExpressionInterrupted &&
- options.DoesUnwindOnError()) ||
- (execution_result == lldb::eExpressionHitBreakpoint &&
- options.DoesIgnoreBreakpoints()))
- diagnostic_manager.AppendMessageToDiagnostic(
- "The process has been returned to the state before expression "
- "evaluation.");
- else {
- if (execution_result == lldb::eExpressionHitBreakpoint)
- user_expression_plan->TransferExpressionOwnership();
- diagnostic_manager.AppendMessageToDiagnostic(
- "The process has been left at the point where it was "
- "interrupted, "
- "use \"thread return -x\" to return to the state before "
- "expression evaluation.");
- }
-
- return execution_result;
- } else if (execution_result == lldb::eExpressionStoppedForDebug) {
- diagnostic_manager.PutString(
- eDiagnosticSeverityRemark,
- "Execution was halted at the first instruction of the expression "
- "function because \"debug\" was requested.\n"
- "Use \"thread return -x\" to return to the state before expression "
+ LLDB_LOGF(log, "-- [UserExpression::Execute] Execution of expression "
+ "completed --");
+
+ if (execution_result == lldb::eExpressionInterrupted ||
+ execution_result == lldb::eExpressionHitBreakpoint) {
+ const char *error_desc = nullptr;
+
+ if (call_plan_sp) {
+ lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
+ if (real_stop_info_sp)
+ error_desc = real_stop_info_sp->GetDescription();
+ }
+ if (error_desc)
+ diagnostic_manager.Printf(eDiagnosticSeverityError,
+ "Execution was interrupted, reason: %s.",
+ error_desc);
+ else
+ diagnostic_manager.PutString(eDiagnosticSeverityError,
+ "Execution was interrupted.");
+
+ if ((execution_result == lldb::eExpressionInterrupted &&
+ options.DoesUnwindOnError()) ||
+ (execution_result == lldb::eExpressionHitBreakpoint &&
+ options.DoesIgnoreBreakpoints()))
+ diagnostic_manager.AppendMessageToDiagnostic(
+ "The process has been returned to the state before expression "
"evaluation.");
- return execution_result;
- } else if (execution_result != lldb::eExpressionCompleted) {
- diagnostic_manager.Printf(
- eDiagnosticSeverityError,
- "Couldn't execute function; result was %s",
- Process::ExecutionResultAsCString(execution_result));
- return execution_result;
+ else {
+ if (execution_result == lldb::eExpressionHitBreakpoint)
+ user_expression_plan->TransferExpressionOwnership();
+ diagnostic_manager.AppendMessageToDiagnostic(
+ "The process has been left at the point where it was "
+ "interrupted, "
+ "use \"thread return -x\" to return to the state before "
+ "expression evaluation.");
}
- }
- if (FinalizeJITExecution(diagnostic_manager, exe_ctx, result,
- function_stack_bottom, function_stack_top)) {
- return lldb::eExpressionCompleted;
- } else {
- return lldb::eExpressionResultUnavailable;
+ return execution_result;
+ } else if (execution_result == lldb::eExpressionStoppedForDebug) {
+ diagnostic_manager.PutString(
+ eDiagnosticSeverityRemark,
+ "Execution was halted at the first instruction of the expression "
+ "function because \"debug\" was requested.\n"
+ "Use \"thread return -x\" to return to the state before expression "
+ "evaluation.");
+ return execution_result;
+ } else if (execution_result != lldb::eExpressionCompleted) {
+ diagnostic_manager.Printf(
+ eDiagnosticSeverityError, "Couldn't execute function; result was %s",
+ Process::ExecutionResultAsCString(execution_result));
+ return execution_result;
}
+ }
+
+ if (FinalizeJITExecution(diagnostic_manager, exe_ctx, result,
+ function_stack_bottom, function_stack_top)) {
+ return lldb::eExpressionCompleted;
} else {
- diagnostic_manager.PutString(
- eDiagnosticSeverityError,
- "Expression can't be run, because there is no JIT compiled function");
- return lldb::eExpressionSetupError;
+ return lldb::eExpressionResultUnavailable;
}
}
diff --git a/lldb/source/Expression/REPL.cpp b/lldb/source/Expression/REPL.cpp
index 4f81ee3e56dd..fcd083684738 100644
--- a/lldb/source/Expression/REPL.cpp
+++ b/lldb/source/Expression/REPL.cpp
@@ -283,6 +283,8 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) {
PersistentExpressionState *persistent_state =
m_target.GetPersistentExpressionStateForLanguage(GetLanguage());
+ if (!persistent_state)
+ return;
const size_t var_count_before = persistent_state->GetSize();
diff --git a/lldb/source/Expression/UserExpression.cpp b/lldb/source/Expression/UserExpression.cpp
index e2d1d2f2b3d2..3b507da8e4ab 100644
--- a/lldb/source/Expression/UserExpression.cpp
+++ b/lldb/source/Expression/UserExpression.cpp
@@ -46,13 +46,14 @@
using namespace lldb_private;
+char UserExpression::ID;
+
UserExpression::UserExpression(ExecutionContextScope &exe_scope,
llvm::StringRef expr, llvm::StringRef prefix,
lldb::LanguageType language,
ResultType desired_type,
- const EvaluateExpressionOptions &options,
- ExpressionKind kind)
- : Expression(exe_scope, kind), m_expr_text(expr), m_expr_prefix(prefix),
+ const EvaluateExpressionOptions &options)
+ : Expression(exe_scope), m_expr_text(expr), m_expr_prefix(prefix),
m_language(language), m_desired_type(desired_type), m_options(options) {}
UserExpression::~UserExpression() {}
@@ -83,10 +84,9 @@ bool UserExpression::LockAndCheckContext(ExecutionContext &exe_ctx,
if (m_address.IsValid()) {
if (!frame_sp)
return false;
- else
- return (0 == Address::CompareLoadAddress(m_address,
- frame_sp->GetFrameCodeAddress(),
- target_sp.get()));
+ return (Address::CompareLoadAddress(m_address,
+ frame_sp->GetFrameCodeAddress(),
+ target_sp.get()) == 0);
}
return true;
@@ -396,8 +396,9 @@ UserExpression::Execute(DiagnosticManager &diagnostic_manager,
diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var);
Target *target = exe_ctx.GetTargetPtr();
if (options.GetResultIsInternal() && result_var && target) {
- target->GetPersistentExpressionStateForLanguage(m_language)
- ->RemovePersistentVariable(result_var);
+ if (auto *persistent_state =
+ target->GetPersistentExpressionStateForLanguage(m_language))
+ persistent_state->RemovePersistentVariable(result_var);
}
return expr_result;
}
diff --git a/lldb/source/Expression/UtilityFunction.cpp b/lldb/source/Expression/UtilityFunction.cpp
index aac8b33a6bfa..2dbc0e9d73ed 100644
--- a/lldb/source/Expression/UtilityFunction.cpp
+++ b/lldb/source/Expression/UtilityFunction.cpp
@@ -31,6 +31,8 @@
using namespace lldb_private;
using namespace lldb;
+char UtilityFunction::ID;
+
/// Constructor
///
/// \param[in] text
@@ -39,12 +41,9 @@ using namespace lldb;
/// \param[in] name
/// The name of the function, as used in the text.
UtilityFunction::UtilityFunction(ExecutionContextScope &exe_scope,
- const char *text, const char *name,
- ExpressionKind kind)
- : Expression(exe_scope, kind),
- m_execution_unit_sp(), m_jit_module_wp(),
- m_function_text(),
- m_function_name(name) {}
+ const char *text, const char *name)
+ : Expression(exe_scope), m_execution_unit_sp(), m_jit_module_wp(),
+ m_function_text(), m_function_name(name) {}
UtilityFunction::~UtilityFunction() {
lldb::ProcessSP process_sp(m_jit_process_wp.lock());
diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp
index 3e655244b107..5fd5a0cfc7fc 100644
--- a/lldb/source/Host/common/Editline.cpp
+++ b/lldb/source/Host/common/Editline.cpp
@@ -97,6 +97,33 @@ bool IsOnlySpaces(const EditLineStringType &content) {
return true;
}
+static int GetOperation(HistoryOperation op) {
+ // The naming used by editline for the history operations is counter
+ // intuitive to how it's used here.
+ //
+ // - The H_PREV operation returns the previous element in the history, which
+ // is newer than the current one.
+ //
+ // - The H_NEXT operation returns the next element in the history, which is
+ // older than the current one.
+ //
+ // The naming of the enum entries match the semantic meaning.
+ switch(op) {
+ case HistoryOperation::Oldest:
+ return H_FIRST;
+ case HistoryOperation::Older:
+ return H_NEXT;
+ case HistoryOperation::Current:
+ return H_CURR;
+ case HistoryOperation::Newer:
+ return H_PREV;
+ case HistoryOperation::Newest:
+ return H_LAST;
+ }
+ llvm_unreachable("Fully covered switch!");
+}
+
+
EditLineStringType CombineLines(const std::vector<EditLineStringType> &lines) {
EditLineStringStreamType combined_stream;
for (EditLineStringType line : lines) {
@@ -423,7 +450,8 @@ StringList Editline::GetInputAsStringList(int line_count) {
return lines;
}
-unsigned char Editline::RecallHistory(bool earlier) {
+unsigned char Editline::RecallHistory(HistoryOperation op) {
+ assert(op == HistoryOperation::Older || op == HistoryOperation::Newer);
if (!m_history_sp || !m_history_sp->IsValid())
return CC_ERROR;
@@ -433,27 +461,38 @@ unsigned char Editline::RecallHistory(bool earlier) {
// Treat moving from the "live" entry differently
if (!m_in_history) {
- if (!earlier)
+ switch (op) {
+ case HistoryOperation::Newer:
return CC_ERROR; // Can't go newer than the "live" entry
- if (history_w(pHistory, &history_event, H_FIRST) == -1)
- return CC_ERROR;
-
- // Save any edits to the "live" entry in case we return by moving forward
- // in history (it would be more bash-like to save over any current entry,
- // but libedit doesn't offer the ability to add entries anywhere except the
- // end.)
- SaveEditedLine();
- m_live_history_lines = m_input_lines;
- m_in_history = true;
+ case HistoryOperation::Older: {
+ if (history_w(pHistory, &history_event,
+ GetOperation(HistoryOperation::Newest)) == -1)
+ return CC_ERROR;
+ // Save any edits to the "live" entry in case we return by moving forward
+ // in history (it would be more bash-like to save over any current entry,
+ // but libedit doesn't offer the ability to add entries anywhere except
+ // the end.)
+ SaveEditedLine();
+ m_live_history_lines = m_input_lines;
+ m_in_history = true;
+ } break;
+ default:
+ llvm_unreachable("unsupported history direction");
+ }
} else {
- if (history_w(pHistory, &history_event, earlier ? H_PREV : H_NEXT) == -1) {
- // Can't move earlier than the earliest entry
- if (earlier)
+ if (history_w(pHistory, &history_event, GetOperation(op)) == -1) {
+ switch (op) {
+ case HistoryOperation::Older:
+ // Can't move earlier than the earliest entry.
return CC_ERROR;
-
- // ... but moving to newer than the newest yields the "live" entry
- new_input_lines = m_live_history_lines;
- m_in_history = false;
+ case HistoryOperation::Newer:
+ // Moving to newer-than-the-newest entry yields the "live" entry.
+ new_input_lines = m_live_history_lines;
+ m_in_history = false;
+ break;
+ default:
+ llvm_unreachable("unsupported history direction");
+ }
}
}
@@ -468,8 +507,17 @@ unsigned char Editline::RecallHistory(bool earlier) {
// Prepare to edit the last line when moving to previous entry, or the first
// line when moving to next entry
- SetCurrentLine(m_current_line_index =
- earlier ? (int)m_input_lines.size() - 1 : 0);
+ switch (op) {
+ case HistoryOperation::Older:
+ m_current_line_index = (int)m_input_lines.size() - 1;
+ break;
+ case HistoryOperation::Newer:
+ m_current_line_index = 0;
+ break;
+ default:
+ llvm_unreachable("unsupported history direction");
+ }
+ SetCurrentLine(m_current_line_index);
MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
return CC_NEWLINE;
}
@@ -721,7 +769,7 @@ unsigned char Editline::PreviousLineCommand(int ch) {
SaveEditedLine();
if (m_current_line_index == 0) {
- return RecallHistory(true);
+ return RecallHistory(HistoryOperation::Older);
}
// Start from a known location
@@ -747,7 +795,7 @@ unsigned char Editline::NextLineCommand(int ch) {
// Don't add an extra line if the existing last line is blank, move through
// history instead
if (IsOnlySpaces()) {
- return RecallHistory(false);
+ return RecallHistory(HistoryOperation::Newer);
}
// Determine indentation for the new line
@@ -779,13 +827,13 @@ unsigned char Editline::NextLineCommand(int ch) {
unsigned char Editline::PreviousHistoryCommand(int ch) {
SaveEditedLine();
- return RecallHistory(true);
+ return RecallHistory(HistoryOperation::Older);
}
unsigned char Editline::NextHistoryCommand(int ch) {
SaveEditedLine();
- return RecallHistory(false);
+ return RecallHistory(HistoryOperation::Newer);
}
unsigned char Editline::FixIndentationCommand(int ch) {
@@ -1105,6 +1153,15 @@ void Editline::ConfigureEditor(bool multiline) {
el_set(m_editline, EL_BIND, "\t", "lldb-complete",
NULL); // Bind TAB to auto complete
+ // Allow ctrl-left-arrow and ctrl-right-arrow for navigation, behave like
+ // bash in emacs mode.
+ el_set(m_editline, EL_BIND, ESCAPE "[1;5C", "em-next-word", NULL);
+ el_set(m_editline, EL_BIND, ESCAPE "[1;5D", "ed-prev-word", NULL);
+ el_set(m_editline, EL_BIND, ESCAPE "[5C", "em-next-word", NULL);
+ el_set(m_editline, EL_BIND, ESCAPE "[5D", "ed-prev-word", NULL);
+ el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[C", "em-next-word", NULL);
+ el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[D", "ed-prev-word", NULL);
+
// Allow user-specific customization prior to registering bindings we
// absolutely require
el_source(m_editline, nullptr);
@@ -1427,7 +1484,7 @@ bool Editline::CompleteCharacter(char ch, EditLineGetCharType &out) {
switch (cvt.in(state, input.begin(), input.end(), from_next, &out, &out + 1,
to_next)) {
case std::codecvt_base::ok:
- return out != WEOF;
+ return out != (int)WEOF;
case std::codecvt_base::error:
case std::codecvt_base::noconv:
diff --git a/lldb/source/Host/common/File.cpp b/lldb/source/Host/common/File.cpp
index 9dae24d766f6..7850222376f7 100644
--- a/lldb/source/Host/common/File.cpp
+++ b/lldb/source/Host/common/File.cpp
@@ -310,7 +310,7 @@ Status NativeFile::Close() {
if (m_own_stream) {
if (::fclose(m_stream) == EOF)
error.SetErrorToErrno();
- } else {
+ } else if (m_options & eOpenOptionWrite) {
if (::fflush(m_stream) == EOF)
error.SetErrorToErrno();
}
diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp
index 8e210c7e5fa5..5fbb655fc793 100644
--- a/lldb/source/Host/common/Host.cpp
+++ b/lldb/source/Host/common/Host.cpp
@@ -293,10 +293,21 @@ void Host::SystemLog(SystemLogType type, const char *format, va_list args) {
#endif
void Host::SystemLog(SystemLogType type, const char *format, ...) {
- va_list args;
- va_start(args, format);
- SystemLog(type, format, args);
- va_end(args);
+ {
+ va_list args;
+ va_start(args, format);
+ SystemLog(type, format, args);
+ va_end(args);
+ }
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST));
+ if (log && log->GetVerbose()) {
+ // Log to log channel. This allows testcases to grep for log output.
+ va_list args;
+ va_start(args, format);
+ log->VAPrintf(format, args);
+ va_end(args);
+ }
}
lldb::pid_t Host::GetCurrentProcessID() { return ::getpid(); }
diff --git a/lldb/source/Host/common/HostInfoBase.cpp b/lldb/source/Host/common/HostInfoBase.cpp
index 3765f36fc79a..8f263e90d90f 100644
--- a/lldb/source/Host/common/HostInfoBase.cpp
+++ b/lldb/source/Host/common/HostInfoBase.cpp
@@ -47,18 +47,28 @@ struct HostInfoBaseFields {
}
}
- std::string m_host_triple;
+ llvm::once_flag m_host_triple_once;
+ llvm::Triple m_host_triple;
+ llvm::once_flag m_host_arch_once;
ArchSpec m_host_arch_32;
ArchSpec m_host_arch_64;
+ llvm::once_flag m_lldb_so_dir_once;
FileSpec m_lldb_so_dir;
+ llvm::once_flag m_lldb_support_exe_dir_once;
FileSpec m_lldb_support_exe_dir;
+ llvm::once_flag m_lldb_headers_dir_once;
FileSpec m_lldb_headers_dir;
+ llvm::once_flag m_lldb_clang_resource_dir_once;
FileSpec m_lldb_clang_resource_dir;
+ llvm::once_flag m_lldb_system_plugin_dir_once;
FileSpec m_lldb_system_plugin_dir;
+ llvm::once_flag m_lldb_user_plugin_dir_once;
FileSpec m_lldb_user_plugin_dir;
+ llvm::once_flag m_lldb_process_tmp_dir_once;
FileSpec m_lldb_process_tmp_dir;
+ llvm::once_flag m_lldb_global_tmp_dir_once;
FileSpec m_lldb_global_tmp_dir;
};
@@ -72,18 +82,16 @@ void HostInfoBase::Terminate() {
g_fields = nullptr;
}
-llvm::StringRef HostInfoBase::GetTargetTriple() {
- static llvm::once_flag g_once_flag;
- llvm::call_once(g_once_flag, []() {
+llvm::Triple HostInfoBase::GetTargetTriple() {
+ llvm::call_once(g_fields->m_host_triple_once, []() {
g_fields->m_host_triple =
- HostInfo::GetArchitecture().GetTriple().getTriple();
+ HostInfo::GetArchitecture().GetTriple();
});
return g_fields->m_host_triple;
}
const ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) {
- static llvm::once_flag g_once_flag;
- llvm::call_once(g_once_flag, []() {
+ llvm::call_once(g_fields->m_host_arch_once, []() {
HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32,
g_fields->m_host_arch_64);
});
@@ -108,87 +116,76 @@ llvm::Optional<HostInfoBase::ArchitectureKind> HostInfoBase::ParseArchitectureKi
}
FileSpec HostInfoBase::GetShlibDir() {
- static llvm::once_flag g_once_flag;
- static bool success = false;
- llvm::call_once(g_once_flag, []() {
- success = HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir);
+ llvm::call_once(g_fields->m_lldb_so_dir_once, []() {
+ if (!HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir))
+ g_fields->m_lldb_so_dir = FileSpec();
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
LLDB_LOG(log, "shlib dir -> `{0}`", g_fields->m_lldb_so_dir);
});
- return success ? g_fields->m_lldb_so_dir : FileSpec();
+ return g_fields->m_lldb_so_dir;
}
FileSpec HostInfoBase::GetSupportExeDir() {
- static llvm::once_flag g_once_flag;
- static bool success = false;
- llvm::call_once(g_once_flag, []() {
- success =
- HostInfo::ComputeSupportExeDirectory(g_fields->m_lldb_support_exe_dir);
+ llvm::call_once(g_fields->m_lldb_support_exe_dir_once, []() {
+ if (!HostInfo::ComputeSupportExeDirectory(g_fields->m_lldb_support_exe_dir))
+ g_fields->m_lldb_support_exe_dir = FileSpec();
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
LLDB_LOG(log, "support exe dir -> `{0}`", g_fields->m_lldb_support_exe_dir);
});
- return success ? g_fields->m_lldb_support_exe_dir : FileSpec();
+ return g_fields->m_lldb_support_exe_dir;
}
FileSpec HostInfoBase::GetHeaderDir() {
- static llvm::once_flag g_once_flag;
- static bool success = false;
- llvm::call_once(g_once_flag, []() {
- success = HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir);
+ llvm::call_once(g_fields->m_lldb_headers_dir_once, []() {
+ if (!HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir))
+ g_fields->m_lldb_headers_dir = FileSpec();
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
LLDB_LOG(log, "header dir -> `{0}`", g_fields->m_lldb_headers_dir);
});
- return success ? g_fields->m_lldb_headers_dir : FileSpec();
+ return g_fields->m_lldb_headers_dir;
}
FileSpec HostInfoBase::GetSystemPluginDir() {
- static llvm::once_flag g_once_flag;
- static bool success = false;
- llvm::call_once(g_once_flag, []() {
- success = HostInfo::ComputeSystemPluginsDirectory(
- g_fields->m_lldb_system_plugin_dir);
+ llvm::call_once(g_fields->m_lldb_system_plugin_dir_once, []() {
+ if (!HostInfo::ComputeSystemPluginsDirectory(g_fields->m_lldb_system_plugin_dir))
+ g_fields->m_lldb_system_plugin_dir = FileSpec();
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
LLDB_LOG(log, "system plugin dir -> `{0}`",
g_fields->m_lldb_system_plugin_dir);
});
- return success ? g_fields->m_lldb_system_plugin_dir : FileSpec();
+ return g_fields->m_lldb_system_plugin_dir;
}
FileSpec HostInfoBase::GetUserPluginDir() {
- static llvm::once_flag g_once_flag;
- static bool success = false;
- llvm::call_once(g_once_flag, []() {
- success =
- HostInfo::ComputeUserPluginsDirectory(g_fields->m_lldb_user_plugin_dir);
+ llvm::call_once(g_fields->m_lldb_user_plugin_dir_once, []() {
+ if (!HostInfo::ComputeUserPluginsDirectory(g_fields->m_lldb_user_plugin_dir))
+ g_fields->m_lldb_user_plugin_dir = FileSpec();
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
LLDB_LOG(log, "user plugin dir -> `{0}`", g_fields->m_lldb_user_plugin_dir);
});
- return success ? g_fields->m_lldb_user_plugin_dir : FileSpec();
+ return g_fields->m_lldb_user_plugin_dir;
}
FileSpec HostInfoBase::GetProcessTempDir() {
- static llvm::once_flag g_once_flag;
- static bool success = false;
- llvm::call_once(g_once_flag, []() {
- success = HostInfo::ComputeProcessTempFileDirectory(
- g_fields->m_lldb_process_tmp_dir);
+ llvm::call_once(g_fields->m_lldb_process_tmp_dir_once, []() {
+ if (!HostInfo::ComputeProcessTempFileDirectory( g_fields->m_lldb_process_tmp_dir))
+ g_fields->m_lldb_process_tmp_dir = FileSpec();
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
LLDB_LOG(log, "process temp dir -> `{0}`",
g_fields->m_lldb_process_tmp_dir);
});
- return success ? g_fields->m_lldb_process_tmp_dir : FileSpec();
+ return g_fields->m_lldb_process_tmp_dir;
}
FileSpec HostInfoBase::GetGlobalTempDir() {
- static llvm::once_flag g_once_flag;
- static bool success = false;
- llvm::call_once(g_once_flag, []() {
- success = HostInfo::ComputeGlobalTempFileDirectory(
- g_fields->m_lldb_global_tmp_dir);
+ llvm::call_once(g_fields->m_lldb_global_tmp_dir_once, []() {
+ if (!HostInfo::ComputeGlobalTempFileDirectory( g_fields->m_lldb_global_tmp_dir))
+ g_fields->m_lldb_global_tmp_dir = FileSpec();
+
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
LLDB_LOG(log, "global temp dir -> `{0}`", g_fields->m_lldb_global_tmp_dir);
});
- return success ? g_fields->m_lldb_global_tmp_dir : FileSpec();
+ return g_fields->m_lldb_global_tmp_dir;
}
ArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) {
@@ -249,8 +246,8 @@ bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) {
// On other posix systems, we will get .../lib(64|32)?/liblldb.so.
FileSpec lldb_file_spec(Host::GetModuleFileSpecForHostAddress(
- reinterpret_cast<void *>(reinterpret_cast<intptr_t>(
- HostInfoBase::ComputeSharedLibraryDirectory))));
+ reinterpret_cast<void *>(
+ HostInfoBase::ComputeSharedLibraryDirectory)));
// This is necessary because when running the testsuite the shlib might be a
// symbolic link inside the Python resource dir.
diff --git a/lldb/source/Host/common/MainLoop.cpp b/lldb/source/Host/common/MainLoop.cpp
index 6f774451c8a4..240320f83242 100644
--- a/lldb/source/Host/common/MainLoop.cpp
+++ b/lldb/source/Host/common/MainLoop.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Config/llvm-config.h"
+#include "lldb/Host/Config.h"
#include "lldb/Host/MainLoop.h"
#include "lldb/Host/PosixApi.h"
diff --git a/lldb/source/Host/common/NativeProcessProtocol.cpp b/lldb/source/Host/common/NativeProcessProtocol.cpp
index fd349cc2915b..712c448dc2c1 100644
--- a/lldb/source/Host/common/NativeProcessProtocol.cpp
+++ b/lldb/source/Host/common/NativeProcessProtocol.cpp
@@ -682,7 +682,7 @@ NativeProcessProtocol::ReadCStringFromMemory(lldb::addr_t addr, char *buffer,
addr_t cache_line_bytes_left =
cache_line_size - (curr_addr % cache_line_size);
addr_t bytes_to_read = std::min<addr_t>(bytes_left, cache_line_bytes_left);
- status = ReadMemory(curr_addr, reinterpret_cast<void *>(curr_buffer),
+ status = ReadMemory(curr_addr, static_cast<void *>(curr_buffer),
bytes_to_read, bytes_read);
if (bytes_read == 0)
@@ -691,7 +691,7 @@ NativeProcessProtocol::ReadCStringFromMemory(lldb::addr_t addr, char *buffer,
void *str_end = std::memchr(curr_buffer, '\0', bytes_read);
if (str_end != nullptr) {
total_bytes_read =
- (size_t)(reinterpret_cast<char *>(str_end) - buffer + 1);
+ static_cast<size_t>((static_cast<char *>(str_end) - buffer + 1));
status.Clear();
break;
}
diff --git a/lldb/source/Host/common/PseudoTerminal.cpp b/lldb/source/Host/common/PseudoTerminal.cpp
index 85e54f4d3d6a..85828283e210 100644
--- a/lldb/source/Host/common/PseudoTerminal.cpp
+++ b/lldb/source/Host/common/PseudoTerminal.cpp
@@ -79,7 +79,7 @@ bool PseudoTerminal::OpenFirstAvailableMaster(int oflag, char *error_str,
if (error_str)
error_str[0] = '\0';
-#if !defined(LLDB_DISABLE_POSIX)
+#if LLDB_ENABLE_POSIX
// Open the master side of a pseudo terminal
m_master_fd = ::posix_openpt(oflag);
if (m_master_fd < 0) {
@@ -193,7 +193,7 @@ lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) {
if (error_str)
error_str[0] = '\0';
pid_t pid = LLDB_INVALID_PROCESS_ID;
-#if !defined(LLDB_DISABLE_POSIX)
+#if LLDB_ENABLE_POSIX
int flags = O_RDWR;
flags |= O_CLOEXEC;
if (OpenFirstAvailableMaster(flags, error_str, error_len)) {
diff --git a/lldb/source/Host/common/Socket.cpp b/lldb/source/Host/common/Socket.cpp
index 6358ab8a8e77..7fba1daff75f 100644
--- a/lldb/source/Host/common/Socket.cpp
+++ b/lldb/source/Host/common/Socket.cpp
@@ -22,7 +22,7 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/WindowsError.h"
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
#include "lldb/Host/posix/DomainSocket.h"
#include <arpa/inet.h>
@@ -122,7 +122,7 @@ std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol,
std::make_unique<UDPSocket>(true, child_processes_inherit);
break;
case ProtocolUnixDomain:
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
socket_up =
std::make_unique<DomainSocket>(true, child_processes_inherit);
#else
diff --git a/lldb/source/Host/common/SocketAddress.cpp b/lldb/source/Host/common/SocketAddress.cpp
index 882fd24558f7..960ed18dc768 100644
--- a/lldb/source/Host/common/SocketAddress.cpp
+++ b/lldb/source/Host/common/SocketAddress.cpp
@@ -174,12 +174,6 @@ bool SocketAddress::SetPort(uint16_t port) {
}
// SocketAddress assignment operator
-const SocketAddress &SocketAddress::operator=(const SocketAddress &rhs) {
- if (this != &rhs)
- m_socket_addr = rhs.m_socket_addr;
- return *this;
-}
-
const SocketAddress &SocketAddress::
operator=(const struct addrinfo *addr_info) {
Clear();
diff --git a/lldb/source/Host/common/TCPSocket.cpp b/lldb/source/Host/common/TCPSocket.cpp
index e84054f3f581..b716935db6e6 100644
--- a/lldb/source/Host/common/TCPSocket.cpp
+++ b/lldb/source/Host/common/TCPSocket.cpp
@@ -20,7 +20,7 @@
#include "llvm/Support/Errno.h"
#include "llvm/Support/raw_ostream.h"
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
@@ -149,9 +149,9 @@ Status TCPSocket::Connect(llvm::StringRef name) {
if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
return error;
- auto addresses = lldb_private::SocketAddress::GetAddressInfo(
+ std::vector<SocketAddress> addresses = SocketAddress::GetAddressInfo(
host_str.c_str(), nullptr, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
- for (auto address : addresses) {
+ for (SocketAddress &address : addresses) {
error = CreateSocket(address.GetFamily());
if (error.Fail())
continue;
@@ -187,9 +187,9 @@ Status TCPSocket::Listen(llvm::StringRef name, int backlog) {
if (host_str == "*")
host_str = "0.0.0.0";
- auto addresses = lldb_private::SocketAddress::GetAddressInfo(
+ std::vector<SocketAddress> addresses = SocketAddress::GetAddressInfo(
host_str.c_str(), nullptr, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
- for (auto address : addresses) {
+ for (SocketAddress &address : addresses) {
int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP,
m_child_processes_inherit, error);
if (error.Fail()) {
@@ -273,7 +273,7 @@ Status TCPSocket::Accept(Socket *&conn_socket) {
// Loop until we are happy with our connection
while (!accept_connection) {
accept_loop.Run();
-
+
if (error.Fail())
return error;
diff --git a/lldb/source/Host/common/Terminal.cpp b/lldb/source/Host/common/Terminal.cpp
index 4b536b03d852..e1aea26eeb90 100644
--- a/lldb/source/Host/common/Terminal.cpp
+++ b/lldb/source/Host/common/Terminal.cpp
@@ -15,7 +15,7 @@
#include <fcntl.h>
#include <signal.h>
-#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
+#if LLDB_ENABLE_TERMIOS
#include <termios.h>
#endif
@@ -25,7 +25,7 @@ bool Terminal::IsATerminal() const { return m_fd >= 0 && ::isatty(m_fd); }
bool Terminal::SetEcho(bool enabled) {
if (FileDescriptorIsValid()) {
-#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
+#if LLDB_ENABLE_TERMIOS
if (IsATerminal()) {
struct termios fd_termios;
if (::tcgetattr(m_fd, &fd_termios) == 0) {
@@ -47,14 +47,14 @@ bool Terminal::SetEcho(bool enabled) {
return ::tcsetattr(m_fd, TCSANOW, &fd_termios) == 0;
}
}
-#endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
+#endif // #if LLDB_ENABLE_TERMIOS
}
return false;
}
bool Terminal::SetCanonical(bool enabled) {
if (FileDescriptorIsValid()) {
-#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
+#if LLDB_ENABLE_TERMIOS
if (IsATerminal()) {
struct termios fd_termios;
if (::tcgetattr(m_fd, &fd_termios) == 0) {
@@ -76,7 +76,7 @@ bool Terminal::SetCanonical(bool enabled) {
return ::tcsetattr(m_fd, TCSANOW, &fd_termios) == 0;
}
}
-#endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
+#endif // #if LLDB_ENABLE_TERMIOS
}
return false;
}
@@ -84,7 +84,7 @@ bool Terminal::SetCanonical(bool enabled) {
// Default constructor
TerminalState::TerminalState()
: m_tty(), m_tflags(-1),
-#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
+#if LLDB_ENABLE_TERMIOS
m_termios_up(),
#endif
m_process_group(-1) {
@@ -96,7 +96,7 @@ TerminalState::~TerminalState() {}
void TerminalState::Clear() {
m_tty.Clear();
m_tflags = -1;
-#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
+#if LLDB_ENABLE_TERMIOS
m_termios_up.reset();
#endif
m_process_group = -1;
@@ -108,17 +108,17 @@ void TerminalState::Clear() {
bool TerminalState::Save(int fd, bool save_process_group) {
m_tty.SetFileDescriptor(fd);
if (m_tty.IsATerminal()) {
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
m_tflags = ::fcntl(fd, F_GETFL, 0);
#endif
-#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
+#if LLDB_ENABLE_TERMIOS
if (m_termios_up == nullptr)
m_termios_up.reset(new struct termios);
int err = ::tcgetattr(fd, m_termios_up.get());
if (err != 0)
m_termios_up.reset();
-#endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
-#ifndef LLDB_DISABLE_POSIX
+#endif // #if LLDB_ENABLE_TERMIOS
+#if LLDB_ENABLE_POSIX
if (save_process_group)
m_process_group = ::tcgetpgrp(0);
else
@@ -127,7 +127,7 @@ bool TerminalState::Save(int fd, bool save_process_group) {
} else {
m_tty.Clear();
m_tflags = -1;
-#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
+#if LLDB_ENABLE_TERMIOS
m_termios_up.reset();
#endif
m_process_group = -1;
@@ -138,16 +138,16 @@ bool TerminalState::Save(int fd, bool save_process_group) {
// Restore the state of the TTY using the cached values from a previous call to
// Save().
bool TerminalState::Restore() const {
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
if (IsValid()) {
const int fd = m_tty.GetFileDescriptor();
if (TFlagsIsValid())
fcntl(fd, F_SETFL, m_tflags);
-#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
+#if LLDB_ENABLE_TERMIOS
if (TTYStateIsValid())
tcsetattr(fd, TCSANOW, m_termios_up.get());
-#endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
+#endif // #if LLDB_ENABLE_TERMIOS
if (ProcessGroupIsValid()) {
// Save the original signal handler.
@@ -176,7 +176,7 @@ bool TerminalState::TFlagsIsValid() const { return m_tflags != -1; }
// Returns true if m_ttystate is valid
bool TerminalState::TTYStateIsValid() const {
-#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
+#if LLDB_ENABLE_TERMIOS
return m_termios_up != nullptr;
#else
return false;
diff --git a/lldb/source/Host/common/UDPSocket.cpp b/lldb/source/Host/common/UDPSocket.cpp
index 7accbb651ba9..0a991c33645b 100644
--- a/lldb/source/Host/common/UDPSocket.cpp
+++ b/lldb/source/Host/common/UDPSocket.cpp
@@ -11,7 +11,7 @@
#include "lldb/Host/Config.h"
#include "lldb/Utility/Log.h"
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
#include <arpa/inet.h>
#include <sys/socket.h>
#endif
diff --git a/lldb/source/Host/common/XML.cpp b/lldb/source/Host/common/XML.cpp
index cb23ac17ef53..28d1f5a8eaf4 100644
--- a/lldb/source/Host/common/XML.cpp
+++ b/lldb/source/Host/common/XML.cpp
@@ -8,6 +8,7 @@
#include <stdlib.h> /* atof */
+#include "lldb/Host/Config.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Host/XML.h"
@@ -21,7 +22,7 @@ XMLDocument::XMLDocument() : m_document(nullptr) {}
XMLDocument::~XMLDocument() { Clear(); }
void XMLDocument::Clear() {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (m_document) {
xmlDocPtr doc = m_document;
m_document = nullptr;
@@ -42,7 +43,7 @@ void XMLDocument::ErrorCallback(void *ctx, const char *format, ...) {
}
bool XMLDocument::ParseFile(const char *path) {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
Clear();
xmlSetGenericErrorFunc((void *)this, XMLDocument::ErrorCallback);
m_document = xmlParseFile(path);
@@ -53,7 +54,7 @@ bool XMLDocument::ParseFile(const char *path) {
bool XMLDocument::ParseMemory(const char *xml, size_t xml_length,
const char *url) {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
Clear();
xmlSetGenericErrorFunc((void *)this, XMLDocument::ErrorCallback);
m_document = xmlReadMemory(xml, (int)xml_length, url, nullptr, 0);
@@ -63,7 +64,7 @@ bool XMLDocument::ParseMemory(const char *xml, size_t xml_length,
}
XMLNode XMLDocument::GetRootElement(const char *required_name) {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid()) {
XMLNode root_node(xmlDocGetRootElement(m_document));
if (required_name) {
@@ -81,7 +82,7 @@ XMLNode XMLDocument::GetRootElement(const char *required_name) {
llvm::StringRef XMLDocument::GetErrors() const { return m_errors.GetString(); }
bool XMLDocument::XMLEnabled() {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
return true;
#else
return false;
@@ -99,7 +100,7 @@ XMLNode::~XMLNode() {}
void XMLNode::Clear() { m_node = nullptr; }
XMLNode XMLNode::GetParent() const {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid())
return XMLNode(m_node->parent);
else
@@ -110,7 +111,7 @@ XMLNode XMLNode::GetParent() const {
}
XMLNode XMLNode::GetSibling() const {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid())
return XMLNode(m_node->next);
else
@@ -121,7 +122,7 @@ XMLNode XMLNode::GetSibling() const {
}
XMLNode XMLNode::GetChild() const {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid())
return XMLNode(m_node->children);
@@ -135,7 +136,7 @@ XMLNode XMLNode::GetChild() const {
llvm::StringRef XMLNode::GetAttributeValue(const char *name,
const char *fail_value) const {
const char *attr_value = nullptr;
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid())
attr_value = (const char *)xmlGetProp(m_node, (const xmlChar *)name);
@@ -152,7 +153,7 @@ llvm::StringRef XMLNode::GetAttributeValue(const char *name,
bool XMLNode::GetAttributeValueAsUnsigned(const char *name, uint64_t &value,
uint64_t fail_value, int base) const {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
llvm::StringRef str_value = GetAttributeValue(name, "");
#else
llvm::StringRef str_value;
@@ -163,14 +164,14 @@ bool XMLNode::GetAttributeValueAsUnsigned(const char *name, uint64_t &value,
}
void XMLNode::ForEachChildNode(NodeCallback const &callback) const {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid())
GetChild().ForEachSiblingNode(callback);
#endif
}
void XMLNode::ForEachChildElement(NodeCallback const &callback) const {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
XMLNode child = GetChild();
if (child)
child.ForEachSiblingElement(callback);
@@ -179,7 +180,7 @@ void XMLNode::ForEachChildElement(NodeCallback const &callback) const {
void XMLNode::ForEachChildElementWithName(const char *name,
NodeCallback const &callback) const {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
XMLNode child = GetChild();
if (child)
child.ForEachSiblingElementWithName(name, callback);
@@ -187,7 +188,7 @@ void XMLNode::ForEachChildElementWithName(const char *name,
}
void XMLNode::ForEachAttribute(AttributeCallback const &callback) const {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid()) {
for (xmlAttrPtr attr = m_node->properties; attr != nullptr;
@@ -210,7 +211,7 @@ void XMLNode::ForEachAttribute(AttributeCallback const &callback) const {
}
void XMLNode::ForEachSiblingNode(NodeCallback const &callback) const {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid()) {
// iterate through all siblings
@@ -223,7 +224,7 @@ void XMLNode::ForEachSiblingNode(NodeCallback const &callback) const {
}
void XMLNode::ForEachSiblingElement(NodeCallback const &callback) const {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid()) {
// iterate through all siblings
@@ -241,7 +242,7 @@ void XMLNode::ForEachSiblingElement(NodeCallback const &callback) const {
void XMLNode::ForEachSiblingElementWithName(
const char *name, NodeCallback const &callback) const {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid()) {
// iterate through all siblings
@@ -269,7 +270,7 @@ void XMLNode::ForEachSiblingElementWithName(
}
llvm::StringRef XMLNode::GetName() const {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid()) {
if (m_node->name)
return llvm::StringRef((const char *)m_node->name);
@@ -280,7 +281,7 @@ llvm::StringRef XMLNode::GetName() const {
bool XMLNode::GetElementText(std::string &text) const {
text.clear();
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid()) {
bool success = false;
if (m_node->type == XML_ELEMENT_NODE) {
@@ -302,7 +303,7 @@ bool XMLNode::GetElementText(std::string &text) const {
bool XMLNode::GetElementTextAsUnsigned(uint64_t &value, uint64_t fail_value,
int base) const {
bool success = false;
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid()) {
std::string text;
if (GetElementText(text))
@@ -316,7 +317,7 @@ bool XMLNode::GetElementTextAsUnsigned(uint64_t &value, uint64_t fail_value,
bool XMLNode::GetElementTextAsFloat(double &value, double fail_value) const {
bool success = false;
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid()) {
std::string text;
if (GetElementText(text)) {
@@ -331,7 +332,7 @@ bool XMLNode::GetElementTextAsFloat(double &value, double fail_value) const {
}
bool XMLNode::NameIs(const char *name) const {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid()) {
// In case we are looking for a nullptr name or an exact pointer match
@@ -347,7 +348,7 @@ bool XMLNode::NameIs(const char *name) const {
XMLNode XMLNode::FindFirstChildElementWithName(const char *name) const {
XMLNode result_node;
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
ForEachChildElementWithName(
name, [&result_node](const XMLNode &node) -> bool {
result_node = node;
@@ -362,7 +363,7 @@ XMLNode XMLNode::FindFirstChildElementWithName(const char *name) const {
bool XMLNode::IsValid() const { return m_node != nullptr; }
bool XMLNode::IsElement() const {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid())
return m_node->type == XML_ELEMENT_NODE;
#endif
@@ -370,7 +371,7 @@ bool XMLNode::IsElement() const {
}
XMLNode XMLNode::GetElementForPath(const NamePath &path) {
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid()) {
if (path.empty())
@@ -430,7 +431,7 @@ bool ApplePropertyList::GetValueAsString(const char *key,
XMLNode ApplePropertyList::GetValueNode(const char *key) const {
XMLNode value_node;
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid()) {
m_dict_node.ForEachChildElementWithName(
@@ -454,7 +455,7 @@ XMLNode ApplePropertyList::GetValueNode(const char *key) const {
bool ApplePropertyList::ExtractStringFromValueNode(const XMLNode &node,
std::string &value) {
value.clear();
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (node.IsValid()) {
llvm::StringRef element_name = node.GetName();
if (element_name == "true" || element_name == "false") {
@@ -470,7 +471,7 @@ bool ApplePropertyList::ExtractStringFromValueNode(const XMLNode &node,
return false;
}
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
namespace {
@@ -532,7 +533,7 @@ StructuredData::ObjectSP CreatePlistValue(XMLNode node) {
StructuredData::ObjectSP ApplePropertyList::GetStructuredData() {
StructuredData::ObjectSP root_sp;
-#if defined(LIBXML2_DEFINED)
+#if LLDB_ENABLE_LIBXML2
if (IsValid()) {
return CreatePlistValue(m_dict_node);
}
diff --git a/lldb/source/Host/netbsd/Host.cpp b/lldb/source/Host/netbsd/Host.cpp
index 08fec099bf49..20f3db3c22c1 100644
--- a/lldb/source/Host/netbsd/Host.cpp
+++ b/lldb/source/Host/netbsd/Host.cpp
@@ -78,6 +78,7 @@ static bool GetNetBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,
match_info_ptr->GetProcessInfo().GetName())))
return false;
+ process_info.SetArg0(cstr);
Args &proc_args = process_info.GetArguments();
while (1) {
const uint8_t *p = data.PeekData(offset, 1);
diff --git a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
index 325d854921e3..2223e1625b19 100644
--- a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
+++ b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
@@ -26,7 +26,7 @@
#include <string.h>
#include <sys/types.h>
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
#include <termios.h>
#include <unistd.h>
#endif
@@ -179,7 +179,7 @@ ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path,
// unix-abstract-connect://SOCKNAME
return UnixAbstractSocketConnect(*addr, error_ptr);
}
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
else if ((addr = GetURLAddress(path, FD_SCHEME))) {
// Just passing a native file descriptor within this current process that
// is already opened (possibly from a service or other source).
diff --git a/lldb/source/Host/posix/FileSystem.cpp b/lldb/source/Host/posix/FileSystemPosix.cpp
index 32fae68abb4d..32fae68abb4d 100644
--- a/lldb/source/Host/posix/FileSystem.cpp
+++ b/lldb/source/Host/posix/FileSystemPosix.cpp
diff --git a/lldb/source/Host/posix/PipePosix.cpp b/lldb/source/Host/posix/PipePosix.cpp
index efdc151e3763..ce1baf3f12a3 100644
--- a/lldb/source/Host/posix/PipePosix.cpp
+++ b/lldb/source/Host/posix/PipePosix.cpp
@@ -270,8 +270,8 @@ Status PipePosix::ReadWithTimeout(void *buf, size_t size,
while (error.Success()) {
error = select_helper.Select();
if (error.Success()) {
- auto result = ::read(fd, reinterpret_cast<char *>(buf) + bytes_read,
- size - bytes_read);
+ auto result =
+ ::read(fd, static_cast<char *>(buf) + bytes_read, size - bytes_read);
if (result != -1) {
bytes_read += result;
if (bytes_read == size || result == 0)
@@ -301,9 +301,8 @@ Status PipePosix::Write(const void *buf, size_t size, size_t &bytes_written) {
while (error.Success()) {
error = select_helper.Select();
if (error.Success()) {
- auto result =
- ::write(fd, reinterpret_cast<const char *>(buf) + bytes_written,
- size - bytes_written);
+ auto result = ::write(fd, static_cast<const char *>(buf) + bytes_written,
+ size - bytes_written);
if (result != -1) {
bytes_written += result;
if (bytes_written == size)
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index 0c059096c6cd..1ee80503f569 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -48,7 +48,8 @@
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"
-#ifndef LLDB_DISABLE_LIBEDIT
+#include "lldb/Host/Config.h"
+#if LLDB_ENABLE_LIBEDIT
#include "lldb/Host/Editline.h"
#endif
#include "lldb/Host/Host.h"
@@ -137,9 +138,9 @@ bool CommandInterpreter::GetPromptOnQuit() const {
nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0);
}
-void CommandInterpreter::SetPromptOnQuit(bool b) {
+void CommandInterpreter::SetPromptOnQuit(bool enable) {
const uint32_t idx = ePropertyPromptOnQuit;
- m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, enable);
}
bool CommandInterpreter::GetEchoCommands() const {
@@ -148,9 +149,9 @@ bool CommandInterpreter::GetEchoCommands() const {
nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0);
}
-void CommandInterpreter::SetEchoCommands(bool b) {
+void CommandInterpreter::SetEchoCommands(bool enable) {
const uint32_t idx = ePropertyEchoCommands;
- m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, enable);
}
bool CommandInterpreter::GetEchoCommentCommands() const {
@@ -159,9 +160,9 @@ bool CommandInterpreter::GetEchoCommentCommands() const {
nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0);
}
-void CommandInterpreter::SetEchoCommentCommands(bool b) {
+void CommandInterpreter::SetEchoCommentCommands(bool enable) {
const uint32_t idx = ePropertyEchoCommentCommands;
- m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, enable);
}
void CommandInterpreter::AllowExitCodeOnQuit(bool allow) {
@@ -362,10 +363,23 @@ void CommandInterpreter::Initialize() {
"controlled by the type's author.");
po->SetHelpLong("");
}
- AddAlias("parray", cmd_obj_sp, "--element-count %1 --")->SetHelpLong("");
- AddAlias("poarray", cmd_obj_sp,
- "--object-description --element-count %1 --")
- ->SetHelpLong("");
+ CommandAlias *parray_alias =
+ AddAlias("parray", cmd_obj_sp, "--element-count %1 --");
+ if (parray_alias) {
+ parray_alias->SetHelp
+ ("parray <COUNT> <EXPRESSION> -- lldb will evaluate EXPRESSION "
+ "to get a typed-pointer-to-an-array in memory, and will display "
+ "COUNT elements of that type from the array.");
+ parray_alias->SetHelpLong("");
+ }
+ CommandAlias *poarray_alias = AddAlias("poarray", cmd_obj_sp,
+ "--object-description --element-count %1 --");
+ if (poarray_alias) {
+ poarray_alias->SetHelp("poarray <COUNT> <EXPRESSION> -- lldb will "
+ "evaluate EXPRESSION to get the address of an array of COUNT "
+ "objects in memory, and will call po on them.");
+ poarray_alias->SetHelpLong("");
+ }
}
cmd_obj_sp = GetCommandSPExact("process kill", false);
@@ -2825,8 +2839,7 @@ bool CommandInterpreter::IOHandlerInterrupt(IOHandler &io_handler) {
}
void CommandInterpreter::GetLLDBCommandsFromIOHandler(
- const char *prompt, IOHandlerDelegate &delegate, bool asynchronously,
- void *baton) {
+ const char *prompt, IOHandlerDelegate &delegate, void *baton) {
Debugger &debugger = GetDebugger();
IOHandlerSP io_handler_sp(
new IOHandlerEditline(debugger, IOHandler::Type::CommandList,
@@ -2841,16 +2854,12 @@ void CommandInterpreter::GetLLDBCommandsFromIOHandler(
if (io_handler_sp) {
io_handler_sp->SetUserData(baton);
- if (asynchronously)
- debugger.PushIOHandler(io_handler_sp);
- else
- debugger.RunIOHandler(io_handler_sp);
+ debugger.PushIOHandler(io_handler_sp);
}
}
void CommandInterpreter::GetPythonCommandsFromIOHandler(
- const char *prompt, IOHandlerDelegate &delegate, bool asynchronously,
- void *baton) {
+ const char *prompt, IOHandlerDelegate &delegate, void *baton) {
Debugger &debugger = GetDebugger();
IOHandlerSP io_handler_sp(
new IOHandlerEditline(debugger, IOHandler::Type::PythonCode,
@@ -2865,10 +2874,7 @@ void CommandInterpreter::GetPythonCommandsFromIOHandler(
if (io_handler_sp) {
io_handler_sp->SetUserData(baton);
- if (asynchronously)
- debugger.PushIOHandler(io_handler_sp);
- else
- debugger.RunIOHandler(io_handler_sp);
+ debugger.PushIOHandler(io_handler_sp);
}
}
diff --git a/lldb/source/Interpreter/CommandObjectScript.cpp b/lldb/source/Interpreter/CommandObjectScript.cpp
index edb1f67e7b37..d61d0cac9762 100644
--- a/lldb/source/Interpreter/CommandObjectScript.cpp
+++ b/lldb/source/Interpreter/CommandObjectScript.cpp
@@ -7,12 +7,9 @@
//===----------------------------------------------------------------------===//
#include "CommandObjectScript.h"
-
-
#include "lldb/Core/Debugger.h"
-
#include "lldb/DataFormatters/DataVisualization.h"
-
+#include "lldb/Host/Config.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
@@ -35,13 +32,6 @@ CommandObjectScript::~CommandObjectScript() {}
bool CommandObjectScript::DoExecute(llvm::StringRef command,
CommandReturnObject &result) {
-#ifdef LLDB_DISABLE_PYTHON
- // if we ever support languages other than Python this simple #ifdef won't
- // work
- result.AppendError("your copy of LLDB does not support scripting.");
- result.SetStatus(eReturnStatusFailed);
- return false;
-#else
if (m_interpreter.GetDebugger().GetScriptLanguage() ==
lldb::eScriptLanguageNone) {
result.AppendError(
@@ -58,9 +48,9 @@ bool CommandObjectScript::DoExecute(llvm::StringRef command,
return false;
}
- DataVisualization::ForceUpdate(); // script might change Python code we use
- // for formatting.. make sure we keep up to
- // date with it
+ // Script might change Python code we use for formatting. Make sure we keep
+ // up to date with it.
+ DataVisualization::ForceUpdate();
if (command.empty()) {
script_interpreter->ExecuteInterpreterLoop();
@@ -75,5 +65,4 @@ bool CommandObjectScript::DoExecute(llvm::StringRef command,
result.SetStatus(eReturnStatusFailed);
return result.Succeeded();
-#endif
}
diff --git a/lldb/source/Interpreter/OptionArgParser.cpp b/lldb/source/Interpreter/OptionArgParser.cpp
index 14b81cd7b3d2..56d99a4220f0 100644
--- a/lldb/source/Interpreter/OptionArgParser.cpp
+++ b/lldb/source/Interpreter/OptionArgParser.cpp
@@ -127,6 +127,8 @@ lldb::ScriptLanguage OptionArgParser::ToScriptLanguage(
if (s.equals_lower("python"))
return eScriptLanguagePython;
+ if (s.equals_lower("lua"))
+ return eScriptLanguageLua;
if (s.equals_lower("default"))
return eScriptLanguageDefault;
if (s.equals_lower("none"))
diff --git a/lldb/source/Interpreter/OptionGroupPythonClassWithDict.cpp b/lldb/source/Interpreter/OptionGroupPythonClassWithDict.cpp
index 9a893ec53625..e41f9d7b40ee 100644
--- a/lldb/source/Interpreter/OptionGroupPythonClassWithDict.cpp
+++ b/lldb/source/Interpreter/OptionGroupPythonClassWithDict.cpp
@@ -15,30 +15,29 @@ using namespace lldb_private;
OptionGroupPythonClassWithDict::OptionGroupPythonClassWithDict
(const char *class_use,
+ bool is_class,
int class_option,
int key_option,
- int value_option,
- const char *class_long_option,
- const char *key_long_option,
- const char *value_long_option,
- bool required) {
- m_key_usage_text.assign("The key for a key/value pair passed to the class"
- " that implements a ");
+ int value_option) : OptionGroup(), m_is_class(is_class) {
+ m_key_usage_text.assign("The key for a key/value pair passed to the "
+ "implementation of a ");
m_key_usage_text.append(class_use);
m_key_usage_text.append(". Pairs can be specified more than once.");
- m_value_usage_text.assign("The value for a previous key in the pair passed to"
- " the class that implements a ");
+ m_value_usage_text.assign("The value for the previous key in the pair passed "
+ "to the implementation of a ");
m_value_usage_text.append(class_use);
m_value_usage_text.append(". Pairs can be specified more than once.");
- m_class_usage_text.assign("The name of the class that will manage a ");
+ m_class_usage_text.assign("The name of the ");
+ m_class_usage_text.append(m_is_class ? "class" : "function");
+ m_class_usage_text.append(" that will manage a ");
m_class_usage_text.append(class_use);
m_class_usage_text.append(".");
m_option_definition[0].usage_mask = LLDB_OPT_SET_1;
- m_option_definition[0].required = required;
- m_option_definition[0].long_option = class_long_option;
+ m_option_definition[0].required = true;
+ m_option_definition[0].long_option = "script-class";
m_option_definition[0].short_option = class_option;
m_option_definition[0].validator = nullptr;
m_option_definition[0].option_has_arg = OptionParser::eRequiredArgument;
@@ -47,9 +46,9 @@ OptionGroupPythonClassWithDict::OptionGroupPythonClassWithDict
m_option_definition[0].argument_type = eArgTypePythonClass;
m_option_definition[0].usage_text = m_class_usage_text.data();
- m_option_definition[1].usage_mask = LLDB_OPT_SET_1;
- m_option_definition[1].required = required;
- m_option_definition[1].long_option = key_long_option;
+ m_option_definition[1].usage_mask = LLDB_OPT_SET_2;
+ m_option_definition[1].required = false;
+ m_option_definition[1].long_option = "structured-data-key";
m_option_definition[1].short_option = key_option;
m_option_definition[1].validator = nullptr;
m_option_definition[1].option_has_arg = OptionParser::eRequiredArgument;
@@ -58,9 +57,9 @@ OptionGroupPythonClassWithDict::OptionGroupPythonClassWithDict
m_option_definition[1].argument_type = eArgTypeNone;
m_option_definition[1].usage_text = m_key_usage_text.data();
- m_option_definition[2].usage_mask = LLDB_OPT_SET_1;
- m_option_definition[2].required = required;
- m_option_definition[2].long_option = value_long_option;
+ m_option_definition[2].usage_mask = LLDB_OPT_SET_2;
+ m_option_definition[2].required = false;
+ m_option_definition[2].long_option = "structured-data-value";
m_option_definition[2].short_option = value_option;
m_option_definition[2].validator = nullptr;
m_option_definition[2].option_has_arg = OptionParser::eRequiredArgument;
@@ -68,6 +67,18 @@ OptionGroupPythonClassWithDict::OptionGroupPythonClassWithDict
m_option_definition[2].completion_type = 0;
m_option_definition[2].argument_type = eArgTypeNone;
m_option_definition[2].usage_text = m_value_usage_text.data();
+
+ m_option_definition[3].usage_mask = LLDB_OPT_SET_3;
+ m_option_definition[3].required = true;
+ m_option_definition[3].long_option = "python-function";
+ m_option_definition[3].short_option = class_option;
+ m_option_definition[3].validator = nullptr;
+ m_option_definition[3].option_has_arg = OptionParser::eRequiredArgument;
+ m_option_definition[3].enum_values = {};
+ m_option_definition[3].completion_type = 0;
+ m_option_definition[3].argument_type = eArgTypePythonFunction;
+ m_option_definition[3].usage_text = m_class_usage_text.data();
+
}
OptionGroupPythonClassWithDict::~OptionGroupPythonClassWithDict() {}
@@ -78,10 +89,13 @@ Status OptionGroupPythonClassWithDict::SetOptionValue(
ExecutionContext *execution_context) {
Status error;
switch (option_idx) {
- case 0: {
- m_class_name.assign(option_arg);
+ case 0:
+ case 3: {
+ m_name.assign(option_arg);
} break;
case 1: {
+ if (!m_dict_sp)
+ m_dict_sp = std::make_shared<StructuredData::Dictionary>();
if (m_current_key.empty())
m_current_key.assign(option_arg);
else
@@ -90,6 +104,8 @@ Status OptionGroupPythonClassWithDict::SetOptionValue(
} break;
case 2: {
+ if (!m_dict_sp)
+ m_dict_sp = std::make_shared<StructuredData::Dictionary>();
if (!m_current_key.empty()) {
m_dict_sp->AddStringItem(m_current_key, option_arg);
m_current_key.clear();
@@ -107,7 +123,11 @@ Status OptionGroupPythonClassWithDict::SetOptionValue(
void OptionGroupPythonClassWithDict::OptionParsingStarting(
ExecutionContext *execution_context) {
m_current_key.erase();
- m_dict_sp = std::make_shared<StructuredData::Dictionary>();
+ // Leave the dictionary shared pointer unset. That way you can tell that
+ // the user didn't pass any -k -v pairs. We want to be able to warn if these
+ // were passed when the function they passed won't use them.
+ m_dict_sp.reset();
+ m_name.clear();
}
Status OptionGroupPythonClassWithDict::OptionParsingFinished(
diff --git a/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
index 81c10a6c762e..da0437ac299c 100644
--- a/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
+++ b/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
@@ -41,7 +41,7 @@ static const OptionDefinition g_option_table[] = {
{}, 0, eArgTypeNone, "Show variable location information."},
{LLDB_OPT_SET_1, false, "object-description", 'O',
OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone,
- "Print as an Objective-C object."},
+ "Display using a language-specific description API, if possible."},
{LLDB_OPT_SET_1, false, "ptr-depth", 'P', OptionParser::eRequiredArgument,
nullptr, {}, 0, eArgTypeCount, "The number of pointers to be traversed "
"when dumping values (default is zero)."},
diff --git a/lldb/source/Interpreter/OptionValueFileSpecList.cpp b/lldb/source/Interpreter/OptionValueFileSpecList.cpp
index 1a9d3c9ecb87..f2367b1941c9 100644
--- a/lldb/source/Interpreter/OptionValueFileSpecList.cpp
+++ b/lldb/source/Interpreter/OptionValueFileSpecList.cpp
@@ -33,7 +33,7 @@ void OptionValueFileSpecList::DumpValue(const ExecutionContext *exe_ctx,
strm.Indent();
strm.Printf("[%u]: ", i);
}
- m_current_value.GetFileSpecAtIndex(i).Dump(&strm);
+ m_current_value.GetFileSpecAtIndex(i).Dump(strm.AsRawOstream());
if (one_line)
strm << ' ';
}
diff --git a/lldb/source/Interpreter/OptionValueProperties.cpp b/lldb/source/Interpreter/OptionValueProperties.cpp
index 4dae930c3a6f..21750cf18615 100644
--- a/lldb/source/Interpreter/OptionValueProperties.cpp
+++ b/lldb/source/Interpreter/OptionValueProperties.cpp
@@ -60,10 +60,10 @@ void OptionValueProperties::Initialize(const PropertyDefinitions &defs) {
}
void OptionValueProperties::SetValueChangedCallback(
- uint32_t property_idx, OptionValueChangedCallback callback, void *baton) {
+ uint32_t property_idx, std::function<void()> callback) {
Property *property = ProtectedGetPropertyAtIndex(property_idx);
if (property)
- property->SetValueChangedCallback(callback, baton);
+ property->SetValueChangedCallback(std::move(callback));
}
void OptionValueProperties::AppendProperty(ConstString name,
diff --git a/lldb/source/Interpreter/Property.cpp b/lldb/source/Interpreter/Property.cpp
index 78209311e2e5..a81098373c25 100644
--- a/lldb/source/Interpreter/Property.cpp
+++ b/lldb/source/Interpreter/Property.cpp
@@ -292,8 +292,7 @@ void Property::DumpDescription(CommandInterpreter &interpreter, Stream &strm,
}
}
-void Property::SetValueChangedCallback(OptionValueChangedCallback callback,
- void *baton) {
+void Property::SetValueChangedCallback(std::function<void()> callback) {
if (m_value_sp)
- m_value_sp->SetValueChangedCallback(callback, baton);
+ m_value_sp->SetValueChangedCallback(std::move(callback));
}
diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp
index d04baec76e60..00c460612ac1 100644
--- a/lldb/source/Interpreter/ScriptInterpreter.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -32,32 +32,36 @@ void ScriptInterpreter::CollectDataForBreakpointCommandCallback(
CommandReturnObject &result) {
result.SetStatus(eReturnStatusFailed);
result.AppendError(
- "ScriptInterpreter::GetScriptCommands(StringList &) is not implemented.");
+ "This script interpreter does not support breakpoint callbacks.");
}
void ScriptInterpreter::CollectDataForWatchpointCommandCallback(
WatchpointOptions *bp_options, CommandReturnObject &result) {
result.SetStatus(eReturnStatusFailed);
result.AppendError(
- "ScriptInterpreter::GetScriptCommands(StringList &) is not implemented.");
+ "This script interpreter does not support watchpoint callbacks.");
}
-std::string ScriptInterpreter::LanguageToString(lldb::ScriptLanguage language) {
- std::string return_value;
+bool ScriptInterpreter::LoadScriptingModule(
+ const char *filename, bool init_session, lldb_private::Status &error,
+ StructuredData::ObjectSP *module_sp) {
+ error.SetErrorString(
+ "This script interpreter does not support importing modules.");
+ return false;
+}
+std::string ScriptInterpreter::LanguageToString(lldb::ScriptLanguage language) {
switch (language) {
case eScriptLanguageNone:
- return_value = "None";
- break;
+ return "None";
case eScriptLanguagePython:
- return_value = "Python";
- break;
+ return "Python";
+ case eScriptLanguageLua:
+ return "Lua";
case eScriptLanguageUnknown:
- return_value = "Unknown";
- break;
+ return "Unknown";
}
-
- return return_value;
+ llvm_unreachable("Unhandled ScriptInterpreter!");
}
lldb::ScriptLanguage
@@ -66,6 +70,8 @@ ScriptInterpreter::StringToLanguage(const llvm::StringRef &language) {
return eScriptLanguageNone;
if (language.equals_lower(LanguageToString(eScriptLanguagePython)))
return eScriptLanguagePython;
+ if (language.equals_lower(LanguageToString(eScriptLanguageLua)))
+ return eScriptLanguageLua;
return eScriptLanguageUnknown;
}
@@ -81,12 +87,17 @@ Status ScriptInterpreter::SetBreakpointCommandCallback(
return return_error;
}
-void ScriptInterpreter::SetBreakpointCommandCallbackFunction(
- std::vector<BreakpointOptions *> &bp_options_vec,
- const char *function_name) {
+Status ScriptInterpreter::SetBreakpointCommandCallbackFunction(
+ std::vector<BreakpointOptions *> &bp_options_vec, const char *function_name,
+ StructuredData::ObjectSP extra_args_sp) {
+ Status error;
for (BreakpointOptions *bp_options : bp_options_vec) {
- SetBreakpointCommandCallbackFunction(bp_options, function_name);
+ error = SetBreakpointCommandCallbackFunction(bp_options, function_name,
+ extra_args_sp);
+ if (!error.Success())
+ return error;
}
+ return error;
}
std::unique_ptr<ScriptInterpreterLocker>
diff --git a/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
index 6473ccf9a19a..ec7588dfb50c 100644
--- a/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
+++ b/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
@@ -2020,6 +2020,8 @@ bool ABIMacOSX_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
// registers x19 through x28 and sp are callee preserved. v8-v15 are non-
// volatile (and specifically only the lower 8 bytes of these regs), the rest
// of the fp/SIMD registers are volatile.
+//
+// v. https://github.com/ARM-software/software-standards/blob/master/abi/aapcs64/
// We treat x29 as callee preserved also, else the unwinder won't try to
// retrieve fp saves.
diff --git a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
index 28c9de2c1e96..dbdb3520087e 100644
--- a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
+++ b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
@@ -20,6 +20,7 @@
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/TargetRegistry.h"
@@ -949,8 +950,9 @@ DisassemblerLLVMC::MCDisasmInstance::Create(const char *triple, const char *cpu,
if (!subtarget_info_up)
return Instance();
+ llvm::MCTargetOptions MCOptions;
std::unique_ptr<llvm::MCAsmInfo> asm_info_up(
- curr_target->createMCAsmInfo(*reg_info_up, triple));
+ curr_target->createMCAsmInfo(*reg_info_up, triple, MCOptions));
if (!asm_info_up)
return Instance();
@@ -1018,7 +1020,7 @@ uint64_t DisassemblerLLVMC::MCDisasmInstance::GetMCInst(
uint64_t new_inst_size;
status = m_disasm_up->getInstruction(mc_inst, new_inst_size, data, pc,
- llvm::nulls(), llvm::nulls());
+ llvm::nulls());
if (status == llvm::MCDisassembler::Success)
return new_inst_size;
else
@@ -1032,8 +1034,8 @@ void DisassemblerLLVMC::MCDisasmInstance::PrintMCInst(
llvm::raw_string_ostream comments_stream(comments_string);
m_instr_printer_up->setCommentStream(comments_stream);
- m_instr_printer_up->printInst(&mc_inst, inst_stream, llvm::StringRef(),
- *m_subtarget_info_up);
+ m_instr_printer_up->printInst(&mc_inst, 0, llvm::StringRef(),
+ *m_subtarget_info_up, inst_stream);
m_instr_printer_up->setCommentStream(llvm::nulls());
comments_stream.flush();
@@ -1212,7 +1214,7 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
if (llvm_arch == llvm::Triple::arm) {
std::string thumb_triple(thumb_arch.GetTriple().getTriple());
m_alternate_disasm_up =
- MCDisasmInstance::Create(thumb_triple.c_str(), "", features_str.c_str(),
+ MCDisasmInstance::Create(thumb_triple.c_str(), "", features_str.c_str(),
flavor, *this);
if (!m_alternate_disasm_up)
m_disasm_up.reset();
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp
deleted file mode 100644
index f33a713cc0b2..000000000000
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-//===-- ASTDumper.cpp -------------------------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#include "ASTDumper.h"
-
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangUtil.h"
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Utility/Log.h"
-
-#include "llvm/Support/raw_ostream.h"
-
-using namespace lldb_private;
-
-ASTDumper::ASTDumper(clang::Decl *decl) {
- clang::DeclContext *decl_ctx = llvm::dyn_cast<clang::DeclContext>(decl);
-
- bool has_external_lexical_storage;
- bool has_external_visible_storage;
-
- if (decl_ctx) {
- has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage();
- has_external_visible_storage = decl_ctx->hasExternalVisibleStorage();
- decl_ctx->setHasExternalLexicalStorage(false);
- decl_ctx->setHasExternalVisibleStorage(false);
- }
-
- llvm::raw_string_ostream os(m_dump);
- decl->print(os);
- os.flush();
-
- if (decl_ctx) {
- decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage);
- decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage);
- }
-}
-
-ASTDumper::ASTDumper(clang::DeclContext *decl_ctx) {
- bool has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage();
- bool has_external_visible_storage = decl_ctx->hasExternalVisibleStorage();
-
- decl_ctx->setHasExternalLexicalStorage(false);
- decl_ctx->setHasExternalVisibleStorage(false);
-
- if (clang::Decl *decl = llvm::dyn_cast<clang::Decl>(decl_ctx)) {
- llvm::raw_string_ostream os(m_dump);
- decl->print(os);
- os.flush();
- } else {
- m_dump.assign("<DeclContext is not a Decl>");
- }
-
- decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage);
- decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage);
-}
-
-ASTDumper::ASTDumper(const clang::Type *type) {
- m_dump = clang::QualType(type, 0).getAsString();
-}
-
-ASTDumper::ASTDumper(clang::QualType type) { m_dump = type.getAsString(); }
-
-ASTDumper::ASTDumper(lldb::opaque_compiler_type_t type) {
- m_dump = clang::QualType::getFromOpaquePtr(type).getAsString();
-}
-
-ASTDumper::ASTDumper(const CompilerType &compiler_type) {
- m_dump = ClangUtil::GetQualType(compiler_type).getAsString();
-}
-
-const char *ASTDumper::GetCString() { return m_dump.c_str(); }
-
-void ASTDumper::ToLog(Log *log, const char *prefix) {
- size_t len = m_dump.length() + 1;
-
- char *alloc = (char *)malloc(len);
- char *str = alloc;
-
- memcpy(str, m_dump.c_str(), len);
-
- char *end = nullptr;
-
- end = strchr(str, '\n');
-
- while (end) {
- *end = '\0';
-
- LLDB_LOGF(log, "%s%s", prefix, str);
-
- *end = '\n';
-
- str = end + 1;
- end = strchr(str, '\n');
- }
-
- LLDB_LOGF(log, "%s%s", prefix, str);
-
- free(alloc);
-}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h
deleted file mode 100644
index ddf055d9c0c3..000000000000
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//===-- ASTDumper.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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_ASTDumper_h_
-#define liblldb_ASTDumper_h_
-
-#include "clang/AST/DeclVisitor.h"
-#include "clang/AST/TypeVisitor.h"
-
-#include "lldb/Utility/Stream.h"
-#include "llvm/ADT/DenseSet.h"
-
-namespace lldb_private {
-
-class ASTDumper {
-public:
- ASTDumper(clang::Decl *decl);
- ASTDumper(clang::DeclContext *decl_ctx);
- ASTDumper(const clang::Type *type);
- ASTDumper(clang::QualType type);
- ASTDumper(lldb::opaque_compiler_type_t type);
- ASTDumper(const CompilerType &compiler_type);
-
- const char *GetCString();
- void ToSTDERR();
- void ToLog(Log *log, const char *prefix);
- void ToStream(lldb::StreamSP &stream);
-
-private:
- std::string m_dump;
-};
-
-} // namespace lldb_private
-
-#endif
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
index 68eaad33f51c..77bb9544ea40 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
@@ -388,8 +388,7 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body,
// replace the old statement with the new one
//
- *last_stmt_ptr =
- reinterpret_cast<Stmt *>(result_initialization_stmt_result.get());
+ *last_stmt_ptr = static_cast<Stmt *>(result_initialization_stmt_result.get());
return true;
}
@@ -448,13 +447,20 @@ void ASTResultSynthesizer::RecordPersistentDecl(NamedDecl *D) {
}
void ASTResultSynthesizer::CommitPersistentDecls() {
+ auto *state =
+ m_target.GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC);
+ if (!state)
+ return;
+
+ auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state);
+ ClangASTContext *scratch_ctx = ClangASTContext::GetScratch(m_target);
+
for (clang::NamedDecl *decl : m_decls) {
StringRef name = decl->getName();
ConstString name_cs(name.str().c_str());
Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl(
- m_target.GetScratchClangASTContext()->getASTContext(), m_ast_context,
- decl);
+ &scratch_ctx->getASTContext(), decl);
if (!D_scratch) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
@@ -472,10 +478,8 @@ void ASTResultSynthesizer::CommitPersistentDecls() {
}
if (NamedDecl *NamedDecl_scratch = dyn_cast<NamedDecl>(D_scratch))
- llvm::cast<ClangPersistentVariables>(
- m_target.GetPersistentExpressionStateForLanguage(
- lldb::eLanguageTypeC))
- ->RegisterPersistentDecl(name_cs, NamedDecl_scratch);
+ persistent_vars->RegisterPersistentDecl(name_cs, NamedDecl_scratch,
+ scratch_ctx);
}
}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h
index 670ba6dce72e..0b0f3b97705d 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h
@@ -135,18 +135,11 @@ private:
void RecordPersistentTypes(clang::DeclContext *FunDeclCtx);
/// Given a TypeDecl, if it declares a type whose name starts with a dollar
- /// sign, register it as a pointer type in the target's scratch
- /// AST context.
- ///
- /// \param[in] Body
- /// The body of the function.
+ /// sign, register it as a pointer type in the target's scratch AST context.
void MaybeRecordPersistentType(clang::TypeDecl *D);
/// Given a NamedDecl, register it as a pointer type in the target's scratch
/// AST context.
- ///
- /// \param[in] Body
- /// The body of the function.
void RecordPersistentDecl(clang::NamedDecl *D);
clang::ASTContext
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp
index 190eacaa2b62..a164d48ae3e0 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp
@@ -30,8 +30,8 @@ ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough,
const char *struct_name,
ClangFunctionCaller &function)
: m_ast_context(nullptr), m_passthrough(passthrough),
- m_passthrough_sema(nullptr), m_sema(nullptr), m_action(nullptr),
- m_function(function), m_struct_name(struct_name) {
+ m_passthrough_sema(nullptr), m_sema(nullptr), m_function(function),
+ m_struct_name(struct_name) {
if (!m_passthrough)
return;
@@ -170,7 +170,6 @@ void ASTStructExtractor::PrintStats() {
void ASTStructExtractor::InitializeSema(Sema &S) {
m_sema = &S;
- m_action = reinterpret_cast<Action *>(m_sema);
if (m_passthrough_sema)
m_passthrough_sema->InitializeSema(S);
@@ -178,7 +177,6 @@ void ASTStructExtractor::InitializeSema(Sema &S) {
void ASTStructExtractor::ForgetSema() {
m_sema = nullptr;
- m_action = nullptr;
if (m_passthrough_sema)
m_passthrough_sema->ForgetSema();
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h
index 7aef2e254e1f..078cf095975f 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h
@@ -121,8 +121,6 @@ private:
///for passthrough. NULL if it's an
///ASTConsumer.
clang::Sema *m_sema; ///< The Sema to use.
- clang::Action
- *m_action; ///< The Sema to use, cast to an Action so it's usable.
ClangFunctionCaller &m_function; ///< The function to populate with
///information about the argument structure.
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
index 372c2439ebf0..42927ab6cc8a 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
@@ -8,7 +8,6 @@
#include "ClangASTSource.h"
-#include "ASTDumper.h"
#include "ClangDeclVendor.h"
#include "ClangModulesDeclVendor.h"
@@ -50,114 +49,42 @@ private:
};
}
-ClangASTSource::ClangASTSource(const lldb::TargetSP &target)
+ClangASTSource::ClangASTSource(const lldb::TargetSP &target,
+ const lldb::ClangASTImporterSP &importer)
: m_import_in_progress(false), m_lookups_enabled(false), m_target(target),
m_ast_context(nullptr), m_active_lexical_decls(), m_active_lookups() {
- if (!target->GetUseModernTypeLookup()) {
- m_ast_importer_sp = m_target->GetClangASTImporter();
- }
+ m_ast_importer_sp = importer;
}
-void ClangASTSource::InstallASTContext(clang::ASTContext &ast_context,
- clang::FileManager &file_manager,
- bool is_shared_context) {
- m_ast_context = &ast_context;
- m_file_manager = &file_manager;
- if (m_target->GetUseModernTypeLookup()) {
- // Configure the ExternalASTMerger. The merger needs to be able to import
- // types from any source that we would do lookups in, which includes the
- // persistent AST context as well as the modules and Objective-C runtime
- // AST contexts.
-
- lldbassert(!m_merger_up);
- clang::ExternalASTMerger::ImporterTarget target = {ast_context,
- file_manager};
- std::vector<clang::ExternalASTMerger::ImporterSource> sources;
- for (lldb::ModuleSP module_sp : m_target->GetImages().Modules()) {
- auto type_system_or_err =
- module_sp->GetTypeSystemForLanguage(lldb::eLanguageTypeC);
- if (auto err = type_system_or_err.takeError()) {
- LLDB_LOG_ERROR(
- lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS),
- std::move(err), "Failed to get ClangASTContext");
- } else if (auto *module_ast_ctx = llvm::cast_or_null<ClangASTContext>(
- &type_system_or_err.get())) {
- lldbassert(module_ast_ctx->getASTContext());
- lldbassert(module_ast_ctx->getFileManager());
- sources.emplace_back(*module_ast_ctx->getASTContext(),
- *module_ast_ctx->getFileManager(),
- module_ast_ctx->GetOriginMap());
- }
- }
-
- do {
- lldb::ProcessSP process(m_target->GetProcessSP());
-
- if (!process)
- break;
-
- ObjCLanguageRuntime *language_runtime(ObjCLanguageRuntime::Get(*process));
-
- if (!language_runtime)
- break;
-
- if (auto *runtime_decl_vendor = llvm::dyn_cast_or_null<ClangDeclVendor>(
- language_runtime->GetDeclVendor())) {
- sources.push_back(runtime_decl_vendor->GetImporterSource());
- }
- } while (false);
-
- do {
- auto *modules_decl_vendor = m_target->GetClangModulesDeclVendor();
-
- if (!modules_decl_vendor)
- break;
-
- sources.push_back(modules_decl_vendor->GetImporterSource());
- } while (false);
-
- if (!is_shared_context) {
- // Update the scratch AST context's merger to reflect any new sources we
- // might have come across since the last time an expression was parsed.
-
- auto scratch_ast_context = static_cast<ClangASTContextForExpressions*>(
- m_target->GetScratchClangASTContext());
-
- scratch_ast_context->GetMergerUnchecked().AddSources(sources);
-
- sources.push_back({*scratch_ast_context->getASTContext(),
- *scratch_ast_context->getFileManager(),
- scratch_ast_context->GetOriginMap()});
- }
-
- m_merger_up =
- std::make_unique<clang::ExternalASTMerger>(target, sources);
- } else {
- m_ast_importer_sp->InstallMapCompleter(&ast_context, *this);
- }
+void ClangASTSource::InstallASTContext(ClangASTContext &clang_ast_context) {
+ m_ast_context = &clang_ast_context.getASTContext();
+ m_clang_ast_context = &clang_ast_context;
+ m_file_manager = &m_ast_context->getSourceManager().getFileManager();
+ m_ast_importer_sp->InstallMapCompleter(m_ast_context, *this);
}
ClangASTSource::~ClangASTSource() {
- if (m_ast_importer_sp)
- m_ast_importer_sp->ForgetDestination(m_ast_context);
+ if (!m_ast_importer_sp)
+ return;
+
+ m_ast_importer_sp->ForgetDestination(m_ast_context);
+ if (!m_target)
+ return;
// We are in the process of destruction, don't create clang ast context on
// demand by passing false to
// Target::GetScratchClangASTContext(create_on_demand).
ClangASTContext *scratch_clang_ast_context =
- m_target->GetScratchClangASTContext(false);
+ ClangASTContext::GetScratch(*m_target, false);
if (!scratch_clang_ast_context)
return;
- clang::ASTContext *scratch_ast_context =
+ clang::ASTContext &scratch_ast_context =
scratch_clang_ast_context->getASTContext();
- if (!scratch_ast_context)
- return;
-
- if (m_ast_context != scratch_ast_context && m_ast_importer_sp)
- m_ast_importer_sp->ForgetSource(scratch_ast_context, m_ast_context);
+ if (m_ast_context != &scratch_ast_context && m_ast_importer_sp)
+ m_ast_importer_sp->ForgetSource(&scratch_ast_context, m_ast_context);
}
void ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer) {
@@ -279,9 +206,8 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) {
current_id, static_cast<void *>(m_ast_context),
static_cast<void *>(tag_decl), tag_decl->getName().str().c_str());
- LLDB_LOGF(log, " CTD[%u] Before:", current_id);
- ASTDumper dumper((Decl *)tag_decl);
- dumper.ToLog(log, " [CTD] ");
+ LLDB_LOG(log, " CTD[%u] Before:\n{0}", current_id,
+ ClangUtil::DumpDecl(tag_decl));
}
auto iter = m_active_lexical_decls.find(tag_decl);
@@ -291,9 +217,6 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) {
ScopedLexicalDeclEraser eraser(m_active_lexical_decls, tag_decl);
if (!m_ast_importer_sp) {
- if (HasMerger()) {
- GetMergerUnchecked().CompleteType(tag_decl);
- }
return;
}
@@ -365,7 +288,6 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) {
TypeList types;
ConstString name(tag_decl->getName().str().c_str());
- CompilerDeclContext namespace_decl;
const ModuleList &module_list = m_target->GetImages();
@@ -407,50 +329,30 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) {
}
}
- if (log) {
- LLDB_LOGF(log, " [CTD] After:");
- ASTDumper dumper((Decl *)tag_decl);
- dumper.ToLog(log, " [CTD] ");
- }
+ LLDB_LOG(log, " [CTD] After:\n{0}", ClangUtil::DumpDecl(tag_decl));
}
void ClangASTSource::CompleteType(clang::ObjCInterfaceDecl *interface_decl) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- if (log) {
- LLDB_LOGF(log,
- " [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing "
- "an ObjCInterfaceDecl named %s",
- static_cast<void *>(m_ast_context),
- interface_decl->getName().str().c_str());
- LLDB_LOGF(log, " [COID] Before:");
- ASTDumper dumper((Decl *)interface_decl);
- dumper.ToLog(log, " [COID] ");
- }
+ LLDB_LOGF(log,
+ " [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing "
+ "an ObjCInterfaceDecl named %s",
+ static_cast<void *>(m_ast_context),
+ interface_decl->getName().str().c_str());
+ LLDB_LOG(log, " [COID] Before:\n{0}",
+ ClangUtil::DumpDecl(interface_decl));
if (!m_ast_importer_sp) {
- if (HasMerger()) {
- ObjCInterfaceDecl *complete_iface_decl =
- GetCompleteObjCInterface(interface_decl);
-
- if (complete_iface_decl && (complete_iface_decl != interface_decl)) {
- m_merger_up->ForceRecordOrigin(interface_decl, {complete_iface_decl, &complete_iface_decl->getASTContext()});
- }
-
- GetMergerUnchecked().CompleteType(interface_decl);
- } else {
- lldbassert(0 && "No mechanism for completing a type!");
- }
+ lldbassert(0 && "No mechanism for completing a type!");
return;
}
- Decl *original_decl = nullptr;
- ASTContext *original_ctx = nullptr;
+ ClangASTImporter::DeclOrigin original = m_ast_importer_sp->GetDeclOrigin(interface_decl);
- if (m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl,
- &original_ctx)) {
+ if (original.Valid()) {
if (ObjCInterfaceDecl *original_iface_decl =
- dyn_cast<ObjCInterfaceDecl>(original_decl)) {
+ dyn_cast<ObjCInterfaceDecl>(original.decl)) {
ObjCInterfaceDecl *complete_iface_decl =
GetCompleteObjCInterface(original_iface_decl);
@@ -468,8 +370,7 @@ void ClangASTSource::CompleteType(clang::ObjCInterfaceDecl *interface_decl) {
if (log) {
LLDB_LOGF(log, " [COID] After:");
- ASTDumper dumper((Decl *)interface_decl);
- dumper.ToLog(log, " [COID] ");
+ LLDB_LOG(log, " [COID] {0}", ClangUtil::DumpDecl(interface_decl));
}
}
@@ -519,23 +420,9 @@ void ClangASTSource::FindExternalLexicalDecls(
llvm::function_ref<bool(Decl::Kind)> predicate,
llvm::SmallVectorImpl<Decl *> &decls) {
- if (HasMerger()) {
- if (auto *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl_context)) {
- ObjCInterfaceDecl *complete_iface_decl =
- GetCompleteObjCInterface(interface_decl);
-
- if (complete_iface_decl && (complete_iface_decl != interface_decl)) {
- m_merger_up->ForceRecordOrigin(interface_decl, {complete_iface_decl, &complete_iface_decl->getASTContext()});
- }
- }
- return GetMergerUnchecked().FindExternalLexicalDecls(decl_context,
- predicate,
- decls);
- } else if (!m_ast_importer_sp)
+ if (!m_ast_importer_sp)
return;
- ClangASTMetrics::RegisterLexicalQuery();
-
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
const Decl *context_decl = dyn_cast<Decl>(decl_context);
@@ -574,42 +461,38 @@ void ClangASTSource::FindExternalLexicalDecls(
current_id, static_cast<const void *>(m_ast_context));
}
- Decl *original_decl = nullptr;
- ASTContext *original_ctx = nullptr;
+ ClangASTImporter::DeclOrigin original = m_ast_importer_sp->GetDeclOrigin(context_decl);
- if (!m_ast_importer_sp->ResolveDeclOrigin(context_decl, &original_decl,
- &original_ctx))
+ if (!original.Valid())
return;
- if (log) {
- LLDB_LOGF(
- log, " FELD[%u] Original decl (ASTContext*)%p (Decl*)%p:", current_id,
- static_cast<void *>(original_ctx), static_cast<void *>(original_decl));
- ASTDumper(original_decl).ToLog(log, " ");
- }
+ LLDB_LOG(
+ log, " FELD[{0}] Original decl (ASTContext*){1:x} (Decl*){2:x}:\n{3}",
+ current_id, static_cast<void *>(original.ctx),
+ static_cast<void *>(original.decl), ClangUtil::DumpDecl(original.decl));
if (ObjCInterfaceDecl *original_iface_decl =
- dyn_cast<ObjCInterfaceDecl>(original_decl)) {
+ dyn_cast<ObjCInterfaceDecl>(original.decl)) {
ObjCInterfaceDecl *complete_iface_decl =
GetCompleteObjCInterface(original_iface_decl);
if (complete_iface_decl && (complete_iface_decl != original_iface_decl)) {
- original_decl = complete_iface_decl;
- original_ctx = &complete_iface_decl->getASTContext();
+ original.decl = complete_iface_decl;
+ original.ctx = &complete_iface_decl->getASTContext();
m_ast_importer_sp->SetDeclOrigin(context_decl, complete_iface_decl);
}
}
- if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original_decl)) {
- ExternalASTSource *external_source = original_ctx->getExternalSource();
+ if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original.decl)) {
+ ExternalASTSource *external_source = original.ctx->getExternalSource();
if (external_source)
external_source->CompleteType(original_tag_decl);
}
const DeclContext *original_decl_context =
- dyn_cast<DeclContext>(original_decl);
+ dyn_cast<DeclContext>(original.decl);
if (!original_decl_context)
return;
@@ -625,16 +508,16 @@ void ClangASTSource::FindExternalLexicalDecls(
// See clang::ExternalASTSource::FindExternalLexicalDecls()
if (predicate(decl->getKind())) {
if (log) {
- ASTDumper ast_dumper(decl);
+ std::string ast_dump = ClangUtil::DumpDecl(decl);
if (const NamedDecl *context_named_decl =
dyn_cast<NamedDecl>(context_decl))
LLDB_LOGF(log, " FELD[%d] Adding [to %sDecl %s] lexical %sDecl %s",
current_id, context_named_decl->getDeclKindName(),
context_named_decl->getNameAsString().c_str(),
- decl->getDeclKindName(), ast_dumper.GetCString());
+ decl->getDeclKindName(), ast_dump.c_str());
else
LLDB_LOGF(log, " FELD[%d] Adding lexical %sDecl %s", current_id,
- decl->getDeclKindName(), ast_dumper.GetCString());
+ decl->getDeclKindName(), ast_dump.c_str());
}
Decl *copied_decl = CopyDecl(decl);
@@ -647,20 +530,6 @@ void ClangASTSource::FindExternalLexicalDecls(
m_ast_importer_sp->RequireCompleteType(copied_field_type);
}
- auto decl_context_non_const = const_cast<DeclContext *>(decl_context);
-
- // The decl ended up in the wrong DeclContext. Let's fix that so
- // the decl we copied will actually be found.
- // FIXME: This is a horrible hack that shouldn't be necessary. However
- // it seems our current setup sometimes fails to copy decls to the right
- // place. See rdar://55129537.
- if (copied_decl->getDeclContext() != decl_context) {
- assert(copied_decl->getDeclContext()->containsDecl(copied_decl));
- copied_decl->getDeclContext()->removeDecl(copied_decl);
- copied_decl->setDeclContext(decl_context_non_const);
- assert(!decl_context_non_const->containsDecl(copied_decl));
- decl_context_non_const->addDeclInternal(copied_decl);
- }
} else {
SkippedDecls = true;
}
@@ -683,8 +552,6 @@ void ClangASTSource::FindExternalLexicalDecls(
void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) {
assert(m_ast_context);
- ClangASTMetrics::RegisterVisibleQuery();
-
const ConstString name(context.m_decl_name.getAsString().c_str());
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
@@ -715,25 +582,6 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) {
name.GetCString(), context.m_decl_context->getDeclKindName());
}
- if (HasMerger() && !isa<TranslationUnitDecl>(context.m_decl_context)
- /* possibly handle NamespaceDecls here? */) {
- if (auto *interface_decl =
- dyn_cast<ObjCInterfaceDecl>(context.m_decl_context)) {
- ObjCInterfaceDecl *complete_iface_decl =
- GetCompleteObjCInterface(interface_decl);
-
- if (complete_iface_decl && (complete_iface_decl != interface_decl)) {
- GetMergerUnchecked().ForceRecordOrigin(
- interface_decl,
- {complete_iface_decl, &complete_iface_decl->getASTContext()});
- }
- }
-
- GetMergerUnchecked().FindExternalVisibleDeclsByName(context.m_decl_context,
- context.m_decl_name);
- return; // otherwise we may need to fall back
- }
-
context.m_namespace_map = std::make_shared<ClangASTImporter::NamespaceMap>();
if (const NamespaceDecl *namespace_context =
@@ -758,7 +606,7 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) {
FindExternalVisibleDecls(context, i->first, i->second, current_id);
}
- } else if (isa<ObjCInterfaceDecl>(context.m_decl_context) && !HasMerger()) {
+ } else if (isa<ObjCInterfaceDecl>(context.m_decl_context)) {
FindObjCPropertyAndIvarDecls(context);
} else if (!isa<TranslationUnitDecl>(context.m_decl_context)) {
// we shouldn't be getting FindExternalVisibleDecls calls for these
@@ -788,7 +636,7 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) {
}
clang::Sema *ClangASTSource::getSema() {
- return ClangASTContext::GetASTContext(m_ast_context)->getSema();
+ return m_clang_ast_context->getSema();
}
bool ClangASTSource::IgnoreName(const ConstString name,
@@ -821,6 +669,9 @@ void ClangASTSource::FindExternalVisibleDecls(
if (IgnoreName(name, true))
return;
+ if (!m_target)
+ return;
+
if (module_sp && namespace_decl) {
CompilerDeclContext found_namespace_decl;
@@ -837,7 +688,7 @@ void ClangASTSource::FindExternalVisibleDecls(
module_sp->GetFileSpec().GetFilename().GetCString());
}
}
- } else if (!HasMerger()) {
+ } else {
const ModuleList &target_images = m_target->GetImages();
std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex());
@@ -1049,11 +900,10 @@ public:
template <class D>
DeclFromUser<D> DeclFromParser<D>::GetOrigin(ClangASTSource &source) {
- DeclFromUser<> origin_decl;
- source.ResolveDeclOrigin(this->decl, &origin_decl.decl, nullptr);
- if (origin_decl.IsInvalid())
+ ClangASTImporter::DeclOrigin origin = source.GetDeclOrigin(this->decl);
+ if (!origin.Valid())
return DeclFromUser<D>();
- return DeclFromUser<D>(dyn_cast<D>(origin_decl.decl));
+ return DeclFromUser<D>(dyn_cast<D>(origin.decl));
}
template <class D>
@@ -1137,11 +987,8 @@ bool ClangASTSource::FindObjCMethodDeclsWithOrigin(
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- if (log) {
- ASTDumper dumper((Decl *)copied_method_decl);
- LLDB_LOGF(log, " CAS::FOMD[%d] found (%s) %s", current_id, log_info,
- dumper.GetCString());
- }
+ LLDB_LOG(log, " CAS::FOMD[{0}] found ({1}) {2}", current_id, log_info,
+ ClangUtil::DumpDecl(copied_method_decl));
context.AddNamedDecl(copied_method_decl);
}
@@ -1152,21 +999,6 @@ bool ClangASTSource::FindObjCMethodDeclsWithOrigin(
void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- if (HasMerger()) {
- if (auto *interface_decl = dyn_cast<ObjCInterfaceDecl>(context.m_decl_context)) {
- ObjCInterfaceDecl *complete_iface_decl =
- GetCompleteObjCInterface(interface_decl);
-
- if (complete_iface_decl && (complete_iface_decl != context.m_decl_context)) {
- m_merger_up->ForceRecordOrigin(interface_decl, {complete_iface_decl, &complete_iface_decl->getASTContext()});
- }
- }
-
- GetMergerUnchecked().FindExternalVisibleDeclsByName(context.m_decl_context,
- context.m_decl_name);
- return;
- }
-
static unsigned int invocation_id = 0;
unsigned int current_id = invocation_id++;
@@ -1180,17 +1012,13 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) {
return;
do {
- Decl *original_decl = nullptr;
- ASTContext *original_ctx = nullptr;
-
- m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl,
- &original_ctx);
+ ClangASTImporter::DeclOrigin original = m_ast_importer_sp->GetDeclOrigin(interface_decl);
- if (!original_decl)
+ if (!original.Valid())
break;
ObjCInterfaceDecl *original_interface_decl =
- dyn_cast<ObjCInterfaceDecl>(original_decl);
+ dyn_cast<ObjCInterfaceDecl>(original.decl);
if (FindObjCMethodDeclsWithOrigin(current_id, context,
original_interface_decl, "at origin"))
@@ -1343,11 +1171,8 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) {
if (!copied_method_decl)
continue;
- if (log) {
- ASTDumper dumper((Decl *)copied_method_decl);
- LLDB_LOGF(log, " CAS::FOMD[%d] found (in symbols) %s", current_id,
- dumper.GetCString());
- }
+ LLDB_LOG(log, " CAS::FOMD[{0}] found (in symbols)\n{1}", current_id,
+ ClangUtil::DumpDecl(copied_method_decl));
context.AddNamedDecl(copied_method_decl);
}
@@ -1476,11 +1301,8 @@ static bool FindObjCPropertyAndIvarDeclsWithOrigin(
DeclFromParser<ObjCPropertyDecl> parser_property_decl(
origin_property_decl.Import(source));
if (parser_property_decl.IsValid()) {
- if (log) {
- ASTDumper dumper((Decl *)parser_property_decl.decl);
- LLDB_LOGF(log, " CAS::FOPD[%d] found %s", current_id,
- dumper.GetCString());
- }
+ LLDB_LOG(log, " CAS::FOPD[{0}] found\n{1}", current_id,
+ ClangUtil::DumpDecl(parser_property_decl.decl));
context.AddNamedDecl(parser_property_decl.decl);
found = true;
@@ -1495,9 +1317,8 @@ static bool FindObjCPropertyAndIvarDeclsWithOrigin(
origin_ivar_decl.Import(source));
if (parser_ivar_decl.IsValid()) {
if (log) {
- ASTDumper dumper((Decl *)parser_ivar_decl.decl);
- LLDB_LOGF(log, " CAS::FOPD[%d] found %s", current_id,
- dumper.GetCString());
+ LLDB_LOG(log, " CAS::FOPD[{0}] found\n{1}", current_id,
+ ClangUtil::DumpDecl(parser_ivar_decl.decl));
}
context.AddNamedDecl(parser_ivar_decl.decl);
@@ -1736,8 +1557,6 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size,
FieldOffsetMap &field_offsets,
BaseOffsetMap &base_offsets,
BaseOffsetMap &virtual_base_offsets) {
- ClangASTMetrics::RegisterRecordLayout();
-
static unsigned int invocation_id = 0;
unsigned int current_id = invocation_id++;
@@ -1984,90 +1803,37 @@ NamespaceDecl *ClangASTSource::AddNamespace(
return dyn_cast<NamespaceDecl>(copied_decl);
}
-clang::QualType ClangASTSource::CopyTypeWithMerger(
- clang::ASTContext &from_context,
- clang::ExternalASTMerger &merger,
- clang::QualType type) {
- if (!merger.HasImporterForOrigin(from_context)) {
- lldbassert(0 && "Couldn't find the importer for a source context!");
- return QualType();
- }
-
- if (llvm::Expected<QualType> type_or_error =
- merger.ImporterForOrigin(from_context).Import(type)) {
- return *type_or_error;
- } else {
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
- LLDB_LOG_ERROR(log, type_or_error.takeError(), "Couldn't import type: {0}");
- return QualType();
- }
-}
-
clang::Decl *ClangASTSource::CopyDecl(Decl *src_decl) {
- clang::ASTContext &from_context = src_decl->getASTContext();
if (m_ast_importer_sp) {
- return m_ast_importer_sp->CopyDecl(m_ast_context, &from_context, src_decl);
- } else if (m_merger_up) {
- if (!m_merger_up->HasImporterForOrigin(from_context)) {
- lldbassert(0 && "Couldn't find the importer for a source context!");
- return nullptr;
- }
-
- if (llvm::Expected<Decl *> decl_or_error =
- m_merger_up->ImporterForOrigin(from_context).Import(src_decl)) {
- return *decl_or_error;
- } else {
- Log *log =
- lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
- LLDB_LOG_ERROR(log, decl_or_error.takeError(),
- "Couldn't import decl: {0}");
- return nullptr;
- }
+ return m_ast_importer_sp->CopyDecl(m_ast_context, src_decl);
} else {
lldbassert(0 && "No mechanism for copying a decl!");
return nullptr;
}
}
-bool ClangASTSource::ResolveDeclOrigin(const clang::Decl *decl,
- clang::Decl **original_decl,
- clang::ASTContext **original_ctx) {
+ClangASTImporter::DeclOrigin ClangASTSource::GetDeclOrigin(const clang::Decl *decl) {
if (m_ast_importer_sp) {
- return m_ast_importer_sp->ResolveDeclOrigin(decl, original_decl,
- original_ctx);
- } else if (m_merger_up) {
- return false; // Implement this correctly in ExternalASTMerger
+ return m_ast_importer_sp->GetDeclOrigin(decl);
} else {
// this can happen early enough that no ExternalASTSource is installed.
- return false;
+ return ClangASTImporter::DeclOrigin();
}
}
-clang::ExternalASTMerger &ClangASTSource::GetMergerUnchecked() {
- lldbassert(m_merger_up != nullptr);
- return *m_merger_up;
-}
-
CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) {
ClangASTContext *src_ast =
llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem());
if (src_ast == nullptr)
return CompilerType();
- ClangASTMetrics::RegisterLLDBImport();
-
SetImportInProgress(true);
QualType copied_qual_type;
if (m_ast_importer_sp) {
- copied_qual_type =
- m_ast_importer_sp->CopyType(m_ast_context, src_ast->getASTContext(),
- ClangUtil::GetQualType(src_type));
- } else if (m_merger_up) {
- copied_qual_type =
- CopyTypeWithMerger(*src_ast->getASTContext(), *m_merger_up,
- ClangUtil::GetQualType(src_type));
+ copied_qual_type = ClangUtil::GetQualType(
+ m_ast_importer_sp->CopyType(*m_clang_ast_context, src_type));
} else {
lldbassert(0 && "No mechanism for copying a type!");
return CompilerType();
@@ -2081,8 +1847,7 @@ CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) {
// seems to be generating bad types on occasion.
return CompilerType();
- return CompilerType(ClangASTContext::GetASTContext(m_ast_context),
- copied_qual_type.getAsOpaquePtr());
+ return m_clang_ast_context->GetType(copied_qual_type);
}
clang::NamedDecl *NameSearchContext::AddVarDecl(const CompilerType &type) {
@@ -2098,10 +1863,10 @@ clang::NamedDecl *NameSearchContext::AddVarDecl(const CompilerType &type) {
IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo();
- clang::ASTContext *ast = lldb_ast->getASTContext();
+ clang::ASTContext &ast = lldb_ast->getASTContext();
clang::NamedDecl *Decl = VarDecl::Create(
- *ast, const_cast<DeclContext *>(m_decl_context), SourceLocation(),
+ ast, const_cast<DeclContext *>(m_decl_context), SourceLocation(),
SourceLocation(), ii, ClangUtil::GetQualType(type), nullptr, SC_Static);
m_decls.push_back(Decl);
@@ -2127,7 +1892,7 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type,
QualType qual_type(ClangUtil::GetQualType(type));
- clang::ASTContext *ast = lldb_ast->getASTContext();
+ clang::ASTContext &ast = lldb_ast->getASTContext();
const bool isInlineSpecified = false;
const bool hasWrittenPrototype = true;
@@ -2137,7 +1902,7 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type,
if (extern_c) {
context = LinkageSpecDecl::Create(
- *ast, context, SourceLocation(), SourceLocation(),
+ ast, context, SourceLocation(), SourceLocation(),
clang::LinkageSpecDecl::LanguageIDs::lang_c, false);
}
@@ -2149,7 +1914,7 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type,
: m_decl_name;
clang::FunctionDecl *func_decl = FunctionDecl::Create(
- *ast, context, SourceLocation(), SourceLocation(), decl_name, qual_type,
+ ast, context, SourceLocation(), SourceLocation(), decl_name, qual_type,
nullptr, SC_Extern, isInlineSpecified, hasWrittenPrototype,
isConstexprSpecified ? CSK_constexpr : CSK_unspecified);
@@ -2170,7 +1935,7 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type,
QualType arg_qual_type(func_proto_type->getParamType(ArgIndex));
parm_var_decls.push_back(
- ParmVarDecl::Create(*ast, const_cast<DeclContext *>(context),
+ ParmVarDecl::Create(ast, const_cast<DeclContext *>(context),
SourceLocation(), SourceLocation(), nullptr,
arg_qual_type, nullptr, SC_Static, nullptr));
}
@@ -2210,9 +1975,7 @@ clang::NamedDecl *NameSearchContext::AddGenericFunDecl() {
proto_info));
return AddFunDecl(
- CompilerType(ClangASTContext::GetASTContext(m_ast_source.m_ast_context),
- generic_function_type.getAsOpaquePtr()),
- true);
+ m_ast_source.m_clang_ast_context->GetType(generic_function_type), true);
}
clang::NamedDecl *
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
index 7a8bacf48a8f..3149b4266b2f 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
@@ -12,10 +12,9 @@
#include <set>
#include "lldb/Symbol/ClangASTImporter.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/Target.h"
-#include "clang/AST/ExternalASTMerger.h"
+#include "clang/AST/ExternalASTSource.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/SmallSet.h"
@@ -30,7 +29,7 @@ namespace lldb_private {
/// knows the name it is looking for, but nothing else. The ExternalSemaSource
/// class provides Decls (VarDecl, FunDecl, TypeDecl) to Clang for these
/// names, consulting the ClangExpressionDeclMap to do the actual lookups.
-class ClangASTSource : public ClangExternalASTSourceCommon,
+class ClangASTSource : public clang::ExternalASTSource,
public ClangASTImporter::MapCompleter {
public:
/// Constructor
@@ -39,7 +38,11 @@ public:
///
/// \param[in] target
/// A reference to the target containing debug information to use.
- ClangASTSource(const lldb::TargetSP &target);
+ ///
+ /// \param[in] importer
+ /// The ClangASTImporter to use.
+ ClangASTSource(const lldb::TargetSP &target,
+ const lldb::ClangASTImporterSP &importer);
/// Destructor
~ClangASTSource() override;
@@ -57,9 +60,7 @@ public:
}
void MaterializeVisibleDecls(const clang::DeclContext *DC) { return; }
- void InstallASTContext(clang::ASTContext &ast_context,
- clang::FileManager &file_manager,
- bool is_shared_context = false);
+ void InstallASTContext(ClangASTContext &ast_context);
//
// APIs for ExternalASTSource
@@ -89,7 +90,7 @@ public:
/// \param[in] DC
/// The DeclContext being searched.
///
- /// \param[in] isKindWeWant
+ /// \param[in] IsKindWeWant
/// A callback function that returns true given the
/// DeclKinds of desired Decls, and false otherwise.
///
@@ -155,7 +156,7 @@ public:
/// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() that
/// this object has something to say about undefined names.
///
- /// \param[in] ASTConsumer
+ /// \param[in] Consumer
/// Unused.
void StartTranslationUnit(clang::ASTConsumer *Consumer) override;
@@ -210,7 +211,7 @@ public:
///
/// Clang AST contexts like to own their AST sources, so this is a state-
/// free proxy object.
- class ClangASTSourceProxy : public ClangExternalASTSourceCommon {
+ class ClangASTSourceProxy : public clang::ExternalASTSource {
public:
ClangASTSourceProxy(ClangASTSource &original) : m_original(original) {}
@@ -249,18 +250,6 @@ public:
return m_original.StartTranslationUnit(Consumer);
}
- ClangASTMetadata *GetMetadata(const void *object) {
- return m_original.GetMetadata(object);
- }
-
- void SetMetadata(const void *object, ClangASTMetadata &metadata) {
- return m_original.SetMetadata(object, metadata);
- }
-
- bool HasMetadata(const void *object) {
- return m_original.HasMetadata(object);
- }
-
private:
ClangASTSource &m_original;
};
@@ -321,13 +310,6 @@ protected:
/// A wrapper for ClangASTContext::CopyType that sets a flag that
/// indicates that we should not respond to queries during import.
///
- /// \param[in] dest_context
- /// The target AST context, typically the parser's AST context.
- ///
- /// \param[in] source_context
- /// The source AST context, typically the AST context of whatever
- /// symbol file the type was found in.
- ///
/// \param[in] src_type
/// The source type.
///
@@ -341,7 +323,7 @@ public:
/// \param[in] name
/// The name to be considered.
///
- /// \param[in] ignore_all_dollar_nmmes
+ /// \param[in] ignore_all_dollar_names
/// True if $-names of all sorts should be ignored.
///
/// \return
@@ -358,24 +340,6 @@ public:
/// \return
/// A copy of the Decl in m_ast_context, or NULL if the copy failed.
clang::Decl *CopyDecl(clang::Decl *src_decl);
-
- /// Copies a single Type to the target of the given ExternalASTMerger.
- ///
- /// \param[in] src_context
- /// The ASTContext containing the type.
- ///
- /// \param[in] merger
- /// The merger to use. This isn't just *m_merger_up because it might be
- /// the persistent AST context's merger.
- ///
- /// \param[in] type
- /// The type to copy.
- ///
- /// \return
- /// A copy of the Type in the merger's target context.
- clang::QualType CopyTypeWithMerger(clang::ASTContext &src_context,
- clang::ExternalASTMerger &merger,
- clang::QualType type);
/// Determined the origin of a single Decl, if it can be found.
///
@@ -390,16 +354,7 @@ public:
///
/// \return
/// True if lookup succeeded; false otherwise.
- bool ResolveDeclOrigin(const clang::Decl *decl, clang::Decl **original_decl,
- clang::ASTContext **original_ctx);
-
- /// Returns m_merger_up. Only call this if the target is configured to use
- /// modern lookup,
- clang::ExternalASTMerger &GetMergerUnchecked();
-
- /// Returns true if there is a merger. This only occurs if the target is
- /// using modern lookup.
- bool HasMerger() { return (bool)m_merger_up; }
+ ClangASTImporter::DeclOrigin GetDeclOrigin(const clang::Decl *decl);
protected:
bool FindObjCMethodDeclsWithOrigin(
@@ -411,15 +366,16 @@ protected:
bool m_import_in_progress;
bool m_lookups_enabled;
- const lldb::TargetSP
- m_target; ///< The target to use in finding variables and types.
- clang::ASTContext
- *m_ast_context; ///< The AST context requests are coming in for.
- clang::FileManager
- *m_file_manager; ///< The file manager paired with the AST context.
- lldb::ClangASTImporterSP m_ast_importer_sp; ///< The target's AST importer.
- std::unique_ptr<clang::ExternalASTMerger> m_merger_up;
- ///< The ExternalASTMerger for this parse.
+ /// The target to use in finding variables and types.
+ const lldb::TargetSP m_target;
+ /// The AST context requests are coming in for.
+ clang::ASTContext *m_ast_context;
+ /// The ClangASTContext for m_ast_context.
+ ClangASTContext *m_clang_ast_context;
+ /// The file manager paired with the AST context.
+ clang::FileManager *m_file_manager;
+ /// The target's AST importer.
+ lldb::ClangASTImporterSP m_ast_importer_sp;
std::set<const clang::Decl *> m_active_lexical_decls;
std::set<const char *> m_active_lookups;
};
@@ -432,20 +388,20 @@ protected:
/// what name is being searched for and provides helper functions to construct
/// Decls given appropriate type information.
struct NameSearchContext {
- ClangASTSource &m_ast_source; ///< The AST source making the request
- llvm::SmallVectorImpl<clang::NamedDecl *>
- &m_decls; ///< The list of declarations already constructed
- ClangASTImporter::NamespaceMapSP m_namespace_map; ///< The mapping of all
- ///namespaces found for this
- ///request back to their
- ///modules
- const clang::DeclarationName &m_decl_name; ///< The name being looked for
- const clang::DeclContext
- *m_decl_context; ///< The DeclContext to put declarations into
- llvm::SmallSet<CompilerType, 5> m_function_types; ///< All the types of
- ///functions that have been
- ///reported, so we don't
- ///report conflicts
+ /// The AST source making the request.
+ ClangASTSource &m_ast_source;
+ /// The list of declarations already constructed.
+ llvm::SmallVectorImpl<clang::NamedDecl *> &m_decls;
+ /// The mapping of all namespaces found for this request back to their
+ /// modules.
+ ClangASTImporter::NamespaceMapSP m_namespace_map;
+ /// The name being looked for.
+ const clang::DeclarationName &m_decl_name;
+ /// The DeclContext to put declarations into.
+ const clang::DeclContext *m_decl_context;
+ /// All the types of functions that have been reported, so we don't
+ /// report conflicts.
+ llvm::SmallSet<CompilerType, 5> m_function_types;
struct {
bool variable : 1;
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp
index c59722b7b4f8..c87507a25855 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp
@@ -15,16 +15,16 @@ using namespace lldb_private;
uint32_t ClangDeclVendor::FindDecls(ConstString name, bool append,
uint32_t max_matches,
- std::vector<CompilerDecl> &decls) {
+ std::vector<clang::NamedDecl *> &decls) {
if (!append)
decls.clear();
- std::vector<clang::NamedDecl *> named_decls;
- uint32_t ret = FindDecls(name, /*append*/ false, max_matches, named_decls);
- for (auto *named_decl : named_decls) {
- decls.push_back(CompilerDecl(
- ClangASTContext::GetASTContext(&named_decl->getASTContext()),
- named_decl));
+ std::vector<CompilerDecl> compiler_decls;
+ uint32_t ret = FindDecls(name, /*append*/ false, max_matches, compiler_decls);
+ for (CompilerDecl compiler_decl : compiler_decls) {
+ clang::Decl *d = static_cast<clang::Decl *>(compiler_decl.GetOpaqueDecl());
+ clang::NamedDecl *nd = llvm::cast<clang::NamedDecl>(d);
+ decls.push_back(nd);
}
return ret;
}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h
index 90b715f37cba..0c888de08841 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h
@@ -12,8 +12,6 @@
#include "lldb/Core/ClangForward.h"
#include "lldb/Symbol/DeclVendor.h"
-#include "clang/AST/ExternalASTMerger.h"
-
namespace lldb_private {
// A clang specialized extension to DeclVendor.
@@ -23,19 +21,10 @@ public:
virtual ~ClangDeclVendor() {}
- /// Interface for ExternalASTMerger. Returns an ImporterSource allowing type
- /// completion.
- ///
- /// \return
- /// An ImporterSource for this ClangDeclVendor.
- virtual clang::ExternalASTMerger::ImporterSource GetImporterSource() = 0;
+ using DeclVendor::FindDecls;
uint32_t FindDecls(ConstString name, bool append, uint32_t max_matches,
- std::vector<CompilerDecl> &decls) override;
-
- virtual uint32_t FindDecls(ConstString name, bool append,
- uint32_t max_matches,
- std::vector<clang::NamedDecl *> &decls) = 0;
+ std::vector<clang::NamedDecl *> &decls);
static bool classof(const DeclVendor *vendor) {
return vendor->GetKind() >= eClangDeclVendor &&
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
index f4457fc1b740..bf3023be5f60 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -8,7 +8,6 @@
#include "ClangExpressionDeclMap.h"
-#include "ASTDumper.h"
#include "ClangASTSource.h"
#include "ClangModulesDeclVendor.h"
#include "ClangPersistentVariables.h"
@@ -20,6 +19,7 @@
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Expression/Materializer.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/CompilerDecl.h"
#include "lldb/Symbol/CompilerDeclContext.h"
@@ -65,9 +65,10 @@ const char *g_lldb_local_vars_namespace_cstr = "$__lldb_local_vars";
ClangExpressionDeclMap::ClangExpressionDeclMap(
bool keep_result_in_memory,
Materializer::PersistentVariableDelegate *result_delegate,
- ExecutionContext &exe_ctx, ValueObject *ctx_obj)
- : ClangASTSource(exe_ctx.GetTargetSP()), m_found_entities(),
- m_struct_members(), m_keep_result_in_memory(keep_result_in_memory),
+ const lldb::TargetSP &target, const lldb::ClangASTImporterSP &importer,
+ ValueObject *ctx_obj)
+ : ClangASTSource(target, importer), m_found_entities(), m_struct_members(),
+ m_keep_result_in_memory(keep_result_in_memory),
m_result_delegate(result_delegate), m_ctx_obj(ctx_obj), m_parser_vars(),
m_struct_vars() {
EnableStructVars();
@@ -84,8 +85,6 @@ ClangExpressionDeclMap::~ClangExpressionDeclMap() {
bool ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx,
Materializer *materializer) {
- ClangASTMetrics::ClearLocalCounters();
-
EnableParserVars();
m_parser_vars->m_exe_ctx = exe_ctx;
@@ -110,7 +109,7 @@ bool ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx,
m_parser_vars->m_persistent_vars = llvm::cast<ClangPersistentVariables>(
target->GetPersistentExpressionStateForLanguage(eLanguageTypeC));
- if (!target->GetScratchClangASTContext())
+ if (!ClangASTContext::GetScratch(*target))
return false;
}
@@ -127,12 +126,7 @@ void ClangExpressionDeclMap::InstallCodeGenerator(
}
void ClangExpressionDeclMap::DidParse() {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- ClangASTMetrics::DumpCounters(log);
-
- if (m_parser_vars) {
+ if (m_parser_vars && m_parser_vars->m_persistent_vars) {
for (size_t entity_index = 0, num_entities = m_found_entities.GetSize();
entity_index < num_entities; ++entity_index) {
ExpressionVariableSP var_sp(
@@ -180,55 +174,15 @@ ClangExpressionDeclMap::TargetInfo ClangExpressionDeclMap::GetTargetInfo() {
return ret;
}
-static clang::QualType ExportAllDeclaredTypes(
- clang::ExternalASTMerger &parent_merger, clang::ExternalASTMerger &merger,
- clang::ASTContext &source, clang::FileManager &source_file_manager,
- const clang::ExternalASTMerger::OriginMap &source_origin_map,
- clang::FileID file, clang::QualType root) {
- // Mark the source as temporary to make sure all declarations from the
- // AST are exported. Also add the parent_merger as the merger into the
- // source AST so that the merger can track back any declarations from
- // the persistent ASTs we used as sources.
- clang::ExternalASTMerger::ImporterSource importer_source(
- source, source_file_manager, source_origin_map, /*Temporary*/ true,
- &parent_merger);
- merger.AddSources(importer_source);
- clang::ASTImporter &exporter = merger.ImporterForOrigin(source);
- llvm::Expected<clang::QualType> ret_or_error = exporter.Import(root);
- merger.RemoveSources(importer_source);
- if (ret_or_error) {
- return *ret_or_error;
- } else {
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
- LLDB_LOG_ERROR(log, ret_or_error.takeError(), "Couldn't import type: {0}");
- return clang::QualType();
- }
-}
-
TypeFromUser ClangExpressionDeclMap::DeportType(ClangASTContext &target,
ClangASTContext &source,
TypeFromParser parser_type) {
- assert(&target == m_target->GetScratchClangASTContext());
+ assert(&target == ClangASTContext::GetScratch(*m_target));
assert((TypeSystem *)&source == parser_type.GetTypeSystem());
- assert(source.getASTContext() == m_ast_context);
+ assert(&source.getASTContext() == m_ast_context);
if (m_ast_importer_sp) {
- return TypeFromUser(m_ast_importer_sp->DeportType(
- target.getASTContext(), source.getASTContext(),
- parser_type.GetOpaqueQualType()),
- &target);
- } else if (m_merger_up) {
- clang::FileID source_file =
- source.getASTContext()->getSourceManager().getFileID(
- source.getASTContext()->getTranslationUnitDecl()->getLocation());
- auto scratch_ast_context = static_cast<ClangASTContextForExpressions *>(
- m_target->GetScratchClangASTContext());
- clang::QualType exported_type = ExportAllDeclaredTypes(
- *m_merger_up.get(), scratch_ast_context->GetMergerUnchecked(),
- *source.getASTContext(), *source.getFileManager(),
- m_merger_up->GetOrigins(), source_file,
- clang::QualType::getFromOpaquePtr(parser_type.GetOpaqueQualType()));
- return TypeFromUser(exported_type.getAsOpaquePtr(), &target);
+ return TypeFromUser(m_ast_importer_sp->DeportType(target, parser_type));
} else {
lldbassert(0 && "No mechanism for deporting a type!");
return TypeFromUser();
@@ -255,8 +209,11 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl,
if (target == nullptr)
return false;
- TypeFromUser user_type =
- DeportType(*target->GetScratchClangASTContext(), *ast, parser_type);
+ auto *clang_ast_context = ClangASTContext::GetScratch(*target);
+ if (!clang_ast_context)
+ return false;
+
+ TypeFromUser user_type = DeportType(*clang_ast_context, *ast, parser_type);
uint32_t offset = m_parser_vars->m_materializer->AddResultVariable(
user_type, is_lvalue, m_keep_result_in_memory, m_result_delegate, err);
@@ -291,7 +248,9 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl,
if (target == nullptr)
return false;
- ClangASTContext *context(target->GetScratchClangASTContext());
+ ClangASTContext *context = ClangASTContext::GetScratch(*target);
+ if (!context)
+ return false;
TypeFromUser user_type = DeportType(*context, *ast, parser_type);
@@ -303,6 +262,9 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl,
if (!m_parser_vars->m_target_info.IsValid())
return false;
+ if (!m_parser_vars->m_persistent_vars)
+ return false;
+
ClangExpressionVariable *var = llvm::cast<ClangExpressionVariable>(
m_parser_vars->m_persistent_vars
->CreatePersistentVariable(
@@ -368,7 +330,7 @@ bool ClangExpressionDeclMap::AddValueToStruct(const NamedDecl *decl,
ClangExpressionVariable *var(ClangExpressionVariable::FindVariableInList(
m_found_entities, decl, GetParserID()));
- if (!var) {
+ if (!var && m_parser_vars->m_persistent_vars) {
var = ClangExpressionVariable::FindVariableInList(
*m_parser_vars->m_persistent_vars, decl, GetParserID());
is_persistent_variable = true;
@@ -638,7 +600,7 @@ addr_t ClangExpressionDeclMap::GetSymbolAddress(ConstString name,
lldb::VariableSP ClangExpressionDeclMap::FindGlobalVariable(
Target &target, ModuleSP &module, ConstString name,
- CompilerDeclContext *namespace_decl, TypeFromUser *type) {
+ CompilerDeclContext *namespace_decl) {
VariableList vars;
if (module && namespace_decl)
@@ -646,21 +608,9 @@ lldb::VariableSP ClangExpressionDeclMap::FindGlobalVariable(
else
target.GetImages().FindGlobalVariables(name, -1, vars);
- if (vars.GetSize()) {
- if (type) {
- for (size_t i = 0; i < vars.GetSize(); ++i) {
- VariableSP var_sp = vars.GetVariableAtIndex(i);
-
- if (ClangASTContext::AreTypesSame(
- *type, var_sp->GetType()->GetFullCompilerType()))
- return var_sp;
- }
- } else {
- return vars.GetVariableAtIndex(0);
- }
- }
-
- return VariableSP();
+ if (vars.GetSize() == 0)
+ return VariableSP();
+ return vars.GetVariableAtIndex(0);
}
ClangASTContext *ClangExpressionDeclMap::GetClangASTContext() {
@@ -687,8 +637,6 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
NameSearchContext &context) {
assert(m_ast_context);
- ClangASTMetrics::RegisterVisibleQuery();
-
const ConstString name(context.m_decl_name.getAsString().c_str());
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
@@ -727,9 +675,9 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
dyn_cast<NamespaceDecl>(context.m_decl_context)) {
if (namespace_context->getName().str() ==
std::string(g_lldb_local_vars_namespace_cstr)) {
- CompilerDeclContext compiler_decl_ctx(
- GetClangASTContext(), const_cast<void *>(static_cast<const void *>(
- context.m_decl_context)));
+ CompilerDeclContext compiler_decl_ctx =
+ m_clang_ast_context->CreateDeclContext(
+ const_cast<clang::DeclContext *>(context.m_decl_context));
FindExternalVisibleDecls(context, lldb::ModuleSP(), compiler_decl_ctx,
current_id);
return;
@@ -771,743 +719,760 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
ClangASTSource::FindExternalVisibleDecls(context);
}
-void ClangExpressionDeclMap::FindExternalVisibleDecls(
- NameSearchContext &context, lldb::ModuleSP module_sp,
- CompilerDeclContext &namespace_decl, unsigned int current_id) {
- assert(m_ast_context);
+void ClangExpressionDeclMap::MaybeRegisterFunctionBody(
+ FunctionDecl *copied_function_decl) {
+ if (copied_function_decl->getBody() && m_parser_vars->m_code_gen) {
+ clang::DeclGroupRef decl_group_ref(copied_function_decl);
+ m_parser_vars->m_code_gen->HandleTopLevelDecl(decl_group_ref);
+ }
+}
- std::function<void(clang::FunctionDecl *)> MaybeRegisterFunctionBody =
- [this](clang::FunctionDecl *copied_function_decl) {
- if (copied_function_decl->getBody() && m_parser_vars->m_code_gen) {
- DeclGroupRef decl_group_ref(copied_function_decl);
- m_parser_vars->m_code_gen->HandleTopLevelDecl(decl_group_ref);
- }
- };
+clang::NamedDecl *ClangExpressionDeclMap::GetPersistentDecl(ConstString name) {
+ if (!m_parser_vars)
+ return nullptr;
+ Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
+ if (!target)
+ return nullptr;
+
+ ClangASTContext::GetScratch(*target);
+
+ if (!m_parser_vars->m_persistent_vars)
+ return nullptr;
+ return m_parser_vars->m_persistent_vars->GetPersistentDecl(name);
+}
+void ClangExpressionDeclMap::SearchPersistenDecls(NameSearchContext &context,
+ const ConstString name,
+ unsigned int current_id) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- SymbolContextList sc_list;
+ NamedDecl *persistent_decl = GetPersistentDecl(name);
- const ConstString name(context.m_decl_name.getAsString().c_str());
- if (IgnoreName(name, false))
+ if (!persistent_decl)
return;
- // Only look for functions by name out in our symbols if the function doesn't
- // start with our phony prefix of '$'
- Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
+ Decl *parser_persistent_decl = CopyDecl(persistent_decl);
+
+ if (!parser_persistent_decl)
+ return;
+
+ NamedDecl *parser_named_decl = dyn_cast<NamedDecl>(parser_persistent_decl);
+
+ if (!parser_named_decl)
+ return;
+
+ if (clang::FunctionDecl *parser_function_decl =
+ llvm::dyn_cast<clang::FunctionDecl>(parser_named_decl)) {
+ MaybeRegisterFunctionBody(parser_function_decl);
+ }
+
+ LLDB_LOGF(log, " CEDM::FEVD[%u] Found persistent decl %s", current_id,
+ name.GetCString());
+
+ context.AddNamedDecl(parser_named_decl);
+}
+
+void ClangExpressionDeclMap::LookUpLldbClass(NameSearchContext &context,
+ unsigned int current_id) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
SymbolContext sym_ctx;
if (frame != nullptr)
sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
lldb::eSymbolContextBlock);
- // Try the persistent decls, which take precedence over all else.
- if (!namespace_decl) {
- do {
- if (!target)
- break;
+ if (m_ctx_obj) {
+ Status status;
+ lldb::ValueObjectSP ctx_obj_ptr = m_ctx_obj->AddressOf(status);
+ if (!ctx_obj_ptr || status.Fail())
+ return;
- ClangASTContext *scratch_clang_ast_context =
- target->GetScratchClangASTContext();
+ AddThisType(context, TypeFromUser(m_ctx_obj->GetCompilerType()),
+ current_id);
- if (!scratch_clang_ast_context)
- break;
+ m_struct_vars->m_object_pointer_type =
+ TypeFromUser(ctx_obj_ptr->GetCompilerType());
- ASTContext *scratch_ast_context =
- scratch_clang_ast_context->getASTContext();
+ return;
+ }
- if (!scratch_ast_context)
- break;
+ // Clang is looking for the type of "this"
- NamedDecl *persistent_decl =
- m_parser_vars->m_persistent_vars->GetPersistentDecl(name);
+ if (frame == nullptr)
+ return;
- if (!persistent_decl)
- break;
+ // Find the block that defines the function represented by "sym_ctx"
+ Block *function_block = sym_ctx.GetFunctionBlock();
- Decl *parser_persistent_decl = CopyDecl(persistent_decl);
+ if (!function_block)
+ return;
- if (!parser_persistent_decl)
- break;
+ CompilerDeclContext function_decl_ctx = function_block->GetDeclContext();
- NamedDecl *parser_named_decl =
- dyn_cast<NamedDecl>(parser_persistent_decl);
+ if (!function_decl_ctx)
+ return;
- if (!parser_named_decl)
- break;
+ clang::CXXMethodDecl *method_decl =
+ ClangASTContext::DeclContextGetAsCXXMethodDecl(function_decl_ctx);
- if (clang::FunctionDecl *parser_function_decl =
- llvm::dyn_cast<clang::FunctionDecl>(parser_named_decl)) {
- MaybeRegisterFunctionBody(parser_function_decl);
- }
+ if (method_decl) {
+ clang::CXXRecordDecl *class_decl = method_decl->getParent();
- LLDB_LOGF(log, " CEDM::FEVD[%u] Found persistent decl %s", current_id,
- name.GetCString());
+ QualType class_qual_type(class_decl->getTypeForDecl(), 0);
- context.AddNamedDecl(parser_named_decl);
- } while (false);
- }
+ TypeFromUser class_user_type(class_qual_type.getAsOpaquePtr(),
+ function_decl_ctx.GetTypeSystem());
- if (name.GetCString()[0] == '$' && !namespace_decl) {
- static ConstString g_lldb_class_name("$__lldb_class");
+ LLDB_LOG(log, " CEDM::FEVD[{0}] Adding type for $__lldb_class: {1}",
+ current_id, class_qual_type.getAsString());
- if (name == g_lldb_class_name) {
- if (m_ctx_obj) {
- Status status;
- lldb::ValueObjectSP ctx_obj_ptr = m_ctx_obj->AddressOf(status);
- if (!ctx_obj_ptr || status.Fail())
- return;
+ AddThisType(context, class_user_type, current_id);
- AddThisType(context, TypeFromUser(m_ctx_obj->GetCompilerType()),
- current_id);
+ if (method_decl->isInstance()) {
+ // self is a pointer to the object
- m_struct_vars->m_object_pointer_type =
- TypeFromUser(ctx_obj_ptr->GetCompilerType());
+ QualType class_pointer_type =
+ method_decl->getASTContext().getPointerType(class_qual_type);
- return;
- }
+ TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(),
+ function_decl_ctx.GetTypeSystem());
- // Clang is looking for the type of "this"
+ m_struct_vars->m_object_pointer_type = self_user_type;
+ }
+ return;
+ }
- if (frame == nullptr)
- return;
+ // This branch will get hit if we are executing code in the context of
+ // a function that claims to have an object pointer (through
+ // DW_AT_object_pointer?) but is not formally a method of the class.
+ // In that case, just look up the "this" variable in the current scope
+ // and use its type.
+ // FIXME: This code is formally correct, but clang doesn't currently
+ // emit DW_AT_object_pointer
+ // for C++ so it hasn't actually been tested.
- // Find the block that defines the function represented by "sym_ctx"
- Block *function_block = sym_ctx.GetFunctionBlock();
+ VariableList *vars = frame->GetVariableList(false);
- if (!function_block)
- return;
+ lldb::VariableSP this_var = vars->FindVariable(ConstString("this"));
- CompilerDeclContext function_decl_ctx = function_block->GetDeclContext();
+ if (this_var && this_var->IsInScope(frame) &&
+ this_var->LocationIsValidForFrame(frame)) {
+ Type *this_type = this_var->GetType();
- if (!function_decl_ctx)
- return;
+ if (!this_type)
+ return;
- clang::CXXMethodDecl *method_decl =
- ClangASTContext::DeclContextGetAsCXXMethodDecl(function_decl_ctx);
+ TypeFromUser pointee_type =
+ this_type->GetForwardCompilerType().GetPointeeType();
- if (method_decl) {
- clang::CXXRecordDecl *class_decl = method_decl->getParent();
+ LLDB_LOG(log, " FEVD[{0}] Adding type for $__lldb_class: {1}", current_id,
+ ClangUtil::GetQualType(pointee_type).getAsString());
- QualType class_qual_type(class_decl->getTypeForDecl(), 0);
+ AddThisType(context, pointee_type, current_id);
+ TypeFromUser this_user_type(this_type->GetFullCompilerType());
+ m_struct_vars->m_object_pointer_type = this_user_type;
+ }
+}
- TypeFromUser class_user_type(
- class_qual_type.getAsOpaquePtr(),
- ClangASTContext::GetASTContext(&class_decl->getASTContext()));
+void ClangExpressionDeclMap::LookUpLldbObjCClass(NameSearchContext &context,
+ unsigned int current_id) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- if (log) {
- ASTDumper ast_dumper(class_qual_type);
- LLDB_LOGF(log, " CEDM::FEVD[%u] Adding type for $__lldb_class: %s",
- current_id, ast_dumper.GetCString());
- }
+ StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
- AddThisType(context, class_user_type, current_id);
+ if (m_ctx_obj) {
+ Status status;
+ lldb::ValueObjectSP ctx_obj_ptr = m_ctx_obj->AddressOf(status);
+ if (!ctx_obj_ptr || status.Fail())
+ return;
- if (method_decl->isInstance()) {
- // self is a pointer to the object
+ AddOneType(context, TypeFromUser(m_ctx_obj->GetCompilerType()), current_id);
- QualType class_pointer_type =
- method_decl->getASTContext().getPointerType(class_qual_type);
+ m_struct_vars->m_object_pointer_type =
+ TypeFromUser(ctx_obj_ptr->GetCompilerType());
- TypeFromUser self_user_type(
- class_pointer_type.getAsOpaquePtr(),
- ClangASTContext::GetASTContext(&method_decl->getASTContext()));
+ return;
+ }
- m_struct_vars->m_object_pointer_type = self_user_type;
- }
- } else {
- // This branch will get hit if we are executing code in the context of
- // a function that claims to have an object pointer (through
- // DW_AT_object_pointer?) but is not formally a method of the class.
- // In that case, just look up the "this" variable in the current scope
- // and use its type.
- // FIXME: This code is formally correct, but clang doesn't currently
- // emit DW_AT_object_pointer
- // for C++ so it hasn't actually been tested.
+ // Clang is looking for the type of "*self"
+
+ if (!frame)
+ return;
- VariableList *vars = frame->GetVariableList(false);
+ SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
+ lldb::eSymbolContextBlock);
- lldb::VariableSP this_var = vars->FindVariable(ConstString("this"));
+ // Find the block that defines the function represented by "sym_ctx"
+ Block *function_block = sym_ctx.GetFunctionBlock();
- if (this_var && this_var->IsInScope(frame) &&
- this_var->LocationIsValidForFrame(frame)) {
- Type *this_type = this_var->GetType();
+ if (!function_block)
+ return;
- if (!this_type)
- return;
+ CompilerDeclContext function_decl_ctx = function_block->GetDeclContext();
- TypeFromUser pointee_type =
- this_type->GetForwardCompilerType().GetPointeeType();
+ if (!function_decl_ctx)
+ return;
- if (pointee_type.IsValid()) {
- if (log) {
- ASTDumper ast_dumper(pointee_type);
- LLDB_LOGF(log, " FEVD[%u] Adding type for $__lldb_class: %s",
- current_id, ast_dumper.GetCString());
- }
+ clang::ObjCMethodDecl *method_decl =
+ ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx);
- AddThisType(context, pointee_type, current_id);
- TypeFromUser this_user_type(this_type->GetFullCompilerType());
- m_struct_vars->m_object_pointer_type = this_user_type;
- return;
- }
- }
- }
+ if (method_decl) {
+ ObjCInterfaceDecl *self_interface = method_decl->getClassInterface();
+ if (!self_interface)
return;
- }
- static ConstString g_lldb_objc_class_name("$__lldb_objc_class");
- if (name == g_lldb_objc_class_name) {
- if (m_ctx_obj) {
- Status status;
- lldb::ValueObjectSP ctx_obj_ptr = m_ctx_obj->AddressOf(status);
- if (!ctx_obj_ptr || status.Fail())
- return;
+ const clang::Type *interface_type = self_interface->getTypeForDecl();
- AddOneType(context, TypeFromUser(m_ctx_obj->GetCompilerType()),
- current_id);
+ if (!interface_type)
+ return; // This is unlikely, but we have seen crashes where this
+ // occurred
- m_struct_vars->m_object_pointer_type =
- TypeFromUser(ctx_obj_ptr->GetCompilerType());
+ TypeFromUser class_user_type(QualType(interface_type, 0).getAsOpaquePtr(),
+ function_decl_ctx.GetTypeSystem());
- return;
- }
+ LLDB_LOG(log, " FEVD[{0}] Adding type for $__lldb_objc_class: {1}",
+ current_id, ClangUtil::ToString(interface_type));
- // Clang is looking for the type of "*self"
+ AddOneType(context, class_user_type, current_id);
- if (!frame)
- return;
+ if (method_decl->isInstanceMethod()) {
+ // self is a pointer to the object
- SymbolContext sym_ctx = frame->GetSymbolContext(
- lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);
+ QualType class_pointer_type =
+ method_decl->getASTContext().getObjCObjectPointerType(
+ QualType(interface_type, 0));
- // Find the block that defines the function represented by "sym_ctx"
- Block *function_block = sym_ctx.GetFunctionBlock();
+ TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(),
+ function_decl_ctx.GetTypeSystem());
- if (!function_block)
- return;
+ m_struct_vars->m_object_pointer_type = self_user_type;
+ } else {
+ // self is a Class pointer
+ QualType class_type = method_decl->getASTContext().getObjCClassType();
- CompilerDeclContext function_decl_ctx = function_block->GetDeclContext();
+ TypeFromUser self_user_type(class_type.getAsOpaquePtr(),
+ function_decl_ctx.GetTypeSystem());
- if (!function_decl_ctx)
- return;
+ m_struct_vars->m_object_pointer_type = self_user_type;
+ }
- clang::ObjCMethodDecl *method_decl =
- ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx);
+ return;
+ }
+ // This branch will get hit if we are executing code in the context of
+ // a function that claims to have an object pointer (through
+ // DW_AT_object_pointer?) but is not formally a method of the class.
+ // In that case, just look up the "self" variable in the current scope
+ // and use its type.
- if (method_decl) {
- ObjCInterfaceDecl *self_interface = method_decl->getClassInterface();
+ VariableList *vars = frame->GetVariableList(false);
- if (!self_interface)
- return;
+ lldb::VariableSP self_var = vars->FindVariable(ConstString("self"));
- const clang::Type *interface_type = self_interface->getTypeForDecl();
+ if (!self_var)
+ return;
+ if (!self_var->IsInScope(frame))
+ return;
+ if (!self_var->LocationIsValidForFrame(frame))
+ return;
- if (!interface_type)
- return; // This is unlikely, but we have seen crashes where this
- // occurred
+ Type *self_type = self_var->GetType();
- TypeFromUser class_user_type(
- QualType(interface_type, 0).getAsOpaquePtr(),
- ClangASTContext::GetASTContext(&method_decl->getASTContext()));
+ if (!self_type)
+ return;
- if (log) {
- ASTDumper ast_dumper(interface_type);
- LLDB_LOGF(log, " FEVD[%u] Adding type for $__lldb_objc_class: %s",
- current_id, ast_dumper.GetCString());
- }
+ CompilerType self_clang_type = self_type->GetFullCompilerType();
- AddOneType(context, class_user_type, current_id);
+ if (ClangASTContext::IsObjCClassType(self_clang_type)) {
+ return;
+ }
+ if (!ClangASTContext::IsObjCObjectPointerType(self_clang_type))
+ return;
+ self_clang_type = self_clang_type.GetPointeeType();
- if (method_decl->isInstanceMethod()) {
- // self is a pointer to the object
+ if (!self_clang_type)
+ return;
- QualType class_pointer_type =
- method_decl->getASTContext().getObjCObjectPointerType(
- QualType(interface_type, 0));
+ LLDB_LOG(log, " FEVD[{0}] Adding type for $__lldb_objc_class: {1}",
+ current_id, ClangUtil::ToString(self_type->GetFullCompilerType()));
- TypeFromUser self_user_type(
- class_pointer_type.getAsOpaquePtr(),
- ClangASTContext::GetASTContext(&method_decl->getASTContext()));
+ TypeFromUser class_user_type(self_clang_type);
- m_struct_vars->m_object_pointer_type = self_user_type;
- } else {
- // self is a Class pointer
- QualType class_type = method_decl->getASTContext().getObjCClassType();
+ AddOneType(context, class_user_type, current_id);
- TypeFromUser self_user_type(
- class_type.getAsOpaquePtr(),
- ClangASTContext::GetASTContext(&method_decl->getASTContext()));
+ TypeFromUser self_user_type(self_type->GetFullCompilerType());
- m_struct_vars->m_object_pointer_type = self_user_type;
- }
+ m_struct_vars->m_object_pointer_type = self_user_type;
+}
- return;
- } else {
- // This branch will get hit if we are executing code in the context of
- // a function that claims to have an object pointer (through
- // DW_AT_object_pointer?) but is not formally a method of the class.
- // In that case, just look up the "self" variable in the current scope
- // and use its type.
+void ClangExpressionDeclMap::LookupLocalVarNamespace(
+ SymbolContext &sym_ctx, NameSearchContext &name_context) {
+ if (sym_ctx.block == nullptr)
+ return;
- VariableList *vars = frame->GetVariableList(false);
+ CompilerDeclContext frame_decl_context = sym_ctx.block->GetDeclContext();
+ if (!frame_decl_context)
+ return;
- lldb::VariableSP self_var = vars->FindVariable(ConstString("self"));
+ ClangASTContext *frame_ast = llvm::dyn_cast_or_null<ClangASTContext>(
+ frame_decl_context.GetTypeSystem());
+ if (!frame_ast)
+ return;
- if (self_var && self_var->IsInScope(frame) &&
- self_var->LocationIsValidForFrame(frame)) {
- Type *self_type = self_var->GetType();
+ clang::NamespaceDecl *namespace_decl =
+ m_clang_ast_context->GetUniqueNamespaceDeclaration(
+ g_lldb_local_vars_namespace_cstr, nullptr);
+ if (!namespace_decl)
+ return;
- if (!self_type)
- return;
+ name_context.AddNamedDecl(namespace_decl);
+ clang::DeclContext *ctxt = clang::Decl::castToDeclContext(namespace_decl);
+ ctxt->setHasExternalVisibleStorage(true);
+ name_context.m_found.local_vars_nsp = true;
+}
- CompilerType self_clang_type = self_type->GetFullCompilerType();
+void ClangExpressionDeclMap::LookupInModulesDeclVendor(
+ NameSearchContext &context, ConstString name, unsigned current_id) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- if (ClangASTContext::IsObjCClassType(self_clang_type)) {
- return;
- } else if (ClangASTContext::IsObjCObjectPointerType(
- self_clang_type)) {
- self_clang_type = self_clang_type.GetPointeeType();
+ if (!m_target)
+ return;
- if (!self_clang_type)
- return;
+ auto *modules_decl_vendor = m_target->GetClangModulesDeclVendor();
+ if (!modules_decl_vendor)
+ return;
- if (log) {
- ASTDumper ast_dumper(self_type->GetFullCompilerType());
- LLDB_LOGF(log,
- " FEVD[%u] Adding type for $__lldb_objc_class: %s",
- current_id, ast_dumper.GetCString());
- }
+ bool append = false;
+ uint32_t max_matches = 1;
+ std::vector<clang::NamedDecl *> decls;
- TypeFromUser class_user_type(self_clang_type);
+ if (!modules_decl_vendor->FindDecls(name, append, max_matches, decls))
+ return;
- AddOneType(context, class_user_type, current_id);
+ assert(!decls.empty() && "FindDecls returned true but no decls?");
+ clang::NamedDecl *const decl_from_modules = decls[0];
- TypeFromUser self_user_type(self_type->GetFullCompilerType());
+ LLDB_LOG(log,
+ " CAS::FEVD[{0}] Matching decl found for "
+ "\"{1}\" in the modules",
+ current_id, name);
- m_struct_vars->m_object_pointer_type = self_user_type;
- return;
- }
- }
- }
+ clang::Decl *copied_decl = CopyDecl(decl_from_modules);
+ if (!copied_decl) {
+ LLDB_LOG(log,
+ " CAS::FEVD[{0}] - Couldn't export a "
+ "declaration from the modules",
+ current_id);
+ return;
+ }
- return;
- }
+ if (auto copied_function = dyn_cast<clang::FunctionDecl>(copied_decl)) {
+ MaybeRegisterFunctionBody(copied_function);
- if (name == ConstString(g_lldb_local_vars_namespace_cstr)) {
- CompilerDeclContext frame_decl_context =
- sym_ctx.block != nullptr ? sym_ctx.block->GetDeclContext()
- : CompilerDeclContext();
-
- if (frame_decl_context) {
- ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(
- frame_decl_context.GetTypeSystem());
-
- if (ast) {
- clang::NamespaceDecl *namespace_decl =
- ClangASTContext::GetUniqueNamespaceDeclaration(
- m_ast_context, name.GetCString(), nullptr);
- if (namespace_decl) {
- context.AddNamedDecl(namespace_decl);
- clang::DeclContext *clang_decl_ctx =
- clang::Decl::castToDeclContext(namespace_decl);
- clang_decl_ctx->setHasExternalVisibleStorage(true);
- context.m_found.local_vars_nsp = true;
- }
- }
- }
+ context.AddNamedDecl(copied_function);
- return;
- }
+ context.m_found.function_with_type_info = true;
+ context.m_found.function = true;
+ } else if (auto copied_var = dyn_cast<clang::VarDecl>(copied_decl)) {
+ context.AddNamedDecl(copied_var);
+ context.m_found.variable = true;
+ }
+}
- // any other $__lldb names should be weeded out now
- if (name.GetStringRef().startswith("$__lldb"))
- return;
+bool ClangExpressionDeclMap::LookupLocalVariable(
+ NameSearchContext &context, ConstString name, unsigned current_id,
+ SymbolContext &sym_ctx, CompilerDeclContext &namespace_decl) {
+ if (sym_ctx.block == nullptr)
+ return false;
- ExpressionVariableSP pvar_sp(
- m_parser_vars->m_persistent_vars->GetVariable(name));
+ CompilerDeclContext decl_context = sym_ctx.block->GetDeclContext();
+ if (!decl_context)
+ return false;
- if (pvar_sp) {
- AddOneVariable(context, pvar_sp, current_id);
- return;
+ // Make sure that the variables are parsed so that we have the
+ // declarations.
+ StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
+ VariableListSP vars = frame->GetInScopeVariableList(true);
+ for (size_t i = 0; i < vars->GetSize(); i++)
+ vars->GetVariableAtIndex(i)->GetDecl();
+
+ // Search for declarations matching the name. Do not include imported
+ // decls in the search if we are looking for decls in the artificial
+ // namespace $__lldb_local_vars.
+ std::vector<CompilerDecl> found_decls =
+ decl_context.FindDeclByName(name, namespace_decl.IsValid());
+
+ VariableSP var;
+ bool variable_found = false;
+ for (CompilerDecl decl : found_decls) {
+ for (size_t vi = 0, ve = vars->GetSize(); vi != ve; ++vi) {
+ VariableSP candidate_var = vars->GetVariableAtIndex(vi);
+ if (candidate_var->GetDecl() == decl) {
+ var = candidate_var;
+ break;
+ }
}
- const char *reg_name(&name.GetCString()[1]);
+ if (var && !variable_found) {
+ variable_found = true;
+ ValueObjectSP valobj = ValueObjectVariable::Create(frame, var);
+ AddOneVariable(context, var, valobj, current_id);
+ context.m_found.variable = true;
+ }
+ }
+ return variable_found;
+}
- if (m_parser_vars->m_exe_ctx.GetRegisterContext()) {
- const RegisterInfo *reg_info(
- m_parser_vars->m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName(
- reg_name));
+/// Structure to hold the info needed when comparing function
+/// declarations.
+namespace {
+struct FuncDeclInfo {
+ ConstString m_name;
+ CompilerType m_copied_type;
+ uint32_t m_decl_lvl;
+ SymbolContext m_sym_ctx;
+};
+} // namespace
+
+SymbolContextList ClangExpressionDeclMap::SearchFunctionsInSymbolContexts(
+ const SymbolContextList &sc_list,
+ const CompilerDeclContext &frame_decl_context) {
+ // First, symplify things by looping through the symbol contexts to
+ // remove unwanted functions and separate out the functions we want to
+ // compare and prune into a separate list. Cache the info needed about
+ // the function declarations in a vector for efficiency.
+ uint32_t num_indices = sc_list.GetSize();
+ SymbolContextList sc_sym_list;
+ std::vector<FuncDeclInfo> decl_infos;
+ decl_infos.reserve(num_indices);
+ clang::DeclContext *frame_decl_ctx =
+ (clang::DeclContext *)frame_decl_context.GetOpaqueDeclContext();
+ ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(
+ frame_decl_context.GetTypeSystem());
- if (reg_info) {
- LLDB_LOGF(log, " CEDM::FEVD[%u] Found register %s", current_id,
- reg_info->name);
+ for (uint32_t index = 0; index < num_indices; ++index) {
+ FuncDeclInfo fdi;
+ SymbolContext sym_ctx;
+ sc_list.GetContextAtIndex(index, sym_ctx);
- AddOneRegister(context, reg_info, current_id);
- }
+ // We don't know enough about symbols to compare them, but we should
+ // keep them in the list.
+ Function *function = sym_ctx.function;
+ if (!function) {
+ sc_sym_list.Append(sym_ctx);
+ continue;
+ }
+ // Filter out functions without declaration contexts, as well as
+ // class/instance methods, since they'll be skipped in the code that
+ // follows anyway.
+ CompilerDeclContext func_decl_context = function->GetDeclContext();
+ if (!func_decl_context ||
+ func_decl_context.IsClassMethod(nullptr, nullptr, nullptr))
+ continue;
+ // We can only prune functions for which we can copy the type.
+ CompilerType func_clang_type = function->GetType()->GetFullCompilerType();
+ CompilerType copied_func_type = GuardedCopyType(func_clang_type);
+ if (!copied_func_type) {
+ sc_sym_list.Append(sym_ctx);
+ continue;
}
- } else {
- ValueObjectSP valobj;
- VariableSP var;
-
- bool local_var_lookup =
- !namespace_decl || (namespace_decl.GetName() ==
- ConstString(g_lldb_local_vars_namespace_cstr));
- if (frame && local_var_lookup) {
- CompilerDeclContext compiler_decl_context =
- sym_ctx.block != nullptr ? sym_ctx.block->GetDeclContext()
- : CompilerDeclContext();
-
- if (compiler_decl_context) {
- // Make sure that the variables are parsed so that we have the
- // declarations.
- VariableListSP vars = frame->GetInScopeVariableList(true);
- for (size_t i = 0; i < vars->GetSize(); i++)
- vars->GetVariableAtIndex(i)->GetDecl();
-
- // Search for declarations matching the name. Do not include imported
- // decls in the search if we are looking for decls in the artificial
- // namespace $__lldb_local_vars.
- std::vector<CompilerDecl> found_decls =
- compiler_decl_context.FindDeclByName(name,
- namespace_decl.IsValid());
-
- bool variable_found = false;
- for (CompilerDecl decl : found_decls) {
- for (size_t vi = 0, ve = vars->GetSize(); vi != ve; ++vi) {
- VariableSP candidate_var = vars->GetVariableAtIndex(vi);
- if (candidate_var->GetDecl() == decl) {
- var = candidate_var;
- break;
- }
- }
- if (var && !variable_found) {
- variable_found = true;
- valobj = ValueObjectVariable::Create(frame, var);
- AddOneVariable(context, var, valobj, current_id);
- context.m_found.variable = true;
- }
- }
- if (variable_found)
- return;
- }
+ fdi.m_sym_ctx = sym_ctx;
+ fdi.m_name = function->GetName();
+ fdi.m_copied_type = copied_func_type;
+ fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL;
+ if (fdi.m_copied_type && func_decl_context) {
+ // Call CountDeclLevels to get the number of parent scopes we have
+ // to look through before we find the function declaration. When
+ // comparing functions of the same type, the one with a lower count
+ // will be closer to us in the lookup scope and shadows the other.
+ clang::DeclContext *func_decl_ctx =
+ (clang::DeclContext *)func_decl_context.GetOpaqueDeclContext();
+ fdi.m_decl_lvl = ast->CountDeclLevels(frame_decl_ctx, func_decl_ctx,
+ &fdi.m_name, &fdi.m_copied_type);
}
- if (target) {
- var = FindGlobalVariable(*target, module_sp, name, &namespace_decl,
- nullptr);
+ decl_infos.emplace_back(fdi);
+ }
- if (var) {
- valobj = ValueObjectVariable::Create(target, var);
- AddOneVariable(context, var, valobj, current_id);
- context.m_found.variable = true;
- return;
- }
+ // Loop through the functions in our cache looking for matching types,
+ // then compare their scope levels to see which is closer.
+ std::multimap<CompilerType, const FuncDeclInfo *> matches;
+ for (const FuncDeclInfo &fdi : decl_infos) {
+ const CompilerType t = fdi.m_copied_type;
+ auto q = matches.find(t);
+ if (q != matches.end()) {
+ if (q->second->m_decl_lvl > fdi.m_decl_lvl)
+ // This function is closer; remove the old set.
+ matches.erase(t);
+ else if (q->second->m_decl_lvl < fdi.m_decl_lvl)
+ // The functions in our set are closer - skip this one.
+ continue;
}
+ matches.insert(std::make_pair(t, &fdi));
+ }
- std::vector<clang::NamedDecl *> decls_from_modules;
+ // Loop through our matches and add their symbol contexts to our list.
+ SymbolContextList sc_func_list;
+ for (const auto &q : matches)
+ sc_func_list.Append(q.second->m_sym_ctx);
- if (target) {
- if (ClangModulesDeclVendor *decl_vendor =
- target->GetClangModulesDeclVendor()) {
- decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules);
- }
- }
+ // Rejoin the lists with the functions in front.
+ sc_func_list.Append(sc_sym_list);
+ return sc_func_list;
+}
- const bool include_inlines = false;
- sc_list.Clear();
- if (namespace_decl && module_sp) {
- const bool include_symbols = false;
+void ClangExpressionDeclMap::LookupFunction(NameSearchContext &context,
+ lldb::ModuleSP module_sp,
+ ConstString name,
+ CompilerDeclContext &namespace_decl,
+ unsigned current_id) {
+ if (!m_parser_vars)
+ return;
- module_sp->FindFunctions(name, &namespace_decl, eFunctionNameTypeBase,
- include_symbols, include_inlines, sc_list);
- } else if (target && !namespace_decl) {
- const bool include_symbols = true;
+ Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
- // TODO Fix FindFunctions so that it doesn't return
- // instance methods for eFunctionNameTypeBase.
+ std::vector<clang::NamedDecl *> decls_from_modules;
- target->GetImages().FindFunctions(name, eFunctionNameTypeFull,
- include_symbols, include_inlines,
- sc_list);
+ if (target) {
+ if (ClangModulesDeclVendor *decl_vendor =
+ target->GetClangModulesDeclVendor()) {
+ decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules);
}
+ }
- // If we found more than one function, see if we can use the frame's decl
- // context to remove functions that are shadowed by other functions which
- // match in type but are nearer in scope.
- //
- // AddOneFunction will not add a function whose type has already been
- // added, so if there's another function in the list with a matching type,
- // check to see if their decl context is a parent of the current frame's or
- // was imported via a and using statement, and pick the best match
- // according to lookup rules.
- if (sc_list.GetSize() > 1) {
- // Collect some info about our frame's context.
- StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
- SymbolContext frame_sym_ctx;
- if (frame != nullptr)
- frame_sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
- lldb::eSymbolContextBlock);
- CompilerDeclContext frame_decl_context =
- frame_sym_ctx.block != nullptr ? frame_sym_ctx.block->GetDeclContext()
- : CompilerDeclContext();
-
- // We can't do this without a compiler decl context for our frame.
- if (frame_decl_context) {
- clang::DeclContext *frame_decl_ctx =
- (clang::DeclContext *)frame_decl_context.GetOpaqueDeclContext();
- ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(
- frame_decl_context.GetTypeSystem());
-
- // Structure to hold the info needed when comparing function
- // declarations.
- struct FuncDeclInfo {
- ConstString m_name;
- CompilerType m_copied_type;
- uint32_t m_decl_lvl;
- SymbolContext m_sym_ctx;
- };
-
- // First, symplify things by looping through the symbol contexts to
- // remove unwanted functions and separate out the functions we want to
- // compare and prune into a separate list. Cache the info needed about
- // the function declarations in a vector for efficiency.
- SymbolContextList sc_sym_list;
- uint32_t num_indices = sc_list.GetSize();
- std::vector<FuncDeclInfo> fdi_cache;
- fdi_cache.reserve(num_indices);
- for (uint32_t index = 0; index < num_indices; ++index) {
- FuncDeclInfo fdi;
- SymbolContext sym_ctx;
- sc_list.GetContextAtIndex(index, sym_ctx);
-
- // We don't know enough about symbols to compare them, but we should
- // keep them in the list.
- Function *function = sym_ctx.function;
- if (!function) {
- sc_sym_list.Append(sym_ctx);
- continue;
- }
- // Filter out functions without declaration contexts, as well as
- // class/instance methods, since they'll be skipped in the code that
- // follows anyway.
- CompilerDeclContext func_decl_context = function->GetDeclContext();
- if (!func_decl_context ||
- func_decl_context.IsClassMethod(nullptr, nullptr, nullptr))
- continue;
- // We can only prune functions for which we can copy the type.
- CompilerType func_clang_type =
- function->GetType()->GetFullCompilerType();
- CompilerType copied_func_type = GuardedCopyType(func_clang_type);
- if (!copied_func_type) {
- sc_sym_list.Append(sym_ctx);
- continue;
- }
+ const bool include_inlines = false;
+ SymbolContextList sc_list;
+ if (namespace_decl && module_sp) {
+ const bool include_symbols = false;
- fdi.m_sym_ctx = sym_ctx;
- fdi.m_name = function->GetName();
- fdi.m_copied_type = copied_func_type;
- fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL;
- if (fdi.m_copied_type && func_decl_context) {
- // Call CountDeclLevels to get the number of parent scopes we have
- // to look through before we find the function declaration. When
- // comparing functions of the same type, the one with a lower count
- // will be closer to us in the lookup scope and shadows the other.
- clang::DeclContext *func_decl_ctx =
- (clang::DeclContext *)func_decl_context.GetOpaqueDeclContext();
- fdi.m_decl_lvl = ast->CountDeclLevels(
- frame_decl_ctx, func_decl_ctx, &fdi.m_name, &fdi.m_copied_type);
- }
- fdi_cache.emplace_back(fdi);
- }
+ module_sp->FindFunctions(name, &namespace_decl, eFunctionNameTypeBase,
+ include_symbols, include_inlines, sc_list);
+ } else if (target && !namespace_decl) {
+ const bool include_symbols = true;
- // Loop through the functions in our cache looking for matching types,
- // then compare their scope levels to see which is closer.
- std::multimap<CompilerType, const FuncDeclInfo *> matches;
- for (const FuncDeclInfo &fdi : fdi_cache) {
- const CompilerType t = fdi.m_copied_type;
- auto q = matches.find(t);
- if (q != matches.end()) {
- if (q->second->m_decl_lvl > fdi.m_decl_lvl)
- // This function is closer; remove the old set.
- matches.erase(t);
- else if (q->second->m_decl_lvl < fdi.m_decl_lvl)
- // The functions in our set are closer - skip this one.
- continue;
- }
- matches.insert(std::make_pair(t, &fdi));
- }
+ // TODO Fix FindFunctions so that it doesn't return
+ // instance methods for eFunctionNameTypeBase.
- // Loop through our matches and add their symbol contexts to our list.
- SymbolContextList sc_func_list;
- for (const auto &q : matches)
- sc_func_list.Append(q.second->m_sym_ctx);
+ target->GetImages().FindFunctions(
+ name, eFunctionNameTypeFull | eFunctionNameTypeBase, include_symbols,
+ include_inlines, sc_list);
+ }
- // Rejoin the lists with the functions in front.
- sc_list = sc_func_list;
- sc_list.Append(sc_sym_list);
- }
+ // If we found more than one function, see if we can use the frame's decl
+ // context to remove functions that are shadowed by other functions which
+ // match in type but are nearer in scope.
+ //
+ // AddOneFunction will not add a function whose type has already been
+ // added, so if there's another function in the list with a matching type,
+ // check to see if their decl context is a parent of the current frame's or
+ // was imported via a and using statement, and pick the best match
+ // according to lookup rules.
+ if (sc_list.GetSize() > 1) {
+ // Collect some info about our frame's context.
+ StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
+ SymbolContext frame_sym_ctx;
+ if (frame != nullptr)
+ frame_sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
+ lldb::eSymbolContextBlock);
+ CompilerDeclContext frame_decl_context =
+ frame_sym_ctx.block != nullptr ? frame_sym_ctx.block->GetDeclContext()
+ : CompilerDeclContext();
+
+ // We can't do this without a compiler decl context for our frame.
+ if (frame_decl_context) {
+ sc_list = SearchFunctionsInSymbolContexts(sc_list, frame_decl_context);
}
+ }
- if (sc_list.GetSize()) {
- Symbol *extern_symbol = nullptr;
- Symbol *non_extern_symbol = nullptr;
-
- for (uint32_t index = 0, num_indices = sc_list.GetSize();
- index < num_indices; ++index) {
- SymbolContext sym_ctx;
- sc_list.GetContextAtIndex(index, sym_ctx);
+ if (sc_list.GetSize()) {
+ Symbol *extern_symbol = nullptr;
+ Symbol *non_extern_symbol = nullptr;
- if (sym_ctx.function) {
- CompilerDeclContext decl_ctx = sym_ctx.function->GetDeclContext();
+ for (uint32_t index = 0, num_indices = sc_list.GetSize();
+ index < num_indices; ++index) {
+ SymbolContext sym_ctx;
+ sc_list.GetContextAtIndex(index, sym_ctx);
- if (!decl_ctx)
- continue;
+ if (sym_ctx.function) {
+ CompilerDeclContext decl_ctx = sym_ctx.function->GetDeclContext();
- // Filter out class/instance methods.
- if (decl_ctx.IsClassMethod(nullptr, nullptr, nullptr))
- continue;
+ if (!decl_ctx)
+ continue;
- AddOneFunction(context, sym_ctx.function, nullptr, current_id);
- context.m_found.function_with_type_info = true;
- context.m_found.function = true;
- } else if (sym_ctx.symbol) {
- if (sym_ctx.symbol->GetType() == eSymbolTypeReExported && target) {
- sym_ctx.symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target);
- if (sym_ctx.symbol == nullptr)
- continue;
- }
+ // Filter out class/instance methods.
+ if (decl_ctx.IsClassMethod(nullptr, nullptr, nullptr))
+ continue;
- if (sym_ctx.symbol->IsExternal())
- extern_symbol = sym_ctx.symbol;
- else
- non_extern_symbol = sym_ctx.symbol;
+ AddOneFunction(context, sym_ctx.function, nullptr, current_id);
+ context.m_found.function_with_type_info = true;
+ context.m_found.function = true;
+ } else if (sym_ctx.symbol) {
+ if (sym_ctx.symbol->GetType() == eSymbolTypeReExported && target) {
+ sym_ctx.symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target);
+ if (sym_ctx.symbol == nullptr)
+ continue;
}
+
+ if (sym_ctx.symbol->IsExternal())
+ extern_symbol = sym_ctx.symbol;
+ else
+ non_extern_symbol = sym_ctx.symbol;
}
+ }
- if (!context.m_found.function_with_type_info) {
- for (clang::NamedDecl *decl : decls_from_modules) {
- if (llvm::isa<clang::FunctionDecl>(decl)) {
- clang::NamedDecl *copied_decl =
- llvm::cast_or_null<FunctionDecl>(CopyDecl(decl));
- if (copied_decl) {
- context.AddNamedDecl(copied_decl);
- context.m_found.function_with_type_info = true;
- }
+ if (!context.m_found.function_with_type_info) {
+ for (clang::NamedDecl *decl : decls_from_modules) {
+ if (llvm::isa<clang::FunctionDecl>(decl)) {
+ clang::NamedDecl *copied_decl =
+ llvm::cast_or_null<FunctionDecl>(CopyDecl(decl));
+ if (copied_decl) {
+ context.AddNamedDecl(copied_decl);
+ context.m_found.function_with_type_info = true;
}
}
}
+ }
- if (!context.m_found.function_with_type_info) {
- if (extern_symbol) {
- AddOneFunction(context, nullptr, extern_symbol, current_id);
- context.m_found.function = true;
- } else if (non_extern_symbol) {
- AddOneFunction(context, nullptr, non_extern_symbol, current_id);
- context.m_found.function = true;
- }
+ if (!context.m_found.function_with_type_info) {
+ if (extern_symbol) {
+ AddOneFunction(context, nullptr, extern_symbol, current_id);
+ context.m_found.function = true;
+ } else if (non_extern_symbol) {
+ AddOneFunction(context, nullptr, non_extern_symbol, current_id);
+ context.m_found.function = true;
}
}
+ }
+}
- if (!context.m_found.function_with_type_info) {
- // Try the modules next.
+void ClangExpressionDeclMap::FindExternalVisibleDecls(
+ NameSearchContext &context, lldb::ModuleSP module_sp,
+ CompilerDeclContext &namespace_decl, unsigned int current_id) {
+ assert(m_ast_context);
- do {
- if (ClangModulesDeclVendor *modules_decl_vendor =
- m_target->GetClangModulesDeclVendor()) {
- bool append = false;
- uint32_t max_matches = 1;
- std::vector<clang::NamedDecl *> decls;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- if (!modules_decl_vendor->FindDecls(name, append, max_matches, decls))
- break;
+ const ConstString name(context.m_decl_name.getAsString().c_str());
+ if (IgnoreName(name, false))
+ return;
- clang::NamedDecl *const decl_from_modules = decls[0];
+ // Only look for functions by name out in our symbols if the function doesn't
+ // start with our phony prefix of '$'
- if (llvm::isa<clang::FunctionDecl>(decl_from_modules)) {
- if (log) {
- LLDB_LOGF(log,
- " CAS::FEVD[%u] Matching function found for "
- "\"%s\" in the modules",
- current_id, name.GetCString());
- }
+ Target *target = nullptr;
+ StackFrame *frame = nullptr;
+ SymbolContext sym_ctx;
+ if (m_parser_vars) {
+ target = m_parser_vars->m_exe_ctx.GetTargetPtr();
+ frame = m_parser_vars->m_exe_ctx.GetFramePtr();
+ }
+ if (frame != nullptr)
+ sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
+ lldb::eSymbolContextBlock);
- clang::Decl *copied_decl = CopyDecl(decl_from_modules);
- clang::FunctionDecl *copied_function_decl =
- copied_decl ? dyn_cast<clang::FunctionDecl>(copied_decl)
- : nullptr;
+ // Try the persistent decls, which take precedence over all else.
+ if (!namespace_decl)
+ SearchPersistenDecls(context, name, current_id);
- if (!copied_function_decl) {
- LLDB_LOGF(log,
- " CAS::FEVD[%u] - Couldn't export a function "
- "declaration from the modules",
- current_id);
+ if (name.GetStringRef().startswith("$") && !namespace_decl) {
+ if (name == "$__lldb_class") {
+ LookUpLldbClass(context, current_id);
+ return;
+ }
- break;
- }
+ if (name == "$__lldb_objc_class") {
+ LookUpLldbObjCClass(context, current_id);
+ return;
+ }
+ if (name == g_lldb_local_vars_namespace_cstr) {
+ LookupLocalVarNamespace(sym_ctx, context);
+ return;
+ }
+
+ // any other $__lldb names should be weeded out now
+ if (name.GetStringRef().startswith("$__lldb"))
+ return;
- MaybeRegisterFunctionBody(copied_function_decl);
+ // No ParserVars means we can't do register or variable lookup.
+ if (!m_parser_vars || !m_parser_vars->m_persistent_vars)
+ return;
- context.AddNamedDecl(copied_function_decl);
+ ExpressionVariableSP pvar_sp(
+ m_parser_vars->m_persistent_vars->GetVariable(name));
- context.m_found.function_with_type_info = true;
- context.m_found.function = true;
- } else if (llvm::isa<clang::VarDecl>(decl_from_modules)) {
- if (log) {
- LLDB_LOGF(log,
- " CAS::FEVD[%u] Matching variable found for "
- "\"%s\" in the modules",
- current_id, name.GetCString());
- }
+ if (pvar_sp) {
+ AddOneVariable(context, pvar_sp, current_id);
+ return;
+ }
- clang::Decl *copied_decl = CopyDecl(decl_from_modules);
- clang::VarDecl *copied_var_decl =
- copied_decl ? dyn_cast_or_null<clang::VarDecl>(copied_decl)
- : nullptr;
+ assert(name.GetStringRef().startswith("$"));
+ llvm::StringRef reg_name = name.GetStringRef().substr(1);
- if (!copied_var_decl) {
- LLDB_LOGF(log,
- " CAS::FEVD[%u] - Couldn't export a variable "
- "declaration from the modules",
- current_id);
+ if (m_parser_vars->m_exe_ctx.GetRegisterContext()) {
+ const RegisterInfo *reg_info(
+ m_parser_vars->m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName(
+ reg_name));
- break;
- }
+ if (reg_info) {
+ LLDB_LOGF(log, " CEDM::FEVD[%u] Found register %s", current_id,
+ reg_info->name);
- context.AddNamedDecl(copied_var_decl);
+ AddOneRegister(context, reg_info, current_id);
+ }
+ }
+ return;
+ }
- context.m_found.variable = true;
- }
- }
- } while (false);
+ bool local_var_lookup = !namespace_decl || (namespace_decl.GetName() ==
+ g_lldb_local_vars_namespace_cstr);
+ if (frame && local_var_lookup)
+ if (LookupLocalVariable(context, name, current_id, sym_ctx, namespace_decl))
+ return;
+
+ if (target) {
+ ValueObjectSP valobj;
+ VariableSP var;
+ var = FindGlobalVariable(*target, module_sp, name, &namespace_decl);
+
+ if (var) {
+ valobj = ValueObjectVariable::Create(target, var);
+ AddOneVariable(context, var, valobj, current_id);
+ context.m_found.variable = true;
+ return;
}
+ }
- if (target && !context.m_found.variable && !namespace_decl) {
- // We couldn't find a non-symbol variable for this. Now we'll hunt for a
- // generic data symbol, and -- if it is found -- treat it as a variable.
- Status error;
+ LookupFunction(context, module_sp, name, namespace_decl, current_id);
- const Symbol *data_symbol =
- m_parser_vars->m_sym_ctx.FindBestGlobalDataSymbol(name, error);
+ // Try the modules next.
+ if (!context.m_found.function_with_type_info)
+ LookupInModulesDeclVendor(context, name, current_id);
- if (!error.Success()) {
- const unsigned diag_id =
- m_ast_context->getDiagnostics().getCustomDiagID(
- clang::DiagnosticsEngine::Level::Error, "%0");
- m_ast_context->getDiagnostics().Report(diag_id) << error.AsCString();
- }
+ if (target && !context.m_found.variable && !namespace_decl) {
+ // We couldn't find a non-symbol variable for this. Now we'll hunt for a
+ // generic data symbol, and -- if it is found -- treat it as a variable.
+ Status error;
- if (data_symbol) {
- std::string warning("got name from symbols: ");
- warning.append(name.AsCString());
- const unsigned diag_id =
- m_ast_context->getDiagnostics().getCustomDiagID(
- clang::DiagnosticsEngine::Level::Warning, "%0");
- m_ast_context->getDiagnostics().Report(diag_id) << warning.c_str();
- AddOneGenericVariable(context, *data_symbol, current_id);
- context.m_found.variable = true;
- }
+ const Symbol *data_symbol =
+ m_parser_vars->m_sym_ctx.FindBestGlobalDataSymbol(name, error);
+
+ if (!error.Success()) {
+ const unsigned diag_id =
+ m_ast_context->getDiagnostics().getCustomDiagID(
+ clang::DiagnosticsEngine::Level::Error, "%0");
+ m_ast_context->getDiagnostics().Report(diag_id) << error.AsCString();
+ }
+
+ if (data_symbol) {
+ std::string warning("got name from symbols: ");
+ warning.append(name.AsCString());
+ const unsigned diag_id =
+ m_ast_context->getDiagnostics().getCustomDiagID(
+ clang::DiagnosticsEngine::Level::Warning, "%0");
+ m_ast_context->getDiagnostics().Report(diag_id) << warning.c_str();
+ AddOneGenericVariable(context, *data_symbol, current_id);
+ context.m_found.variable = true;
}
}
}
@@ -1543,15 +1508,6 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var,
return false;
}
- ASTContext *ast = clang_ast->getASTContext();
-
- if (!ast) {
- if (log)
- log->PutCString(
- "There is no AST context for the current execution context");
- return false;
- }
-
DWARFExpression &var_location_expr = var->LocationExpression();
Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
@@ -1664,14 +1620,10 @@ void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
if (is_reference)
entity->m_flags |= ClangExpressionVariable::EVTypeIsReference;
- if (log) {
- ASTDumper orig_dumper(ut.GetOpaqueQualType());
- ASTDumper ast_dumper(var_decl);
- LLDB_LOGF(log,
- " CEDM::FEVD[%u] Found variable %s, returned %s (original %s)",
- current_id, decl_name.c_str(), ast_dumper.GetCString(),
- orig_dumper.GetCString());
- }
+ LLDB_LOG(log,
+ " CEDM::FEVD[{0}] Found variable {1}, returned\n{2} (original {3})",
+ current_id, decl_name, ClangUtil::DumpDecl(var_decl),
+ ClangUtil::ToString(ut));
}
void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
@@ -1703,11 +1655,8 @@ void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
parser_vars->m_llvm_value = nullptr;
parser_vars->m_lldb_value.Clear();
- if (log) {
- ASTDumper ast_dumper(var_decl);
- LLDB_LOGF(log, " CEDM::FEVD[%u] Added pvar %s, returned %s", current_id,
- pvar_sp->GetName().GetCString(), ast_dumper.GetCString());
- }
+ LLDB_LOG(log, " CEDM::FEVD[{0}] Added pvar {1}, returned\n{2}", current_id,
+ pvar_sp->GetName(), ClangUtil::DumpDecl(var_decl));
}
void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context,
@@ -1722,17 +1671,16 @@ void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context,
if (target == nullptr)
return;
- ASTContext *scratch_ast_context =
- target->GetScratchClangASTContext()->getASTContext();
+ ClangASTContext *scratch_ast_context = ClangASTContext::GetScratch(*target);
+ if (!scratch_ast_context)
+ return;
- TypeFromUser user_type(
- ClangASTContext::GetBasicType(scratch_ast_context, eBasicTypeVoid)
- .GetPointerType()
- .GetLValueReferenceType());
- TypeFromParser parser_type(
- ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid)
- .GetPointerType()
- .GetLValueReferenceType());
+ TypeFromUser user_type(scratch_ast_context->GetBasicType(eBasicTypeVoid)
+ .GetPointerType()
+ .GetLValueReferenceType());
+ TypeFromParser parser_type(m_clang_ast_context->GetBasicType(eBasicTypeVoid)
+ .GetPointerType()
+ .GetLValueReferenceType());
NamedDecl *var_decl = context.AddVarDecl(parser_type);
std::string decl_name(context.m_decl_name.getAsString());
@@ -1761,86 +1709,8 @@ void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context,
parser_vars->m_llvm_value = nullptr;
parser_vars->m_lldb_sym = &symbol;
- if (log) {
- ASTDumper ast_dumper(var_decl);
-
- LLDB_LOGF(log, " CEDM::FEVD[%u] Found variable %s, returned %s",
- current_id, decl_name.c_str(), ast_dumper.GetCString());
- }
-}
-
-bool ClangExpressionDeclMap::ResolveUnknownTypes() {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
-
- ClangASTContextForExpressions *scratch_ast_context =
- static_cast<ClangASTContextForExpressions *>(
- target->GetScratchClangASTContext());
-
- for (size_t index = 0, num_entities = m_found_entities.GetSize();
- index < num_entities; ++index) {
- ExpressionVariableSP entity = m_found_entities.GetVariableAtIndex(index);
-
- ClangExpressionVariable::ParserVars *parser_vars =
- llvm::cast<ClangExpressionVariable>(entity.get())
- ->GetParserVars(GetParserID());
-
- if (entity->m_flags & ClangExpressionVariable::EVUnknownType) {
- const NamedDecl *named_decl = parser_vars->m_named_decl;
- const VarDecl *var_decl = dyn_cast<VarDecl>(named_decl);
-
- if (!var_decl) {
- LLDB_LOGF(log, "Entity of unknown type does not have a VarDecl");
- return false;
- }
-
- if (log) {
- ASTDumper ast_dumper(const_cast<VarDecl *>(var_decl));
- LLDB_LOGF(log, "Variable of unknown type now has Decl %s",
- ast_dumper.GetCString());
- }
-
- QualType var_type = var_decl->getType();
- TypeFromParser parser_type(
- var_type.getAsOpaquePtr(),
- ClangASTContext::GetASTContext(&var_decl->getASTContext()));
-
- lldb::opaque_compiler_type_t copied_type = nullptr;
- if (m_ast_importer_sp) {
- copied_type = m_ast_importer_sp->CopyType(
- scratch_ast_context->getASTContext(), &var_decl->getASTContext(),
- var_type.getAsOpaquePtr());
- } else if (HasMerger()) {
- copied_type = CopyTypeWithMerger(
- var_decl->getASTContext(),
- scratch_ast_context->GetMergerUnchecked(), var_type)
- .getAsOpaquePtr();
- } else {
- lldbassert(0 && "No mechanism to copy a resolved unknown type!");
- return false;
- }
-
- if (!copied_type) {
- LLDB_LOGF(log, "ClangExpressionDeclMap::ResolveUnknownType - Couldn't "
- "import the type for a variable");
-
- return (bool)lldb::ExpressionVariableSP();
- }
-
- TypeFromUser user_type(copied_type, scratch_ast_context);
-
- // parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType,
- // user_type.GetOpaqueQualType());
- parser_vars->m_lldb_value.SetCompilerType(user_type);
- parser_vars->m_parser_type = parser_type;
-
- entity->SetCompilerType(user_type);
-
- entity->m_flags &= ~(ClangExpressionVariable::EVUnknownType);
- }
- }
-
- return true;
+ LLDB_LOG(log, " CEDM::FEVD[{0}] Found variable {1}, returned\n{2}",
+ current_id, decl_name, ClangUtil::DumpDecl(var_decl));
}
void ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context,
@@ -1849,8 +1719,8 @@ void ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context,
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
CompilerType clang_type =
- ClangASTContext::GetBuiltinTypeForEncodingAndBitSize(
- m_ast_context, reg_info->encoding, reg_info->byte_size * 8);
+ m_clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(
+ reg_info->encoding, reg_info->byte_size * 8);
if (!clang_type) {
LLDB_LOGF(log, " Tried to add a type for %s, but couldn't get one",
@@ -1880,12 +1750,9 @@ void ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context,
parser_vars->m_lldb_value.Clear();
entity->m_flags |= ClangExpressionVariable::EVBareRegister;
- if (log) {
- ASTDumper ast_dumper(var_decl);
- LLDB_LOGF(log, " CEDM::FEVD[%d] Added register %s, returned %s",
- current_id, context.m_decl_name.getAsString().c_str(),
- ast_dumper.GetCString());
- }
+ LLDB_LOG(log, " CEDM::FEVD[{0}] Added register {1}, returned\n{2}",
+ current_id, context.m_decl_name.getAsString(),
+ ClangUtil::DumpDecl(var_decl));
}
void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
@@ -1928,17 +1795,16 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
CopyDecl(function_template));
if (copied_function_template) {
if (log) {
- ASTDumper ast_dumper((clang::Decl *)copied_function_template);
-
StreamString ss;
function->DumpSymbolContext(&ss);
- log->Printf(" CEDM::FEVD[%u] Imported decl for function template"
- " %s (description %s), returned %s",
- current_id,
- copied_function_template->getNameAsString().c_str(),
- ss.GetData(), ast_dumper.GetCString());
+ LLDB_LOG(log,
+ " CEDM::FEVD[{0}] Imported decl for function template"
+ " {1} (description {2}), returned\n{3}",
+ current_id, copied_function_template->getNameAsString(),
+ ss.GetData(),
+ ClangUtil::DumpDecl(copied_function_template));
}
context.AddNamedDecl(copied_function_template);
@@ -1948,18 +1814,15 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
llvm::dyn_cast_or_null<clang::FunctionDecl>(
CopyDecl(src_function_decl))) {
if (log) {
- ASTDumper ast_dumper((clang::Decl *)copied_function_decl);
-
StreamString ss;
function->DumpSymbolContext(&ss);
- LLDB_LOGF(log,
- " CEDM::FEVD[%u] Imported decl for function %s "
- "(description %s), returned %s",
- current_id,
- copied_function_decl->getNameAsString().c_str(),
- ss.GetData(), ast_dumper.GetCString());
+ LLDB_LOG(log,
+ " CEDM::FEVD[{0}]] Imported decl for function {1} "
+ "(description {2}), returned\n{3}",
+ current_id, copied_function_decl->getNameAsString(),
+ ss.GetData(), ClangUtil::DumpDecl(copied_function_decl));
}
context.AddNamedDecl(copied_function_decl);
@@ -2061,20 +1924,17 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
parser_vars->m_llvm_value = nullptr;
if (log) {
- std::string function_str =
- function_decl ? ASTDumper(function_decl).GetCString() : "nullptr";
-
StreamString ss;
fun_address.Dump(&ss,
m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(),
Address::DumpStyleResolvedDescription);
- LLDB_LOGF(
- log,
- " CEDM::FEVD[%u] Found %s function %s (description %s), returned %s",
- current_id, (function ? "specific" : "generic"), decl_name.c_str(),
- ss.GetData(), function_str.c_str());
+ LLDB_LOG(log,
+ " CEDM::FEVD[{0}] Found {1} function {2} (description {3}), "
+ "returned\n{4}",
+ current_id, (function ? "specific" : "generic"), decl_name,
+ ss.GetData(), ClangUtil::DumpDecl(function_decl));
}
}
@@ -2097,11 +1957,11 @@ void ClangExpressionDeclMap::AddThisType(NameSearchContext &context,
if (copied_clang_type.IsAggregateType() &&
copied_clang_type.GetCompleteType()) {
CompilerType void_clang_type =
- ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid);
+ m_clang_ast_context->GetBasicType(eBasicTypeVoid);
CompilerType void_ptr_clang_type = void_clang_type.GetPointerType();
- CompilerType method_type = ClangASTContext::CreateFunctionType(
- m_ast_context, void_clang_type, &void_ptr_clang_type, 1, false, 0);
+ CompilerType method_type = m_clang_ast_context->CreateFunctionType(
+ void_clang_type, &void_ptr_clang_type, 1, false, 0);
const bool is_virtual = false;
const bool is_static = false;
@@ -2110,22 +1970,16 @@ void ClangExpressionDeclMap::AddThisType(NameSearchContext &context,
const bool is_attr_used = true;
const bool is_artificial = false;
- CXXMethodDecl *method_decl =
- ClangASTContext::GetASTContext(m_ast_context)
- ->AddMethodToCXXRecordType(
- copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", nullptr,
- method_type, lldb::eAccessPublic, is_virtual, is_static,
- is_inline, is_explicit, is_attr_used, is_artificial);
-
- if (log) {
- ASTDumper method_ast_dumper((clang::Decl *)method_decl);
- ASTDumper type_ast_dumper(copied_clang_type);
+ CXXMethodDecl *method_decl = m_clang_ast_context->AddMethodToCXXRecordType(
+ copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", nullptr,
+ method_type, lldb::eAccessPublic, is_virtual, is_static, is_inline,
+ is_explicit, is_attr_used, is_artificial);
- LLDB_LOGF(log,
- " CEDM::AddThisType Added function $__lldb_expr "
- "(description %s) for this type %s",
- method_ast_dumper.GetCString(), type_ast_dumper.GetCString());
- }
+ LLDB_LOG(log,
+ " CEDM::AddThisType Added function $__lldb_expr "
+ "(description {0}) for this type\n{1}",
+ ClangUtil::ToString(copied_clang_type),
+ ClangUtil::DumpDecl(method_decl));
}
if (!copied_clang_type.IsValid())
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
index 2711e90726e7..722f5e15a2aa 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
@@ -63,12 +63,15 @@ public:
/// the result persistent variable, and instead marks the variable
/// as persisting.
///
- /// \param[in] delegate
+ /// \param[in] result_delegate
/// If non-NULL, use this delegate to report result values. This
/// allows the client ClangUserExpression to report a result.
///
- /// \param[in] exe_ctx
- /// The execution context to use when parsing.
+ /// \param[in] target
+ /// The target to use when parsing.
+ ///
+ /// \param[in] importer
+ /// The ClangASTImporter to use when parsing.
///
/// \param[in] ctx_obj
/// If not empty, then expression is evaluated in context of this object.
@@ -76,7 +79,7 @@ public:
ClangExpressionDeclMap(
bool keep_result_in_memory,
Materializer::PersistentVariableDelegate *result_delegate,
- ExecutionContext &exe_ctx,
+ const lldb::TargetSP &target, const lldb::ClangASTImporterSP &importer,
ValueObject *ctx_obj);
/// Destructor
@@ -98,13 +101,6 @@ public:
void InstallCodeGenerator(clang::ASTConsumer *code_gen);
- /// [Used by ClangExpressionParser] For each variable that had an unknown
- /// type at the beginning of parsing, determine its final type now.
- ///
- /// \return
- /// True on success; false otherwise.
- bool ResolveUnknownTypes();
-
/// Disable the state needed for parsing and IR transformation.
void DidParse();
@@ -248,17 +244,6 @@ public:
lldb::addr_t GetSymbolAddress(ConstString name,
lldb::SymbolType symbol_type);
- /// [Used by IRInterpreter] Get basic target information.
- ///
- /// \param[out] byte_order
- /// The byte order of the target.
- ///
- /// \param[out] address_byte_size
- /// The size of a pointer in bytes.
- ///
- /// \return
- /// True if the information could be determined; false
- /// otherwise.
struct TargetInfo {
lldb::ByteOrder byte_order;
size_t address_byte_size;
@@ -276,9 +261,6 @@ public:
///
/// \param[in] context
/// The NameSearchContext that can construct Decls for this name.
- ///
- /// \return
- /// True on success; false otherwise.
void FindExternalVisibleDecls(NameSearchContext &context) override;
/// Find all entities matching a given name in a given module/namespace,
@@ -296,14 +278,19 @@ public:
/// \param[in] current_id
/// The ID for the current FindExternalVisibleDecls invocation,
/// for logging purposes.
- ///
- /// \return
- /// True on success; false otherwise.
void FindExternalVisibleDecls(NameSearchContext &context,
lldb::ModuleSP module,
CompilerDeclContext &namespace_decl,
unsigned int current_id);
+protected:
+ /// Retrieves the declaration with the given name from the storage of
+ /// persistent declarations.
+ ///
+ /// \return
+ /// A persistent decl with the given name or a nullptr.
+ virtual clang::NamedDecl *GetPersistentDecl(ConstString name);
+
private:
ExpressionVariableList
m_found_entities; ///< All entities that were looked up for the parser.
@@ -329,7 +316,7 @@ private:
if (m_exe_ctx.GetTargetPtr())
return m_exe_ctx.GetTargetPtr();
else if (m_sym_ctx.target_sp)
- m_sym_ctx.target_sp.get();
+ return m_sym_ctx.target_sp.get();
return nullptr;
}
@@ -396,6 +383,130 @@ private:
/// from persistent variables.
uint64_t GetParserID() { return (uint64_t) this; }
+ /// Should be called on all copied functions.
+ void MaybeRegisterFunctionBody(clang::FunctionDecl *copied_function_decl);
+
+ /// Searches the persistent decls of the target for entities with the
+ /// given name.
+ ///
+ /// \param[in] context
+ /// The NameSearchContext that can construct Decls for this name.
+ ///
+ /// \param[in] name
+ /// The name of the entities that need to be found.
+ ///
+ /// \param[in] current_id
+ /// The ID for the current FindExternalVisibleDecls invocation,
+ /// for logging purposes.
+ void SearchPersistenDecls(NameSearchContext &context, const ConstString name,
+ unsigned int current_id);
+
+ /// Handles looking up $__lldb_class which requires special treatment.
+ ///
+ /// \param[in] context
+ /// The NameSearchContext that can construct Decls for this name.
+ ///
+ /// \param[in] current_id
+ /// The ID for the current FindExternalVisibleDecls invocation,
+ /// for logging purposes.
+ void LookUpLldbClass(NameSearchContext &context, unsigned int current_id);
+
+ /// Handles looking up $__lldb_objc_class which requires special treatment.
+ ///
+ /// \param[in] context
+ /// The NameSearchContext that can construct Decls for this name.
+ ///
+ /// \param[in] current_id
+ /// The ID for the current FindExternalVisibleDecls invocation,
+ /// for logging purposes.
+ void LookUpLldbObjCClass(NameSearchContext &context, unsigned int current_id);
+
+ /// Handles looking up the synthetic namespace that contains our local
+ /// variables for the current frame.
+ ///
+ /// \param[in] sym_ctx
+ /// The current SymbolContext of this frame.
+ ///
+ /// \param[in] name_context
+ /// The NameSearchContext that can construct Decls for this name.
+ void LookupLocalVarNamespace(SymbolContext &sym_ctx,
+ NameSearchContext &name_context);
+
+ /// Lookup entities in the ClangModulesDeclVendor.
+ /// \param[in] context
+ /// The NameSearchContext that can construct Decls for this name.
+ ///
+ /// \param[in] name
+ /// The name of the entities that need to be found.
+ ///
+ /// \param[in] current_id
+ /// The ID for the current FindExternalVisibleDecls invocation,
+ /// for logging purposes.
+ void LookupInModulesDeclVendor(NameSearchContext &context, ConstString name,
+ unsigned current_id);
+
+ /// Looks up a local variable.
+ ///
+ /// \param[in] context
+ /// The NameSearchContext that can construct Decls for this name.
+ ///
+ /// \param[in] name
+ /// The name of the entities that need to be found.
+ ///
+ /// \param[in] current_id
+ /// The ID for the current FindExternalVisibleDecls invocation,
+ /// for logging purposes.
+ ///
+ /// \param[in] sym_ctx
+ /// The current SymbolContext of this frame.
+ ///
+ /// \param[in] namespace_decl
+ /// The parent namespace if there is one.
+ ///
+ /// \return
+ /// True iff a local variable was found.
+ bool LookupLocalVariable(NameSearchContext &context, ConstString name,
+ unsigned current_id, SymbolContext &sym_ctx,
+ CompilerDeclContext &namespace_decl);
+
+ /// Searches for functions in the given SymbolContextList.
+ ///
+ /// \param[in] sc_list
+ /// The SymbolContextList to search.
+ ///
+ /// \param[in] frame_decl_context
+ /// The current DeclContext of the current frame.
+ ///
+ /// \return
+ /// A SymbolContextList with any found functions in the front and
+ /// any unknown SymbolContexts which are not functions in the back.
+ /// The SymbolContexts for the functions are ordered by how close they are
+ /// to the DeclContext for the given frame DeclContext.
+ SymbolContextList SearchFunctionsInSymbolContexts(
+ const SymbolContextList &sc_list,
+ const CompilerDeclContext &frame_decl_context);
+
+ /// Looks up a function.
+ ///
+ /// \param[in] context
+ /// The NameSearchContext that can construct Decls for this name.
+ ///
+ /// \param[in] module_sp
+ /// If non-NULL, the module to query.
+ ///
+ /// \param[in] name
+ /// The name of the function that should be find.
+ ///
+ /// \param[in] namespace_decl
+ /// If valid and module is non-NULL, the parent namespace.
+ ///
+ /// \param[in] current_id
+ /// The ID for the current FindExternalVisibleDecls invocation,
+ /// for logging purposes.
+ void LookupFunction(NameSearchContext &context, lldb::ModuleSP module_sp,
+ ConstString name, CompilerDeclContext &namespace_decl,
+ unsigned current_id);
+
/// Given a target, find a variable that matches the given name and type.
///
/// \param[in] target
@@ -410,17 +521,11 @@ private:
/// \param[in] namespace_decl
/// If non-NULL and module is non-NULL, the parent namespace.
///
- /// \param[in] type
- /// The required type for the variable. This function may be called
- /// during parsing, in which case we don't know its type; hence the
- /// default.
- ///
/// \return
/// The LLDB Variable found, or NULL if none was found.
lldb::VariableSP FindGlobalVariable(Target &target, lldb::ModuleSP &module,
ConstString name,
- CompilerDeclContext *namespace_decl,
- TypeFromUser *type = nullptr);
+ CompilerDeclContext *namespace_decl);
/// Get the value of a variable in a given execution context and return the
/// associated Types if needed.
@@ -441,9 +546,6 @@ private:
/// AST context. This is only useful when the variable is being
/// inspected on behalf of the parser, hence the default.
///
- /// \param[in] decl
- /// The Decl to be looked up.
- ///
/// \return
/// Return true if the value was successfully filled in.
bool GetVariableValue(lldb::VariableSP &var,
@@ -471,7 +573,7 @@ private:
/// \param[in] context
/// The NameSearchContext to use when constructing the Decl.
///
- /// \param[in] pvar
+ /// \param[in] pvar_sp
/// The persistent variable that needs a Decl.
///
/// \param[in] current_id
@@ -483,12 +585,6 @@ private:
/// Use the NameSearchContext to generate a Decl for the given LLDB symbol
/// (treated as a variable), and put it in the list of found entities.
- ///
- /// \param[in] context
- /// The NameSearchContext to use when constructing the Decl.
- ///
- /// \param[in] var
- /// The LLDB Variable that needs a Decl.
void AddOneGenericVariable(NameSearchContext &context, const Symbol &symbol,
unsigned int current_id);
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index 1422911d6546..8abd14942885 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -10,6 +10,7 @@
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/PrettyPrinter.h"
+#include "clang/Basic/Builtins.h"
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
@@ -582,15 +583,16 @@ ClangExpressionParser::ClangExpressionParser(
if (ClangModulesDeclVendor *decl_vendor =
target_sp->GetClangModulesDeclVendor()) {
- ClangPersistentVariables *clang_persistent_vars =
- llvm::cast<ClangPersistentVariables>(
+ if (auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(
target_sp->GetPersistentExpressionStateForLanguage(
- lldb::eLanguageTypeC));
- std::unique_ptr<PPCallbacks> pp_callbacks(new LLDBPreprocessorCallbacks(
- *decl_vendor, *clang_persistent_vars, m_compiler->getSourceManager()));
- m_pp_callbacks =
- static_cast<LLDBPreprocessorCallbacks *>(pp_callbacks.get());
- m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
+ lldb::eLanguageTypeC))) {
+ std::unique_ptr<PPCallbacks> pp_callbacks(
+ new LLDBPreprocessorCallbacks(*decl_vendor, *clang_persistent_vars,
+ m_compiler->getSourceManager()));
+ m_pp_callbacks =
+ static_cast<LLDBPreprocessorCallbacks *>(pp_callbacks.get());
+ m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
+ }
}
// 8. Most of this we get from the CompilerInstance, but we also want to give
@@ -696,10 +698,7 @@ class CodeComplete : public CodeCompleteConsumer {
public:
/// Constructs a CodeComplete consumer that can be attached to a Sema.
- /// \param[out] matches
- /// The list of matches that the lldb completion API expects as a result.
- /// This may already contain matches, so it's only allowed to append
- /// to this variable.
+ ///
/// \param[out] expr
/// The whole expression string that we are currently parsing. This
/// string needs to be equal to the input the user typed, and NOT the
@@ -976,7 +975,7 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager,
m_compiler->setASTConsumer(std::move(Consumer));
if (ast_context.getLangOpts().Modules) {
- m_compiler->createModuleManager();
+ m_compiler->createASTReader();
m_ast_context->setSema(&m_compiler->getSema());
}
@@ -999,7 +998,7 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager,
} else {
ast_context.setExternalSource(ast_source);
}
- decl_map->InstallASTContext(ast_context, m_compiler->getFileManager());
+ decl_map->InstallASTContext(*m_ast_context);
}
// Check that the ASTReader is properly attached to ASTContext and Sema.
@@ -1036,15 +1035,6 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager,
}
if (!num_errors) {
- if (type_system_helper->DeclMap() &&
- !type_system_helper->DeclMap()->ResolveUnknownTypes()) {
- diagnostic_manager.Printf(eDiagnosticSeverityError,
- "Couldn't infer the type of a variable");
- num_errors++;
- }
- }
-
- if (!num_errors) {
type_system_helper->CommitPersistentDecls();
}
@@ -1268,8 +1258,9 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution(
interpret_error, interpret_function_calls);
if (!can_interpret && execution_policy == eExecutionPolicyNever) {
- err.SetErrorStringWithFormat("Can't run the expression locally: %s",
- interpret_error.AsCString());
+ err.SetErrorStringWithFormat(
+ "Can't evaluate the expression without a running target due to: %s",
+ interpret_error.AsCString());
return err;
}
}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
index 79ad5728bf74..4a410cecb94a 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
@@ -42,7 +42,7 @@ public:
///
/// Initializes class variables.
///
- /// \param[in] exe_scope,
+ /// \param[in] exe_scope
/// If non-NULL, an execution context scope that can help to
/// correctly create an expression with a valid process for
/// optional tuning Objective-C runtime support. Can be NULL.
@@ -77,7 +77,7 @@ public:
/// \return
/// The number of errors encountered during parsing. 0 means
/// success.
- unsigned Parse(DiagnosticManager &diagnostic_manager) override;
+ unsigned Parse(DiagnosticManager &diagnostic_manager);
bool RewriteExpression(DiagnosticManager &diagnostic_manager) override;
@@ -99,15 +99,6 @@ public:
/// \param[in] exe_ctx
/// The execution context to write the function into.
///
- /// \param[out] evaluated_statically
- /// Set to true if the expression could be interpreted statically;
- /// untouched otherwise.
- ///
- /// \param[out] const_result
- /// If the result of the expression is constant, and the
- /// expression has no side effects, this is set to the result of the
- /// expression.
- ///
/// \param[in] execution_policy
/// Determines whether the expression must be JIT-compiled, must be
/// evaluated statically, or whether this decision may be made
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
index 21cb33402e7f..7ebb5fee1ec6 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
@@ -315,12 +315,10 @@ bool ClangExpressionSourceCode::GetText(
}
}
- if (ClangModulesDeclVendor *decl_vendor =
- target->GetClangModulesDeclVendor()) {
- ClangPersistentVariables *persistent_vars =
- llvm::cast<ClangPersistentVariables>(
- target->GetPersistentExpressionStateForLanguage(
- lldb::eLanguageTypeC));
+ ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor();
+ auto *persistent_vars = llvm::cast<ClangPersistentVariables>(
+ target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
+ if (decl_vendor && persistent_vars) {
const ClangModulesDeclVendor::ModuleVector &hand_imported_modules =
persistent_vars->GetHandLoadedClangModules();
ClangModulesDeclVendor::ModuleVector modules_for_macros;
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
index eb7f74f20a20..0e6de28ee4df 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
@@ -74,9 +74,6 @@ public:
/// Finds a variable by NamedDecl in the list.
///
- /// \param[in] name
- /// The name of the requested variable.
- ///
/// \return
/// The variable requested, or NULL if that variable is not in the list.
static ClangExpressionVariable *
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
index 8fbfa6e47578..7f7c0a97f538 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
@@ -42,6 +42,8 @@
using namespace lldb_private;
+char ClangFunctionCaller::ID;
+
// ClangFunctionCaller constructor
ClangFunctionCaller::ClangFunctionCaller(ExecutionContextScope &exe_scope,
const CompilerType &return_type,
@@ -186,10 +188,10 @@ ClangFunctionCaller::CompileFunction(lldb::ThreadSP thread_to_use_sp,
lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
if (jit_process_sp) {
const bool generate_debug_info = true;
- m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this,
- generate_debug_info));
-
- num_errors = m_parser->Parse(diagnostic_manager);
+ auto *clang_parser = new ClangExpressionParser(jit_process_sp.get(), *this,
+ generate_debug_info);
+ num_errors = clang_parser->Parse(diagnostic_manager);
+ m_parser.reset(clang_parser);
} else {
diagnostic_manager.PutString(eDiagnosticSeverityError,
"no process - unable to inject function");
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
index 24f6f2eb91b3..150a913152d0 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
@@ -59,11 +59,6 @@ class ClangExpressionParser;
class ClangFunctionCaller : public FunctionCaller {
friend class ASTStructExtractor;
- /// LLVM-style RTTI support.
- static bool classof(const Expression *E) {
- return E->getKind() == eKindClangFunctionCaller;
- }
-
class ClangFunctionCallerHelper : public ClangExpressionHelper {
public:
ClangFunctionCallerHelper(ClangFunctionCaller &owner) : m_owner(owner) {}
@@ -91,18 +86,23 @@ class ClangFunctionCaller : public FunctionCaller {
///layout.
};
+ // LLVM RTTI support
+ static char ID;
+
public:
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || FunctionCaller::isA(ClassID);
+ }
+ static bool classof(const Expression *obj) { return obj->isA(&ID); }
+
/// Constructor
///
/// \param[in] exe_scope
/// An execution context scope that gets us at least a target and
/// process.
///
- /// \param[in] ast_context
- /// The AST context to evaluate argument types in.
- ///
- /// \param[in] return_qualtype
- /// An opaque Clang QualType for the function result. Should be
+ /// \param[in] return_type
+ /// A compiler type for the function result. Should be
/// defined in ast_context.
///
/// \param[in] function_address
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
index f3df589d7311..0696c669f2e2 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
@@ -80,12 +80,10 @@ public:
Stream &error_stream) override;
uint32_t FindDecls(ConstString name, bool append, uint32_t max_matches,
- std::vector<clang::NamedDecl *> &decls) override;
+ std::vector<CompilerDecl> &decls) override;
void ForEachMacro(const ModuleVector &modules,
std::function<bool(const std::string &)> handler) override;
-
- clang::ExternalASTMerger::ImporterSource GetImporterSource() override;
private:
void
ReportModuleExportsHelper(std::set<ClangModulesDeclVendor::ModuleID> &exports,
@@ -110,7 +108,6 @@ private:
typedef std::set<ModuleID> ImportedModuleSet;
ImportedModuleMap m_imported_modules;
ImportedModuleSet m_user_imported_modules;
- const clang::ExternalASTMerger::OriginMap m_origin_map;
// We assume that every ASTContext has an ClangASTContext, so we also store
// a custom ClangASTContext for our internal ASTContext.
std::unique_ptr<ClangASTContext> m_ast_context;
@@ -160,7 +157,7 @@ ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(
: m_diagnostics_engine(std::move(diagnostics_engine)),
m_compiler_invocation(std::move(compiler_invocation)),
m_compiler_instance(std::move(compiler_instance)),
- m_parser(std::move(parser)), m_origin_map() {
+ m_parser(std::move(parser)) {
// Initialize our ClangASTContext.
m_ast_context.reset(new ClangASTContext(m_compiler_instance->getASTContext()));
@@ -359,7 +356,7 @@ bool ClangModulesDeclVendorImpl::AddModulesForCompileUnit(
uint32_t
ClangModulesDeclVendorImpl::FindDecls(ConstString name, bool append,
uint32_t max_matches,
- std::vector<clang::NamedDecl *> &decls) {
+ std::vector<CompilerDecl> &decls) {
if (!m_enabled) {
return 0;
}
@@ -385,7 +382,7 @@ ClangModulesDeclVendorImpl::FindDecls(ConstString name, bool append,
if (num_matches >= max_matches)
return num_matches;
- decls.push_back(named_decl);
+ decls.push_back(CompilerDecl(m_ast_context.get(), named_decl));
++num_matches;
}
@@ -569,13 +566,6 @@ ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path,
is_inclusion_directive);
}
-clang::ExternalASTMerger::ImporterSource
-ClangModulesDeclVendorImpl::GetImporterSource() {
- return clang::ExternalASTMerger::ImporterSource(
- m_compiler_instance->getASTContext(),
- m_compiler_instance->getFileManager(), m_origin_map);
-}
-
static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer";
lldb_private::ClangModulesDeclVendor *
@@ -704,7 +694,7 @@ ClangModulesDeclVendor::Create(Target &target) {
instance->getPreprocessor().enableIncrementalProcessing();
- instance->createModuleManager();
+ instance->createASTReader();
instance->createSema(action->getTranslationUnitKind(), nullptr);
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
index 24dd705e37b1..41d62a462ab4 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
@@ -67,39 +67,35 @@ void ClangPersistentVariables::RemovePersistentVariable(
llvm::Optional<CompilerType>
ClangPersistentVariables::GetCompilerTypeFromPersistentDecl(
ConstString type_name) {
- CompilerType compiler_type;
- if (clang::TypeDecl *tdecl = llvm::dyn_cast_or_null<clang::TypeDecl>(
- GetPersistentDecl(type_name))) {
- compiler_type.SetCompilerType(
- ClangASTContext::GetASTContext(&tdecl->getASTContext()),
- reinterpret_cast<lldb::opaque_compiler_type_t>(
- const_cast<clang::Type *>(tdecl->getTypeForDecl())));
- return compiler_type;
+ PersistentDecl p = m_persistent_decls.lookup(type_name.GetCString());
+
+ if (p.m_decl == nullptr)
+ return llvm::None;
+
+ if (clang::TypeDecl *tdecl = llvm::dyn_cast<clang::TypeDecl>(p.m_decl)) {
+ opaque_compiler_type_t t = static_cast<opaque_compiler_type_t>(
+ const_cast<clang::Type *>(tdecl->getTypeForDecl()));
+ return CompilerType(p.m_context, t);
}
return llvm::None;
}
void ClangPersistentVariables::RegisterPersistentDecl(ConstString name,
- clang::NamedDecl *decl) {
- m_persistent_decls.insert(
- std::pair<const char *, clang::NamedDecl *>(name.GetCString(), decl));
+ clang::NamedDecl *decl,
+ ClangASTContext *ctx) {
+ PersistentDecl p = {decl, ctx};
+ m_persistent_decls.insert(std::make_pair(name.GetCString(), p));
if (clang::EnumDecl *enum_decl = llvm::dyn_cast<clang::EnumDecl>(decl)) {
for (clang::EnumConstantDecl *enumerator_decl : enum_decl->enumerators()) {
- m_persistent_decls.insert(std::pair<const char *, clang::NamedDecl *>(
- ConstString(enumerator_decl->getNameAsString()).GetCString(),
- enumerator_decl));
+ p = {enumerator_decl, ctx};
+ m_persistent_decls.insert(std::make_pair(
+ ConstString(enumerator_decl->getNameAsString()).GetCString(), p));
}
}
}
clang::NamedDecl *
ClangPersistentVariables::GetPersistentDecl(ConstString name) {
- PersistentDeclMap::const_iterator i =
- m_persistent_decls.find(name.GetCString());
-
- if (i == m_persistent_decls.end())
- return nullptr;
- else
- return i->second;
+ return m_persistent_decls.lookup(name.GetCString()).m_decl;
}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
index 95e6c3ac963d..434196b35fd5 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
@@ -62,7 +62,8 @@ public:
llvm::Optional<CompilerType>
GetCompilerTypeFromPersistentDecl(ConstString type_name) override;
- void RegisterPersistentDecl(ConstString name, clang::NamedDecl *decl);
+ void RegisterPersistentDecl(ConstString name, clang::NamedDecl *decl,
+ ClangASTContext *ctx);
clang::NamedDecl *GetPersistentDecl(ConstString name);
@@ -80,7 +81,14 @@ private:
// The counter used by GetNextPersistentVariableName
uint32_t m_next_persistent_variable_id = 0;
- typedef llvm::DenseMap<const char *, clang::NamedDecl *> PersistentDeclMap;
+ struct PersistentDecl {
+ /// The persistent decl.
+ clang::NamedDecl *m_decl = nullptr;
+ /// The ClangASTContext for the ASTContext of m_decl.
+ ClangASTContext *m_context = nullptr;
+ };
+
+ typedef llvm::DenseMap<const char *, PersistentDecl> PersistentDeclMap;
PersistentDeclMap
m_persistent_decls; ///< Persistent entities declared by the user.
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
index da1ca785635c..6698797617a3 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -38,10 +38,11 @@
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/ClangASTMetadata.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/VariableList.h"
@@ -62,13 +63,15 @@
using namespace lldb_private;
+char ClangUserExpression::ID;
+
ClangUserExpression::ClangUserExpression(
ExecutionContextScope &exe_scope, llvm::StringRef expr,
llvm::StringRef prefix, lldb::LanguageType language,
ResultType desired_type, const EvaluateExpressionOptions &options,
ValueObject *ctx_obj)
: LLVMUserExpression(exe_scope, expr, prefix, language, desired_type,
- options, eKindClangUserExpression),
+ options),
m_type_system_helper(*m_target_wp.lock(), options.GetExecutionPolicy() ==
eExecutionPolicyTopLevel),
m_result_delegate(exe_scope.CalculateTarget()), m_ctx_obj(ctx_obj) {
@@ -347,11 +350,12 @@ bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_man
static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target) {
if (ClangModulesDeclVendor *decl_vendor =
target->GetClangModulesDeclVendor()) {
+ auto *persistent_state = llvm::cast<ClangPersistentVariables>(
+ target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
+ if (!persistent_state)
+ return;
const ClangModulesDeclVendor::ModuleVector &hand_imported_modules =
- llvm::cast<ClangPersistentVariables>(
- target->GetPersistentExpressionStateForLanguage(
- lldb::eLanguageTypeC))
- ->GetHandLoadedClangModules();
+ persistent_state->GetHandLoadedClangModules();
ClangModulesDeclVendor::ModuleVector modules_for_macros;
for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) {
@@ -476,15 +480,18 @@ CppModuleConfiguration GetModuleConfig(lldb::LanguageType language,
files.AppendIfUnique(f);
// We also need to look at external modules in the case of -gmodules as they
// contain the support files for libc++ and the C library.
- sc.comp_unit->ForEachExternalModule([&files](lldb::ModuleSP module) {
- for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i) {
- const FileSpecList &support_files =
- module->GetCompileUnitAtIndex(i)->GetSupportFiles();
- for (const FileSpec &f : support_files) {
- files.AppendIfUnique(f);
- }
- }
- });
+ llvm::DenseSet<SymbolFile *> visited_symbol_files;
+ sc.comp_unit->ForEachExternalModule(
+ visited_symbol_files, [&files](Module &module) {
+ for (std::size_t i = 0; i < module.GetNumCompileUnits(); ++i) {
+ const FileSpecList &support_files =
+ module.GetCompileUnitAtIndex(i)->GetSupportFiles();
+ for (const FileSpec &f : support_files) {
+ files.AppendIfUnique(f);
+ }
+ }
+ return false;
+ });
LLDB_LOG(log, "[C++ module config] Found {0} support files to analyze",
files.GetSize());
@@ -576,7 +583,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); });
- if (!DeclMap()->WillParse(exe_ctx, m_materializer_up.get())) {
+ if (!DeclMap()->WillParse(exe_ctx, GetMaterializer())) {
diagnostic_manager.PutString(
eDiagnosticSeverityError,
"current process state is unsuitable for expression parsing");
@@ -676,10 +683,12 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
register_execution_unit = true;
}
- if (register_execution_unit)
- exe_ctx.GetTargetPtr()
- ->GetPersistentExpressionStateForLanguage(m_language)
- ->RegisterExecutionUnit(m_execution_unit_sp);
+ if (register_execution_unit) {
+ if (auto *persistent_state =
+ exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage(
+ m_language))
+ persistent_state->RegisterExecutionUnit(m_execution_unit_sp);
+ }
}
if (generate_debug_info) {
@@ -764,7 +773,7 @@ bool ClangUserExpression::Complete(ExecutionContext &exe_ctx,
auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); });
- if (!DeclMap()->WillParse(exe_ctx, m_materializer_up.get())) {
+ if (!DeclMap()->WillParse(exe_ctx, GetMaterializer())) {
diagnostic_manager.PutString(
eDiagnosticSeverityError,
"current process state is unsuitable for expression parsing");
@@ -887,9 +896,9 @@ void ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(
Materializer::PersistentVariableDelegate &delegate,
bool keep_result_in_memory,
ValueObject *ctx_obj) {
- m_expr_decl_map_up.reset(
- new ClangExpressionDeclMap(keep_result_in_memory, &delegate, exe_ctx,
- ctx_obj));
+ m_expr_decl_map_up.reset(new ClangExpressionDeclMap(
+ keep_result_in_memory, &delegate, exe_ctx.GetTargetSP(),
+ exe_ctx.GetTargetRef().GetClangASTImporter(), ctx_obj));
}
clang::ASTConsumer *
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
index d94f9cc5e066..00cbffa7fd6f 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
@@ -38,11 +38,14 @@ namespace lldb_private {
/// the objects needed to parse and interpret or JIT an expression. It uses
/// the Clang parser to produce LLVM IR from the expression.
class ClangUserExpression : public LLVMUserExpression {
+ // LLVM RTTI support
+ static char ID;
+
public:
- /// LLVM-style RTTI support.
- static bool classof(const Expression *E) {
- return E->getKind() == eKindClangUserExpression;
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || LLVMUserExpression::isA(ClassID);
}
+ static bool classof(const Expression *obj) { return obj->isA(&ID); }
enum { kDefaultTimeout = 500000u };
@@ -93,7 +96,7 @@ public:
/// \param[in] expr
/// The expression to parse.
///
- /// \param[in] expr_prefix
+ /// \param[in] prefix
/// If non-NULL, a C string containing translation-unit level
/// definitions to be included when the expression is parsed.
///
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
index 564c62c6a2c6..199e4898e118 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
@@ -31,6 +31,8 @@
using namespace lldb_private;
+char ClangUtilityFunction::ID;
+
/// Constructor
///
/// \param[in] text
@@ -40,7 +42,7 @@ using namespace lldb_private;
/// The name of the function, as used in the text.
ClangUtilityFunction::ClangUtilityFunction(ExecutionContextScope &exe_scope,
const char *text, const char *name)
- : UtilityFunction(exe_scope, text, name, eKindClangUtilityFunction) {
+ : UtilityFunction(exe_scope, text, name) {
m_function_text.assign(ClangExpressionSourceCode::g_expression_prefix);
if (text && text[0])
m_function_text.append(text);
@@ -157,7 +159,7 @@ bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager,
void ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(
ExecutionContext &exe_ctx, bool keep_result_in_memory) {
- m_expr_decl_map_up.reset(
- new ClangExpressionDeclMap(keep_result_in_memory, nullptr, exe_ctx,
- nullptr));
+ m_expr_decl_map_up.reset(new ClangExpressionDeclMap(
+ keep_result_in_memory, nullptr, exe_ctx.GetTargetSP(),
+ exe_ctx.GetTargetRef().GetClangASTImporter(), nullptr));
}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
index 70ebb2f3ad8a..9efaa0254c3e 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
@@ -33,11 +33,14 @@ namespace lldb_private {
/// simply provide a way to push a function into the target for the debugger
/// to call later on.
class ClangUtilityFunction : public UtilityFunction {
+ // LLVM RTTI support
+ static char ID;
+
public:
- /// LLVM-style RTTI support.
- static bool classof(const Expression *E) {
- return E->getKind() == eKindClangUtilityFunction;
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || UtilityFunction::isA(ClassID);
}
+ static bool classof(const Expression *obj) { return obj->isA(&ID); }
class ClangUtilityFunctionHelper : public ClangExpressionHelper {
public:
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h b/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h
index 60c0691b21c1..5b9c8007ab76 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h
@@ -76,10 +76,6 @@ public:
///
/// \param[in] func_name
/// The name of the function to prepare for execution in the target.
- ///
- /// \param[in] decl_map
- /// The mapping used to look up entities in the target process. In
- /// this case, used to find objc_msgSend
IRDynamicChecks(ClangDynamicCheckerFunctions &checker_functions,
const char *func_name = "$__lldb_expr");
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
index 4e871f7d6a44..103a7ee46f35 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
@@ -355,7 +355,7 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) {
ConstantInt *new_constant_int =
ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()),
- reinterpret_cast<uint64_t>(result_decl), false);
+ reinterpret_cast<uintptr_t>(result_decl), false);
llvm::Metadata *values[2];
values[0] = ConstantAsMetadata::get(new_result_global);
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
index 893620f7f8e0..262e8ee0c06c 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
@@ -71,15 +71,6 @@ public:
/// variables) should be resolved. If not, only external functions
/// are resolved.
///
- /// \param[in] execution_policy
- /// Determines whether an IR interpreter can be used to statically
- /// evaluate the expression.
- ///
- /// \param[in] const_result
- /// This variable is populated with the statically-computed result
- /// of the function, if it has no side-effects and the result can
- /// be computed statically.
- ///
/// \param[in] execution_unit
/// The holder for raw data associated with the expression.
///
@@ -105,10 +96,6 @@ public:
/// $__lldb_expr, and that function is passed to the passes one by
/// one.
///
- /// \param[in] interpreter_error
- /// An error. If the expression fails to be interpreted, this error
- /// is set to a reason why.
- ///
/// \return
/// True on success; false otherwise
bool runOnModule(llvm::Module &llvm_module) override;
@@ -142,9 +129,6 @@ private:
/// The top-level pass implementation
///
- /// \param[in] llvm_module
- /// The module currently being processed.
- ///
/// \param[in] llvm_function
/// The function currently being processed.
///
@@ -184,12 +168,12 @@ private:
/// Find the NamedDecl corresponding to a Value. This interface is exposed
/// for the IR interpreter.
///
+ /// \param[in] global_val
+ /// The global entity to search for
+ ///
/// \param[in] module
/// The module containing metadata to search
///
- /// \param[in] global
- /// The global entity to search for
- ///
/// \return
/// The corresponding variable declaration
public:
@@ -287,7 +271,7 @@ private:
/// Replace a single old-style class reference
///
- /// \param[in] selector_load
+ /// \param[in] class_load
/// The load of the statically-allocated selector.
///
/// \return
@@ -362,7 +346,7 @@ private:
/// Handle all the arguments to a function call
///
- /// \param[in] C
+ /// \param[in] call_inst
/// The call instruction.
///
/// \return
@@ -381,8 +365,8 @@ private:
/// Remove calls to __cxa_atexit, which should never be generated by
/// expressions.
///
- /// \param[in] call_inst
- /// The call instruction.
+ /// \param[in] basic_block
+ /// The basic block currently being processed.
///
/// \return
/// True if the scan was successful; false if some operation
@@ -391,7 +375,7 @@ private:
/// The top-level pass implementation
///
- /// \param[in] basic_block
+ /// \param[in] llvm_function
/// The function currently being processed.
///
/// \return
@@ -474,28 +458,9 @@ private:
///pointer (see comments in
/// ASTResultSynthesizer::SynthesizeBodyResult)
- llvm::GlobalVariable *m_reloc_placeholder; ///< A placeholder that will be
- ///replaced by a pointer to the
- ///final
- /// location of the static allocation.
-
- /// UnfoldConstant operates on a constant [Old] which has just been replaced
- /// with a value [New]. We assume that new_value has been properly placed
- /// early in the function, in front of the first instruction in the entry
- /// basic block [FirstEntryInstruction].
- ///
- /// UnfoldConstant reads through the uses of Old and replaces Old in those
- /// uses with New. Where those uses are constants, the function generates
- /// new instructions to compute the result of the new, non-constant
- /// expression and places them before FirstEntryInstruction. These
- /// instructions replace the constant uses, so UnfoldConstant calls itself
- /// recursively for those.
- ///
- /// \param[in] llvm_function
- /// The function currently being processed.
- ///
- /// \return
- /// True on success; false otherwise
+ /// A placeholder that will be replaced by a pointer to the final location of
+ /// the static allocation.
+ llvm::GlobalVariable *m_reloc_placeholder;
class FunctionValueCache {
public:
@@ -513,6 +478,20 @@ private:
FunctionValueCache m_entry_instruction_finder;
+ /// UnfoldConstant operates on a constant [Old] which has just been replaced
+ /// with a value [New]. We assume that new_value has been properly placed
+ /// early in the function, in front of the first instruction in the entry
+ /// basic block [FirstEntryInstruction].
+ ///
+ /// UnfoldConstant reads through the uses of Old and replaces Old in those
+ /// uses with New. Where those uses are constants, the function generates
+ /// new instructions to compute the result of the new, non-constant
+ /// expression and places them before FirstEntryInstruction. These
+ /// instructions replace the constant uses, so UnfoldConstant calls itself
+ /// recursively for those.
+ ///
+ /// \return
+ /// True on success; false otherwise
static bool UnfoldConstant(llvm::Constant *old_constant,
llvm::Function *llvm_function,
FunctionValueCache &value_maker,
@@ -522,9 +501,6 @@ private:
/// Commit the allocation in m_data_allocator and use its final location to
/// replace m_reloc_placeholder.
///
- /// \param[in] module
- /// The module that m_data_allocator resides in
- ///
/// \return
/// True on success; false otherwise
bool CompleteDataAllocation();
diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index 19a987b0f004..ff142e6f35ff 100644
--- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -850,6 +850,7 @@ uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const {
/* On Apple iOS et al, the frame pointer register is always r7.
* Typically on other ARM systems, thumb code uses r7; arm code uses r11.
+ * Windows on ARM, which is in thumb mode, uses r11 though.
*/
uint32_t fp_regnum = 11;
@@ -857,7 +858,7 @@ uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const {
if (is_apple)
fp_regnum = 7;
- if (m_opcode_mode == eModeThumb)
+ if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())
fp_regnum = 7;
return fp_regnum;
@@ -879,6 +880,7 @@ uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const {
/* On Apple iOS et al, the frame pointer register is always r7.
* Typically on other ARM systems, thumb code uses r7; arm code uses r11.
+ * Windows on ARM, which is in thumb mode, uses r11 though.
*/
uint32_t fp_regnum = dwarf_r11;
@@ -886,7 +888,7 @@ uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const {
if (is_apple)
fp_regnum = dwarf_r7;
- if (m_opcode_mode == eModeThumb)
+ if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())
fp_regnum = dwarf_r7;
return fp_regnum;
@@ -1343,6 +1345,8 @@ bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode,
EmulateInstruction::Context context;
if (Rd == 13)
context.type = EmulateInstruction::eContextAdjustStackPointer;
+ else if (Rd == GetFramePointerRegisterNumber() && Rm == 13)
+ context.type = EmulateInstruction::eContextSetFramePointer;
else
context.type = EmulateInstruction::eContextRegisterPlusOffset;
RegisterInfo dwarf_reg;
diff --git a/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
index 21b6296745bd..b55eeb0eaf46 100644
--- a/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
+++ b/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
@@ -28,6 +28,7 @@
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
@@ -149,7 +150,9 @@ EmulateInstructionMIPS::EmulateInstructionMIPS(
m_insn_info.reset(target->createMCInstrInfo());
assert(m_insn_info.get());
- m_asm_info.reset(target->createMCAsmInfo(*m_reg_info, triple.getTriple()));
+ llvm::MCTargetOptions MCOptions;
+ m_asm_info.reset(
+ target->createMCAsmInfo(*m_reg_info, triple.getTriple(), MCOptions));
m_subtype_info.reset(
target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
assert(m_asm_info.get() && m_subtype_info.get());
@@ -978,13 +981,11 @@ EmulateInstructionMIPS::GetSizeOfInstruction(lldb_private::DataExtractor &data,
llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
if (m_use_alt_disaasm)
- decode_status =
- m_alt_disasm->getInstruction(mc_insn, next_inst_size, raw_insn,
- inst_addr, llvm::nulls(), llvm::nulls());
+ decode_status = m_alt_disasm->getInstruction(
+ mc_insn, next_inst_size, raw_insn, inst_addr, llvm::nulls());
else
- decode_status =
- m_disasm->getInstruction(mc_insn, next_inst_size, raw_insn, inst_addr,
- llvm::nulls(), llvm::nulls());
+ decode_status = m_disasm->getInstruction(mc_insn, next_inst_size, raw_insn,
+ inst_addr, llvm::nulls());
if (decode_status != llvm::MCDisassembler::Success)
return false;
@@ -1067,11 +1068,11 @@ bool EmulateInstructionMIPS::EvaluateInstruction(uint32_t evaluate_options) {
llvm::MCDisassembler::DecodeStatus decode_status;
llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
if (m_use_alt_disaasm)
- decode_status = m_alt_disasm->getInstruction(
- mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls());
+ decode_status = m_alt_disasm->getInstruction(mc_insn, insn_size, raw_insn,
+ m_addr, llvm::nulls());
else
- decode_status = m_disasm->getInstruction(
- mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls());
+ decode_status = m_disasm->getInstruction(mc_insn, insn_size, raw_insn,
+ m_addr, llvm::nulls());
if (decode_status != llvm::MCDisassembler::Success)
return false;
diff --git a/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
index 5fabbeb756cc..3baf942bc17f 100644
--- a/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
+++ b/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
@@ -28,6 +28,7 @@
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
@@ -153,7 +154,9 @@ EmulateInstructionMIPS64::EmulateInstructionMIPS64(
m_insn_info.reset(target->createMCInstrInfo());
assert(m_insn_info.get());
- m_asm_info.reset(target->createMCAsmInfo(*m_reg_info, triple.getTriple()));
+ llvm::MCTargetOptions MCOptions;
+ m_asm_info.reset(
+ target->createMCAsmInfo(*m_reg_info, triple.getTriple(), MCOptions));
m_subtype_info.reset(
target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
assert(m_asm_info.get() && m_subtype_info.get());
@@ -962,8 +965,8 @@ bool EmulateInstructionMIPS64::EvaluateInstruction(uint32_t evaluate_options) {
if (m_opcode.GetData(data)) {
llvm::MCDisassembler::DecodeStatus decode_status;
llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
- decode_status = m_disasm->getInstruction(
- mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls());
+ decode_status = m_disasm->getInstruction(mc_insn, insn_size, raw_insn,
+ m_addr, llvm::nulls());
if (decode_status != llvm::MCDisassembler::Success)
return false;
}
@@ -1360,7 +1363,7 @@ bool EmulateInstructionMIPS64::Emulate_BXX_3ops(llvm::MCInst &insn) {
if (!success)
return false;
- if (!strcasecmp(op_name, "BEQ") || !strcasecmp(op_name, "BEQL")
+ if (!strcasecmp(op_name, "BEQ") || !strcasecmp(op_name, "BEQL")
|| !strcasecmp(op_name, "BEQ64") ) {
if (rs_val == rt_val)
target = pc + offset;
@@ -1602,7 +1605,7 @@ bool EmulateInstructionMIPS64::Emulate_BXX_2ops(llvm::MCInst &insn) {
target = pc + offset;
else
target = pc + 8;
- } else if (!strcasecmp(op_name, "BLEZL") || !strcasecmp(op_name, "BLEZ")
+ } else if (!strcasecmp(op_name, "BLEZL") || !strcasecmp(op_name, "BLEZ")
|| !strcasecmp(op_name, "BLEZ64")) {
if (rs_val <= 0)
target = pc + offset;
diff --git a/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp b/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp
index dfe61316b042..b73b6c095368 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp
+++ b/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp
@@ -153,7 +153,7 @@ bool MainThreadCheckerRuntime::NotifyBreakpointHit(
user_id_t break_loc_id) {
assert(baton && "null baton");
if (!baton)
- return false; //< false => resume execution.
+ return false; ///< false => resume execution.
MainThreadCheckerRuntime *const instance =
static_cast<MainThreadCheckerRuntime *>(baton);
@@ -241,30 +241,30 @@ MainThreadCheckerRuntime::GetBacktracesFromExtendedStopInfo(
StructuredData::ObjectSP info) {
ThreadCollectionSP threads;
threads = std::make_shared<ThreadCollection>();
-
+
ProcessSP process_sp = GetProcessSP();
-
+
if (info->GetObjectForDotSeparatedPath("instrumentation_class")
->GetStringValue() != "MainThreadChecker")
return threads;
-
+
std::vector<lldb::addr_t> PCs;
auto trace = info->GetObjectForDotSeparatedPath("trace")->GetAsArray();
trace->ForEach([&PCs](StructuredData::Object *PC) -> bool {
PCs.push_back(PC->GetAsInteger()->GetValue());
return true;
});
-
+
if (PCs.empty())
return threads;
-
+
StructuredData::ObjectSP thread_id_obj =
info->GetObjectForDotSeparatedPath("tid");
tid_t tid = thread_id_obj ? thread_id_obj->GetIntegerValue() : 0;
HistoryThread *history_thread = new HistoryThread(*process_sp, tid, PCs);
ThreadSP new_thread_sp(history_thread);
-
+
// Save this in the Process' ExtendedThreadList so a strong pointer retains
// the object
process_sp->GetExtendedThreadList().AddThread(new_thread_sp);
diff --git a/lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp b/lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
index 50f1d48d03e0..137ecab224bc 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
+++ b/lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
@@ -207,7 +207,7 @@ bool UndefinedBehaviorSanitizerRuntime::NotifyBreakpointHit(
user_id_t break_loc_id) {
assert(baton && "null baton");
if (!baton)
- return false; //< false => resume execution.
+ return false; ///< false => resume execution.
UndefinedBehaviorSanitizerRuntime *const instance =
static_cast<UndefinedBehaviorSanitizerRuntime *>(baton);
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 489fa7d0ad91..4385a60f5862 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -19,6 +19,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Demangle/ItaniumDemangle.h"
+#include "lldb/Core/Mangled.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/DataFormatters/CXXFunctionPointer.h"
@@ -238,18 +239,16 @@ std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() {
return res;
}
-bool CPlusPlusLanguage::IsCPPMangledName(const char *name) {
+bool CPlusPlusLanguage::IsCPPMangledName(llvm::StringRef name) {
// FIXME!! we should really run through all the known C++ Language plugins
// and ask each one if this is a C++ mangled name
- if (name == nullptr)
- return false;
+ Mangled::ManglingScheme scheme = Mangled::GetManglingScheme(name);
- // MSVC style mangling
- if (name[0] == '?')
- return true;
+ if (scheme == Mangled::eManglingSchemeNone)
+ return false;
- return (name[0] != '\0' && name[0] == '_' && name[1] == 'Z');
+ return true;
}
bool CPlusPlusLanguage::ExtractContextAndIdentifier(
@@ -285,46 +284,34 @@ public:
}
};
-/// Given a mangled function `Mangled`, replace all the primitive function type
-/// arguments of `Search` with type `Replace`.
-class TypeSubstitutor
- : public llvm::itanium_demangle::AbstractManglingParser<TypeSubstitutor,
+template <typename Derived>
+class ManglingSubstitutor
+ : public llvm::itanium_demangle::AbstractManglingParser<Derived,
NodeAllocator> {
- /// Input character until which we have constructed the respective output
- /// already
- const char *Written;
+ using Base =
+ llvm::itanium_demangle::AbstractManglingParser<Derived, NodeAllocator>;
- llvm::StringRef Search;
- llvm::StringRef Replace;
- llvm::SmallString<128> Result;
+public:
+ ManglingSubstitutor() : Base(nullptr, nullptr) {}
- /// Whether we have performed any substitutions.
- bool Substituted;
+ template<typename... Ts>
+ ConstString substitute(llvm::StringRef Mangled, Ts &&... Vals) {
+ this->getDerived().reset(Mangled, std::forward<Ts>(Vals)...);
+ return substituteImpl(Mangled);
+ }
- void reset(llvm::StringRef Mangled, llvm::StringRef Search,
- llvm::StringRef Replace) {
- AbstractManglingParser::reset(Mangled.begin(), Mangled.end());
+
+protected:
+ void reset(llvm::StringRef Mangled) {
+ Base::reset(Mangled.begin(), Mangled.end());
Written = Mangled.begin();
- this->Search = Search;
- this->Replace = Replace;
Result.clear();
Substituted = false;
}
- void appendUnchangedInput() {
- Result += llvm::StringRef(Written, First - Written);
- Written = First;
- }
-
-public:
- TypeSubstitutor() : AbstractManglingParser(nullptr, nullptr) {}
-
- ConstString substitute(llvm::StringRef Mangled, llvm::StringRef From,
- llvm::StringRef To) {
+ ConstString substituteImpl(llvm::StringRef Mangled) {
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
-
- reset(Mangled, From, To);
- if (parse() == nullptr) {
+ if (this->parse() == nullptr) {
LLDB_LOG(log, "Failed to substitute mangling in {0}", Mangled);
return ConstString();
}
@@ -337,20 +324,69 @@ public:
return ConstString(Result);
}
+ void trySubstitute(llvm::StringRef From, llvm::StringRef To) {
+ if (!llvm::StringRef(currentParserPos(), this->numLeft()).startswith(From))
+ return;
+
+ // We found a match. Append unmodified input up to this point.
+ appendUnchangedInput();
+
+ // And then perform the replacement.
+ Result += To;
+ Written += From.size();
+ Substituted = true;
+ }
+
+private:
+ /// Input character until which we have constructed the respective output
+ /// already.
+ const char *Written;
+
+ llvm::SmallString<128> Result;
+
+ /// Whether we have performed any substitutions.
+ bool Substituted;
+
+ const char *currentParserPos() const { return this->First; }
+
+ void appendUnchangedInput() {
+ Result +=
+ llvm::StringRef(Written, std::distance(Written, currentParserPos()));
+ Written = currentParserPos();
+ }
+
+};
+
+/// Given a mangled function `Mangled`, replace all the primitive function type
+/// arguments of `Search` with type `Replace`.
+class TypeSubstitutor : public ManglingSubstitutor<TypeSubstitutor> {
+ llvm::StringRef Search;
+ llvm::StringRef Replace;
+
+public:
+ void reset(llvm::StringRef Mangled, llvm::StringRef Search,
+ llvm::StringRef Replace) {
+ ManglingSubstitutor::reset(Mangled);
+ this->Search = Search;
+ this->Replace = Replace;
+ }
+
llvm::itanium_demangle::Node *parseType() {
- if (llvm::StringRef(First, numLeft()).startswith(Search)) {
- // We found a match. Append unmodified input up to this point.
- appendUnchangedInput();
-
- // And then perform the replacement.
- Result += Replace;
- Written += Search.size();
- Substituted = true;
- }
- return AbstractManglingParser::parseType();
+ trySubstitute(Search, Replace);
+ return ManglingSubstitutor::parseType();
}
};
-}
+
+class CtorDtorSubstitutor : public ManglingSubstitutor<CtorDtorSubstitutor> {
+public:
+ llvm::itanium_demangle::Node *
+ parseCtorDtorName(llvm::itanium_demangle::Node *&SoFar, NameState *State) {
+ trySubstitute("C1", "C2");
+ trySubstitute("D1", "D2");
+ return ManglingSubstitutor::parseCtorDtorName(SoFar, State);
+ }
+};
+} // namespace
uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings(
const ConstString mangled_name, std::set<ConstString> &alternates) {
@@ -398,6 +434,10 @@ uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings(
TS.substitute(mangled_name.GetStringRef(), "y", "m"))
alternates.insert(ulong_fixup);
+ if (ConstString ctor_fixup =
+ CtorDtorSubstitutor().substitute(mangled_name.GetStringRef()))
+ alternates.insert(ctor_fixup);
+
return alternates.size() - start_size;
}
@@ -426,6 +466,13 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"std::__[[:alnum:]]+::char_traits<char>, "
"std::__[[:alnum:]]+::allocator<char> >$"),
stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp,
+ lldb_private::formatters::LibcxxStringSummaryProviderASCII,
+ "std::string summary provider",
+ ConstString("^std::__[[:alnum:]]+::basic_string<unsigned char, "
+ "std::__[[:alnum:]]+::char_traits<unsigned char>, "
+ "std::__[[:alnum:]]+::allocator<unsigned char> >$"),
+ stl_summary_flags, true);
AddCXXSummary(cpp_category_sp,
lldb_private::formatters::LibcxxStringSummaryProviderUTF16,
@@ -568,6 +615,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"weak_ptr synthetic children",
ConstString("^(std::__[[:alnum:]]+::)weak_ptr<.+>(( )?&)?$"),
stl_synth_flags, true);
+ AddCXXSummary(cpp_category_sp,
+ lldb_private::formatters::LibcxxFunctionSummaryProvider,
+ "libc++ std::function summary provider",
+ ConstString("^std::__[[:alnum:]]+::function<.+>$"),
+ stl_summary_flags, true);
stl_summary_flags.SetDontShowChildren(false);
stl_summary_flags.SetSkipPointers(false);
@@ -719,6 +771,10 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
ConstString("std::__cxx11::basic_string<char, std::char_traits<char>, "
"std::allocator<char> >"),
cxx11_string_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(
+ ConstString("std::__cxx11::basic_string<unsigned char, std::char_traits<unsigned char>, "
+ "std::allocator<unsigned char> >"),
+ cxx11_string_summary_sp);
// making sure we force-pick the summary for printing wstring (_M_p is a
// wchar_t*)
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
index d30e56080732..4ed45bc904ce 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
@@ -101,7 +101,7 @@ public:
static lldb_private::ConstString GetPluginNameStatic();
- static bool IsCPPMangledName(const char *name);
+ static bool IsCPPMangledName(llvm::StringRef name);
// Extract C++ context and identifier from a string using heuristic matching
// (as opposed to
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index abe89035c532..ecadaef7a87e 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -572,10 +572,13 @@ bool lldb_private::formatters::LibcxxWStringSummaryProvider(
location_sp->GetPointeeData(extractor, 0, size);
// std::wstring::size() is measured in 'characters', not bytes
- auto wchar_t_size = valobj.GetTargetSP()
- ->GetScratchClangASTContext()
- ->GetBasicType(lldb::eBasicTypeWChar)
- .GetByteSize(nullptr);
+ ClangASTContext *ast_context =
+ ClangASTContext::GetScratch(*valobj.GetTargetSP());
+ if (!ast_context)
+ return false;
+
+ auto wchar_t_size =
+ ast_context->GetBasicType(lldb::eBasicTypeWChar).GetByteSize(nullptr);
if (!wchar_t_size)
return false;
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
index 619c718a1c1b..f6d8d4d9a7eb 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
@@ -94,6 +94,8 @@ public:
MapIterator(ValueObject *entry, size_t depth = 0)
: m_entry(entry), m_max_depth(depth), m_error(false) {}
+ MapIterator &operator=(const MapIterator &) = default;
+
ValueObjectSP value() { return m_entry.GetEntry(); }
ValueObjectSP advance(size_t count) {
diff --git a/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp b/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp
index a9a1b44731f2..3e77b1646739 100644
--- a/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp
+++ b/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp
@@ -139,6 +139,22 @@ void ClangHighlighter::Highlight(const HighlightStyle &options,
FileManager file_mgr(file_opts,
FileSystem::Instance().GetVirtualFileSystem());
+ // The line might end in a backslash which would cause Clang to drop the
+ // backslash and the terminating new line. This makes sense when parsing C++,
+ // but when highlighting we care about preserving the backslash/newline. To
+ // not lose this information we remove the new line here so that Clang knows
+ // this is just a single line we are highlighting. We add back the newline
+ // after tokenizing.
+ llvm::StringRef line_ending = "";
+ // There are a few legal line endings Clang recognizes and we need to
+ // temporarily remove from the string.
+ if (line.consume_back("\r\n"))
+ line_ending = "\r\n";
+ else if (line.consume_back("\n"))
+ line_ending = "\n";
+ else if (line.consume_back("\r"))
+ line_ending = "\r";
+
unsigned line_number = previous_lines.count('\n') + 1U;
// Let's build the actual source code Clang needs and setup some utility
@@ -227,6 +243,9 @@ void ClangHighlighter::Highlight(const HighlightStyle &options,
color.Apply(result, to_print);
}
+ // Add the line ending we trimmed before tokenizing.
+ result << line_ending;
+
// If we went over the whole file but couldn't find our own file, then
// somehow our setup was wrong. When we're in release mode we just give the
// user the normal line and pretend we don't know how to highlight it. In
diff --git a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
index ddf3953bb512..8a81abbaedbe 100644
--- a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
+++ b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
@@ -694,32 +694,44 @@ bool lldb_private::formatters::NSURLSummaryProvider(
CompilerType type(valobj.GetCompilerType());
ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset_text, type, true));
ValueObjectSP base(valobj.GetSyntheticChildAtOffset(offset_base, type, true));
- if (!text)
- return false;
- if (text->GetValueAsUnsigned(0) == 0)
+ if (!text || text->GetValueAsUnsigned(0) == 0)
return false;
+
+ StreamString base_summary;
+ if (base && base->GetValueAsUnsigned(0)) {
+ if (!NSURLSummaryProvider(*base, base_summary, options))
+ base_summary.Clear();
+ }
+ if (base_summary.Empty())
+ return NSStringSummaryProvider(*text, stream, options);
+
StreamString summary;
- if (!NSStringSummaryProvider(*text, summary, options))
+ if (!NSStringSummaryProvider(*text, summary, options) || summary.Empty())
return false;
- if (base && base->GetValueAsUnsigned(0)) {
- std::string summary_str = summary.GetString();
-
- if (!summary_str.empty())
- summary_str.pop_back();
- summary_str += " -- ";
- StreamString base_summary;
- if (NSURLSummaryProvider(*base, base_summary, options) &&
- !base_summary.Empty()) {
- llvm::StringRef base_str = base_summary.GetString();
- if (base_str.size() > 2)
- base_str = base_str.drop_front(2);
- summary_str += base_str;
+
+ const char quote_char = '"';
+ std::string prefix, suffix;
+ if (Language *language = Language::FindPlugin(options.GetLanguage())) {
+ if (!language->GetFormatterPrefixSuffix(*text, ConstString("NSString"),
+ prefix, suffix)) {
+ prefix.clear();
+ suffix.clear();
}
- summary.Clear();
- summary.PutCString(summary_str);
}
- if (!summary.Empty()) {
- stream.PutCString(summary.GetString());
+ // @"A" -> @"A
+ llvm::StringRef summary_str = summary.GetString();
+ bool back_consumed = summary_str.consume_back(quote_char + suffix);
+ assert(back_consumed);
+ UNUSED_IF_ASSERT_DISABLED(back_consumed);
+ // @"B" -> B"
+ llvm::StringRef base_summary_str = base_summary.GetString();
+ bool front_consumed = base_summary_str.consume_front(prefix + quote_char);
+ assert(front_consumed);
+ UNUSED_IF_ASSERT_DISABLED(front_consumed);
+ // @"A -- B"
+ if (!summary_str.empty() && !base_summary_str.empty()) {
+ stream.Printf("%s -- %s", summary_str.str().c_str(),
+ base_summary_str.str().c_str());
return true;
}
diff --git a/lldb/source/Plugins/Language/ObjC/NSArray.cpp b/lldb/source/Plugins/Language/ObjC/NSArray.cpp
index 7219c016dfd1..73335aff2fd7 100644
--- a/lldb/source/Plugins/Language/ObjC/NSArray.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSArray.cpp
@@ -96,31 +96,6 @@ private:
D64 *m_data_64;
};
-namespace Foundation109 {
- struct DataDescriptor_32 {
- uint32_t _used;
- uint32_t _priv1 : 2;
- uint32_t _size : 30;
- uint32_t _priv2 : 2;
- uint32_t _offset : 30;
- uint32_t _priv3;
- uint32_t _data;
- };
-
- struct DataDescriptor_64 {
- uint64_t _used;
- uint64_t _priv1 : 2;
- uint64_t _size : 62;
- uint64_t _priv2 : 2;
- uint64_t _offset : 62;
- uint32_t _priv3;
- uint64_t _data;
- };
-
- using NSArrayMSyntheticFrontEnd =
- GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;
-}
-
namespace Foundation1010 {
struct DataDescriptor_32 {
uint32_t _used;
@@ -461,13 +436,12 @@ lldb_private::formatters::NSArrayMSyntheticFrontEndBase::NSArrayMSyntheticFrontE
: SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8),
m_id_type() {
if (valobj_sp) {
- auto *clang_ast_context = valobj_sp->GetExecutionContextRef()
- .GetTargetSP()
- ->GetScratchClangASTContext();
+ auto *clang_ast_context = ClangASTContext::GetScratch(
+ *valobj_sp->GetExecutionContextRef().GetTargetSP());
if (clang_ast_context)
m_id_type = CompilerType(
clang_ast_context,
- clang_ast_context->getASTContext()->ObjCBuiltinIdTy.getAsOpaquePtr());
+ clang_ast_context->getASTContext().ObjCBuiltinIdTy.getAsOpaquePtr());
if (valobj_sp->GetProcessSP())
m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize();
}
@@ -610,13 +584,11 @@ lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>::
if (valobj_sp) {
CompilerType type = valobj_sp->GetCompilerType();
if (type) {
- auto *clang_ast_context = valobj_sp->GetExecutionContextRef()
- .GetTargetSP()
- ->GetScratchClangASTContext();
+ auto *clang_ast_context = ClangASTContext::GetScratch(
+ *valobj_sp->GetExecutionContextRef().GetTargetSP());
if (clang_ast_context)
- m_id_type = CompilerType(clang_ast_context,
- clang_ast_context->getASTContext()
- ->ObjCBuiltinIdTy.getAsOpaquePtr());
+ m_id_type = clang_ast_context->GetType(
+ clang_ast_context->getASTContext().ObjCBuiltinIdTy);
}
}
}
@@ -780,11 +752,15 @@ lldb_private::formatters::NSArray1SyntheticFrontEnd::GetChildAtIndex(
static const ConstString g_zero("[0]");
if (idx == 0) {
- CompilerType id_type(
- m_backend.GetTargetSP()->GetScratchClangASTContext()->GetBasicType(
- lldb::eBasicTypeObjCID));
- return m_backend.GetSyntheticChildAtOffset(
- m_backend.GetProcessSP()->GetAddressByteSize(), id_type, true, g_zero);
+ auto *clang_ast_context =
+ ClangASTContext::GetScratch(*m_backend.GetTargetSP());
+ if (clang_ast_context) {
+ CompilerType id_type(
+ clang_ast_context->GetBasicType(lldb::eBasicTypeObjCID));
+ return m_backend.GetSyntheticChildAtOffset(
+ m_backend.GetProcessSP()->GetAddressByteSize(), id_type, true,
+ g_zero);
+ }
}
return lldb::ValueObjectSP();
}
@@ -857,8 +833,6 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator(
return (new Foundation1428::NSArrayMSyntheticFrontEnd(valobj_sp));
if (runtime->GetFoundationVersion() >= 1100)
return (new Foundation1010::NSArrayMSyntheticFrontEnd(valobj_sp));
- else
- return (new Foundation109::NSArrayMSyntheticFrontEnd(valobj_sp));
} else if (class_name == g_NSCallStackArray) {
return (new CallStackArray::NSCallStackArraySyntheticFrontEnd(valobj_sp));
} else {
diff --git a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
index 10f66c4a37f8..ae00674c49f3 100644
--- a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
@@ -65,7 +65,7 @@ NSDictionary_Additionals::GetAdditionalSynthetics() {
static CompilerType GetLLDBNSPairType(TargetSP target_sp) {
CompilerType compiler_type;
- ClangASTContext *target_ast_context = target_sp->GetScratchClangASTContext();
+ ClangASTContext *target_ast_context = ClangASTContext::GetScratch(*target_sp);
if (target_ast_context) {
ConstString g___lldb_autogen_nspair("__lldb_autogen_nspair");
diff --git a/lldb/source/Plugins/Language/ObjC/NSError.cpp b/lldb/source/Plugins/Language/ObjC/NSError.cpp
index 97df3be72c84..94a97c8ad039 100644
--- a/lldb/source/Plugins/Language/ObjC/NSError.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSError.cpp
@@ -86,10 +86,10 @@ bool lldb_private::formatters::NSError_SummaryProvider(
ValueObjectSP domain_str_sp = ValueObject::CreateValueObjectFromData(
"domain_str", isw.GetAsData(process_sp->GetByteOrder()),
- valobj.GetExecutionContextRef(), process_sp->GetTarget()
- .GetScratchClangASTContext()
- ->GetBasicType(lldb::eBasicTypeVoid)
- .GetPointerType());
+ valobj.GetExecutionContextRef(),
+ ClangASTContext::GetScratch(process_sp->GetTarget())
+ ->GetBasicType(lldb::eBasicTypeVoid)
+ .GetPointerType());
if (!domain_str_sp)
return false;
@@ -156,8 +156,8 @@ public:
m_child_sp = CreateValueObjectFromData(
"_userInfo", isw.GetAsData(process_sp->GetByteOrder()),
m_backend.GetExecutionContextRef(),
- process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(
- lldb::eBasicTypeObjCID));
+ ClangASTContext::GetScratch(process_sp->GetTarget())
+ ->GetBasicType(lldb::eBasicTypeObjCID));
return false;
}
diff --git a/lldb/source/Plugins/Language/ObjC/NSException.cpp b/lldb/source/Plugins/Language/ObjC/NSException.cpp
index 931794a12ab1..9150787361c5 100644
--- a/lldb/source/Plugins/Language/ObjC/NSException.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSException.cpp
@@ -69,10 +69,12 @@ static bool ExtractFields(ValueObject &valobj, ValueObjectSP *name_sp,
InferiorSizedWord userinfo_isw(userinfo, *process_sp);
InferiorSizedWord reserved_isw(reserved, *process_sp);
- CompilerType voidstar = process_sp->GetTarget()
- .GetScratchClangASTContext()
- ->GetBasicType(lldb::eBasicTypeVoid)
- .GetPointerType();
+ auto *clang_ast_context = ClangASTContext::GetScratch(process_sp->GetTarget());
+ if (!clang_ast_context)
+ return false;
+
+ CompilerType voidstar =
+ clang_ast_context->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
if (name_sp)
*name_sp = ValueObject::CreateValueObjectFromData(
@@ -96,21 +98,19 @@ static bool ExtractFields(ValueObject &valobj, ValueObjectSP *name_sp,
bool lldb_private::formatters::NSException_SummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
- lldb::ValueObjectSP name_sp;
lldb::ValueObjectSP reason_sp;
- if (!ExtractFields(valobj, &name_sp, &reason_sp, nullptr, nullptr))
+ if (!ExtractFields(valobj, nullptr, &reason_sp, nullptr, nullptr))
return false;
- if (!name_sp || !reason_sp)
+ if (!reason_sp) {
+ stream.Printf("No reason");
return false;
+ }
- StreamString name_str_summary;
StreamString reason_str_summary;
- if (NSStringSummaryProvider(*name_sp, name_str_summary, options) &&
- NSStringSummaryProvider(*reason_sp, reason_str_summary, options) &&
- !name_str_summary.Empty() && !reason_str_summary.Empty()) {
- stream.Printf("name: %s - reason: %s", name_str_summary.GetData(),
- reason_str_summary.GetData());
+ if (NSStringSummaryProvider(*reason_sp, reason_str_summary, options) &&
+ !reason_str_summary.Empty()) {
+ stream.Printf("%s", reason_str_summary.GetData());
return true;
} else
return false;
diff --git a/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp b/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
index 9ee6021ae56b..587dd13870a0 100644
--- a/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
@@ -53,9 +53,8 @@ public:
if (!type_system)
return false;
- ClangASTContext *ast = m_backend.GetExecutionContextRef()
- .GetTargetSP()
- ->GetScratchClangASTContext();
+ ClangASTContext *ast = ClangASTContext::GetScratch(
+ *m_backend.GetExecutionContextRef().GetTargetSP());
if (!ast)
return false;
diff --git a/lldb/source/Plugins/Language/ObjC/NSString.cpp b/lldb/source/Plugins/Language/ObjC/NSString.cpp
index 55e129b098dc..ce54d657374b 100644
--- a/lldb/source/Plugins/Language/ObjC/NSString.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSString.cpp
@@ -35,7 +35,7 @@ NSString_Additionals::GetAdditionalSummaries() {
static CompilerType GetNSPathStore2Type(Target &target) {
static ConstString g_type_name("__lldb_autogen_nspathstore2");
- ClangASTContext *ast_ctx = target.GetScratchClangASTContext();
+ ClangASTContext *ast_ctx = ClangASTContext::GetScratch(target);
if (!ast_ctx)
return CompilerType();
diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
index c5bfb5747c13..3be548ad4144 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -15,6 +15,7 @@
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/ConstString.h"
@@ -887,7 +888,7 @@ ObjCLanguage::GetPossibleFormattersMatches(ValueObject &valobj,
bool canBeObjCDynamic =
compiler_type.IsPossibleDynamicType(nullptr, check_cpp, check_objc);
- if (canBeObjCDynamic) {
+ if (canBeObjCDynamic && ClangUtil::IsClangType(compiler_type)) {
do {
lldb::ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
index f38014505a8b..d556aae1c458 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
@@ -21,6 +21,7 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/RegisterContext.h"
@@ -28,6 +29,7 @@
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/ThreadPlanRunToAddress.h"
#include "lldb/Target/ThreadPlanStepInRange.h"
+#include "lldb/Utility/Timer.h"
using namespace lldb;
using namespace lldb_private;
@@ -58,9 +60,53 @@ bool CPPLanguageRuntime::GetObjectDescription(
return false;
}
+bool contains_lambda_identifier(llvm::StringRef &str_ref) {
+ return str_ref.contains("$_") || str_ref.contains("'lambda'");
+}
+
+CPPLanguageRuntime::LibCppStdFunctionCallableInfo
+line_entry_helper(Target &target, const SymbolContext &sc, Symbol *symbol,
+ llvm::StringRef first_template_param_sref,
+ bool has___invoke) {
+
+ CPPLanguageRuntime::LibCppStdFunctionCallableInfo optional_info;
+
+ AddressRange range;
+ sc.GetAddressRange(eSymbolContextEverything, 0, false, range);
+
+ Address address = range.GetBaseAddress();
+
+ Address addr;
+ if (target.ResolveLoadAddress(address.GetCallableLoadAddress(&target),
+ addr)) {
+ LineEntry line_entry;
+ addr.CalculateSymbolContextLineEntry(line_entry);
+
+ if (contains_lambda_identifier(first_template_param_sref) || has___invoke) {
+ // Case 1 and 2
+ optional_info.callable_case = lldb_private::CPPLanguageRuntime::
+ LibCppStdFunctionCallableCase::Lambda;
+ } else {
+ // Case 3
+ optional_info.callable_case = lldb_private::CPPLanguageRuntime::
+ LibCppStdFunctionCallableCase::CallableObject;
+ }
+
+ optional_info.callable_symbol = *symbol;
+ optional_info.callable_line_entry = line_entry;
+ optional_info.callable_address = addr;
+ }
+
+ return optional_info;
+}
+
CPPLanguageRuntime::LibCppStdFunctionCallableInfo
CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
lldb::ValueObjectSP &valobj_sp) {
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
+ "CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo");
+
LibCppStdFunctionCallableInfo optional_info;
if (!valobj_sp)
@@ -93,7 +139,7 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
// this entry and lookup operator()() and obtain the line table entry.
// 3) a callable object via operator()(). We will obtain the name of the
// object from the first template parameter from __func's vtable. We will
- // look up the objectc operator()() and obtain the line table entry.
+ // look up the objects operator()() and obtain the line table entry.
// 4) a member function. A pointer to the function will stored after the
// we will obtain the name from this pointer.
// 5) a free function. A pointer to the function will stored after the vtable
@@ -113,6 +159,9 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
optional_info.member__f_pointer_value = member__f_pointer_value;
+ if (!member__f_pointer_value)
+ return optional_info;
+
ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef());
Process *process = exe_ctx.GetProcessPtr();
@@ -130,8 +179,14 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
if (status.Fail())
return optional_info;
+ lldb::addr_t vtable_address_first_entry =
+ process->ReadPointerFromMemory(vtable_address + address_size, status);
+
+ if (status.Fail())
+ return optional_info;
+
lldb::addr_t address_after_vtable = member__f_pointer_value + address_size;
- // As commened above we may not have a function pointer but if we do we will
+ // As commented above we may not have a function pointer but if we do we will
// need it.
lldb::addr_t possible_function_address =
process->ReadPointerFromMemory(address_after_vtable, status);
@@ -144,9 +199,15 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
if (target.GetSectionLoadList().IsEmpty())
return optional_info;
+ Address vtable_first_entry_resolved;
+
+ if (!target.GetSectionLoadList().ResolveLoadAddress(
+ vtable_address_first_entry, vtable_first_entry_resolved))
+ return optional_info;
+
Address vtable_addr_resolved;
SymbolContext sc;
- Symbol *symbol;
+ Symbol *symbol = nullptr;
if (!target.GetSectionLoadList().ResolveLoadAddress(vtable_address,
vtable_addr_resolved))
@@ -159,7 +220,7 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
if (symbol == nullptr)
return optional_info;
- llvm::StringRef vtable_name(symbol->GetName().GetCString());
+ llvm::StringRef vtable_name(symbol->GetName().GetStringRef());
bool found_expected_start_string =
vtable_name.startswith("vtable for std::__1::__function::__func<");
@@ -172,6 +233,11 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
// ... __func<main::$_0, std::__1::allocator<main::$_0> ...
// ^^^^^^^^^
//
+ // We could see names such as:
+ // main::$_0
+ // Bar::add_num2(int)::'lambda'(int)
+ // Bar
+ //
// We do this by find the first < and , and extracting in between.
//
// This covers the case of the lambda known at compile time.
@@ -193,81 +259,28 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
symbol = sc.symbol;
}
- auto get_name = [&first_template_parameter, &symbol]() {
- // Given case 1:
- //
- // main::$_0
- //
- // we want to append ::operator()()
- if (first_template_parameter.contains("$_"))
- return llvm::Regex::escape(first_template_parameter.str()) +
- R"(::operator\(\)\(.*\))";
-
- if (symbol != nullptr &&
- symbol->GetName().GetStringRef().contains("__invoke")) {
-
- llvm::StringRef symbol_name = symbol->GetName().GetStringRef();
- size_t pos2 = symbol_name.find_last_of(':');
-
- // Given case 2:
- //
- // main::$_1::__invoke(...)
- //
- // We want to slice off __invoke(...) and append operator()()
- std::string lambda_operator =
- llvm::Regex::escape(symbol_name.slice(0, pos2 + 1).str()) +
- R"(operator\(\)\(.*\))";
-
- return lambda_operator;
- }
-
- // Case 3
- return first_template_parameter.str() + R"(::operator\(\)\(.*\))";
- ;
+ // These conditions are used several times to simplify statements later on.
+ bool has___invoke =
+ (symbol ? symbol->GetName().GetStringRef().contains("__invoke") : false);
+ auto calculate_symbol_context_helper = [](auto &t,
+ SymbolContextList &sc_list) {
+ SymbolContext sc;
+ t->CalculateSymbolContext(&sc);
+ sc_list.Append(sc);
};
- std::string func_to_match = get_name();
-
- SymbolContextList scl;
-
- target.GetImages().FindSymbolsMatchingRegExAndType(
- RegularExpression{R"(^)" + func_to_match}, eSymbolTypeAny, scl);
+ // Case 2
+ if (has___invoke) {
+ SymbolContextList scl;
+ calculate_symbol_context_helper(symbol, scl);
- // Case 1,2 or 3
- if (scl.GetSize() >= 1) {
- SymbolContext sc2 = scl[0];
-
- AddressRange range;
- sc2.GetAddressRange(eSymbolContextEverything, 0, false, range);
-
- Address address = range.GetBaseAddress();
-
- Address addr;
- if (target.ResolveLoadAddress(address.GetCallableLoadAddress(&target),
- addr)) {
- LineEntry line_entry;
- addr.CalculateSymbolContextLineEntry(line_entry);
-
- if (first_template_parameter.contains("$_") ||
- (symbol != nullptr &&
- symbol->GetName().GetStringRef().contains("__invoke"))) {
- // Case 1 and 2
- optional_info.callable_case = LibCppStdFunctionCallableCase::Lambda;
- } else {
- // Case 3
- optional_info.callable_case =
- LibCppStdFunctionCallableCase::CallableObject;
- }
-
- optional_info.callable_symbol = *symbol;
- optional_info.callable_line_entry = line_entry;
- optional_info.callable_address = addr;
- return optional_info;
- }
+ return line_entry_helper(target, scl[0], symbol, first_template_parameter,
+ has___invoke);
}
// Case 4 or 5
- if (symbol && !symbol->GetName().GetStringRef().startswith("vtable for")) {
+ if (symbol && !symbol->GetName().GetStringRef().startswith("vtable for") &&
+ !contains_lambda_identifier(first_template_parameter) && !has___invoke) {
optional_info.callable_case =
LibCppStdFunctionCallableCase::FreeOrMemberFunction;
optional_info.callable_address = function_address_resolved;
@@ -276,6 +289,50 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
return optional_info;
}
+ std::string func_to_match = first_template_parameter.str();
+
+ auto it = CallableLookupCache.find(func_to_match);
+ if (it != CallableLookupCache.end())
+ return it->second;
+
+ SymbolContextList scl;
+
+ CompileUnit *vtable_cu =
+ vtable_first_entry_resolved.CalculateSymbolContextCompileUnit();
+ llvm::StringRef name_to_use = func_to_match;
+
+ // Case 3, we have a callable object instead of a lambda
+ //
+ // TODO
+ // We currently don't support this case a callable object may have multiple
+ // operator()() varying on const/non-const and number of arguments and we
+ // don't have a way to currently distinguish them so we will bail out now.
+ if (!contains_lambda_identifier(name_to_use))
+ return optional_info;
+
+ if (vtable_cu && !has___invoke) {
+ lldb::FunctionSP func_sp =
+ vtable_cu->FindFunction([name_to_use](const FunctionSP &f) {
+ auto name = f->GetName().GetStringRef();
+ if (name.startswith(name_to_use) && name.contains("operator"))
+ return true;
+
+ return false;
+ });
+
+ if (func_sp) {
+ calculate_symbol_context_helper(func_sp, scl);
+ }
+ }
+
+ // Case 1 or 3
+ if (scl.GetSize() >= 1) {
+ optional_info = line_entry_helper(target, scl[0], symbol,
+ first_template_parameter, has___invoke);
+ }
+
+ CallableLookupCache[func_to_match] = optional_info;
+
return optional_info;
}
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h
index 28526361efc4..abdd79fcd7b9 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h
@@ -10,6 +10,9 @@
#define liblldb_CPPLanguageRuntime_h_
#include <vector>
+
+#include "llvm/ADT/StringMap.h"
+
#include "lldb/Core/PluginInterface.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/lldb-private.h"
@@ -82,6 +85,11 @@ protected:
CPPLanguageRuntime(Process *process);
private:
+ using OperatorStringToCallableInfoMap =
+ llvm::StringMap<CPPLanguageRuntime::LibCppStdFunctionCallableInfo>;
+
+ OperatorStringToCallableInfoMap CallableLookupCache;
+
DISALLOW_COPY_AND_ASSIGN(CPPLanguageRuntime);
};
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index 02e62a263286..9efb021caa83 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -537,7 +537,10 @@ ValueObjectSP ItaniumABILanguageRuntime::GetExceptionObjectForThread(
return {};
ClangASTContext *clang_ast_context =
- m_process->GetTarget().GetScratchClangASTContext();
+ ClangASTContext::GetScratch(m_process->GetTarget());
+ if (!clang_ast_context)
+ return {};
+
CompilerType voidstar =
clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
@@ -559,6 +562,9 @@ ValueObjectSP ItaniumABILanguageRuntime::GetExceptionObjectForThread(
modules.FindSymbolsWithNameAndType(
ConstString("__cxa_current_exception_type"), eSymbolTypeCode, contexts);
contexts.GetContextAtIndex(0, context);
+ if (!context.symbol) {
+ return {};
+ }
Address addr = context.symbol->GetAddress();
Status error;
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
index 93aa07f89165..859b693477a9 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
@@ -111,6 +111,18 @@ bool ClassDescriptorV2::class_rw_t::Read(Process *process, lldb::addr_t addr) {
m_firstSubclass = extractor.GetAddress_unchecked(&cursor);
m_nextSiblingClass = extractor.GetAddress_unchecked(&cursor);
+ if (m_ro_ptr & 1) {
+ DataBufferHeap buffer(ptr_size, '\0');
+ process->ReadMemory(m_ro_ptr ^ 1, buffer.GetBytes(), ptr_size, error);
+ if (error.Fail())
+ return false;
+ cursor = 0;
+ DataExtractor extractor(buffer.GetBytes(), ptr_size,
+ process->GetByteOrder(),
+ process->GetAddressByteSize());
+ m_ro_ptr = extractor.GetAddress_unchecked(&cursor);
+ }
+
return true;
}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
index 1f27a4f0b3ed..73843063606c 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
@@ -8,10 +8,9 @@
#include "AppleObjCDeclVendor.h"
-#include "Plugins/ExpressionParser/Clang/ASTDumper.h"
#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
#include "lldb/Core/Module.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/ClangASTMetadata.h"
#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -19,12 +18,12 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
-
+#include "clang/AST/ExternalASTSource.h"
using namespace lldb_private;
class lldb_private::AppleObjCExternalASTSource
- : public ClangExternalASTSourceCommon {
+ : public clang::ExternalASTSource {
public:
AppleObjCExternalASTSource(AppleObjCDeclVendor &decl_vendor)
: m_decl_vendor(decl_vendor) {}
@@ -77,24 +76,18 @@ public:
Log *log(GetLogIfAllCategoriesSet(
LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
- if (log) {
- LLDB_LOGF(log,
- "AppleObjCExternalASTSource::CompleteType[%u] on "
- "(ASTContext*)%p Completing (TagDecl*)%p named %s",
- current_id, static_cast<void *>(&tag_decl->getASTContext()),
- static_cast<void *>(tag_decl),
- tag_decl->getName().str().c_str());
+ LLDB_LOGF(log,
+ "AppleObjCExternalASTSource::CompleteType[%u] on "
+ "(ASTContext*)%p Completing (TagDecl*)%p named %s",
+ current_id, static_cast<void *>(&tag_decl->getASTContext()),
+ static_cast<void *>(tag_decl), tag_decl->getName().str().c_str());
- LLDB_LOGF(log, " AOEAS::CT[%u] Before:", current_id);
- ASTDumper dumper((clang::Decl *)tag_decl);
- dumper.ToLog(log, " [CT] ");
- }
+ LLDB_LOG(log, " AOEAS::CT[{0}] Before:\n{1}", current_id,
+ ClangUtil::DumpDecl(tag_decl));
+
+ LLDB_LOG(log, " AOEAS::CT[{1}] After:{1}", current_id,
+ ClangUtil::DumpDecl(tag_decl));
- if (log) {
- LLDB_LOGF(log, " AOEAS::CT[%u] After:", current_id);
- ASTDumper dumper((clang::Decl *)tag_decl);
- dumper.ToLog(log, " [CT] ");
- }
return;
}
@@ -115,16 +108,14 @@ public:
interface_decl->getName().str().c_str());
LLDB_LOGF(log, " AOEAS::CT[%u] Before:", current_id);
- ASTDumper dumper((clang::Decl *)interface_decl);
- dumper.ToLog(log, " [CT] ");
+ LLDB_LOG(log, " [CT] {0}", ClangUtil::DumpDecl(interface_decl));
}
m_decl_vendor.FinishDecl(interface_decl);
if (log) {
LLDB_LOGF(log, " [CT] After:");
- ASTDumper dumper((clang::Decl *)interface_decl);
- dumper.ToLog(log, " [CT] ");
+ LLDB_LOG(log, " [CT] {0}", ClangUtil::DumpDecl(interface_decl));
}
return;
}
@@ -141,7 +132,7 @@ public:
void StartTranslationUnit(clang::ASTConsumer *Consumer) override {
clang::TranslationUnitDecl *translation_unit_decl =
- m_decl_vendor.m_ast_ctx.getASTContext()->getTranslationUnitDecl();
+ m_decl_vendor.m_ast_ctx.getASTContext().getTranslationUnitDecl();
translation_unit_decl->setHasExternalVisibleStorage();
translation_unit_decl->setHasExternalLexicalStorage();
}
@@ -155,14 +146,12 @@ AppleObjCDeclVendor::AppleObjCDeclVendor(ObjCLanguageRuntime &runtime)
m_ast_ctx(runtime.GetProcess()
->GetTarget()
.GetArchitecture()
- .GetTriple()
- .getTriple()
- .c_str()),
+ .GetTriple()),
m_type_realizer_sp(m_runtime.GetEncodingToType()) {
m_external_source = new AppleObjCExternalASTSource(*this);
llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> external_source_owning_ptr(
m_external_source);
- m_ast_ctx.getASTContext()->setExternalSource(external_source_owning_ptr);
+ m_ast_ctx.getASTContext().setExternalSource(external_source_owning_ptr);
}
clang::ObjCInterfaceDecl *
@@ -172,7 +161,7 @@ AppleObjCDeclVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa) {
if (iter != m_isa_to_interface.end())
return iter->second;
- clang::ASTContext *ast_ctx = m_ast_ctx.getASTContext();
+ clang::ASTContext &ast_ctx = m_ast_ctx.getASTContext();
ObjCLanguageRuntime::ClassDescriptorSP descriptor =
m_runtime.GetClassDescriptorFromISA(isa);
@@ -183,20 +172,20 @@ AppleObjCDeclVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa) {
ConstString name(descriptor->GetClassName());
clang::IdentifierInfo &identifier_info =
- ast_ctx->Idents.get(name.GetStringRef());
+ ast_ctx.Idents.get(name.GetStringRef());
clang::ObjCInterfaceDecl *new_iface_decl = clang::ObjCInterfaceDecl::Create(
- *ast_ctx, ast_ctx->getTranslationUnitDecl(), clang::SourceLocation(),
+ ast_ctx, ast_ctx.getTranslationUnitDecl(), clang::SourceLocation(),
&identifier_info, nullptr, nullptr);
ClangASTMetadata meta_data;
meta_data.SetISAPtr(isa);
- m_external_source->SetMetadata(new_iface_decl, meta_data);
+ m_ast_ctx.SetMetadata(new_iface_decl, meta_data);
new_iface_decl->setHasExternalVisibleStorage();
new_iface_decl->setHasExternalLexicalStorage();
- ast_ctx->getTranslationUnitDecl()->addDecl(new_iface_decl);
+ ast_ctx.getTranslationUnitDecl()->addDecl(new_iface_decl);
m_isa_to_interface[isa] = new_iface_decl;
@@ -320,7 +309,8 @@ public:
}
clang::ObjCMethodDecl *
- BuildMethod(clang::ObjCInterfaceDecl *interface_decl, const char *name,
+ BuildMethod(ClangASTContext &clang_ast_ctxt,
+ clang::ObjCInterfaceDecl *interface_decl, const char *name,
bool instance,
ObjCLanguageRuntime::EncodingToTypeSP type_realizer_sp) {
if (!m_is_valid || m_type_vector.size() < 3)
@@ -330,7 +320,8 @@ public:
const bool isInstance = instance;
const bool isVariadic = false;
- const bool isSynthesized = false;
+ const bool isPropertyAccessor = false;
+ const bool isSynthesizedAccessorStub = false;
const bool isImplicitlyDeclared = true;
const bool isDefined = false;
const clang::ObjCMethodDecl::ImplementationControl impControl =
@@ -368,8 +359,7 @@ public:
clang::QualType ret_type =
ClangUtil::GetQualType(type_realizer_sp->RealizeType(
- interface_decl->getASTContext(), m_type_vector[0].c_str(),
- for_expression));
+ clang_ast_ctxt, m_type_vector[0].c_str(), for_expression));
if (ret_type.isNull())
return nullptr;
@@ -377,8 +367,8 @@ public:
clang::ObjCMethodDecl *ret = clang::ObjCMethodDecl::Create(
ast_ctx, clang::SourceLocation(), clang::SourceLocation(), sel,
ret_type, nullptr, interface_decl, isInstance, isVariadic,
- isSynthesized, isImplicitlyDeclared, isDefined, impControl,
- HasRelatedResultType);
+ isPropertyAccessor, isSynthesizedAccessorStub, isImplicitlyDeclared,
+ isDefined, impControl, HasRelatedResultType);
std::vector<clang::ParmVarDecl *> parm_vars;
@@ -386,7 +376,7 @@ public:
const bool for_expression = true;
clang::QualType arg_type =
ClangUtil::GetQualType(type_realizer_sp->RealizeType(
- ast_ctx, m_type_vector[ai].c_str(), for_expression));
+ clang_ast_ctxt, m_type_vector[ai].c_str(), for_expression));
if (arg_type.isNull())
return nullptr; // well, we just wasted a bunch of time. Wish we could
@@ -421,7 +411,7 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) {
Log *log(GetLogIfAllCategoriesSet(
LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
- ClangASTMetadata *metadata = m_external_source->GetMetadata(interface_decl);
+ ClangASTMetadata *metadata = m_ast_ctx.GetMetadata(interface_decl);
ObjCLanguageRuntime::ObjCISA objc_isa = 0;
if (metadata)
objc_isa = metadata->GetISAPtr();
@@ -451,9 +441,9 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) {
return;
FinishDecl(superclass_decl);
- clang::ASTContext *context = m_ast_ctx.getASTContext();
- interface_decl->setSuperClass(context->getTrivialTypeSourceInfo(
- context->getObjCInterfaceType(superclass_decl)));
+ clang::ASTContext &context = m_ast_ctx.getASTContext();
+ interface_decl->setSuperClass(context.getTrivialTypeSourceInfo(
+ context.getObjCInterfaceType(superclass_decl)));
};
auto instance_method_func =
@@ -463,8 +453,8 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) {
ObjCRuntimeMethodType method_type(types);
- clang::ObjCMethodDecl *method_decl =
- method_type.BuildMethod(interface_decl, name, true, m_type_realizer_sp);
+ clang::ObjCMethodDecl *method_decl = method_type.BuildMethod(
+ m_ast_ctx, interface_decl, name, true, m_type_realizer_sp);
LLDB_LOGF(log, "[ AOTV::FD] Instance method [%s] [%s]", name, types);
@@ -482,7 +472,7 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) {
ObjCRuntimeMethodType method_type(types);
clang::ObjCMethodDecl *method_decl = method_type.BuildMethod(
- interface_decl, name, false, m_type_realizer_sp);
+ m_ast_ctx, interface_decl, name, false, m_type_realizer_sp);
LLDB_LOGF(log, "[ AOTV::FD] Class method [%s] [%s]", name, types);
@@ -511,8 +501,8 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) {
clang::TypeSourceInfo *const type_source_info = nullptr;
const bool is_synthesized = false;
clang::ObjCIvarDecl *ivar_decl = clang::ObjCIvarDecl::Create(
- *m_ast_ctx.getASTContext(), interface_decl, clang::SourceLocation(),
- clang::SourceLocation(), &m_ast_ctx.getASTContext()->Idents.get(name),
+ m_ast_ctx.getASTContext(), interface_decl, clang::SourceLocation(),
+ clang::SourceLocation(), &m_ast_ctx.getASTContext().Idents.get(name),
ClangUtil::GetQualType(ivar_type),
type_source_info, // TypeSourceInfo *
clang::ObjCIvarDecl::Public, nullptr, is_synthesized);
@@ -525,36 +515,29 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) {
return false;
};
- if (log) {
- ASTDumper method_dumper((clang::Decl *)interface_decl);
-
- LLDB_LOGF(log,
- "[AppleObjCDeclVendor::FinishDecl] Finishing Objective-C "
- "interface for %s",
- descriptor->GetClassName().AsCString());
- }
+ LLDB_LOG(log,
+ "[AppleObjCDeclVendor::FinishDecl] Finishing Objective-C "
+ "interface for %s",
+ descriptor->GetClassName().AsCString());
if (!descriptor->Describe(superclass_func, instance_method_func,
class_method_func, ivar_func))
return false;
if (log) {
- ASTDumper method_dumper((clang::Decl *)interface_decl);
-
LLDB_LOGF(
log,
"[AppleObjCDeclVendor::FinishDecl] Finished Objective-C interface");
- method_dumper.ToLog(log, " [AOTV::FD] ");
+ LLDB_LOG(log, " [AOTV::FD] {0}", ClangUtil::DumpDecl(interface_decl));
}
return true;
}
-uint32_t
-AppleObjCDeclVendor::FindDecls(ConstString name, bool append,
- uint32_t max_matches,
- std::vector<clang::NamedDecl *> &decls) {
+uint32_t AppleObjCDeclVendor::FindDecls(ConstString name, bool append,
+ uint32_t max_matches,
+ std::vector<CompilerDecl> &decls) {
static unsigned int invocation_id = 0;
unsigned int current_id = invocation_id++;
@@ -573,37 +556,35 @@ AppleObjCDeclVendor::FindDecls(ConstString name, bool append,
do {
// See if the type is already in our ASTContext.
- clang::ASTContext *ast_ctx = m_ast_ctx.getASTContext();
+ clang::ASTContext &ast_ctx = m_ast_ctx.getASTContext();
clang::IdentifierInfo &identifier_info =
- ast_ctx->Idents.get(name.GetStringRef());
+ ast_ctx.Idents.get(name.GetStringRef());
clang::DeclarationName decl_name =
- ast_ctx->DeclarationNames.getIdentifier(&identifier_info);
+ ast_ctx.DeclarationNames.getIdentifier(&identifier_info);
clang::DeclContext::lookup_result lookup_result =
- ast_ctx->getTranslationUnitDecl()->lookup(decl_name);
+ ast_ctx.getTranslationUnitDecl()->lookup(decl_name);
if (!lookup_result.empty()) {
if (clang::ObjCInterfaceDecl *result_iface_decl =
llvm::dyn_cast<clang::ObjCInterfaceDecl>(lookup_result[0])) {
if (log) {
clang::QualType result_iface_type =
- ast_ctx->getObjCInterfaceType(result_iface_decl);
- ASTDumper dumper(result_iface_type);
+ ast_ctx.getObjCInterfaceType(result_iface_decl);
uint64_t isa_value = LLDB_INVALID_ADDRESS;
- ClangASTMetadata *metadata =
- m_external_source->GetMetadata(result_iface_decl);
+ ClangASTMetadata *metadata = m_ast_ctx.GetMetadata(result_iface_decl);
if (metadata)
isa_value = metadata->GetISAPtr();
- LLDB_LOGF(log,
- "AOCTV::FT [%u] Found %s (isa 0x%" PRIx64
- ") in the ASTContext",
- current_id, dumper.GetCString(), isa_value);
+ LLDB_LOG(log,
+ "AOCTV::FT [%u] Found %s (isa 0x%" PRIx64
+ ") in the ASTContext",
+ current_id, result_iface_type.getAsString(), isa_value);
}
- decls.push_back(result_iface_decl);
+ decls.push_back(CompilerDecl(&m_ast_ctx, result_iface_decl));
ret++;
break;
} else {
@@ -640,24 +621,16 @@ AppleObjCDeclVendor::FindDecls(ConstString name, bool append,
}
if (log) {
- clang::QualType new_iface_type =
- ast_ctx->getObjCInterfaceType(iface_decl);
- ASTDumper dumper(new_iface_type);
- LLDB_LOGF(log, "AOCTV::FT [%u] Created %s (isa 0x%" PRIx64 ")",
- current_id, dumper.GetCString(), (uint64_t)isa);
+ clang::QualType new_iface_type = ast_ctx.getObjCInterfaceType(iface_decl);
+
+ LLDB_LOG(log, "AOCTV::FT [{0}] Created {1} (isa 0x{2:x})", current_id,
+ new_iface_type.getAsString(), (uint64_t)isa);
}
- decls.push_back(iface_decl);
+ decls.push_back(CompilerDecl(&m_ast_ctx, iface_decl));
ret++;
break;
} while (false);
return ret;
}
-
-clang::ExternalASTMerger::ImporterSource
-AppleObjCDeclVendor::GetImporterSource() {
- return clang::ExternalASTMerger::ImporterSource(*m_ast_ctx.getASTContext(),
- *m_ast_ctx.getFileManager(),
- m_ast_ctx.GetOriginMap());
-}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h
index 99ca4b748709..f49ca3540c2c 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h
@@ -28,9 +28,7 @@ public:
}
uint32_t FindDecls(ConstString name, bool append, uint32_t max_matches,
- std::vector<clang::NamedDecl *> &decls) override;
-
- clang::ExternalASTMerger::ImporterSource GetImporterSource() override;
+ std::vector<CompilerDecl> &decls) override;
friend class AppleObjCExternalASTSource;
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
index 8ca9ad7b843a..7076959bee97 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
@@ -111,7 +111,10 @@ bool AppleObjCRuntime::GetObjectDescription(Stream &strm, Value &value,
}
} else {
// If it is not a pointer, see if we can make it into a pointer.
- ClangASTContext *ast_context = target->GetScratchClangASTContext();
+ ClangASTContext *ast_context = ClangASTContext::GetScratch(*target);
+ if (!ast_context)
+ return false;
+
CompilerType opaque_type = ast_context->GetBasicType(eBasicTypeObjCID);
if (!opaque_type)
opaque_type = ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
@@ -123,7 +126,9 @@ bool AppleObjCRuntime::GetObjectDescription(Stream &strm, Value &value,
arg_value_list.PushValue(value);
// This is the return value:
- ClangASTContext *ast_context = target->GetScratchClangASTContext();
+ ClangASTContext *ast_context = ClangASTContext::GetScratch(*target);
+ if (!ast_context)
+ return false;
CompilerType return_compiler_type = ast_context->GetCStringType(true);
Value ret;
@@ -494,9 +499,12 @@ ThreadSP AppleObjCRuntime::GetBacktraceThreadFromException(
reserved_dict = reserved_dict->GetSyntheticValue();
if (!reserved_dict) return ThreadSP();
+ ClangASTContext *clang_ast_context =
+ ClangASTContext::GetScratch(*exception_sp->GetTargetSP());
+ if (!clang_ast_context)
+ return ThreadSP();
CompilerType objc_id =
- exception_sp->GetTargetSP()->GetScratchClangASTContext()->GetBasicType(
- lldb::eBasicTypeObjCID);
+ clang_ast_context->GetBasicType(lldb::eBasicTypeObjCID);
ValueObjectSP return_addresses;
auto objc_object_from_address = [&exception_sp, &objc_id](uint64_t addr,
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index 9bdbef393e39..4015f10c4966 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -1301,7 +1301,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
return DescriptorMapUpdateResult::Fail();
thread_sp->CalculateExecutionContext(exe_ctx);
- ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
+ ClangASTContext *ast = ClangASTContext::GetScratch(process->GetTarget());
if (!ast)
return DescriptorMapUpdateResult::Fail();
@@ -1563,7 +1563,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
return DescriptorMapUpdateResult::Fail();
thread_sp->CalculateExecutionContext(exe_ctx);
- ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
+ ClangASTContext *ast = ClangASTContext::GetScratch(process->GetTarget());
if (!ast)
return DescriptorMapUpdateResult::Fail();
@@ -1625,19 +1625,13 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
// Substitute in the correct class_getName / class_getNameRaw function name,
// concatenate the two parts of our expression text. The format string
// has two %s's, so provide the name twice.
- int prefix_string_size = snprintf (nullptr, 0,
+ std::string shared_class_expression;
+ llvm::raw_string_ostream(shared_class_expression) << llvm::format(
g_shared_cache_class_name_funcptr,
class_name_getter_function_name.AsCString(),
class_name_getter_function_name.AsCString());
- char *class_name_func_ptr_expr = (char*) malloc (prefix_string_size + 1);
- snprintf (class_name_func_ptr_expr, prefix_string_size + 1,
- g_shared_cache_class_name_funcptr,
- class_name_getter_function_name.AsCString(),
- class_name_getter_function_name.AsCString());
- std::string shared_class_expression = class_name_func_ptr_expr;
shared_class_expression += g_get_shared_cache_class_info_body;
- free (class_name_func_ptr_expr);
m_get_shared_cache_class_info_code.reset(
GetTargetRef().GetUtilityFunctionForLanguage(
@@ -1984,36 +1978,6 @@ void AppleObjCRuntimeV2::WarnIfNoClassesCached(
}
}
-ConstString
-AppleObjCRuntimeV2::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) {
- if (isa == g_objc_Tagged_ISA) {
- static const ConstString g_objc_tagged_isa_name("_lldb_Tagged_ObjC_ISA");
- return g_objc_tagged_isa_name;
- }
- if (isa == g_objc_Tagged_ISA_NSAtom) {
- static const ConstString g_objc_tagged_isa_nsatom_name("NSAtom");
- return g_objc_tagged_isa_nsatom_name;
- }
- if (isa == g_objc_Tagged_ISA_NSNumber) {
- static const ConstString g_objc_tagged_isa_nsnumber_name("NSNumber");
- return g_objc_tagged_isa_nsnumber_name;
- }
- if (isa == g_objc_Tagged_ISA_NSDateTS) {
- static const ConstString g_objc_tagged_isa_nsdatets_name("NSDateTS");
- return g_objc_tagged_isa_nsdatets_name;
- }
- if (isa == g_objc_Tagged_ISA_NSManagedObject) {
- static const ConstString g_objc_tagged_isa_nsmanagedobject_name(
- "NSManagedObject");
- return g_objc_tagged_isa_nsmanagedobject_name;
- }
- if (isa == g_objc_Tagged_ISA_NSDate) {
- static const ConstString g_objc_tagged_isa_nsdate_name("NSDate");
- return g_objc_tagged_isa_nsdate_name;
- }
- return ObjCLanguageRuntime::GetActualTypeName(isa);
-}
-
DeclVendor *AppleObjCRuntimeV2::GetDeclVendor() {
if (!m_decl_vendor_up)
m_decl_vendor_up.reset(new AppleObjCDeclVendor(*this));
@@ -2678,10 +2642,12 @@ class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame {
const lldb::ABISP &abi = process_sp->GetABI();
if (!abi) return;
- CompilerType voidstar = process_sp->GetTarget()
- .GetScratchClangASTContext()
- ->GetBasicType(lldb::eBasicTypeVoid)
- .GetPointerType();
+ ClangASTContext *clang_ast_context =
+ ClangASTContext::GetScratch(process_sp->GetTarget());
+ if (!clang_ast_context)
+ return;
+ CompilerType voidstar =
+ clang_ast_context->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
ValueList args;
Value input_value;
@@ -2699,7 +2665,7 @@ class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame {
exception = ValueObjectRecognizerSynthesizedValue::Create(
*exception, eValueTypeVariableArgument);
exception = exception->GetDynamicValue(eDynamicDontRunTarget);
-
+
m_arguments = ValueObjectListSP(new ValueObjectList());
m_arguments->Append(exception);
}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
index a0fd39dc03b2..785bb3938d2c 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
@@ -69,8 +69,6 @@ public:
void UpdateISAToDescriptorMapIfNeeded() override;
- ConstString GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) override;
-
ClassDescriptorSP GetClassDescriptor(ValueObject &in_value) override;
ClassDescriptorSP GetClassDescriptorFromISA(ObjCISA isa) override;
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
index 379ef3dca86c..36f95c063b81 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
@@ -522,7 +522,10 @@ bool AppleObjCTrampolineHandler::AppleObjCVTables::RefreshTrampolines(
const ABI *abi = process->GetABI().get();
ClangASTContext *clang_ast_context =
- process->GetTarget().GetScratchClangASTContext();
+ ClangASTContext::GetScratch(process->GetTarget());
+ if (!clang_ast_context)
+ return false;
+
ValueList argument_values;
Value input_value;
CompilerType clang_void_ptr_type =
@@ -802,7 +805,10 @@ AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread,
// Next make the runner function for our implementation utility function.
ClangASTContext *clang_ast_context =
- thread.GetProcess()->GetTarget().GetScratchClangASTContext();
+ ClangASTContext::GetScratch(thread.GetProcess()->GetTarget());
+ if (!clang_ast_context)
+ return LLDB_INVALID_ADDRESS;
+
CompilerType clang_void_ptr_type =
clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
Status error;
@@ -895,7 +901,10 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
TargetSP target_sp(thread.CalculateTarget());
- ClangASTContext *clang_ast_context = target_sp->GetScratchClangASTContext();
+ ClangASTContext *clang_ast_context = ClangASTContext::GetScratch(*target_sp);
+ if (!clang_ast_context)
+ return ret_plan_sp;
+
ValueList argument_values;
Value void_ptr_value;
CompilerType clang_void_ptr_type =
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
index 6402e80d6f98..66f04bef6cbd 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
@@ -26,9 +26,7 @@ AppleObjCTypeEncodingParser::AppleObjCTypeEncodingParser(
m_scratch_ast_ctx_up.reset(new ClangASTContext(runtime.GetProcess()
->GetTarget()
.GetArchitecture()
- .GetTriple()
- .str()
- .c_str()));
+ .GetTriple()));
}
std::string AppleObjCTypeEncodingParser::ReadStructName(StringLexer &type) {
@@ -63,7 +61,7 @@ AppleObjCTypeEncodingParser::StructElement::StructElement()
: name(""), type(clang::QualType()), bitfield(0) {}
AppleObjCTypeEncodingParser::StructElement
-AppleObjCTypeEncodingParser::ReadStructElement(clang::ASTContext &ast_ctx,
+AppleObjCTypeEncodingParser::ReadStructElement(ClangASTContext &ast_ctx,
StringLexer &type,
bool for_expression) {
StructElement retval;
@@ -78,19 +76,19 @@ AppleObjCTypeEncodingParser::ReadStructElement(clang::ASTContext &ast_ctx,
}
clang::QualType AppleObjCTypeEncodingParser::BuildStruct(
- clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression) {
+ ClangASTContext &ast_ctx, StringLexer &type, bool for_expression) {
return BuildAggregate(ast_ctx, type, for_expression, '{', '}',
clang::TTK_Struct);
}
clang::QualType AppleObjCTypeEncodingParser::BuildUnion(
- clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression) {
+ ClangASTContext &ast_ctx, StringLexer &type, bool for_expression) {
return BuildAggregate(ast_ctx, type, for_expression, '(', ')',
clang::TTK_Union);
}
clang::QualType AppleObjCTypeEncodingParser::BuildAggregate(
- clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression,
+ ClangASTContext &ast_ctx, StringLexer &type, bool for_expression,
char opener, char closer, uint32_t kind) {
if (!type.NextIf(opener))
return clang::QualType();
@@ -124,11 +122,8 @@ clang::QualType AppleObjCTypeEncodingParser::BuildAggregate(
if (is_templated)
return clang::QualType(); // This is where we bail out. Sorry!
- ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
- if (!lldb_ctx)
- return clang::QualType();
- CompilerType union_type(lldb_ctx->CreateRecordType(
- nullptr, lldb::eAccessPublic, name.c_str(), kind, lldb::eLanguageTypeC));
+ CompilerType union_type(ast_ctx.CreateRecordType(
+ nullptr, lldb::eAccessPublic, name, kind, lldb::eLanguageTypeC));
if (union_type) {
ClangASTContext::StartTagDeclarationDefinition(union_type);
@@ -140,9 +135,7 @@ clang::QualType AppleObjCTypeEncodingParser::BuildAggregate(
element.name = elem_name.GetString();
}
ClangASTContext::AddFieldToRecordType(
- union_type, element.name.c_str(),
- CompilerType(ClangASTContext::GetASTContext(&ast_ctx),
- element.type.getAsOpaquePtr()),
+ union_type, element.name.c_str(), ast_ctx.GetType(element.type),
lldb::eAccessPublic, element.bitfield);
++count;
}
@@ -152,20 +145,15 @@ clang::QualType AppleObjCTypeEncodingParser::BuildAggregate(
}
clang::QualType AppleObjCTypeEncodingParser::BuildArray(
- clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression) {
+ ClangASTContext &ast_ctx, StringLexer &type, bool for_expression) {
if (!type.NextIf('['))
return clang::QualType();
uint32_t size = ReadNumber(type);
clang::QualType element_type(BuildType(ast_ctx, type, for_expression));
if (!type.NextIf(']'))
return clang::QualType();
- ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
- if (!lldb_ctx)
- return clang::QualType();
- CompilerType array_type(lldb_ctx->CreateArrayType(
- CompilerType(ClangASTContext::GetASTContext(&ast_ctx),
- element_type.getAsOpaquePtr()),
- size, false));
+ CompilerType array_type(ast_ctx.CreateArrayType(
+ CompilerType(&ast_ctx, element_type.getAsOpaquePtr()), size, false));
return ClangUtil::GetQualType(array_type);
}
@@ -175,10 +163,12 @@ clang::QualType AppleObjCTypeEncodingParser::BuildArray(
// consume but ignore the type info and always return an 'id'; if anything,
// dynamic typing will resolve things for us anyway
clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType(
- clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression) {
+ ClangASTContext &clang_ast_ctx, StringLexer &type, bool for_expression) {
if (!type.NextIf('@'))
return clang::QualType();
+ clang::ASTContext &ast_ctx = clang_ast_ctx.getASTContext();
+
std::string name;
if (type.NextIf('"')) {
@@ -257,23 +247,25 @@ clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType(
}
clang::QualType
-AppleObjCTypeEncodingParser::BuildType(clang::ASTContext &ast_ctx,
+AppleObjCTypeEncodingParser::BuildType(ClangASTContext &clang_ast_ctx,
StringLexer &type, bool for_expression,
uint32_t *bitfield_bit_size) {
if (!type.HasAtLeast(1))
return clang::QualType();
+ clang::ASTContext &ast_ctx = clang_ast_ctx.getASTContext();
+
switch (type.Peek()) {
default:
break;
case '{':
- return BuildStruct(ast_ctx, type, for_expression);
+ return BuildStruct(clang_ast_ctx, type, for_expression);
case '[':
- return BuildArray(ast_ctx, type, for_expression);
+ return BuildArray(clang_ast_ctx, type, for_expression);
case '(':
- return BuildUnion(ast_ctx, type, for_expression);
+ return BuildUnion(clang_ast_ctx, type, for_expression);
case '@':
- return BuildObjCObjectPointerType(ast_ctx, type, for_expression);
+ return BuildObjCObjectPointerType(clang_ast_ctx, type, for_expression);
}
switch (type.Next()) {
@@ -289,10 +281,7 @@ AppleObjCTypeEncodingParser::BuildType(clang::ASTContext &ast_ctx,
case 'l':
return ast_ctx.getIntTypeForBitwidth(32, true);
// this used to be done like this:
- // ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
- // if (!lldb_ctx)
- // return clang::QualType();
- // return lldb_ctx->GetIntTypeFromBitSize(32, true).GetQualType();
+ // return clang_ast_ctx->GetIntTypeFromBitSize(32, true).GetQualType();
// which uses one of the constants if one is available, but we don't think
// all this work is necessary.
case 'q':
@@ -331,7 +320,8 @@ AppleObjCTypeEncodingParser::BuildType(clang::ASTContext &ast_ctx,
return clang::QualType();
}
case 'r': {
- clang::QualType target_type = BuildType(ast_ctx, type, for_expression);
+ clang::QualType target_type =
+ BuildType(clang_ast_ctx, type, for_expression);
if (target_type.isNull())
return clang::QualType();
else if (target_type == ast_ctx.UnknownAnyTy)
@@ -348,7 +338,8 @@ AppleObjCTypeEncodingParser::BuildType(clang::ASTContext &ast_ctx,
// practical cases
return ast_ctx.VoidPtrTy;
} else {
- clang::QualType target_type = BuildType(ast_ctx, type, for_expression);
+ clang::QualType target_type =
+ BuildType(clang_ast_ctx, type, for_expression);
if (target_type.isNull())
return clang::QualType();
else if (target_type == ast_ctx.UnknownAnyTy)
@@ -362,13 +353,13 @@ AppleObjCTypeEncodingParser::BuildType(clang::ASTContext &ast_ctx,
}
}
-CompilerType AppleObjCTypeEncodingParser::RealizeType(
- clang::ASTContext &ast_ctx, const char *name, bool for_expression) {
+CompilerType AppleObjCTypeEncodingParser::RealizeType(ClangASTContext &ast_ctx,
+ const char *name,
+ bool for_expression) {
if (name && name[0]) {
StringLexer lexer(name);
clang::QualType qual_type = BuildType(ast_ctx, lexer, for_expression);
- return CompilerType(ClangASTContext::GetASTContext(&ast_ctx),
- qual_type.getAsOpaquePtr());
+ return ast_ctx.GetType(qual_type);
}
return CompilerType();
}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
index 590bc4ba9eae..e43711bf4ee4 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
@@ -22,7 +22,7 @@ public:
AppleObjCTypeEncodingParser(ObjCLanguageRuntime &runtime);
~AppleObjCTypeEncodingParser() override = default;
- CompilerType RealizeType(clang::ASTContext &ast_ctx, const char *name,
+ CompilerType RealizeType(ClangASTContext &ast_ctx, const char *name,
bool for_expression) override;
private:
@@ -35,29 +35,29 @@ private:
~StructElement() = default;
};
- clang::QualType BuildType(clang::ASTContext &ast_ctx, StringLexer &type,
+ clang::QualType BuildType(ClangASTContext &clang_ast_ctx, StringLexer &type,
bool for_expression,
uint32_t *bitfield_bit_size = nullptr);
- clang::QualType BuildStruct(clang::ASTContext &ast_ctx, StringLexer &type,
+ clang::QualType BuildStruct(ClangASTContext &ast_ctx, StringLexer &type,
bool for_expression);
- clang::QualType BuildAggregate(clang::ASTContext &ast_ctx, StringLexer &type,
- bool for_expression, char opener, char closer,
- uint32_t kind);
+ clang::QualType BuildAggregate(ClangASTContext &clang_ast_ctx,
+ StringLexer &type, bool for_expression,
+ char opener, char closer, uint32_t kind);
- clang::QualType BuildUnion(clang::ASTContext &ast_ctx, StringLexer &type,
+ clang::QualType BuildUnion(ClangASTContext &ast_ctx, StringLexer &type,
bool for_expression);
- clang::QualType BuildArray(clang::ASTContext &ast_ctx, StringLexer &type,
+ clang::QualType BuildArray(ClangASTContext &ast_ctx, StringLexer &type,
bool for_expression);
std::string ReadStructName(StringLexer &type);
- StructElement ReadStructElement(clang::ASTContext &ast_ctx, StringLexer &type,
+ StructElement ReadStructElement(ClangASTContext &ast_ctx, StringLexer &type,
bool for_expression);
- clang::QualType BuildObjCObjectPointerType(clang::ASTContext &ast_ctx,
+ clang::QualType BuildObjCObjectPointerType(ClangASTContext &clang_ast_ctx,
StringLexer &type,
bool for_expression);
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp
index 87ae4c2c6c48..9eb493f83c84 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp
@@ -222,14 +222,6 @@ ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa) {
return 0;
}
-ConstString
-ObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) {
- ClassDescriptorSP objc_class_sp(GetNonKVOClassDescriptor(isa));
- if (objc_class_sp)
- return objc_class_sp->GetClassName();
- return ConstString();
-}
-
ObjCLanguageRuntime::ClassDescriptorSP
ObjCLanguageRuntime::GetClassDescriptorFromClassName(
ConstString class_name) {
@@ -313,14 +305,6 @@ ObjCLanguageRuntime::EncodingToType::RealizeType(const char *name,
return CompilerType();
}
-CompilerType ObjCLanguageRuntime::EncodingToType::RealizeType(
- ClangASTContext &ast_ctx, const char *name, bool for_expression) {
- clang::ASTContext *clang_ast = ast_ctx.getASTContext();
- if (!clang_ast)
- return CompilerType();
- return RealizeType(*clang_ast, name, for_expression);
-}
-
ObjCLanguageRuntime::EncodingToType::~EncodingToType() {}
ObjCLanguageRuntime::EncodingToTypeSP ObjCLanguageRuntime::GetEncodingToType() {
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h
index 39acd6e9f268..b9a4d5dae08a 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h
@@ -145,12 +145,9 @@ public:
virtual ~EncodingToType();
virtual CompilerType RealizeType(ClangASTContext &ast_ctx, const char *name,
- bool for_expression);
+ bool for_expression) = 0;
virtual CompilerType RealizeType(const char *name, bool for_expression);
- virtual CompilerType RealizeType(clang::ASTContext &ast_ctx,
- const char *name, bool for_expression) = 0;
-
protected:
std::unique_ptr<ClangASTContext> m_scratch_ast_ctx_up;
};
@@ -274,8 +271,6 @@ public:
virtual ObjCISA GetISA(ConstString name);
- virtual ConstString GetActualTypeName(ObjCISA isa);
-
virtual ObjCISA GetParentClass(ObjCISA isa);
// Finds the byte offset of the child_type ivar in parent_type. If it can't
diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
index 5200749d759f..4edb8dec6082 100644
--- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
@@ -2240,8 +2240,7 @@ void RenderScriptRuntime::FindStructTypeName(Element &elem,
// Iterate over all the global variables looking for one with a matching type
// to the Element. We make the assumption a match exists since there needs to
// be a global variable to reflect the struct type back into java host code.
- for (uint32_t i = 0; i < var_list.GetSize(); ++i) {
- const VariableSP var_sp(var_list.GetVariableAtIndex(i));
+ for (const VariableSP &var_sp : var_list) {
if (!var_sp)
continue;
@@ -3892,7 +3891,7 @@ void RSModuleDescriptor::Dump(Stream &strm) const {
int indent = strm.GetIndentLevel();
strm.Indent();
- m_module->GetFileSpec().Dump(&strm);
+ m_module->GetFileSpec().Dump(strm.AsRawOstream());
strm.Indent(m_module->GetNumCompileUnits() ? "Debug info loaded."
: "Debug info does not exist.");
strm.EOL();
diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
index a6d225d2fbd8..4ddff3ad9c4c 100644
--- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
@@ -72,7 +72,7 @@ bool isRSAllocationTyCallSite(llvm::Module &module, llvm::CallInst *call_inst) {
(void)module;
if (!call_inst->hasByValArgument())
return false;
- for (const auto &param : call_inst->operand_values())
+ for (const auto *param : call_inst->operand_values())
if (isRSAllocationPtrTy(param->getType()))
return true;
return false;
diff --git a/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp b/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp
index de17d986a860..b83b2efb492f 100644
--- a/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp
+++ b/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp
@@ -72,7 +72,7 @@ llvm::Triple::ArchType stringTo<llvm::Triple::ArchType>(llvm::StringRef Str) {
.Case("sparc", Triple::sparc)
.Case("sparcv9", Triple::sparcv9)
.Case("x86", Triple::x86)
- .Case("x86_64", Triple::x86_64)
+ .Cases("x86_64", "x86_64h", Triple::x86_64)
.Default(Triple::UnknownArch);
}
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 3f8502548fc2..8b62afa18cd6 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -1572,8 +1572,10 @@ static SectionType GetSectionTypeFromName(llvm::StringRef Name) {
.Case("info.dwo", eSectionTypeDWARFDebugInfoDwo)
.Cases("line", "line.dwo", eSectionTypeDWARFDebugLine)
.Cases("line_str", "line_str.dwo", eSectionTypeDWARFDebugLineStr)
- .Cases("loc", "loc.dwo", eSectionTypeDWARFDebugLoc)
- .Cases("loclists", "loclists.dwo", eSectionTypeDWARFDebugLocLists)
+ .Case("loc", eSectionTypeDWARFDebugLoc)
+ .Case("loc.dwo", eSectionTypeDWARFDebugLocDwo)
+ .Case("loclists", eSectionTypeDWARFDebugLocLists)
+ .Case("loclists.dwo", eSectionTypeDWARFDebugLocListsDwo)
.Case("macinfo", eSectionTypeDWARFDebugMacInfo)
.Cases("macro", "macro.dwo", eSectionTypeDWARFDebugMacro)
.Case("names", eSectionTypeDWARFDebugNames)
@@ -1581,6 +1583,7 @@ static SectionType GetSectionTypeFromName(llvm::StringRef Name) {
.Case("pubtypes", eSectionTypeDWARFDebugPubTypes)
.Case("ranges", eSectionTypeDWARFDebugRanges)
.Case("rnglists", eSectionTypeDWARFDebugRngLists)
+ .Case("rnglists.dwo", eSectionTypeDWARFDebugRngListsDwo)
.Case("str", eSectionTypeDWARFDebugStr)
.Case("str.dwo", eSectionTypeDWARFDebugStrDwo)
.Case("str_offsets", eSectionTypeDWARFDebugStrOffsets)
@@ -2257,6 +2260,8 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
symbol_size_valid, // Symbol size is valid
has_suffix, // Contains linker annotations?
flags); // Symbol flags.
+ if (symbol.getBinding() == STB_WEAK)
+ dc_symbol.SetIsWeak(true);
symtab->AddSymbol(dc_symbol);
}
return i;
diff --git a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index b777a5319104..b04ac61c99a1 100644
--- a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -6,7 +6,9 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLDB_DISABLE_PYTHON
+#include "lldb/Host/Config.h"
+
+#if LLDB_ENABLE_PYTHON
#include "OperatingSystemPython.h"
@@ -88,13 +90,12 @@ OperatingSystemPython::OperatingSystemPython(lldb_private::Process *process,
python_module_path.GetFilename().AsCString(""));
if (!os_plugin_class_name.empty()) {
const bool init_session = false;
- const bool allow_reload = true;
char python_module_path_cstr[PATH_MAX];
python_module_path.GetPath(python_module_path_cstr,
sizeof(python_module_path_cstr));
Status error;
- if (m_interpreter->LoadScriptingModule(
- python_module_path_cstr, allow_reload, init_session, error)) {
+ if (m_interpreter->LoadScriptingModule(python_module_path_cstr,
+ init_session, error)) {
// Strip the ".py" extension if there is one
size_t py_extension_pos = os_plugin_class_name.rfind(".py");
if (py_extension_pos != std::string::npos)
@@ -166,7 +167,7 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list,
Target &target = m_process->GetTarget();
std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
std::defer_lock);
- api_lock.try_lock();
+ (void)api_lock.try_lock(); // See above.
auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
LLDB_LOGF(log,
@@ -308,7 +309,7 @@ OperatingSystemPython::CreateRegisterContextForThread(Thread *thread,
Target &target = m_process->GetTarget();
std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
std::defer_lock);
- api_lock.try_lock();
+ (void)api_lock.try_lock(); // See above.
auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
@@ -395,7 +396,7 @@ lldb::ThreadSP OperatingSystemPython::CreateThread(lldb::tid_t tid,
Target &target = m_process->GetTarget();
std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
std::defer_lock);
- api_lock.try_lock();
+ (void)api_lock.try_lock(); // See above.
auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
StructuredData::DictionarySP thread_info_dict =
@@ -416,4 +417,4 @@ lldb::ThreadSP OperatingSystemPython::CreateThread(lldb::tid_t tid,
return ThreadSP();
}
-#endif // #ifndef LLDB_DISABLE_PYTHON
+#endif // #if LLDB_ENABLE_PYTHON
diff --git a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
index e76227ddb981..4a594cf29a08 100644
--- a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
+++ b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
@@ -9,7 +9,9 @@
#ifndef liblldb_OperatingSystemPython_h_
#define liblldb_OperatingSystemPython_h_
-#ifndef LLDB_DISABLE_PYTHON
+#include "lldb/Host/Config.h"
+
+#if LLDB_ENABLE_PYTHON
#include "lldb/Target/OperatingSystem.h"
#include "lldb/Utility/StructuredData.h"
@@ -80,6 +82,6 @@ protected:
lldb_private::StructuredData::ObjectSP m_python_object_sp;
};
-#endif // LLDB_DISABLE_PYTHON
+#endif
#endif // liblldb_OperatingSystemPython_h_
diff --git a/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
index 946f0ea3a5cf..261f44c230f9 100644
--- a/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
+++ b/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
@@ -10,7 +10,7 @@
#include "lldb/Host/Config.h"
#include <stdio.h>
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
#include <sys/utsname.h>
#endif
@@ -194,7 +194,7 @@ bool PlatformFreeBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
void PlatformFreeBSD::GetStatus(Stream &strm) {
Platform::GetStatus(strm);
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
// Display local kernel information only when we are running in host mode.
// Otherwise, we would end up printing non-FreeBSD information (when running
// on Mac OS for example).
diff --git a/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
index 63245d18fc5c..53f819e6a272 100644
--- a/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
+++ b/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
@@ -10,7 +10,7 @@
#include "lldb/Host/Config.h"
#include <stdio.h>
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
#include <sys/utsname.h>
#endif
@@ -168,7 +168,7 @@ bool PlatformNetBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
void PlatformNetBSD::GetStatus(Stream &strm) {
Platform::GetStatus(strm);
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
// Display local kernel information only when we are running in host mode.
// Otherwise, we would end up printing non-NetBSD information (when running
// on Mac OS for example).
diff --git a/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp b/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
index 9dfb8844c574..1b63e2da0a4f 100644
--- a/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
+++ b/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
@@ -10,7 +10,7 @@
#include "lldb/Host/Config.h"
#include <stdio.h>
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
#include <sys/utsname.h>
#endif
@@ -173,7 +173,7 @@ bool PlatformOpenBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
void PlatformOpenBSD::GetStatus(Stream &strm) {
Platform::GetStatus(strm);
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
// Display local kernel information only when we are running in host mode.
// Otherwise, we would end up printing non-OpenBSD information (when running
// on Mac OS for example).
diff --git a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index b12e21deb459..2b64be63a623 100644
--- a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -223,7 +223,7 @@ static uint32_t chown_file(Platform *platform, const char *path,
command.Printf(":%d", gid);
command.Printf("%s", path);
int status;
- platform->RunShellCommand(command.GetData(), nullptr, &status, nullptr,
+ platform->RunShellCommand(command.GetData(), FileSpec(), &status, nullptr,
nullptr, std::chrono::seconds(10));
return status;
}
@@ -235,7 +235,7 @@ PlatformPOSIX::PutFile(const lldb_private::FileSpec &source,
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (IsHost()) {
- if (FileSpec::Equal(source, destination, true))
+ if (source == destination)
return Status();
// cp src dst
// chown uid:gid dst
@@ -248,7 +248,7 @@ PlatformPOSIX::PutFile(const lldb_private::FileSpec &source,
StreamString command;
command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
int status;
- RunShellCommand(command.GetData(), nullptr, &status, nullptr, nullptr,
+ RunShellCommand(command.GetData(), FileSpec(), &status, nullptr, nullptr,
std::chrono::seconds(10));
if (status != 0)
return Status("unable to perform copy");
@@ -278,7 +278,7 @@ PlatformPOSIX::PutFile(const lldb_private::FileSpec &source,
GetHostname(), dst_path.c_str());
LLDB_LOGF(log, "[PutFile] Running command: %s\n", command.GetData());
int retcode;
- Host::RunShellCommand(command.GetData(), nullptr, &retcode, nullptr,
+ Host::RunShellCommand(command.GetData(), FileSpec(), &retcode, nullptr,
nullptr, std::chrono::minutes(1));
if (retcode == 0) {
// Don't chown a local file for a remote system
@@ -307,14 +307,14 @@ lldb_private::Status PlatformPOSIX::GetFile(
if (dst_path.empty())
return Status("unable to get file path for destination");
if (IsHost()) {
- if (FileSpec::Equal(source, destination, true))
+ if (source == destination)
return Status("local scenario->source and destination are the same file "
"path: no operation performed");
// cp src dst
StreamString cp_command;
cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
int status;
- RunShellCommand(cp_command.GetData(), nullptr, &status, nullptr, nullptr,
+ RunShellCommand(cp_command.GetData(), FileSpec(), &status, nullptr, nullptr,
std::chrono::seconds(10));
if (status != 0)
return Status("unable to perform copy");
@@ -335,7 +335,7 @@ lldb_private::Status PlatformPOSIX::GetFile(
dst_path.c_str());
LLDB_LOGF(log, "[GetFile] Running command: %s\n", command.GetData());
int retcode;
- Host::RunShellCommand(command.GetData(), nullptr, &retcode, nullptr,
+ Host::RunShellCommand(command.GetData(), FileSpec(), &retcode, nullptr,
nullptr, std::chrono::minutes(1));
if (retcode == 0)
return Status();
@@ -706,7 +706,9 @@ PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx,
FunctionCaller *do_dlopen_function = nullptr;
// Fetch the clang types we will need:
- ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
+ ClangASTContext *ast = ClangASTContext::GetScratch(process->GetTarget());
+ if (!ast)
+ return nullptr;
CompilerType clang_void_pointer_type
= ast->GetBasicType(eBasicTypeVoid).GetPointerType();
@@ -948,7 +950,11 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process,
Value return_value;
// Fetch the clang types we will need:
- ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
+ ClangASTContext *ast = ClangASTContext::GetScratch(process->GetTarget());
+ if (!ast) {
+ error.SetErrorString("dlopen error: Unable to get ClangASTContext");
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
CompilerType clang_void_pointer_type
= ast->GetBasicType(eBasicTypeVoid).GetPointerType();
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
index 8b6f9fbc33c3..4313d27e11e9 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
@@ -8,8 +8,7 @@
#include "NativeProcessNetBSD.h"
-
-
+#include "Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "lldb/Host/HostProcess.h"
#include "lldb/Host/common/NativeRegisterContext.h"
@@ -99,6 +98,17 @@ NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
Info.GetArchitecture(), mainloop));
+ // Enable event reporting
+ ptrace_event_t events;
+ status = PtraceWrapper(PT_GET_EVENT_MASK, pid, &events, sizeof(events));
+ if (status.Fail())
+ return status.ToError();
+ // TODO: PTRACE_FORK | PTRACE_VFORK | PTRACE_POSIX_SPAWN?
+ events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT;
+ status = PtraceWrapper(PT_SET_EVENT_MASK, pid, &events, sizeof(events));
+ if (status.Fail())
+ return status.ToError();
+
status = process_up->ReinitializeThreads();
if (status.Fail())
return status.ToError();
@@ -211,17 +221,32 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
return;
}
+ NativeThreadNetBSD* thread = nullptr;
+ if (info.psi_lwpid > 0) {
+ for (const auto &t : m_threads) {
+ if (t->GetID() == static_cast<lldb::tid_t>(info.psi_lwpid)) {
+ thread = static_cast<NativeThreadNetBSD *>(t.get());
+ break;
+ }
+ static_cast<NativeThreadNetBSD *>(t.get())->SetStoppedWithNoReason();
+ }
+ if (!thread)
+ LLDB_LOG(log,
+ "thread not found in m_threads, pid = {0}, LWP = {1}", pid,
+ info.psi_lwpid);
+ }
+
switch (info.psi_siginfo.si_code) {
case TRAP_BRKPT:
- for (const auto &thread : m_threads) {
- static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByBreakpoint();
- FixupBreakpointPCAsNeeded(static_cast<NativeThreadNetBSD &>(*thread));
+ if (thread) {
+ thread->SetStoppedByBreakpoint();
+ FixupBreakpointPCAsNeeded(*thread);
}
SetState(StateType::eStateStopped, true);
break;
case TRAP_TRACE:
- for (const auto &thread : m_threads)
- static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByTrace();
+ if (thread)
+ thread->SetStoppedByTrace();
SetState(StateType::eStateStopped, true);
break;
case TRAP_EXEC: {
@@ -238,54 +263,66 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByExec();
SetState(StateType::eStateStopped, true);
} break;
- case TRAP_DBREG: {
- // Find the thread.
- NativeThreadNetBSD* thread = nullptr;
- for (const auto &t : m_threads) {
- if (t->GetID() == info.psi_lwpid) {
- thread = static_cast<NativeThreadNetBSD *>(t.get());
+ case TRAP_LWP: {
+ ptrace_state_t pst;
+ Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst));
+ if (error.Fail()) {
+ SetState(StateType::eStateInvalid);
+ return;
+ }
+
+ switch (pst.pe_report_event) {
+ case PTRACE_LWP_CREATE: {
+ LLDB_LOG(log,
+ "monitoring new thread, pid = {0}, LWP = {1}", pid,
+ pst.pe_lwp);
+ NativeThreadNetBSD& t = AddThread(pst.pe_lwp);
+ error = t.CopyWatchpointsFrom(
+ static_cast<NativeThreadNetBSD &>(*GetCurrentThread()));
+ if (error.Fail()) {
+ LLDB_LOG(log,
+ "failed to copy watchpoints to new thread {0}: {1}",
+ pst.pe_lwp, error);
+ SetState(StateType::eStateInvalid);
+ return;
+ }
+ } break;
+ case PTRACE_LWP_EXIT:
+ LLDB_LOG(log,
+ "removing exited thread, pid = {0}, LWP = {1}", pid,
+ pst.pe_lwp);
+ RemoveThread(pst.pe_lwp);
break;
- }
}
- if (!thread) {
- LLDB_LOG(log,
- "thread not found in m_threads, pid = {0}, LWP = {1}",
- GetID(), info.psi_lwpid);
- break;
+
+ error = PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void*>(1), 0);
+ if (error.Fail()) {
+ SetState(StateType::eStateInvalid);
+ return;
}
+ } break;
+ case TRAP_DBREG: {
+ if (!thread)
+ break;
- // If a watchpoint was hit, report it
+ auto &regctx = static_cast<NativeRegisterContextNetBSD &>(
+ thread->GetRegisterContext());
uint32_t wp_index = LLDB_INVALID_INDEX32;
- Status error = thread->GetRegisterContext().GetWatchpointHitIndex(
- wp_index, (uintptr_t)info.psi_siginfo.si_addr);
+ Status error = regctx.GetWatchpointHitIndex(wp_index,
+ (uintptr_t)info.psi_siginfo.si_addr);
if (error.Fail())
LLDB_LOG(log,
"received error while checking for watchpoint hits, pid = "
- "{0}, LWP = {1}, error = {2}",
- GetID(), info.psi_lwpid, error);
+ "{0}, LWP = {1}, error = {2}", pid, info.psi_lwpid, error);
if (wp_index != LLDB_INVALID_INDEX32) {
- for (const auto &thread : m_threads)
- static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByWatchpoint(
- wp_index);
+ thread->SetStoppedByWatchpoint(wp_index);
+ regctx.ClearWatchpointHit(wp_index);
SetState(StateType::eStateStopped, true);
break;
}
- // If a breakpoint was hit, report it
- uint32_t bp_index = LLDB_INVALID_INDEX32;
- error = thread->GetRegisterContext().GetHardwareBreakHitIndex(
- bp_index, (uintptr_t)info.psi_siginfo.si_addr);
- if (error.Fail())
- LLDB_LOG(log,
- "received error while checking for hardware "
- "breakpoint hits, pid = {0}, LWP = {1}, error = {2}",
- GetID(), info.psi_lwpid, error);
- if (bp_index != LLDB_INVALID_INDEX32) {
- for (const auto &thread : m_threads)
- static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByBreakpoint();
- SetState(StateType::eStateStopped, true);
- break;
- }
+ thread->SetStoppedByTrace();
+ SetState(StateType::eStateStopped, true);
} break;
}
}
@@ -295,9 +332,14 @@ void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) {
const auto siginfo_err =
PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
- for (const auto &thread : m_threads) {
- static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(
- info.psi_siginfo.si_signo, &info.psi_siginfo);
+ for (const auto &abs_thread : m_threads) {
+ NativeThreadNetBSD &thread = static_cast<NativeThreadNetBSD &>(*abs_thread);
+ assert(info.psi_lwpid >= 0);
+ if (info.psi_lwpid == 0 ||
+ static_cast<lldb::tid_t>(info.psi_lwpid) == thread.GetID())
+ thread.SetStoppedBySignal(info.psi_siginfo.si_signo, &info.psi_siginfo);
+ else
+ thread.SetStoppedWithNoReason();
}
SetState(StateType::eStateStopped, true);
}
@@ -325,68 +367,137 @@ Status NativeProcessNetBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
return error;
}
+static llvm::Expected<ptrace_siginfo_t> ComputeSignalInfo(
+ const std::vector<std::unique_ptr<NativeThreadProtocol>> &threads,
+ const ResumeActionList &resume_actions) {
+ // We need to account for three possible scenarios:
+ // 1. no signal being sent.
+ // 2. a signal being sent to one thread.
+ // 3. a signal being sent to the whole process.
+
+ // Count signaled threads. While at it, determine which signal is being sent
+ // and ensure there's only one.
+ size_t signaled_threads = 0;
+ int signal = LLDB_INVALID_SIGNAL_NUMBER;
+ lldb::tid_t signaled_lwp;
+ for (const auto &thread : threads) {
+ assert(thread && "thread list should not contain NULL threads");
+ const ResumeAction *action =
+ resume_actions.GetActionForThread(thread->GetID(), true);
+ if (action) {
+ if (action->signal != LLDB_INVALID_SIGNAL_NUMBER) {
+ signaled_threads++;
+ if (action->signal != signal) {
+ if (signal != LLDB_INVALID_SIGNAL_NUMBER)
+ return Status("NetBSD does not support passing multiple signals "
+ "simultaneously")
+ .ToError();
+ signal = action->signal;
+ signaled_lwp = thread->GetID();
+ }
+ }
+ }
+ }
+
+ if (signaled_threads == 0) {
+ ptrace_siginfo_t siginfo;
+ siginfo.psi_siginfo.si_signo = LLDB_INVALID_SIGNAL_NUMBER;
+ return siginfo;
+ }
+
+ if (signaled_threads > 1 && signaled_threads < threads.size())
+ return Status("NetBSD does not support passing signal to 1<i<all threads")
+ .ToError();
+
+ ptrace_siginfo_t siginfo;
+ siginfo.psi_siginfo.si_signo = signal;
+ siginfo.psi_siginfo.si_code = SI_USER;
+ siginfo.psi_siginfo.si_pid = getpid();
+ siginfo.psi_siginfo.si_uid = getuid();
+ if (signaled_threads == 1)
+ siginfo.psi_lwpid = signaled_lwp;
+ else // signal for the whole process
+ siginfo.psi_lwpid = 0;
+ return siginfo;
+}
+
Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
LLDB_LOG(log, "pid {0}", GetID());
- const auto &thread = m_threads[0];
- const ResumeAction *const action =
- resume_actions.GetActionForThread(thread->GetID(), true);
+ Status ret;
- if (action == nullptr) {
- LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
- thread->GetID());
- return Status();
- }
+ Expected<ptrace_siginfo_t> siginfo =
+ ComputeSignalInfo(m_threads, resume_actions);
+ if (!siginfo)
+ return Status(siginfo.takeError());
- Status error;
- int signal =
- action->signal != LLDB_INVALID_SIGNAL_NUMBER ? action->signal : 0;
-
- switch (action->state) {
- case eStateRunning: {
- // Run the thread, possibly feeding it the signal.
- error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1,
- signal);
- if (!error.Success())
- return error;
- for (const auto &thread : m_threads)
- static_cast<NativeThreadNetBSD &>(*thread).SetRunning();
- SetState(eStateRunning, true);
- break;
- }
- case eStateStepping:
- // Run the thread, possibly feeding it the signal.
- error = NativeProcessNetBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1,
- signal);
- if (!error.Success())
- return error;
- for (const auto &thread : m_threads)
- static_cast<NativeThreadNetBSD &>(*thread).SetStepping();
- SetState(eStateStepping, true);
- break;
+ for (const auto &abs_thread : m_threads) {
+ assert(abs_thread && "thread list should not contain NULL threads");
+ NativeThreadNetBSD &thread = static_cast<NativeThreadNetBSD &>(*abs_thread);
- case eStateSuspended:
- case eStateStopped:
- llvm_unreachable("Unexpected state");
+ const ResumeAction *action =
+ resume_actions.GetActionForThread(thread.GetID(), true);
+ // we need to explicit issue suspend requests, so it is simpler to map it
+ // into proper action
+ ResumeAction suspend_action{thread.GetID(), eStateSuspended,
+ LLDB_INVALID_SIGNAL_NUMBER};
- default:
- return Status("NativeProcessNetBSD::%s (): unexpected state %s specified "
- "for pid %" PRIu64 ", tid %" PRIu64,
- __FUNCTION__, StateAsCString(action->state), GetID(),
- thread->GetID());
+ if (action == nullptr) {
+ LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
+ thread.GetID());
+ action = &suspend_action;
+ }
+
+ LLDB_LOG(
+ log,
+ "processing resume action state {0} signal {1} for pid {2} tid {3}",
+ action->state, action->signal, GetID(), thread.GetID());
+
+ switch (action->state) {
+ case eStateRunning:
+ ret = thread.Resume();
+ break;
+ case eStateStepping:
+ ret = thread.SingleStep();
+ break;
+ case eStateSuspended:
+ case eStateStopped:
+ if (action->signal != LLDB_INVALID_SIGNAL_NUMBER)
+ return Status("Passing signal to suspended thread unsupported");
+
+ ret = thread.Suspend();
+ break;
+
+ default:
+ return Status("NativeProcessNetBSD::%s (): unexpected state %s specified "
+ "for pid %" PRIu64 ", tid %" PRIu64,
+ __FUNCTION__, StateAsCString(action->state), GetID(),
+ thread.GetID());
+ }
+
+ if (!ret.Success())
+ return ret;
}
- return Status();
+ int signal = 0;
+ if (siginfo->psi_siginfo.si_signo != LLDB_INVALID_SIGNAL_NUMBER) {
+ ret = PtraceWrapper(PT_SET_SIGINFO, GetID(), &siginfo.get(),
+ sizeof(*siginfo));
+ if (!ret.Success())
+ return ret;
+ signal = siginfo->psi_siginfo.si_signo;
+ }
+
+ ret = PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1),
+ signal);
+ if (ret.Success())
+ SetState(eStateRunning, true);
+ return ret;
}
Status NativeProcessNetBSD::Halt() {
- Status error;
-
- if (kill(GetID(), SIGSTOP) != 0)
- error.SetErrorToErrno();
-
- return error;
+ return PtraceWrapper(PT_STOP, GetID());
}
Status NativeProcessNetBSD::Detach() {
@@ -411,6 +522,10 @@ Status NativeProcessNetBSD::Signal(int signo) {
return error;
}
+Status NativeProcessNetBSD::Interrupt() {
+ return PtraceWrapper(PT_STOP, GetID());
+}
+
Status NativeProcessNetBSD::Kill() {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
LLDB_LOG(log, "pid {0}", GetID());
@@ -650,10 +765,10 @@ bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) {
}
NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
-
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
+ assert(thread_id > 0);
assert(!HasThreadNoLock(thread_id) &&
"attempted to add a thread by id that already exists");
@@ -665,6 +780,22 @@ NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
return static_cast<NativeThreadNetBSD &>(*m_threads.back());
}
+void NativeProcessNetBSD::RemoveThread(lldb::tid_t thread_id) {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+ LLDB_LOG(log, "pid {0} removing thread with tid {1}", GetID(), thread_id);
+
+ assert(thread_id > 0);
+ assert(HasThreadNoLock(thread_id) &&
+ "attempted to remove a thread that does not exist");
+
+ for (auto it = m_threads.begin(); it != m_threads.end(); ++it) {
+ if ((*it)->GetID() == thread_id) {
+ m_threads.erase(it);
+ break;
+ }
+ }
+}
+
Status NativeProcessNetBSD::Attach() {
// Attach to the requested process.
// An attach will cause the thread to stop with a SIGSTOP.
@@ -783,15 +914,23 @@ Status NativeProcessNetBSD::ReinitializeThreads() {
m_threads.clear();
// Initialize new thread
+#ifdef PT_LWPSTATUS
+ struct ptrace_lwpstatus info = {};
+ int op = PT_LWPNEXT;
+#else
struct ptrace_lwpinfo info = {};
- Status error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info));
+ int op = PT_LWPINFO;
+#endif
+
+ Status error = PtraceWrapper(op, GetID(), &info, sizeof(info));
+
if (error.Fail()) {
return error;
}
// Reinitialize from scratch threads and register them in process
while (info.pl_lwpid != 0) {
AddThread(info.pl_lwpid);
- error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info));
+ error = PtraceWrapper(op, GetID(), &info, sizeof(info));
if (error.Fail()) {
return error;
}
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
index 4e7f0a1c13ab..6a06773f40a8 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
@@ -47,6 +47,8 @@ public:
Status Signal(int signo) override;
+ Status Interrupt() override;
+
Status Kill() override;
Status GetMemoryRegionInfo(lldb::addr_t load_addr,
@@ -98,6 +100,7 @@ private:
bool HasThreadNoLock(lldb::tid_t thread_id);
NativeThreadNetBSD &AddThread(lldb::tid_t thread_id);
+ void RemoveThread(lldb::tid_t thread_id);
void MonitorCallback(lldb::pid_t pid, int signal);
void MonitorExited(lldb::pid_t pid, WaitStatus status);
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
index 3a9caaad74c8..a8afa0b20305 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
@@ -8,6 +8,8 @@
#include "NativeRegisterContextNetBSD.h"
+#include "Plugins/Process/NetBSD/NativeProcessNetBSD.h"
+
#include "lldb/Host/common/NativeProcessProtocol.h"
using namespace lldb_private;
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
index f5dd0c33b677..13e023d856d2 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
@@ -11,12 +11,13 @@
#include "lldb/Host/common/NativeThreadProtocol.h"
-#include "Plugins/Process/NetBSD/NativeProcessNetBSD.h"
#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h"
namespace lldb_private {
namespace process_netbsd {
+class NativeProcessNetBSD;
+
class NativeRegisterContextNetBSD : public NativeRegisterContextRegisterInfo {
public:
NativeRegisterContextNetBSD(NativeThreadProtocol &native_thread,
@@ -30,6 +31,10 @@ public:
static NativeRegisterContextNetBSD *
CreateHostNativeRegisterContextNetBSD(const ArchSpec &target_arch,
NativeThreadProtocol &native_thread);
+ virtual Status
+ CopyHardwareWatchpointsFrom(NativeRegisterContextNetBSD &source) = 0;
+
+ virtual Status ClearWatchpointHit(uint32_t wp_index) = 0;
protected:
Status DoRegisterSet(int req, void *buf);
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
index 6cc2810fa235..05a35401da46 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
@@ -84,13 +84,71 @@ static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) -
k_num_gpr_registers_x86_64,
"g_gpr_regnums_x86_64 has wrong number of register infos");
+// x86 64-bit floating point registers.
+static const uint32_t g_fpu_regnums_x86_64[] = {
+ lldb_fctrl_x86_64, lldb_fstat_x86_64, lldb_ftag_x86_64,
+ lldb_fop_x86_64, lldb_fiseg_x86_64, lldb_fioff_x86_64,
+ lldb_foseg_x86_64, lldb_fooff_x86_64, lldb_mxcsr_x86_64,
+ lldb_mxcsrmask_x86_64, lldb_st0_x86_64, lldb_st1_x86_64,
+ lldb_st2_x86_64, lldb_st3_x86_64, lldb_st4_x86_64,
+ lldb_st5_x86_64, lldb_st6_x86_64, lldb_st7_x86_64,
+ lldb_mm0_x86_64, lldb_mm1_x86_64, lldb_mm2_x86_64,
+ lldb_mm3_x86_64, lldb_mm4_x86_64, lldb_mm5_x86_64,
+ lldb_mm6_x86_64, lldb_mm7_x86_64, lldb_xmm0_x86_64,
+ lldb_xmm1_x86_64, lldb_xmm2_x86_64, lldb_xmm3_x86_64,
+ lldb_xmm4_x86_64, lldb_xmm5_x86_64, lldb_xmm6_x86_64,
+ lldb_xmm7_x86_64, lldb_xmm8_x86_64, lldb_xmm9_x86_64,
+ lldb_xmm10_x86_64, lldb_xmm11_x86_64, lldb_xmm12_x86_64,
+ lldb_xmm13_x86_64, lldb_xmm14_x86_64, lldb_xmm15_x86_64,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) -
+ 1 ==
+ k_num_fpr_registers_x86_64,
+ "g_fpu_regnums_x86_64 has wrong number of register infos");
+
+// x86 64-bit registers available via XState.
+static const uint32_t g_xstate_regnums_x86_64[] = {
+ lldb_ymm0_x86_64, lldb_ymm1_x86_64, lldb_ymm2_x86_64, lldb_ymm3_x86_64,
+ lldb_ymm4_x86_64, lldb_ymm5_x86_64, lldb_ymm6_x86_64, lldb_ymm7_x86_64,
+ lldb_ymm8_x86_64, lldb_ymm9_x86_64, lldb_ymm10_x86_64, lldb_ymm11_x86_64,
+ lldb_ymm12_x86_64, lldb_ymm13_x86_64, lldb_ymm14_x86_64, lldb_ymm15_x86_64,
+ // Note: we currently do not provide them but this is needed to avoid
+ // unnamed groups in SBFrame::GetRegisterContext().
+ lldb_bnd0_x86_64, lldb_bnd1_x86_64, lldb_bnd2_x86_64,
+ lldb_bnd3_x86_64, lldb_bndcfgu_x86_64, lldb_bndstatus_x86_64,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_xstate_regnums_x86_64) / sizeof(g_xstate_regnums_x86_64[0])) -
+ 1 ==
+ k_num_avx_registers_x86_64 + k_num_mpx_registers_x86_64,
+ "g_xstate_regnums_x86_64 has wrong number of register infos");
+
+// x86 debug registers.
+static const uint32_t g_dbr_regnums_x86_64[] = {
+ lldb_dr0_x86_64, lldb_dr1_x86_64, lldb_dr2_x86_64, lldb_dr3_x86_64,
+ lldb_dr4_x86_64, lldb_dr5_x86_64, lldb_dr6_x86_64, lldb_dr7_x86_64,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_dbr_regnums_x86_64) / sizeof(g_dbr_regnums_x86_64[0])) -
+ 1 ==
+ k_num_dbr_registers_x86_64,
+ "g_dbr_regnums_x86_64 has wrong number of register infos");
+
// Number of register sets provided by this context.
-enum { k_num_extended_register_sets = 2, k_num_register_sets = 4 };
+enum { k_num_register_sets = 4 };
// Register sets for x86 64-bit.
static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = {
{"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64,
g_gpr_regnums_x86_64},
+ {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64,
+ g_fpu_regnums_x86_64},
+ {"Extended State Registers", "xstate",
+ k_num_avx_registers_x86_64 + k_num_mpx_registers_x86_64,
+ g_xstate_regnums_x86_64},
+ {"Debug Registers", "dbr", k_num_dbr_registers_x86_64,
+ g_dbr_regnums_x86_64},
};
#define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize())
@@ -667,11 +725,6 @@ Status NativeRegisterContextNetBSD_x86_64::ReadAllRegisterValues(
::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize());
dst += GetRegisterInfoInterface().GetGPRSize();
- RegisterValue value((uint64_t)-1);
- const RegisterInfo *reg_info =
- GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_eax");
- if (reg_info == nullptr)
- reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_rax");
return error;
}
@@ -795,10 +848,10 @@ Status NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex(
if (!is_vacant)
return Status("Watchpoint index not vacant");
- RegisterValue reg_value;
const RegisterInfo *const reg_info_dr7 =
GetRegisterInfoAtIndex(lldb_dr7_x86_64);
- error = ReadRegister(reg_info_dr7, reg_value);
+ RegisterValue dr7_value;
+ error = ReadRegister(reg_info_dr7, dr7_value);
if (error.Fail())
return error;
@@ -816,16 +869,28 @@ Status NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex(
uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
- uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
+ uint64_t control_bits = dr7_value.GetAsUInt64() & ~bit_mask;
control_bits |= enable_bit | rw_bits | size_bits;
const RegisterInfo *const reg_info_drN =
GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index);
- error = WriteRegister(reg_info_drN, RegisterValue(addr));
+ RegisterValue drN_value;
+ error = ReadRegister(reg_info_drN, drN_value);
if (error.Fail())
return error;
+ // clear dr6 if address or bits changed (i.e. we're not reenabling the same
+ // watchpoint)
+ if (drN_value.GetAsUInt64() != addr ||
+ (dr7_value.GetAsUInt64() & bit_mask) != (rw_bits | size_bits)) {
+ ClearWatchpointHit(wp_index);
+
+ error = WriteRegister(reg_info_drN, RegisterValue(addr));
+ if (error.Fail())
+ return error;
+ }
+
error = WriteRegister(reg_info_dr7, RegisterValue(control_bits));
if (error.Fail())
return error;
@@ -839,32 +904,36 @@ bool NativeRegisterContextNetBSD_x86_64::ClearHardwareWatchpoint(
if (wp_index >= NumSupportedHardwareWatchpoints())
return false;
+ // for watchpoints 0, 1, 2, or 3, respectively, clear bits 0-1, 2-3, 4-5
+ // or 6-7 of the debug control register (DR7)
+ const RegisterInfo *const reg_info_dr7 =
+ GetRegisterInfoAtIndex(lldb_dr7_x86_64);
RegisterValue reg_value;
+ Status error = ReadRegister(reg_info_dr7, reg_value);
+ if (error.Fail())
+ return false;
+ uint64_t bit_mask = 0x3 << (2 * wp_index);
+ uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
- // for watchpoints 0, 1, 2, or 3, respectively, clear bits 0, 1, 2, or 3 of
+ return WriteRegister(reg_info_dr7, RegisterValue(control_bits)).Success();
+}
+
+Status NativeRegisterContextNetBSD_x86_64::ClearWatchpointHit(uint32_t wp_index) {
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return Status("Watchpoint index out of range");
+
+ // for watchpoints 0, 1, 2, or 3, respectively, check bits 0, 1, 2, or 3 of
// the debug status register (DR6)
const RegisterInfo *const reg_info_dr6 =
GetRegisterInfoAtIndex(lldb_dr6_x86_64);
+ RegisterValue reg_value;
Status error = ReadRegister(reg_info_dr6, reg_value);
if (error.Fail())
- return false;
+ return error;
+
uint64_t bit_mask = 1 << wp_index;
uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
- error = WriteRegister(reg_info_dr6, RegisterValue(status_bits));
- if (error.Fail())
- return false;
-
- // for watchpoints 0, 1, 2, or 3, respectively, clear bits {0-1,16-19},
- // {2-3,20-23}, {4-5,24-27}, or {6-7,28-31} of the debug control register
- // (DR7)
- const RegisterInfo *const reg_info_dr7 =
- GetRegisterInfoAtIndex(lldb_dr7_x86_64);
- error = ReadRegister(reg_info_dr7, reg_value);
- if (error.Fail())
- return false;
- bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
- uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
- return WriteRegister(reg_info_dr7, RegisterValue(control_bits)).Success();
+ return WriteRegister(reg_info_dr6, RegisterValue(status_bits));
}
Status NativeRegisterContextNetBSD_x86_64::ClearAllHardwareWatchpoints() {
@@ -930,4 +999,19 @@ uint32_t NativeRegisterContextNetBSD_x86_64::NumSupportedHardwareWatchpoints() {
return 4;
}
+Status NativeRegisterContextNetBSD_x86_64::CopyHardwareWatchpointsFrom(
+ NativeRegisterContextNetBSD &source) {
+ auto &r_source = static_cast<NativeRegisterContextNetBSD_x86_64&>(source);
+ Status res = r_source.ReadRegisterSet(DBRegSet);
+ if (!res.Fail()) {
+ // copy dbregs only if any watchpoints were set
+ if ((r_source.m_dbr_x86_64.dr[7] & 0xFF) == 0)
+ return res;
+
+ m_dbr_x86_64 = r_source.m_dbr_x86_64;
+ res = WriteRegisterSet(DBRegSet);
+ }
+ return res;
+}
+
#endif // defined(__x86_64__)
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
index 0fed16542a95..54b8a806267f 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
@@ -58,6 +58,8 @@ public:
bool ClearHardwareWatchpoint(uint32_t wp_index) override;
+ Status ClearWatchpointHit(uint32_t wp_index) override;
+
Status ClearAllHardwareWatchpoints() override;
Status SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
@@ -71,9 +73,12 @@ public:
uint32_t NumSupportedHardwareWatchpoints() override;
+ Status
+ CopyHardwareWatchpointsFrom(NativeRegisterContextNetBSD &source) override;
+
private:
// Private member types.
- enum { GPRegSet, FPRegSet, DBRegSet, XStateRegSet };
+ enum { GPRegSet, FPRegSet, XStateRegSet, DBRegSet };
// Private member variables.
struct reg m_gpr_x86_64;
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
index e25975c93446..dd2745d9330e 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
@@ -16,9 +16,20 @@
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/State.h"
+#include "llvm/Support/Errno.h"
+
+// clang-format off
+#include <sys/types.h>
+#include <sys/ptrace.h>
+// clang-format on
#include <sstream>
+// clang-format off
+#include <sys/types.h>
+#include <sys/sysctl.h>
+// clang-format on
+
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_netbsd;
@@ -30,6 +41,38 @@ NativeThreadNetBSD::NativeThreadNetBSD(NativeProcessNetBSD &process,
NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(process.GetArchitecture(), *this)
), m_stop_description() {}
+Status NativeThreadNetBSD::Resume() {
+ Status ret = NativeProcessNetBSD::PtraceWrapper(PT_RESUME, m_process.GetID(),
+ nullptr, GetID());
+ if (!ret.Success())
+ return ret;
+ ret = NativeProcessNetBSD::PtraceWrapper(PT_CLEARSTEP, m_process.GetID(),
+ nullptr, GetID());
+ if (ret.Success())
+ SetRunning();
+ return ret;
+}
+
+Status NativeThreadNetBSD::SingleStep() {
+ Status ret = NativeProcessNetBSD::PtraceWrapper(PT_RESUME, m_process.GetID(),
+ nullptr, GetID());
+ if (!ret.Success())
+ return ret;
+ ret = NativeProcessNetBSD::PtraceWrapper(PT_SETSTEP, m_process.GetID(),
+ nullptr, GetID());
+ if (ret.Success())
+ SetStepping();
+ return ret;
+}
+
+Status NativeThreadNetBSD::Suspend() {
+ Status ret = NativeProcessNetBSD::PtraceWrapper(PT_SUSPEND, m_process.GetID(),
+ nullptr, GetID());
+ if (ret.Success())
+ SetStopped();
+ return ret;
+}
+
void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo,
const siginfo_t *info) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
@@ -89,6 +132,13 @@ void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) {
m_stop_info.details.signal.signo = SIGTRAP;
}
+void NativeThreadNetBSD::SetStoppedWithNoReason() {
+ SetStopped();
+
+ m_stop_info.reason = StopReason::eStopReasonNone;
+ m_stop_info.details.signal.signo = 0;
+}
+
void NativeThreadNetBSD::SetStopped() {
const StateType new_state = StateType::eStateStopped;
m_state = new_state;
@@ -105,7 +155,49 @@ void NativeThreadNetBSD::SetStepping() {
m_stop_info.reason = StopReason::eStopReasonNone;
}
-std::string NativeThreadNetBSD::GetName() { return std::string(""); }
+std::string NativeThreadNetBSD::GetName() {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+
+#ifdef PT_LWPSTATUS
+ struct ptrace_lwpstatus info = {};
+ info.pl_lwpid = m_tid;
+ Status error = NativeProcessNetBSD::PtraceWrapper(
+ PT_LWPSTATUS, static_cast<int>(m_process.GetID()), &info, sizeof(info));
+ if (error.Fail()) {
+ return "";
+ }
+ return info.pl_name;
+#else
+ std::vector<struct kinfo_lwp> infos;
+ int mib[5] = {CTL_KERN, KERN_LWP, static_cast<int>(m_process.GetID()),
+ sizeof(struct kinfo_lwp), 0};
+ size_t size;
+
+ if (::sysctl(mib, 5, nullptr, &size, nullptr, 0) == -1 || size == 0) {
+ LLDB_LOG(log, "sysctl() for LWP info size failed: {0}",
+ llvm::sys::StrError());
+ return "";
+ }
+
+ mib[4] = size / sizeof(size_t);
+ infos.resize(size / sizeof(struct kinfo_lwp));
+
+ if (sysctl(mib, 5, infos.data(), &size, NULL, 0) == -1 || size == 0) {
+ LLDB_LOG(log, "sysctl() for LWP info failed: {0}", llvm::sys::StrError());
+ return "";
+ }
+
+ size_t nlwps = size / sizeof(struct kinfo_lwp);
+ for (size_t i = 0; i < nlwps; i++) {
+ if (static_cast<lldb::tid_t>(infos[i].l_lid) == m_tid) {
+ return infos[i].l_name;
+ }
+ }
+
+ LLDB_LOG(log, "unable to find lwp {0} in LWP infos", m_tid);
+ return "";
+#endif
+}
lldb::StateType NativeThreadNetBSD::GetState() { return m_state; }
@@ -140,9 +232,9 @@ bool NativeThreadNetBSD::GetStopReason(ThreadStopInfo &stop_info,
llvm_unreachable("unhandled StateType!");
}
-NativeRegisterContext& NativeThreadNetBSD::GetRegisterContext() {
+NativeRegisterContextNetBSD &NativeThreadNetBSD::GetRegisterContext() {
assert(m_reg_context_up);
-return *m_reg_context_up;
+ return *m_reg_context_up;
}
Status NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size,
@@ -203,3 +295,13 @@ Status NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) {
return Status("Clearing hardware breakpoint failed.");
}
+
+Status NativeThreadNetBSD::CopyWatchpointsFrom(NativeThreadNetBSD &source) {
+ Status s = GetRegisterContext().CopyHardwareWatchpointsFrom(
+ source.GetRegisterContext());
+ if (!s.Fail()) {
+ m_watchpoint_index_map = source.m_watchpoint_index_map;
+ m_hw_break_index_map = source.m_hw_break_index_map;
+ }
+ return s;
+}
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
index 015d8995db34..89b61ef86722 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
@@ -11,6 +11,8 @@
#include "lldb/Host/common/NativeThreadProtocol.h"
+#include "Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h"
+
#include <csignal>
#include <map>
#include <string>
@@ -34,7 +36,7 @@ public:
bool GetStopReason(ThreadStopInfo &stop_info,
std::string &description) override;
- NativeRegisterContext& GetRegisterContext() override;
+ NativeRegisterContextNetBSD &GetRegisterContext() override;
Status SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags,
bool hardware) override;
@@ -48,19 +50,26 @@ public:
private:
// Interface for friend classes
+ Status Resume();
+ Status SingleStep();
+ Status Suspend();
+
void SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr);
void SetStoppedByBreakpoint();
void SetStoppedByTrace();
void SetStoppedByExec();
void SetStoppedByWatchpoint(uint32_t wp_index);
+ void SetStoppedWithNoReason();
void SetStopped();
void SetRunning();
void SetStepping();
+ Status CopyWatchpointsFrom(NativeThreadNetBSD& source);
+
// Member Variables
lldb::StateType m_state;
ThreadStopInfo m_stop_info;
- std::unique_ptr<NativeRegisterContext> m_reg_context_up;
+ std::unique_ptr<NativeRegisterContextNetBSD> m_reg_context_up;
std::string m_stop_description;
using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>;
WatchpointIndexMap m_watchpoint_index_map;
diff --git a/lldb/source/Plugins/Process/POSIX/CrashReason.cpp b/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
index 9678e48436e7..b872269fdfe1 100644
--- a/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
+++ b/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
@@ -136,15 +136,15 @@ std::string GetCrashReasonString(CrashReason reason, const siginfo_t &info) {
#if defined(si_lower) && defined(si_upper)
if (reason == CrashReason::eBoundViolation) {
str = "signal SIGSEGV";
- AppendBounds(str, reinterpret_cast<lldb::addr_t>(info.si_lower),
- reinterpret_cast<lldb::addr_t>(info.si_upper),
- reinterpret_cast<lldb::addr_t>(info.si_addr));
+ AppendBounds(str, reinterpret_cast<uintptr_t>(info.si_lower),
+ reinterpret_cast<uintptr_t>(info.si_upper),
+ reinterpret_cast<uintptr_t>(info.si_addr));
return str;
}
#endif
return GetCrashReasonString(reason,
- reinterpret_cast<lldb::addr_t>(info.si_addr));
+ reinterpret_cast<uintptr_t>(info.si_addr));
}
std::string GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr) {
diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index 2ccbeacc4960..ee939b01d350 100644
--- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -20,7 +20,7 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
#include <sys/mman.h>
#else
// define them
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
index 4ca33c248c6f..173e66904151 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
@@ -21,12 +21,6 @@
#include <memory>
-// Support building against older versions of LLVM, this macro was added
-// recently.
-#ifndef LLVM_EXTENSION
-#define LLVM_EXTENSION
-#endif
-
#include "Utility/ARM_DWARF_Registers.h"
#include "Utility/ARM_ehframe_Registers.h"
@@ -1146,10 +1140,11 @@ bool RegisterContextDarwin_arm::ReadRegister(const RegisterInfo *reg_info,
case gpr_sp:
case gpr_lr:
case gpr_pc:
- case gpr_cpsr:
value.SetUInt32(gpr.r[reg - gpr_r0]);
break;
-
+ case gpr_cpsr:
+ value.SetUInt32(gpr.cpsr);
+ break;
case fpu_s0:
case fpu_s1:
case fpu_s2:
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
index b3ec24d8905d..fa5197cd6bf4 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
@@ -30,12 +30,6 @@
#include <sys/sysctl.h>
#endif
-// Support building against older versions of LLVM, this macro was added
-// recently.
-#ifndef LLVM_EXTENSION
-#define LLVM_EXTENSION
-#endif
-
#include "Utility/ARM64_DWARF_Registers.h"
using namespace lldb;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
index 873713fd8373..959b04700b17 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
@@ -19,12 +19,6 @@
#include <memory>
-// Support building against older versions of LLVM, this macro was added
-// recently.
-#ifndef LLVM_EXTENSION
-#define LLVM_EXTENSION
-#endif
-
#include "RegisterContextDarwin_i386.h"
using namespace lldb;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
index 47758ce85eb2..22088a7d6448 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
@@ -21,12 +21,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
-// Support building against older versions of LLVM, this macro was added
-// recently.
-#ifndef LLVM_EXTENSION
-#define LLVM_EXTENSION
-#endif
-
#include "RegisterContextDarwin_x86_64.h"
using namespace lldb;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
index 4a3b3c73fd6b..af3027afa73c 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
@@ -25,15 +25,18 @@
LLVM_EXTENSION offsetof(FPR, xsave) + \
LLVM_EXTENSION offsetof(XSAVE, ymmh[0]) + (32 * reg_index))
+// Guarantees BNDR/BNDC offsets do not overlap with YMM offsets.
+#define GDB_REMOTE_OFFSET 128
+
#define BNDR_OFFSET(reg_index) \
(LLVM_EXTENSION offsetof(UserArea, fpr) + \
LLVM_EXTENSION offsetof(FPR, xsave) + \
- LLVM_EXTENSION offsetof(XSAVE, mpxr[reg_index]))
+ LLVM_EXTENSION offsetof(XSAVE, mpxr[reg_index]) + GDB_REMOTE_OFFSET)
#define BNDC_OFFSET(reg_index) \
(LLVM_EXTENSION offsetof(UserArea, fpr) + \
LLVM_EXTENSION offsetof(FPR, xsave) + \
- LLVM_EXTENSION offsetof(XSAVE, mpxc[reg_index]))
+ LLVM_EXTENSION offsetof(XSAVE, mpxc[reg_index]) + GDB_REMOTE_OFFSET)
#ifdef DECLARE_REGISTER_INFOS_X86_64_STRUCT
diff --git a/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h b/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h
index 0d2149c83573..bfdd586d9ded 100644
--- a/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h
+++ b/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h
@@ -294,7 +294,8 @@ enum {
lldb_bndstatus_x86_64,
k_last_mpxc_x86_64 = lldb_bndstatus_x86_64,
- lldb_dr0_x86_64,
+ k_first_dbr_x86_64,
+ lldb_dr0_x86_64 = k_first_dbr_x86_64,
lldb_dr1_x86_64,
lldb_dr2_x86_64,
lldb_dr3_x86_64,
@@ -302,6 +303,7 @@ enum {
lldb_dr5_x86_64,
lldb_dr6_x86_64,
lldb_dr7_x86_64,
+ k_last_dbr_x86_64 = lldb_dr7_x86_64,
k_num_registers_x86_64,
k_num_gpr_registers_x86_64 = k_last_gpr_x86_64 - k_first_gpr_x86_64 + 1,
@@ -312,6 +314,7 @@ enum {
k_num_fpr_registers_x86_64 +
k_num_avx_registers_x86_64 +
k_num_mpx_registers_x86_64,
+ k_num_dbr_registers_x86_64 = k_last_dbr_x86_64 - k_first_dbr_x86_64 + 1,
};
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 144ae103faa4..7cea013eea7f 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -31,6 +31,7 @@
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"
+#include "lldb/Utility/Reproducer.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -49,7 +50,7 @@
#include <compression.h>
#endif
-#if defined(HAVE_LIBZ)
+#if LLVM_ENABLE_ZLIB
#include <zlib.h>
#endif
@@ -581,7 +582,7 @@ bool GDBRemoteCommunication::DecompressPacket() {
}
#endif
-#if defined(HAVE_LIBZ)
+#if LLVM_ENABLE_ZLIB
if (decompressed_bytes == 0 && decompressed_bufsize != ULONG_MAX &&
decompressed_buffer != nullptr &&
m_compression_type == CompressionType::ZlibDeflate) {
@@ -1243,8 +1244,9 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
void GDBRemoteCommunication::DumpHistory(Stream &strm) { m_history.Dump(strm); }
-void GDBRemoteCommunication::SetHistoryStream(llvm::raw_ostream *strm) {
- m_history.SetStream(strm);
+void GDBRemoteCommunication::SetPacketRecorder(
+ repro::PacketRecorder *recorder) {
+ m_history.SetRecorder(recorder);
}
llvm::Error
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index bb777a5c26a7..0b670018bd69 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -27,6 +27,9 @@
#include "lldb/lldb-public.h"
namespace lldb_private {
+namespace repro {
+class PacketRecorder;
+}
namespace process_gdb_remote {
enum GDBStoppointType {
@@ -133,7 +136,8 @@ public:
// fork/exec to avoid having to connect/accept
void DumpHistory(Stream &strm);
- void SetHistoryStream(llvm::raw_ostream *strm);
+
+ void SetPacketRecorder(repro::PacketRecorder *recorder);
static llvm::Error ConnectLocally(GDBRemoteCommunication &client,
GDBRemoteCommunication &server);
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index feb9f0589cee..b2f1ee527e8b 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -543,21 +543,24 @@ GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse(
//
// Takes a valid thread ID because p needs to apply to a thread.
bool GDBRemoteCommunicationClient::GetpPacketSupported(lldb::tid_t tid) {
- if (m_supports_p == eLazyBoolCalculate) {
- m_supports_p = eLazyBoolNo;
- StreamString payload;
- payload.PutCString("p0");
- StringExtractorGDBRemote response;
- if (SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload),
- response, false) ==
- PacketResult::Success &&
- response.IsNormalResponse()) {
- m_supports_p = eLazyBoolYes;
- }
- }
+ if (m_supports_p == eLazyBoolCalculate)
+ m_supports_p = GetThreadPacketSupported(tid, "p0");
return m_supports_p;
}
+LazyBool GDBRemoteCommunicationClient::GetThreadPacketSupported(
+ lldb::tid_t tid, llvm::StringRef packetStr) {
+ StreamString payload;
+ payload.PutCString(packetStr);
+ StringExtractorGDBRemote response;
+ if (SendThreadSpecificPacketAndWaitForResponse(
+ tid, std::move(payload), response, false) == PacketResult::Success &&
+ response.IsNormalResponse()) {
+ return eLazyBoolYes;
+ }
+ return eLazyBoolNo;
+}
+
StructuredData::ObjectSP GDBRemoteCommunicationClient::GetThreadsInfo() {
// Get information on all threads at one using the "jThreadsInfo" packet
StructuredData::ObjectSP object_sp;
@@ -1042,7 +1045,7 @@ void GDBRemoteCommunicationClient::MaybeEnableCompression(
}
#endif
-#if defined(HAVE_LIBZ)
+#if LLVM_ENABLE_ZLIB
if (avail_type == CompressionType::None) {
for (auto compression : supported_compressions) {
if (compression == "zlib-deflate") {
@@ -3737,7 +3740,7 @@ bool GDBRemoteCommunicationClient::ReadExtFeature(
case ('m'):
if (str.length() > 1)
output << &str[1];
- offset += size;
+ offset += str.length() - 1;
break;
// unknown chunk
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index 574cd0fd70c5..11fd40bce44f 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -89,7 +89,7 @@ public:
/// Sends a GDB remote protocol 'A' packet that delivers program
/// arguments to the remote server.
///
- /// \param[in] argv
+ /// \param[in] launch_info
/// A NULL terminated array of const C strings to use as the
/// arguments.
///
@@ -155,7 +155,7 @@ public:
/// Sets the path to use for stdin/out/err for a process
/// that will be launched with the 'A' packet.
///
- /// \param[in] path
+ /// \param[in] file_spec
/// The path to use for stdin/out/err
///
/// \return
@@ -596,6 +596,8 @@ protected:
Status GetQXferMemoryMapRegionInfo(lldb::addr_t addr,
MemoryRegionInfo &region);
+ LazyBool GetThreadPacketSupported(lldb::tid_t tid, llvm::StringRef packetStr);
+
private:
DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationClient);
};
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
index d2cc32f63f20..9e5646985f87 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
@@ -40,8 +40,8 @@ void GDBRemoteCommunicationHistory::AddPacket(char packet_char,
m_packets[idx].bytes_transmitted = bytes_transmitted;
m_packets[idx].packet_idx = m_total_packet_count;
m_packets[idx].tid = llvm::get_threadid();
- if (m_stream)
- m_packets[idx].Serialize(*m_stream);
+ if (m_recorder)
+ m_recorder->Record(m_packets[idx]);
}
void GDBRemoteCommunicationHistory::AddPacket(const std::string &src,
@@ -58,8 +58,8 @@ void GDBRemoteCommunicationHistory::AddPacket(const std::string &src,
m_packets[idx].bytes_transmitted = bytes_transmitted;
m_packets[idx].packet_idx = m_total_packet_count;
m_packets[idx].tid = llvm::get_threadid();
- if (m_stream)
- m_packets[idx].Serialize(*m_stream);
+ if (m_recorder)
+ m_recorder->Record(m_packets[idx]);
}
void GDBRemoteCommunicationHistory::Dump(Stream &strm) const {
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
index c006fbd34a4b..ee265ef86dff 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
@@ -13,11 +13,15 @@
#include <vector>
#include "lldb/Utility/GDBRemote.h"
+#include "lldb/Utility/Reproducer.h"
#include "lldb/lldb-public.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
namespace lldb_private {
+namespace repro {
+class PacketRecorder;
+}
namespace process_gdb_remote {
/// The history keeps a circular buffer of GDB remote packets. The history is
@@ -41,7 +45,7 @@ public:
void Dump(Log *log) const;
bool DidDumpToLog() const { return m_dumped_to_log; }
- void SetStream(llvm::raw_ostream *strm) { m_stream = strm; }
+ void SetRecorder(repro::PacketRecorder *recorder) { m_recorder = recorder; }
private:
uint32_t GetFirstSavedPacketIndex() const {
@@ -73,7 +77,7 @@ private:
uint32_t m_curr_idx;
uint32_t m_total_packet_count;
mutable bool m_dumped_to_log;
- llvm::raw_ostream *m_stream = nullptr;
+ repro::PacketRecorder *m_recorder = nullptr;
};
} // namespace process_gdb_remote
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
index 2d26c550dc76..15c73e78bd44 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
@@ -143,7 +143,14 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse(
entry.packet.data);
LLDB_LOG(log, "GDBRemoteCommunicationReplayServer actual packet: '{0}'",
packet.GetStringRef());
- assert(false && "Encountered unexpected packet during replay");
+#ifndef NDEBUG
+ // This behaves like a regular assert, but prints the expected and
+ // received packet before aborting.
+ printf("Reproducer expected packet: '%s'\n", entry.packet.data.c_str());
+ printf("Reproducer received packet: '%s'\n",
+ packet.GetStringRef().data());
+ llvm::report_fatal_error("Encountered unexpected packet during replay");
+#endif
return PacketResult::ErrorSendFailed;
}
@@ -204,9 +211,9 @@ bool GDBRemoteCommunicationReplayServer::StartAsyncThread() {
"<lldb.gdb-replay.async>",
GDBRemoteCommunicationReplayServer::AsyncThread, this);
if (!async_thread) {
- LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST),
- "failed to launch host thread: {}",
- llvm::toString(async_thread.takeError()));
+ LLDB_LOG_ERROR(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST),
+ async_thread.takeError(),
+ "failed to launch host thread: {}");
return false;
}
m_async_thread = *async_thread;
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index 37980d914dc2..4b5fc0774a6d 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -429,7 +429,7 @@ GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_qUserName(
StringExtractorGDBRemote &packet) {
-#if !defined(LLDB_DISABLE_POSIX)
+#if LLDB_ENABLE_POSIX
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
LLDB_LOGF(log, "GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__);
@@ -452,7 +452,7 @@ GDBRemoteCommunicationServerCommon::Handle_qUserName(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_qGroupName(
StringExtractorGDBRemote &packet) {
-#if !defined(LLDB_DISABLE_POSIX)
+#if LLDB_ENABLE_POSIX
// Packet format: "qGroupName:%i" where %i is the gid
packet.SetFilePos(::strlen("qGroupName:"));
uint32_t gid = packet.GetU32(UINT32_MAX);
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index ad1a39b57969..f33f0ee66304 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -669,9 +669,9 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
response.PutStringAsRawHex8(unescaped_response.GetData());
response.PutChar(';');
} else {
- LLDB_LOG(log, "failed to prepare a jstopinfo field for pid {0}:",
- m_debugged_process_up->GetID(),
- llvm::toString(threads_info.takeError()));
+ LLDB_LOG_ERROR(log, threads_info.takeError(),
+ "failed to prepare a jstopinfo field for pid {1}: {0}",
+ m_debugged_process_up->GetID());
}
}
@@ -2013,7 +2013,7 @@ GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) {
}
const uint8_t *const data =
- reinterpret_cast<const uint8_t *>(reg_value.GetBytes());
+ static_cast<const uint8_t *>(reg_value.GetBytes());
if (!data) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s failed to get data "
@@ -3087,9 +3087,9 @@ GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo(
llvm::Expected<json::Value> threads_info = GetJSONThreadsInfo(
*m_debugged_process_up, threads_with_valid_stop_info_only);
if (!threads_info) {
- LLDB_LOG(log, "failed to prepare a packet for pid {0}: {1}",
- m_debugged_process_up->GetID(),
- llvm::toString(threads_info.takeError()));
+ LLDB_LOG_ERROR(log, threads_info.takeError(),
+ "failed to prepare a packet for pid {1}: {0}",
+ m_debugged_process_up->GetID());
return SendErrorResponse(52);
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index c06c9527708e..ec1a54afd727 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -31,9 +31,11 @@ using namespace lldb_private::process_gdb_remote;
// GDBRemoteRegisterContext constructor
GDBRemoteRegisterContext::GDBRemoteRegisterContext(
ThreadGDBRemote &thread, uint32_t concrete_frame_idx,
- GDBRemoteDynamicRegisterInfo &reg_info, bool read_all_at_once)
+ GDBRemoteDynamicRegisterInfo &reg_info, bool read_all_at_once,
+ bool write_all_at_once)
: RegisterContext(thread, concrete_frame_idx), m_reg_info(reg_info),
- m_reg_valid(), m_reg_data(), m_read_all_at_once(read_all_at_once) {
+ m_reg_valid(), m_reg_data(), m_read_all_at_once(read_all_at_once),
+ m_write_all_at_once(write_all_at_once) {
// Resize our vector of bools to contain one bool for every register. We will
// use these boolean values to know when a register value is valid in
// m_reg_data.
@@ -87,6 +89,9 @@ bool GDBRemoteRegisterContext::ReadRegister(const RegisterInfo *reg_info,
RegisterValue &value) {
// Read the register
if (ReadRegisterBytes(reg_info, m_reg_data)) {
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+ if (m_reg_valid[reg] == false)
+ return false;
const bool partial_data_ok = false;
Status error(value.SetValueFromData(
reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok));
@@ -203,6 +208,18 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
if (buffer_sp->GetByteSize() >= m_reg_data.GetByteSize()) {
SetAllRegisterValid(true);
return true;
+ } else if (buffer_sp->GetByteSize() > 0) {
+ const int regcount = m_reg_info.GetNumRegisters();
+ for (int i = 0; i < regcount; i++) {
+ struct RegisterInfo *reginfo = m_reg_info.GetRegisterInfoAtIndex(i);
+ if (reginfo->byte_offset + reginfo->byte_size
+ <= buffer_sp->GetByteSize()) {
+ m_reg_valid[i] = true;
+ } else {
+ m_reg_valid[i] = false;
+ }
+ }
+ return true;
} else {
Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_THREAD |
GDBR_LOG_PACKETS));
@@ -333,7 +350,7 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
{
GDBRemoteClientBase::Lock lock(gdb_comm, false);
if (lock) {
- if (m_read_all_at_once) {
+ if (m_write_all_at_once) {
// Invalidate all register values
InvalidateIfNeeded(true);
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 25e9b716f8cb..b42c87b5991b 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -41,7 +41,7 @@ class GDBRemoteRegisterContext : public RegisterContext {
public:
GDBRemoteRegisterContext(ThreadGDBRemote &thread, uint32_t concrete_frame_idx,
GDBRemoteDynamicRegisterInfo &reg_info,
- bool read_all_at_once);
+ bool read_all_at_once, bool write_all_at_once);
~GDBRemoteRegisterContext() override;
@@ -114,6 +114,7 @@ protected:
std::vector<bool> m_reg_valid;
DataExtractor m_reg_data;
bool m_read_all_at_once;
+ bool m_write_all_at_once;
private:
// Helper function for ReadRegisterBytes().
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index f1762abc55f8..a49db5d9a934 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -10,7 +10,7 @@
#include <errno.h>
#include <stdlib.h>
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
#include <netinet/in.h>
#include <sys/mman.h>
#include <sys/socket.h>
@@ -154,6 +154,11 @@ public:
nullptr, idx,
g_processgdbremote_properties[idx].default_uint_value != 0);
}
+
+ bool GetUseGPacketForReading() const {
+ const uint32_t idx = ePropertyUseGPacketForReading;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
+ }
};
typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP;
@@ -274,12 +279,9 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
"async thread did exit");
if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) {
- repro::ProcessGDBRemoteProvider &provider =
- g->GetOrCreate<repro::ProcessGDBRemoteProvider>();
- // Set the history stream to the stream owned by the provider.
- m_gdb_comm.SetHistoryStream(provider.GetHistoryStream());
- // Make sure to clear the stream again when we're finished.
- provider.SetCallback([&]() { m_gdb_comm.SetHistoryStream(nullptr); });
+ repro::GDBRemoteProvider &provider =
+ g->GetOrCreate<repro::GDBRemoteProvider>();
+ m_gdb_comm.SetPacketRecorder(provider.GetNewPacketRecorder());
}
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_ASYNC));
@@ -309,6 +311,9 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
GetGlobalPluginProperties()->GetPacketTimeout();
if (timeout_seconds > 0)
m_gdb_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds));
+
+ m_use_g_packet_for_reading =
+ GetGlobalPluginProperties()->GetUseGPacketForReading();
}
// Destructor
@@ -380,36 +385,6 @@ bool ProcessGDBRemote::ParsePythonTargetDefinition(
return false;
}
-// If the remote stub didn't give us eh_frame or DWARF register numbers for a
-// register, see if the ABI can provide them.
-// DWARF and eh_frame register numbers are defined as a part of the ABI.
-static void AugmentRegisterInfoViaABI(RegisterInfo &reg_info,
- ConstString reg_name, ABISP abi_sp) {
- if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM ||
- reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM) {
- if (abi_sp) {
- RegisterInfo abi_reg_info;
- if (abi_sp->GetRegisterInfoByName(reg_name, abi_reg_info)) {
- if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM &&
- abi_reg_info.kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) {
- reg_info.kinds[eRegisterKindEHFrame] =
- abi_reg_info.kinds[eRegisterKindEHFrame];
- }
- if (reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM &&
- abi_reg_info.kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM) {
- reg_info.kinds[eRegisterKindDWARF] =
- abi_reg_info.kinds[eRegisterKindDWARF];
- }
- if (reg_info.kinds[eRegisterKindGeneric] == LLDB_INVALID_REGNUM &&
- abi_reg_info.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) {
- reg_info.kinds[eRegisterKindGeneric] =
- abi_reg_info.kinds[eRegisterKindGeneric];
- }
- }
- }
- }
-}
-
static size_t SplitCommaSeparatedRegisterNumberString(
const llvm::StringRef &comma_separated_regiter_numbers,
std::vector<uint32_t> &regnums, int base) {
@@ -607,12 +582,12 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
reg_info.invalidate_regs = invalidate_regs.data();
}
+ reg_info.name = reg_name.AsCString();
// We have to make a temporary ABI here, and not use the GetABI because
// this code gets called in DidAttach, when the target architecture
// (and consequently the ABI we'll get from the process) may be wrong.
- ABISP abi_to_use = ABI::FindPlugin(shared_from_this(), arch_to_use);
-
- AugmentRegisterInfoViaABI(reg_info, reg_name, abi_to_use);
+ if (ABISP abi_sp = ABI::FindPlugin(shared_from_this(), arch_to_use))
+ abi_sp->AugmentRegisterInfo(reg_info);
m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);
} else {
@@ -2374,21 +2349,22 @@ void ProcessGDBRemote::RefreshStateAfterStop() {
m_thread_ids.clear();
m_thread_pcs.clear();
+
// Set the thread stop info. It might have a "threads" key whose value is a
// list of all thread IDs in the current process, so m_thread_ids might get
// set.
+ // Check to see if SetThreadStopInfo() filled in m_thread_ids?
+ if (m_thread_ids.empty()) {
+ // No, we need to fetch the thread list manually
+ UpdateThreadIDList();
+ }
+
+ // We might set some stop info's so make sure the thread list is up to
+ // date before we do that or we might overwrite what was computed here.
+ UpdateThreadListIfNeeded();
// Scope for the lock
{
- // Check to see if SetThreadStopInfo() filled in m_thread_ids?
- if (m_thread_ids.empty()) {
- // No, we need to fetch the thread list manually
- UpdateThreadIDList();
- }
- // We might set some stop info's so make sure the thread list is up to
- // date before we do that or we might overwrite what was computed here.
- UpdateThreadListIfNeeded();
-
// Lock the thread stack while we access it
std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex);
// Get the number of stop packets on the stack
@@ -3384,17 +3360,20 @@ Status ProcessGDBRemote::ConnectToReplayServer(repro::Loader *loader) {
if (!loader)
return Status("No loader provided.");
- // Construct replay history path.
- FileSpec history_file =
- loader->GetFile<repro::ProcessGDBRemoteProvider::Info>();
- if (!history_file)
- return Status("No provider for gdb-remote.");
+ static std::unique_ptr<repro::MultiLoader<repro::GDBRemoteProvider>>
+ multi_loader = repro::MultiLoader<repro::GDBRemoteProvider>::Create(
+ repro::Reproducer::Instance().GetLoader());
- // Enable replay mode.
- m_replay_mode = true;
+ if (!multi_loader)
+ return Status("No gdb remote provider found.");
+
+ llvm::Optional<std::string> history_file = multi_loader->GetNextFile();
+ if (!history_file)
+ return Status("No gdb remote packet log found.");
// Load replay history.
- if (auto error = m_gdb_replay_server.LoadReplayHistory(history_file))
+ if (auto error =
+ m_gdb_replay_server.LoadReplayHistory(FileSpec(*history_file)))
return Status("Unable to load replay history");
// Make a local connection.
@@ -3402,6 +3381,9 @@ Status ProcessGDBRemote::ConnectToReplayServer(repro::Loader *loader) {
m_gdb_replay_server))
return Status("Unable to connect to replay server");
+ // Enable replay mode.
+ m_replay_mode = true;
+
// Start server thread.
m_gdb_replay_server.StartAsyncThread();
@@ -3627,9 +3609,9 @@ bool ProcessGDBRemote::StartAsyncThread() {
llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread(
"<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this);
if (!async_thread) {
- LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST),
- "failed to launch host thread: {}",
- llvm::toString(async_thread.takeError()));
+ LLDB_LOG_ERROR(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST),
+ async_thread.takeError(),
+ "failed to launch host thread: {}");
return false;
}
m_async_thread = *async_thread;
@@ -4475,7 +4457,9 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
}
++cur_reg_num;
- AugmentRegisterInfoViaABI(reg_info, reg_name, abi_sp);
+ reg_info.name = reg_name.AsCString();
+ if (abi_sp)
+ abi_sp->AugmentRegisterInfo(reg_info);
dyn_reg_info.AddRegister(reg_info, reg_name, alt_name, set_name);
return true; // Keep iterating through all "reg" elements
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 0e3e3b39d9c8..9ea3940103b6 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -284,6 +284,7 @@ protected:
lldb::CommandObjectSP m_command_sp;
int64_t m_breakpoint_pc_offset;
lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach
+ bool m_use_g_packet_for_reading;
bool m_replay_mode;
bool m_allow_flash_writes;
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td
index 16e7723e3061..9cbe3d40ca2c 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td
@@ -13,4 +13,8 @@ let Definition = "processgdbremote" in {
Global,
DefaultFalse,
Desc<"If true, the libraries-svr4 feature will be used to get a hold of the process's loaded modules.">;
+ def UseGPacketForReading: Property<"use-g-packet-for-reading", "Boolean">,
+ Global,
+ DefaultFalse,
+ Desc<"Specify if the server should use 'g' packets to read registers.">;
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 8a6a58c55450..9da481979f73 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -301,13 +301,14 @@ ThreadGDBRemote::CreateRegisterContextForFrame(StackFrame *frame) {
if (process_sp) {
ProcessGDBRemote *gdb_process =
static_cast<ProcessGDBRemote *>(process_sp.get());
- // read_all_registers_at_once will be true if 'p' packet is not
- // supported.
+ bool pSupported =
+ gdb_process->GetGDBRemote().GetpPacketSupported(GetID());
bool read_all_registers_at_once =
- !gdb_process->GetGDBRemote().GetpPacketSupported(GetID());
+ !pSupported || gdb_process->m_use_g_packet_for_reading;
+ bool write_all_registers_at_once = !pSupported;
reg_ctx_sp = std::make_shared<GDBRemoteRegisterContext>(
*this, concrete_frame_idx, gdb_process->m_register_info,
- read_all_registers_at_once);
+ read_all_registers_at_once, write_all_registers_at_once);
}
} else {
Unwind *unwinder = GetUnwinder();
diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
index 70933f91fe51..3c0e1cb49d1d 100644
--- a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
+++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
@@ -174,6 +174,7 @@ ArchSpec MinidumpParser::GetArchitecture() {
triple.setArch(llvm::Triple::ArchType::arm);
break;
case ProcessorArchitecture::ARM64:
+ case ProcessorArchitecture::BP_ARM64:
triple.setArch(llvm::Triple::ArchType::aarch64);
break;
default:
@@ -518,58 +519,26 @@ CreateRegionsCacheFromMemory64List(MinidumpParser &parser,
return !regions.empty();
}
-MemoryRegionInfo
-MinidumpParser::FindMemoryRegion(lldb::addr_t load_addr) const {
- auto begin = m_regions.begin();
- auto end = m_regions.end();
- auto pos = std::lower_bound(begin, end, load_addr);
- if (pos != end && pos->GetRange().Contains(load_addr))
- return *pos;
-
- MemoryRegionInfo region;
- if (pos == begin)
- region.GetRange().SetRangeBase(0);
- else {
- auto prev = pos - 1;
- if (prev->GetRange().Contains(load_addr))
- return *prev;
- region.GetRange().SetRangeBase(prev->GetRange().GetRangeEnd());
- }
- if (pos == end)
- region.GetRange().SetRangeEnd(UINT64_MAX);
- else
- region.GetRange().SetRangeEnd(pos->GetRange().GetRangeBase());
- region.SetReadable(MemoryRegionInfo::eNo);
- region.SetWritable(MemoryRegionInfo::eNo);
- region.SetExecutable(MemoryRegionInfo::eNo);
- region.SetMapped(MemoryRegionInfo::eNo);
- return region;
-}
-
-MemoryRegionInfo
-MinidumpParser::GetMemoryRegionInfo(lldb::addr_t load_addr) {
- if (!m_parsed_regions)
- GetMemoryRegions();
- return FindMemoryRegion(load_addr);
-}
-
-const MemoryRegionInfos &MinidumpParser::GetMemoryRegions() {
- if (!m_parsed_regions) {
- m_parsed_regions = true;
- // We haven't cached our memory regions yet we will create the region cache
- // once. We create the region cache using the best source. We start with
- // the linux maps since they are the most complete and have names for the
- // regions. Next we try the MemoryInfoList since it has
- // read/write/execute/map data, and then fall back to the MemoryList and
- // Memory64List to just get a list of the memory that is mapped in this
- // core file
- if (!CreateRegionsCacheFromLinuxMaps(*this, m_regions))
- if (!CreateRegionsCacheFromMemoryInfoList(*this, m_regions))
- if (!CreateRegionsCacheFromMemoryList(*this, m_regions))
- CreateRegionsCacheFromMemory64List(*this, m_regions);
- llvm::sort(m_regions.begin(), m_regions.end());
- }
- return m_regions;
+std::pair<MemoryRegionInfos, bool> MinidumpParser::BuildMemoryRegions() {
+ // We create the region cache using the best source. We start with
+ // the linux maps since they are the most complete and have names for the
+ // regions. Next we try the MemoryInfoList since it has
+ // read/write/execute/map data, and then fall back to the MemoryList and
+ // Memory64List to just get a list of the memory that is mapped in this
+ // core file
+ MemoryRegionInfos result;
+ const auto &return_sorted = [&](bool is_complete) {
+ llvm::sort(result);
+ return std::make_pair(std::move(result), is_complete);
+ };
+ if (CreateRegionsCacheFromLinuxMaps(*this, result))
+ return return_sorted(true);
+ if (CreateRegionsCacheFromMemoryInfoList(*this, result))
+ return return_sorted(true);
+ if (CreateRegionsCacheFromMemoryList(*this, result))
+ return return_sorted(false);
+ CreateRegionsCacheFromMemory64List(*this, result);
+ return return_sorted(false);
}
#define ENUM_TO_CSTR(ST) \
diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.h b/lldb/source/Plugins/Process/minidump/MinidumpParser.h
index d206fe6c9a00..4bcb2b47d45a 100644
--- a/lldb/source/Plugins/Process/minidump/MinidumpParser.h
+++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.h
@@ -88,9 +88,9 @@ public:
llvm::ArrayRef<uint8_t> GetMemory(lldb::addr_t addr, size_t size);
- MemoryRegionInfo GetMemoryRegionInfo(lldb::addr_t load_addr);
-
- const MemoryRegionInfos &GetMemoryRegions();
+ /// Returns a list of memory regions and a flag indicating whether the list is
+ /// complete (includes all regions mapped into the process memory).
+ std::pair<MemoryRegionInfos, bool> BuildMemoryRegions();
static llvm::StringRef GetStreamTypeAsString(StreamType stream_type);
@@ -100,14 +100,10 @@ private:
MinidumpParser(lldb::DataBufferSP data_sp,
std::unique_ptr<llvm::object::MinidumpFile> file);
- MemoryRegionInfo FindMemoryRegion(lldb::addr_t load_addr) const;
-
private:
lldb::DataBufferSP m_data_sp;
std::unique_ptr<llvm::object::MinidumpFile> m_file;
ArchSpec m_arch;
- MemoryRegionInfos m_regions;
- bool m_parsed_regions = false;
};
} // end namespace minidump
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
index e30a3c82a887..5c090dc6e12f 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -334,15 +334,84 @@ ArchSpec ProcessMinidump::GetArchitecture() {
return ArchSpec(triple);
}
+static MemoryRegionInfo GetMemoryRegionInfo(const MemoryRegionInfos &regions,
+ lldb::addr_t load_addr) {
+ MemoryRegionInfo region;
+ auto pos = llvm::upper_bound(regions, load_addr);
+ if (pos != regions.begin() &&
+ std::prev(pos)->GetRange().Contains(load_addr)) {
+ return *std::prev(pos);
+ }
+
+ if (pos == regions.begin())
+ region.GetRange().SetRangeBase(0);
+ else
+ region.GetRange().SetRangeBase(std::prev(pos)->GetRange().GetRangeEnd());
+
+ if (pos == regions.end())
+ region.GetRange().SetRangeEnd(UINT64_MAX);
+ else
+ region.GetRange().SetRangeEnd(pos->GetRange().GetRangeBase());
+
+ region.SetReadable(MemoryRegionInfo::eNo);
+ region.SetWritable(MemoryRegionInfo::eNo);
+ region.SetExecutable(MemoryRegionInfo::eNo);
+ region.SetMapped(MemoryRegionInfo::eNo);
+ return region;
+}
+
+void ProcessMinidump::BuildMemoryRegions() {
+ if (m_memory_regions)
+ return;
+ m_memory_regions.emplace();
+ bool is_complete;
+ std::tie(*m_memory_regions, is_complete) =
+ m_minidump_parser->BuildMemoryRegions();
+
+ if (is_complete)
+ return;
+
+ MemoryRegionInfos to_add;
+ ModuleList &modules = GetTarget().GetImages();
+ SectionLoadList &load_list = GetTarget().GetSectionLoadList();
+ modules.ForEach([&](const ModuleSP &module_sp) {
+ SectionList *sections = module_sp->GetSectionList();
+ for (size_t i = 0; i < sections->GetSize(); ++i) {
+ SectionSP section_sp = sections->GetSectionAtIndex(i);
+ addr_t load_addr = load_list.GetSectionLoadAddress(section_sp);
+ if (load_addr == LLDB_INVALID_ADDRESS)
+ continue;
+ MemoryRegionInfo::RangeType section_range(load_addr,
+ section_sp->GetByteSize());
+ MemoryRegionInfo region =
+ ::GetMemoryRegionInfo(*m_memory_regions, load_addr);
+ if (region.GetMapped() != MemoryRegionInfo::eYes &&
+ region.GetRange().GetRangeBase() <= section_range.GetRangeBase() &&
+ section_range.GetRangeEnd() <= region.GetRange().GetRangeEnd()) {
+ to_add.emplace_back();
+ to_add.back().GetRange() = section_range;
+ to_add.back().SetLLDBPermissions(section_sp->GetPermissions());
+ to_add.back().SetMapped(MemoryRegionInfo::eYes);
+ to_add.back().SetName(module_sp->GetFileSpec().GetPath().c_str());
+ }
+ }
+ return true;
+ });
+ m_memory_regions->insert(m_memory_regions->end(), to_add.begin(),
+ to_add.end());
+ llvm::sort(*m_memory_regions);
+}
+
Status ProcessMinidump::GetMemoryRegionInfo(lldb::addr_t load_addr,
- MemoryRegionInfo &range_info) {
- range_info = m_minidump_parser->GetMemoryRegionInfo(load_addr);
+ MemoryRegionInfo &region) {
+ BuildMemoryRegions();
+ region = ::GetMemoryRegionInfo(*m_memory_regions, load_addr);
return Status();
}
-Status ProcessMinidump::GetMemoryRegions(
- lldb_private::MemoryRegionInfos &region_list) {
- region_list = m_minidump_parser->GetMemoryRegions();
+Status ProcessMinidump::GetMemoryRegions(MemoryRegionInfos &region_list) {
+ BuildMemoryRegions();
+ region_list = *m_memory_regions;
return Status();
}
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
index 22dc24af7c0e..750164cf8aaf 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
@@ -111,6 +111,9 @@ private:
const minidump::ExceptionStream *m_active_exception;
lldb::CommandObjectSP m_command_sp;
bool m_is_wow64;
+ llvm::Optional<MemoryRegionInfos> m_memory_regions;
+
+ void BuildMemoryRegions();
};
} // namespace minidump
diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
new file mode 100644
index 000000000000..ecee8cc674f8
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
@@ -0,0 +1,59 @@
+//===-- Lua.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 "Lua.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Utility/FileSpec.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+llvm::Error Lua::Run(llvm::StringRef buffer) {
+ int error =
+ luaL_loadbuffer(m_lua_state, buffer.data(), buffer.size(), "buffer") ||
+ lua_pcall(m_lua_state, 0, 0, 0);
+ if (!error)
+ return llvm::Error::success();
+
+ llvm::Error e = llvm::make_error<llvm::StringError>(
+ llvm::formatv("{0}\n", lua_tostring(m_lua_state, -1)),
+ llvm::inconvertibleErrorCode());
+ // Pop error message from the stack.
+ lua_pop(m_lua_state, 1);
+ return e;
+}
+
+llvm::Error Lua::LoadModule(llvm::StringRef filename) {
+ FileSpec file(filename);
+ if (!FileSystem::Instance().Exists(file)) {
+ return llvm::make_error<llvm::StringError>("invalid path",
+ llvm::inconvertibleErrorCode());
+ }
+
+ ConstString module_extension = file.GetFileNameExtension();
+ if (module_extension != ".lua") {
+ return llvm::make_error<llvm::StringError>("invalid extension",
+ llvm::inconvertibleErrorCode());
+ }
+
+ int error = luaL_loadfile(m_lua_state, filename.data()) ||
+ lua_pcall(m_lua_state, 0, 1, 0);
+ if (error) {
+ llvm::Error e = llvm::make_error<llvm::StringError>(
+ llvm::formatv("{0}\n", lua_tostring(m_lua_state, -1)),
+ llvm::inconvertibleErrorCode());
+ // Pop error message from the stack.
+ lua_pop(m_lua_state, 1);
+ return e;
+ }
+
+ ConstString module_name = file.GetFileNameStrippingExtension();
+ lua_setglobal(m_lua_state, module_name.GetCString());
+ return llvm::Error::success();
+}
diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h
new file mode 100644
index 000000000000..f2984a925dfe
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h
@@ -0,0 +1,48 @@
+//===-- ScriptInterpreterLua.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Lua_h_
+#define liblldb_Lua_h_
+
+#include "lldb/lldb-types.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+
+#include "lua.hpp"
+
+#include <mutex>
+
+namespace lldb_private {
+
+extern "C" {
+int luaopen_lldb(lua_State *L);
+}
+
+class Lua {
+public:
+ Lua() : m_lua_state(luaL_newstate()) {
+ assert(m_lua_state);
+ luaL_openlibs(m_lua_state);
+ luaopen_lldb(m_lua_state);
+ }
+
+ ~Lua() {
+ assert(m_lua_state);
+ luaL_openlibs(m_lua_state);
+ }
+
+ llvm::Error Run(llvm::StringRef buffer);
+ llvm::Error LoadModule(llvm::StringRef filename);
+
+private:
+ lua_State *m_lua_state;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_Lua_h_
diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
new file mode 100644
index 000000000000..701d68d1ec08
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
@@ -0,0 +1,157 @@
+//===-- ScriptInterpreterLua.cpp --------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "ScriptInterpreterLua.h"
+#include "Lua.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Utility/Stream.h"
+#include "lldb/Utility/StringList.h"
+#include "lldb/Utility/Timer.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+class IOHandlerLuaInterpreter : public IOHandlerDelegate,
+ public IOHandlerEditline {
+public:
+ IOHandlerLuaInterpreter(Debugger &debugger,
+ ScriptInterpreterLua &script_interpreter)
+ : IOHandlerEditline(debugger, IOHandler::Type::LuaInterpreter, "lua",
+ ">>> ", "..> ", true, debugger.GetUseColor(), 0,
+ *this, nullptr),
+ m_script_interpreter(script_interpreter) {
+ llvm::cantFail(m_script_interpreter.EnterSession(debugger.GetID()));
+ }
+
+ ~IOHandlerLuaInterpreter() {
+ llvm::cantFail(m_script_interpreter.LeaveSession());
+ }
+
+ void IOHandlerInputComplete(IOHandler &io_handler,
+ std::string &data) override {
+ if (llvm::Error error = m_script_interpreter.GetLua().Run(data)) {
+ *GetOutputStreamFileSP() << llvm::toString(std::move(error));
+ }
+ }
+
+private:
+ ScriptInterpreterLua &m_script_interpreter;
+};
+
+ScriptInterpreterLua::ScriptInterpreterLua(Debugger &debugger)
+ : ScriptInterpreter(debugger, eScriptLanguageLua),
+ m_lua(std::make_unique<Lua>()) {}
+
+ScriptInterpreterLua::~ScriptInterpreterLua() {}
+
+bool ScriptInterpreterLua::ExecuteOneLine(llvm::StringRef command,
+ CommandReturnObject *result,
+ const ExecuteScriptOptions &options) {
+ if (llvm::Error e = m_lua->Run(command)) {
+ result->AppendErrorWithFormatv(
+ "lua failed attempting to evaluate '{0}': {1}\n", command,
+ llvm::toString(std::move(e)));
+ return false;
+ }
+ return true;
+}
+
+void ScriptInterpreterLua::ExecuteInterpreterLoop() {
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
+
+ Debugger &debugger = m_debugger;
+
+ // At the moment, the only time the debugger does not have an input file
+ // handle is when this is called directly from lua, in which case it is
+ // both dangerous and unnecessary (not to mention confusing) to try to embed
+ // a running interpreter loop inside the already running lua interpreter
+ // loop, so we won't do it.
+
+ if (!debugger.GetInputFile().IsValid())
+ return;
+
+ IOHandlerSP io_handler_sp(new IOHandlerLuaInterpreter(debugger, *this));
+ debugger.PushIOHandler(io_handler_sp);
+}
+
+bool ScriptInterpreterLua::LoadScriptingModule(
+ const char *filename, bool init_session, lldb_private::Status &error,
+ StructuredData::ObjectSP *module_sp) {
+
+ if (llvm::Error e = m_lua->LoadModule(filename)) {
+ error.SetErrorStringWithFormatv("lua failed to import '{0}': {1}\n",
+ filename, llvm::toString(std::move(e)));
+ return false;
+ }
+ return true;
+}
+
+void ScriptInterpreterLua::Initialize() {
+ static llvm::once_flag g_once_flag;
+
+ llvm::call_once(g_once_flag, []() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(),
+ lldb::eScriptLanguageLua, CreateInstance);
+ });
+}
+
+void ScriptInterpreterLua::Terminate() {}
+
+llvm::Error ScriptInterpreterLua::EnterSession(user_id_t debugger_id) {
+ if (m_session_is_active)
+ return llvm::Error::success();
+
+ const char *fmt_str =
+ "lldb.debugger = lldb.SBDebugger.FindDebuggerWithID({0}); "
+ "lldb.target = lldb.debugger:GetSelectedTarget(); "
+ "lldb.process = lldb.target:GetProcess(); "
+ "lldb.thread = lldb.process:GetSelectedThread(); "
+ "lldb.frame = lldb.thread:GetSelectedFrame()";
+ return m_lua->Run(llvm::formatv(fmt_str, debugger_id).str());
+}
+
+llvm::Error ScriptInterpreterLua::LeaveSession() {
+ if (!m_session_is_active)
+ return llvm::Error::success();
+
+ m_session_is_active = false;
+
+ llvm::StringRef str = "lldb.debugger = nil; "
+ "lldb.target = nil; "
+ "lldb.process = nil; "
+ "lldb.thread = nil; "
+ "lldb.frame = nil";
+ return m_lua->Run(str);
+}
+
+lldb::ScriptInterpreterSP
+ScriptInterpreterLua::CreateInstance(Debugger &debugger) {
+ return std::make_shared<ScriptInterpreterLua>(debugger);
+}
+
+lldb_private::ConstString ScriptInterpreterLua::GetPluginNameStatic() {
+ static ConstString g_name("script-lua");
+ return g_name;
+}
+
+const char *ScriptInterpreterLua::GetPluginDescriptionStatic() {
+ return "Lua script interpreter";
+}
+
+lldb_private::ConstString ScriptInterpreterLua::GetPluginName() {
+ return GetPluginNameStatic();
+}
+
+uint32_t ScriptInterpreterLua::GetPluginVersion() { return 1; }
+
+Lua &ScriptInterpreterLua::GetLua() { return *m_lua; }
diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
new file mode 100644
index 000000000000..4e922151385b
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
@@ -0,0 +1,61 @@
+//===-- ScriptInterpreterLua.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ScriptInterpreterLua_h_
+#define liblldb_ScriptInterpreterLua_h_
+
+#include "lldb/Interpreter/ScriptInterpreter.h"
+
+namespace lldb_private {
+class Lua;
+class ScriptInterpreterLua : public ScriptInterpreter {
+public:
+ ScriptInterpreterLua(Debugger &debugger);
+
+ ~ScriptInterpreterLua() override;
+
+ bool ExecuteOneLine(
+ llvm::StringRef command, CommandReturnObject *result,
+ const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
+
+ void ExecuteInterpreterLoop() override;
+
+ virtual bool
+ LoadScriptingModule(const char *filename, bool init_session,
+ lldb_private::Status &error,
+ StructuredData::ObjectSP *module_sp = nullptr) override;
+
+ // Static Functions
+ static void Initialize();
+
+ static void Terminate();
+
+ static lldb::ScriptInterpreterSP CreateInstance(Debugger &debugger);
+
+ static lldb_private::ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ // PluginInterface protocol
+ lldb_private::ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+ Lua &GetLua();
+
+ llvm::Error EnterSession(lldb::user_id_t debugger_id);
+ llvm::Error LeaveSession();
+
+private:
+ std::unique_ptr<Lua> m_lua;
+ bool m_session_is_active = false;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ScriptInterpreterLua_h_
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
index 70d93424fdec..e5a67653e334 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
@@ -6,11 +6,9 @@
//
//===----------------------------------------------------------------------===//
-#ifdef LLDB_DISABLE_PYTHON
+#include "lldb/Host/Config.h"
-// Python is disabled in this build
-
-#else
+#if LLDB_ENABLE_PYTHON
#include "PythonDataObjects.h"
#include "ScriptInterpreterPython.h"
@@ -802,29 +800,11 @@ bool PythonCallable::Check(PyObject *py_obj) {
return PyCallable_Check(py_obj);
}
-PythonCallable::ArgInfo PythonCallable::GetNumInitArguments() const {
- auto arginfo = GetInitArgInfo();
- if (!arginfo) {
- llvm::consumeError(arginfo.takeError());
- return ArgInfo{};
- }
- return arginfo.get();
-}
-
-Expected<PythonCallable::ArgInfo> PythonCallable::GetInitArgInfo() const {
- if (!IsValid())
- return nullDeref();
- auto init = As<PythonCallable>(GetAttribute("__init__"));
- if (!init)
- return init.takeError();
- return init.get().GetArgInfo();
-}
-
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
static const char get_arg_info_script[] = R"(
from inspect import signature, Parameter, ismethod
from collections import namedtuple
-ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs', 'is_bound_method'])
+ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs'])
def main(f):
count = 0
varargs = False
@@ -840,7 +820,7 @@ def main(f):
pass
else:
raise Exception(f'unknown parameter kind: {kind}')
- return ArgInfo(count, varargs, ismethod(f))
+ return ArgInfo(count, varargs)
)";
#endif
@@ -856,21 +836,27 @@ Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const {
Expected<PythonObject> pyarginfo = get_arg_info(*this);
if (!pyarginfo)
return pyarginfo.takeError();
- result.count = cantFail(As<long long>(pyarginfo.get().GetAttribute("count")));
- result.has_varargs =
+ long long count =
+ cantFail(As<long long>(pyarginfo.get().GetAttribute("count")));
+ bool has_varargs =
cantFail(As<bool>(pyarginfo.get().GetAttribute("has_varargs")));
- bool is_method =
- cantFail(As<bool>(pyarginfo.get().GetAttribute("is_bound_method")));
- result.max_positional_args =
- result.has_varargs ? ArgInfo::UNBOUNDED : result.count;
-
- // FIXME emulate old broken behavior
- if (is_method)
- result.count++;
+ result.max_positional_args = has_varargs ? ArgInfo::UNBOUNDED : count;
#else
+ PyObject *py_func_obj;
bool is_bound_method = false;
- PyObject *py_func_obj = m_py_obj;
+ bool is_class = false;
+
+ if (PyType_Check(m_py_obj) || PyClass_Check(m_py_obj)) {
+ auto init = GetAttribute("__init__");
+ if (!init)
+ return init.takeError();
+ py_func_obj = init.get().get();
+ is_class = true;
+ } else {
+ py_func_obj = m_py_obj;
+ }
+
if (PyMethod_Check(py_func_obj)) {
py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
PythonObject im_self = GetAttributeValue("im_self");
@@ -899,11 +885,11 @@ Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const {
if (!code)
return result;
- result.count = code->co_argcount;
- result.has_varargs = !!(code->co_flags & CO_VARARGS);
- result.max_positional_args = result.has_varargs
- ? ArgInfo::UNBOUNDED
- : (result.count - (int)is_bound_method);
+ auto count = code->co_argcount;
+ bool has_varargs = !!(code->co_flags & CO_VARARGS);
+ result.max_positional_args =
+ has_varargs ? ArgInfo::UNBOUNDED
+ : (count - (int)is_bound_method) - (int)is_class;
#endif
@@ -913,15 +899,6 @@ Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const {
constexpr unsigned
PythonCallable::ArgInfo::UNBOUNDED; // FIXME delete after c++17
-PythonCallable::ArgInfo PythonCallable::GetNumArguments() const {
- auto arginfo = GetArgInfo();
- if (!arginfo) {
- llvm::consumeError(arginfo.takeError());
- return ArgInfo{};
- }
- return arginfo.get();
-}
-
PythonObject PythonCallable::operator()() {
return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr));
}
@@ -1385,11 +1362,13 @@ llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) {
if (!options)
return options.takeError();
- // LLDB and python will not share I/O buffers. We should probably
- // flush the python buffers now.
- auto r = CallMethod("flush");
- if (!r)
- return r.takeError();
+ if (options.get() & File::eOpenOptionWrite) {
+ // LLDB and python will not share I/O buffers. We should probably
+ // flush the python buffers now.
+ auto r = CallMethod("flush");
+ if (!r)
+ return r.takeError();
+ }
FileSP file_sp;
if (borrowed) {
@@ -1498,14 +1477,23 @@ Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) {
PyObject *file_obj;
#if PY_MAJOR_VERSION >= 3
file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr,
- "ignore", nullptr, 0);
+ "ignore", nullptr, /*closefd=*/0);
#else
- // Read through the Python source, doesn't seem to modify these strings
- char *cmode = const_cast<char *>(mode);
- // We pass ::flush instead of ::fclose here so we borrow the FILE* --
- // the lldb_private::File still owns it.
- file_obj =
- PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, ::fflush);
+ // I'd like to pass ::fflush here if the file is writable, so that
+ // when the python side destructs the file object it will be flushed.
+ // However, this would be dangerous. It can cause fflush to be called
+ // after fclose if the python program keeps a reference to the file after
+ // the original lldb_private::File has been destructed.
+ //
+ // It's all well and good to ask a python program not to use a closed file
+ // but asking a python program to make sure objects get released in a
+ // particular order is not safe.
+ //
+ // The tradeoff here is that if a python 2 program wants to make sure this
+ // file gets flushed, they'll have to do it explicitly or wait untill the
+ // original lldb File itself gets flushed.
+ file_obj = PyFile_FromFile(file.GetStream(), py2_const_cast(""),
+ py2_const_cast(mode), [](FILE *) { return 0; });
#endif
if (!file_obj)
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
index 373d3212697d..b75045b239a8 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
@@ -48,7 +48,9 @@
#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
-#ifndef LLDB_DISABLE_PYTHON
+#include "lldb/Host/Config.h"
+
+#if LLDB_ENABLE_PYTHON
// LLDB Python header must be included first
#include "lldb-python.h"
@@ -130,7 +132,7 @@ template <typename T> T Take(PyObject *obj) {
assert(!PyErr_Occurred());
T thing(PyRefType::Owned, obj);
assert(thing.IsValid());
- return std::move(thing);
+ return thing;
}
// Retain a reference you have borrowed, and turn it into
@@ -148,7 +150,7 @@ template <typename T> T Retain(PyObject *obj) {
assert(!PyErr_Occurred());
T thing(PyRefType::Borrowed, obj);
assert(thing.IsValid());
- return std::move(thing);
+ return thing;
}
// This class can be used like a utility function to convert from
@@ -189,6 +191,14 @@ inline llvm::Error keyError() {
"key not in dict");
}
+#if PY_MAJOR_VERSION < 3
+// The python 2 API declares some arguments as char* that should
+// be const char *, but it doesn't actually modify them.
+inline char *py2_const_cast(const char *s) { return const_cast<char *>(s); }
+#else
+inline const char *py2_const_cast(const char *s) { return s; }
+#endif
+
enum class PyInitialValue { Invalid, Empty };
template <typename T, typename Enable = void> struct PythonFormat;
@@ -309,16 +319,6 @@ public:
StructuredData::ObjectSP CreateStructuredObject() const;
-protected:
-
-#if PY_MAJOR_VERSION < 3
- // The python 2 API declares some arguments as char* that should
- // be const char *, but it doesn't actually modify them.
- static char *py2_const_cast(const char *s) { return const_cast<char *>(s); }
-#else
- static const char *py2_const_cast(const char *s) { return s; }
-#endif
-
public:
template <typename... T>
llvm::Expected<PythonObject> CallMethod(const char *name,
@@ -621,30 +621,12 @@ public:
* function and can accept an arbitrary number */
unsigned max_positional_args;
static constexpr unsigned UNBOUNDED = UINT_MAX; // FIXME c++17 inline
- /* the number of positional arguments, including optional ones,
- * and excluding varargs. If this is a bound method, then the
- * count will still include a +1 for self.
- *
- * FIXME. That's crazy. This should be replaced with
- * an accurate min and max for positional args.
- */
- int count;
- /* does the callable have positional varargs? */
- bool has_varargs : 1; // FIXME delete this
};
static bool Check(PyObject *py_obj);
llvm::Expected<ArgInfo> GetArgInfo() const;
- llvm::Expected<ArgInfo> GetInitArgInfo() const;
-
- ArgInfo GetNumArguments() const; // DEPRECATED
-
- // If the callable is a Py_Class, then find the number of arguments
- // of the __init__ method.
- ArgInfo GetNumInitArguments() const; // DEPRECATED
-
PythonObject operator()();
PythonObject operator()(std::initializer_list<PyObject *> args);
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
new file mode 100644
index 000000000000..5f6429f5cd0e
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
@@ -0,0 +1,88 @@
+#include "PythonReadline.h"
+
+#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
+
+#include <stdio.h>
+
+#include <editline/readline.h>
+
+// Simple implementation of the Python readline module using libedit.
+// In the event that libedit is excluded from the build, this turns
+// back into a null implementation that blocks the module from pulling
+// in the GNU readline shared lib, which causes linkage confusion when
+// both readline and libedit's readline compatibility symbols collide.
+//
+// Currently it only installs a PyOS_ReadlineFunctionPointer, without
+// implementing any of the readline module methods. This is meant to
+// work around LLVM pr18841 to avoid seg faults in the stock Python
+// readline.so linked against GNU readline.
+//
+// Bug on the cpython side: https://bugs.python.org/issue38634
+
+PyDoc_STRVAR(moduleDocumentation,
+ "Simple readline module implementation based on libedit.");
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef readline_module = {
+ PyModuleDef_HEAD_INIT, // m_base
+ "lldb_editline", // m_name
+ moduleDocumentation, // m_doc
+ -1, // m_size
+ nullptr, // m_methods
+ nullptr, // m_reload
+ nullptr, // m_traverse
+ nullptr, // m_clear
+ nullptr, // m_free
+};
+#else
+static struct PyMethodDef moduleMethods[] = {{nullptr, nullptr, 0, nullptr}};
+#endif
+
+static char *
+#if PY_MAJOR_VERSION >= 3
+simple_readline(FILE *stdin, FILE *stdout, const char *prompt)
+#else
+simple_readline(FILE *stdin, FILE *stdout, char *prompt)
+#endif
+{
+ rl_instream = stdin;
+ rl_outstream = stdout;
+ char *line = readline(prompt);
+ if (!line) {
+#if PY_MAJOR_VERSION >= 3
+ char *ret = (char *)PyMem_RawMalloc(1);
+#else
+ char *ret = (char *)PyMem_Malloc(1);
+#endif
+ if (ret != NULL)
+ *ret = '\0';
+ return ret;
+ }
+ if (*line)
+ add_history(line);
+ int n = strlen(line);
+#if PY_MAJOR_VERSION >= 3
+ char *ret = (char *)PyMem_RawMalloc(n + 2);
+#else
+ char *ret = (char *)PyMem_Malloc(n + 2);
+#endif
+ if (ret) {
+ memcpy(ret, line, n);
+ free(line);
+ ret[n] = '\n';
+ ret[n + 1] = '\0';
+ }
+ return ret;
+}
+
+PyMODINIT_FUNC initlldb_readline(void) {
+ PyOS_ReadlineFunctionPointer = simple_readline;
+
+#if PY_MAJOR_VERSION >= 3
+ return PyModule_Create(&readline_module);
+#else
+ Py_InitModule4("readline", moduleMethods, moduleDocumentation,
+ static_cast<PyObject *>(NULL), PYTHON_API_VERSION);
+#endif
+}
+#endif
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.h b/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.h
new file mode 100644
index 000000000000..c75219eb1a4f
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.h
@@ -0,0 +1,28 @@
+//===-- PythonReadline.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONREADLINE_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONREADLINE_H
+
+#include "lldb/Host/Config.h"
+
+#if LLDB_ENABLE_LIBEDIT && defined(__linux__)
+// NOTE: Since Python may define some pre-processor definitions which affect the
+// standard headers on some systems, you must include Python.h before any
+// standard headers are included.
+#include "Python.h"
+
+// no need to hack into Python's readline module if libedit isn't used.
+//
+#define LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE 1
+
+PyMODINIT_FUNC initlldb_readline(void);
+
+#endif
+
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONREADLINE_H
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index 3eee52184142..06e0d5bfa63f 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -6,16 +6,15 @@
//
//===----------------------------------------------------------------------===//
-#ifdef LLDB_DISABLE_PYTHON
+#include "lldb/Host/Config.h"
-// Python is disabled in this build
-
-#else
+#if LLDB_ENABLE_PYTHON
// LLDB Python header must be included first
#include "lldb-python.h"
#include "PythonDataObjects.h"
+#include "PythonReadline.h"
#include "ScriptInterpreterPythonImpl.h"
#include "lldb/API/SBFrame.h"
@@ -72,10 +71,28 @@ extern "C" void init_lldb(void);
// These prototypes are the Pythonic implementations of the required callbacks.
// Although these are scripting-language specific, their definition depends on
// the public API.
-extern "C" bool LLDBSwigPythonBreakpointCallbackFunction(
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
+
+// Disable warning C4190: 'LLDBSwigPythonBreakpointCallbackFunction' has
+// C-linkage specified, but returns UDT 'llvm::Expected<bool>' which is
+// incompatible with C
+#if _MSC_VER
+#pragma warning (push)
+#pragma warning (disable : 4190)
+#endif
+
+extern "C" llvm::Expected<bool> LLDBSwigPythonBreakpointCallbackFunction(
const char *python_function_name, const char *session_dictionary_name,
const lldb::StackFrameSP &sb_frame,
- const lldb::BreakpointLocationSP &sb_bp_loc);
+ const lldb::BreakpointLocationSP &sb_bp_loc, StructuredDataImpl *args_impl);
+
+#if _MSC_VER
+#pragma warning (pop)
+#endif
+
+#pragma clang diagnostic pop
extern "C" bool LLDBSwigPythonWatchpointCallbackFunction(
const char *python_function_name, const char *session_dictionary_name,
@@ -211,6 +228,22 @@ public:
InitializePythonHome();
+#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
+ // Python's readline is incompatible with libedit being linked into lldb.
+ // Provide a patched version local to the embedded interpreter.
+ bool ReadlinePatched = false;
+ for (auto *p = PyImport_Inittab; p->name != NULL; p++) {
+ if (strcmp(p->name, "readline") == 0) {
+ p->initfunc = initlldb_readline;
+ break;
+ }
+ }
+ if (!ReadlinePatched) {
+ PyImport_AppendInittab("readline", initlldb_readline);
+ ReadlinePatched = true;
+ }
+#endif
+
// Register _lldb as a built-in module.
PyImport_AppendInittab("_lldb", LLDBSwigPyInit);
@@ -552,8 +585,10 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler,
break;
data_up->user_source.SplitIntoLines(data);
+ StructuredData::ObjectSP empty_args_sp;
if (GenerateBreakpointCommandCallbackData(data_up->user_source,
- data_up->script_source)
+ data_up->script_source,
+ false)
.Success()) {
auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>(
std::move(data_up));
@@ -779,6 +814,32 @@ PythonDictionary &ScriptInterpreterPythonImpl::GetSysModuleDictionary() {
return m_sys_module_dict;
}
+llvm::Expected<unsigned>
+ScriptInterpreterPythonImpl::GetMaxPositionalArgumentsForCallable(
+ const llvm::StringRef &callable_name) {
+ if (callable_name.empty()) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "called with empty callable name.");
+ }
+ Locker py_lock(this, Locker::AcquireLock |
+ Locker::InitSession |
+ Locker::NoSTDIN);
+ auto dict = PythonModule::MainModule()
+ .ResolveName<PythonDictionary>(m_dictionary_name);
+ auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
+ callable_name, dict);
+ if (!pfunc.IsAllocated()) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "can't find callable: %s", callable_name.str().c_str());
+ }
+ llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
+ if (!arg_info)
+ return arg_info.takeError();
+ return arg_info.get().max_positional_args;
+}
+
static std::string GenerateUniqueName(const char *base_name_wanted,
uint32_t &functions_counter,
const void *name_token = nullptr) {
@@ -1139,6 +1200,7 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn(
return true;
}
}
+ llvm_unreachable("Fully covered switch!");
}
Status ScriptInterpreterPythonImpl::ExecuteMultipleLines(
@@ -1186,24 +1248,56 @@ void ScriptInterpreterPythonImpl::CollectDataForBreakpointCommandCallback(
CommandReturnObject &result) {
m_active_io_handler = eIOHandlerBreakpoint;
m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(
- " ", *this, true, &bp_options_vec);
+ " ", *this, &bp_options_vec);
}
void ScriptInterpreterPythonImpl::CollectDataForWatchpointCommandCallback(
WatchpointOptions *wp_options, CommandReturnObject &result) {
m_active_io_handler = eIOHandlerWatchpoint;
m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(
- " ", *this, true, wp_options);
+ " ", *this, wp_options);
}
-void ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction(
- BreakpointOptions *bp_options, const char *function_name) {
+Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction(
+ BreakpointOptions *bp_options, const char *function_name,
+ StructuredData::ObjectSP extra_args_sp) {
+ Status error;
// For now just cons up a oneliner that calls the provided function.
std::string oneliner("return ");
oneliner += function_name;
- oneliner += "(frame, bp_loc, internal_dict)";
- m_debugger.GetScriptInterpreter()->SetBreakpointCommandCallback(
- bp_options, oneliner.c_str());
+
+ llvm::Expected<unsigned> maybe_args =
+ GetMaxPositionalArgumentsForCallable(function_name);
+ if (!maybe_args) {
+ error.SetErrorStringWithFormat(
+ "could not get num args: %s",
+ llvm::toString(maybe_args.takeError()).c_str());
+ return error;
+ }
+ size_t max_args = *maybe_args;
+
+ bool uses_extra_args = false;
+ if (max_args >= 4) {
+ uses_extra_args = true;
+ oneliner += "(frame, bp_loc, extra_args, internal_dict)";
+ } else if (max_args >= 3) {
+ if (extra_args_sp) {
+ error.SetErrorString("cannot pass extra_args to a three argument callback"
+ );
+ return error;
+ }
+ uses_extra_args = false;
+ oneliner += "(frame, bp_loc, internal_dict)";
+ } else {
+ error.SetErrorStringWithFormat("expected 3 or 4 argument "
+ "function, %s can only take %zu",
+ function_name, max_args);
+ return error;
+ }
+
+ SetBreakpointCommandCallback(bp_options, oneliner.c_str(), extra_args_sp,
+ uses_extra_args);
+ return error;
}
Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
@@ -1211,7 +1305,8 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
std::unique_ptr<BreakpointOptions::CommandData> &cmd_data_up) {
Status error;
error = GenerateBreakpointCommandCallbackData(cmd_data_up->user_source,
- cmd_data_up->script_source);
+ cmd_data_up->script_source,
+ false);
if (error.Fail()) {
return error;
}
@@ -1222,11 +1317,17 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
return error;
}
-// Set a Python one-liner as the callback for the breakpoint.
Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
BreakpointOptions *bp_options, const char *command_body_text) {
- auto data_up = std::make_unique<CommandDataPython>();
+ return SetBreakpointCommandCallback(bp_options, command_body_text, {},false);
+}
+// Set a Python one-liner as the callback for the breakpoint.
+Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
+ BreakpointOptions *bp_options, const char *command_body_text,
+ StructuredData::ObjectSP extra_args_sp,
+ bool uses_extra_args) {
+ auto data_up = std::make_unique<CommandDataPython>(extra_args_sp);
// Split the command_body_text into lines, and pass that to
// GenerateBreakpointCommandCallbackData. That will wrap the body in an
// auto-generated function, and return the function name in script_source.
@@ -1234,7 +1335,8 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
data_up->user_source.SplitIntoLines(command_body_text);
Status error = GenerateBreakpointCommandCallbackData(data_up->user_source,
- data_up->script_source);
+ data_up->script_source,
+ uses_extra_args);
if (error.Success()) {
auto baton_sp =
std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up));
@@ -1771,8 +1873,7 @@ StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_CreateThread(
StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan(
const char *class_name, StructuredDataImpl *args_data,
- std::string &error_str,
- lldb::ThreadPlanSP thread_plan_sp) {
+ std::string &error_str, lldb::ThreadPlanSP thread_plan_sp) {
if (class_name == nullptr || class_name[0] == '\0')
return StructuredData::ObjectSP();
@@ -1956,8 +2057,7 @@ ScriptInterpreterPythonImpl::LoadPluginModule(const FileSpec &file_spec,
StructuredData::ObjectSP module_sp;
- if (LoadScriptingModule(file_spec.GetPath().c_str(), true, true, error,
- &module_sp))
+ if (LoadScriptingModule(file_spec.GetPath().c_str(), true, error, &module_sp))
return module_sp;
return StructuredData::ObjectSP();
@@ -2063,7 +2163,8 @@ bool ScriptInterpreterPythonImpl::GenerateTypeSynthClass(
}
Status ScriptInterpreterPythonImpl::GenerateBreakpointCommandCallbackData(
- StringList &user_input, std::string &output) {
+ StringList &user_input, std::string &output,
+ bool has_extra_args) {
static uint32_t num_created_functions = 0;
user_input.RemoveBlankLines();
StreamString sstr;
@@ -2075,8 +2176,12 @@ Status ScriptInterpreterPythonImpl::GenerateBreakpointCommandCallbackData(
std::string auto_generated_function_name(GenerateUniqueName(
"lldb_autogen_python_bp_callback_func_", num_created_functions));
- sstr.Printf("def %s (frame, bp_loc, internal_dict):",
- auto_generated_function_name.c_str());
+ if (has_extra_args)
+ sstr.Printf("def %s (frame, bp_loc, extra_args, internal_dict):",
+ auto_generated_function_name.c_str());
+ else
+ sstr.Printf("def %s (frame, bp_loc, internal_dict):",
+ auto_generated_function_name.c_str());
error = GenerateFunction(sstr.GetData(), user_input);
if (!error.Success())
@@ -2193,10 +2298,26 @@ bool ScriptInterpreterPythonImpl::BreakpointCallbackFunction(
Locker py_lock(python_interpreter, Locker::AcquireLock |
Locker::InitSession |
Locker::NoSTDIN);
- ret_val = LLDBSwigPythonBreakpointCallbackFunction(
- python_function_name,
- python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,
- bp_loc_sp);
+ Expected<bool> maybe_ret_val =
+ LLDBSwigPythonBreakpointCallbackFunction(
+ python_function_name,
+ python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,
+ bp_loc_sp, bp_option_data->m_extra_args_up.get());
+
+ if (!maybe_ret_val) {
+
+ llvm::handleAllErrors(
+ maybe_ret_val.takeError(),
+ [&](PythonException &E) {
+ debugger.GetErrorStream() << E.ReadBacktrace();
+ },
+ [&](const llvm::ErrorInfoBase &E) {
+ debugger.GetErrorStream() << E.message();
+ });
+
+ } else {
+ ret_val = maybe_ret_val.get();
+ }
}
return ret_val;
}
@@ -2615,8 +2736,8 @@ uint64_t replace_all(std::string &str, const std::string &oldStr,
}
bool ScriptInterpreterPythonImpl::LoadScriptingModule(
- const char *pathname, bool can_reload, bool init_session,
- lldb_private::Status &error, StructuredData::ObjectSP *module_sp) {
+ const char *pathname, bool init_session, lldb_private::Status &error,
+ StructuredData::ObjectSP *module_sp) {
if (!pathname || !pathname[0]) {
error.SetErrorString("invalid pathname");
return false;
@@ -2716,11 +2837,6 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule(
bool was_imported = (was_imported_globally || was_imported_locally);
- if (was_imported && !can_reload) {
- error.SetErrorString("module already imported");
- return false;
- }
-
// now actually do the import
command_stream.Clear();
@@ -3171,4 +3287,4 @@ void ScriptInterpreterPythonImpl::AddToSysPath(AddLocation location,
//
// void ScriptInterpreterPythonImpl::Terminate() { Py_Finalize (); }
-#endif // LLDB_DISABLE_PYTHON
+#endif
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
index 33ae308041b2..e59fedbd0971 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
@@ -9,14 +9,13 @@
#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H
-#ifdef LLDB_DISABLE_PYTHON
+#include "lldb/Host/Config.h"
-// Python is disabled in this build
-
-#else
+#if LLDB_ENABLE_PYTHON
#include "lldb/Breakpoint/BreakpointOptions.h"
#include "lldb/Core/IOHandler.h"
+#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/lldb-private.h"
@@ -34,6 +33,13 @@ public:
CommandDataPython() : BreakpointOptions::CommandData() {
interpreter = lldb::eScriptLanguagePython;
}
+ CommandDataPython(StructuredData::ObjectSP extra_args_sp) :
+ BreakpointOptions::CommandData(),
+ m_extra_args_up(new StructuredDataImpl()) {
+ interpreter = lldb::eScriptLanguagePython;
+ m_extra_args_up->SetObjectSP(extra_args_sp);
+ }
+ lldb::StructuredDataImplUP m_extra_args_up;
};
ScriptInterpreterPython(Debugger &debugger)
@@ -52,5 +58,5 @@ protected:
};
} // namespace lldb_private
-#endif // LLDB_DISABLE_PYTHON
+#endif // LLDB_ENABLE_PYTHON
#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
index 929567e579d8..1fa198b07e54 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
@@ -6,11 +6,9 @@
//
//===----------------------------------------------------------------------===//
-#ifdef LLDB_DISABLE_PYTHON
+#include "lldb/Host/Config.h"
-// Python is disabled in this build
-
-#else
+#if LLDB_ENABLE_PYTHON
#include "lldb-python.h"
@@ -179,8 +177,10 @@ public:
Status GenerateFunction(const char *signature,
const StringList &input) override;
- Status GenerateBreakpointCommandCallbackData(StringList &input,
- std::string &output) override;
+ Status GenerateBreakpointCommandCallbackData(
+ StringList &input,
+ std::string &output,
+ bool has_extra_args) override;
bool GenerateWatchpointCommandCallbackData(StringList &input,
std::string &output) override;
@@ -224,7 +224,7 @@ public:
std::string &output, Status &error) override;
bool
- LoadScriptingModule(const char *filename, bool can_reload, bool init_session,
+ LoadScriptingModule(const char *filename, bool init_session,
lldb_private::Status &error,
StructuredData::ObjectSP *module_sp = nullptr) override;
@@ -244,14 +244,21 @@ public:
Status SetBreakpointCommandCallback(BreakpointOptions *bp_options,
const char *callback_body) override;
- void SetBreakpointCommandCallbackFunction(BreakpointOptions *bp_options,
- const char *function_name) override;
+ Status SetBreakpointCommandCallbackFunction(
+ BreakpointOptions *bp_options,
+ const char *function_name,
+ StructuredData::ObjectSP extra_args_sp) override;
/// This one is for deserialization:
Status SetBreakpointCommandCallback(
BreakpointOptions *bp_options,
std::unique_ptr<BreakpointOptions::CommandData> &data_up) override;
+ Status SetBreakpointCommandCallback(BreakpointOptions *bp_options,
+ const char *command_body_text,
+ StructuredData::ObjectSP extra_args_sp,
+ bool uses_extra_args);
+
/// Set a one-liner as the callback for the watchpoint.
void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
const char *oneliner) override;
@@ -369,6 +376,9 @@ public:
python::PythonDictionary &GetSysModuleDictionary();
+ llvm::Expected<unsigned> GetMaxPositionalArgumentsForCallable(
+ const llvm::StringRef &callable_name) override;
+
bool GetEmbeddedInterpreterModuleObjects();
bool SetStdHandle(lldb::FileSP file, const char *py_name,
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h b/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h
index 884514da9924..48f27b09b95c 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h
@@ -9,12 +9,12 @@
#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H
+#include "lldb/Host/Config.h"
+
// Python.h needs to be included before any system headers in order to avoid
// redefinition of macros
-#ifdef LLDB_DISABLE_PYTHON
-// Python is disabled in this build
-#else
+#if LLDB_ENABLE_PYTHON
#include "llvm/Support/Compiler.h"
#if defined(_WIN32)
// If anyone #includes Host/PosixApi.h later, it will try to typedef pid_t. We
@@ -40,6 +40,6 @@
// Include python for non windows machines
#include <Python.h>
-#endif // LLDB_DISABLE_PYTHON
+#endif
#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H
diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
index f84cf0c5368d..b2c4d0883341 100644
--- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
+++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
@@ -25,6 +25,8 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::breakpad;
+char SymbolFileBreakpad::ID;
+
class SymbolFileBreakpad::LineIterator {
public:
// begin iterator for sections of given type
@@ -307,8 +309,9 @@ void SymbolFileBreakpad::FindTypes(
uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files,
TypeMap &types) {}
-void SymbolFileBreakpad::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
- LanguageSet languages, TypeMap &types) {}
+void SymbolFileBreakpad::FindTypes(
+ llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {}
void SymbolFileBreakpad::AddSymbols(Symtab &symtab) {
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS);
@@ -728,7 +731,7 @@ void SymbolFileBreakpad::ParseLineTableAndSupportFiles(CompileUnit &cu,
}
if (next_addr)
finish_sequence();
- data.support_files = map.translate(cu, *m_files);
+ data.support_files = map.translate(cu.GetPrimaryFile(), *m_files);
}
void SymbolFileBreakpad::ParseUnwindData() {
diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
index a10138cdf92f..de271224a65d 100644
--- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
+++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
@@ -21,7 +21,18 @@ namespace lldb_private {
namespace breakpad {
class SymbolFileBreakpad : public SymbolFile {
+ /// LLVM RTTI support.
+ static char ID;
+
public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFile::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
+
// Static Functions
static void Initialize();
static void Terminate();
@@ -112,6 +123,7 @@ public:
TypeMap &types) override;
void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files,
TypeMap &types) override;
llvm::Expected<TypeSystem &>
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 636e6032b877..232063a6f339 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -22,7 +22,7 @@
#include "lldb/Core/Value.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/ClangASTImporter.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/ClangASTMetadata.h"
#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
@@ -135,61 +135,111 @@ static bool IsClangModuleFwdDecl(const DWARFDIE &Die) {
return false;
}
-TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) {
- ModuleSP dwo_module_sp = die.GetContainingDWOModule();
- if (!dwo_module_sp)
+static DWARFDIE GetContainingClangModuleDIE(const DWARFDIE &die) {
+ if (die.IsValid()) {
+ DWARFDIE top_module_die;
+ // Now make sure this DIE is scoped in a DW_TAG_module tag and return true
+ // if so
+ for (DWARFDIE parent = die.GetParent(); parent.IsValid();
+ parent = parent.GetParent()) {
+ const dw_tag_t tag = parent.Tag();
+ if (tag == DW_TAG_module)
+ top_module_die = parent;
+ else if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
+ break;
+ }
+
+ return top_module_die;
+ }
+ return DWARFDIE();
+}
+
+static lldb::ModuleSP GetContainingClangModule(const DWARFDIE &die) {
+ if (die.IsValid()) {
+ DWARFDIE clang_module_die = GetContainingClangModuleDIE(die);
+
+ if (clang_module_die) {
+ const char *module_name = clang_module_die.GetName();
+ if (module_name)
+ return die.GetDWARF()->GetExternalModule(
+ lldb_private::ConstString(module_name));
+ }
+ }
+ return lldb::ModuleSP();
+}
+
+TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
+ const DWARFDIE &die,
+ Log *log) {
+ ModuleSP clang_module_sp = GetContainingClangModule(die);
+ if (!clang_module_sp)
return TypeSP();
- // If this type comes from a Clang module, look in the DWARF section
- // of the pcm file in the module cache. Clang generates DWO skeleton
- // units as breadcrumbs to find them.
+ // If this type comes from a Clang module, recursively look in the
+ // DWARF section of the .pcm file in the module cache. Clang
+ // generates DWO skeleton units as breadcrumbs to find them.
llvm::SmallVector<CompilerContext, 4> decl_context;
die.GetDeclContext(decl_context);
- TypeMap dwo_types;
+ TypeMap pcm_types;
// The type in the Clang module must have the same language as the current CU.
LanguageSet languages;
languages.Insert(die.GetCU()->GetLanguageType());
- dwo_module_sp->GetSymbolFile()->FindTypes(decl_context, languages, dwo_types);
- if (dwo_types.Empty()) {
- if (!IsClangModuleFwdDecl(die))
- return TypeSP();
-
+ llvm::DenseSet<SymbolFile *> searched_symbol_files;
+ clang_module_sp->GetSymbolFile()->FindTypes(decl_context, languages,
+ searched_symbol_files, pcm_types);
+ if (pcm_types.Empty()) {
// Since this type is defined in one of the Clang modules imported
- // by this symbol file, search all of them.
+ // by this symbol file, search all of them. Instead of calling
+ // sym_file->FindTypes(), which would return this again, go straight
+ // to the imported modules.
auto &sym_file = die.GetCU()->GetSymbolFileDWARF();
- for (const auto &name_module : sym_file.getExternalTypeModules()) {
- if (!name_module.second)
- continue;
- name_module.second->GetSymbolFile()->FindTypes(decl_context,
- languages, dwo_types);
- if (dwo_types.GetSize())
- break;
- }
+
+ // Well-formed clang modules never form cycles; guard against corrupted
+ // ones by inserting the current file.
+ searched_symbol_files.insert(&sym_file);
+ sym_file.ForEachExternalModule(
+ *sc.comp_unit, searched_symbol_files, [&](Module &module) {
+ module.GetSymbolFile()->FindTypes(decl_context, languages,
+ searched_symbol_files, pcm_types);
+ return pcm_types.GetSize();
+ });
}
- if (dwo_types.GetSize() != 1)
+ if (!pcm_types.GetSize())
return TypeSP();
// We found a real definition for this type in the Clang module, so lets use
// it and cache the fact that we found a complete type for this die.
- TypeSP dwo_type_sp = dwo_types.GetTypeAtIndex(0);
- if (!dwo_type_sp)
+ TypeSP pcm_type_sp = pcm_types.GetTypeAtIndex(0);
+ if (!pcm_type_sp)
return TypeSP();
- lldb_private::CompilerType dwo_type = dwo_type_sp->GetForwardCompilerType();
-
+ lldb_private::CompilerType pcm_type = pcm_type_sp->GetForwardCompilerType();
lldb_private::CompilerType type =
- GetClangASTImporter().CopyType(m_ast, dwo_type);
+ GetClangASTImporter().CopyType(m_ast, pcm_type);
if (!type)
return TypeSP();
+ // Under normal operation pcm_type is a shallow forward declaration
+ // that gets completed later. This is necessary to support cyclic
+ // data structures. If, however, pcm_type is already complete (for
+ // example, because it was loaded for a different target before),
+ // the definition needs to be imported right away, too.
+ // Type::ResolveClangType() effectively ignores the ResolveState
+ // inside type_sp and only looks at IsDefined(), so it never calls
+ // ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo(),
+ // which does extra work for Objective-C classes. This would result
+ // in only the forward declaration to be visible.
+ if (pcm_type.IsDefined())
+ GetClangASTImporter().RequireCompleteType(ClangUtil::GetQualType(type));
+
SymbolFileDWARF *dwarf = die.GetDWARF();
TypeSP type_sp(new Type(
- die.GetID(), dwarf, dwo_type_sp->GetName(), dwo_type_sp->GetByteSize(),
+ die.GetID(), dwarf, pcm_type_sp->GetName(), pcm_type_sp->GetByteSize(),
nullptr, LLDB_INVALID_UID, Type::eEncodingInvalid,
- &dwo_type_sp->GetDeclaration(), type, Type::eResolveStateForward));
+ &pcm_type_sp->GetDeclaration(), type, Type::ResolveState::Forward));
dwarf->GetTypeList().Insert(type_sp);
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
@@ -205,7 +255,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) {
return type_sp;
}
-static void CompleteExternalTagDeclType(ClangASTImporter &ast_importer,
+static void CompleteExternalTagDeclType(ClangASTContext &ast,
+ ClangASTImporter &ast_importer,
clang::DeclContext *decl_ctx,
DWARFDIE die,
const char *type_name_cstr) {
@@ -214,7 +265,7 @@ static void CompleteExternalTagDeclType(ClangASTImporter &ast_importer,
return;
// If this type was not imported from an external AST, there's nothing to do.
- CompilerType type = ClangASTContext::GetTypeForDecl(tag_decl_ctx);
+ CompilerType type = ast.GetTypeForDecl(tag_decl_ctx);
if (!type || !ast_importer.CanImport(type))
return;
@@ -340,6 +391,10 @@ ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) {
is_complete_objc_class = form_value.Signed();
break;
+ case DW_AT_APPLE_objc_direct:
+ is_objc_direct_call = true;
+ break;
+
case DW_AT_APPLE_runtime_class:
class_language = (LanguageType)form_value.Signed();
break;
@@ -347,6 +402,9 @@ ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) {
case DW_AT_GNU_vector:
is_vector = form_value.Boolean();
break;
+ case DW_AT_export_symbols:
+ exports_symbols = form_value.Boolean();
+ break;
}
}
}
@@ -377,13 +435,12 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
dwarf->GetObjectFile()->GetModule()->LogMessage(
log,
- "SymbolFileDWARF::ParseType (die = 0x%8.8x, decl_ctx = %p (die "
- "0x%8.8x)) %s name = '%s')",
+ "DWARFASTParserClang::ParseTypeFromDWARF "
+ "(die = 0x%8.8x, decl_ctx = %p (die 0x%8.8x)) %s name = '%s')",
die.GetOffset(), static_cast<void *>(context), context_die.GetOffset(),
die.GetTagAsCString(), die.GetName());
}
-
Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE());
if (type_ptr == DIE_IS_BEING_PARSED)
return nullptr;
@@ -411,13 +468,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
const dw_tag_t tag = die.Tag();
- Type::ResolveState resolve_state = Type::eResolveStateUnresolved;
-
- Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
- CompilerType clang_type;
-
TypeSP type_sp;
- LanguageType cu_language = die.GetLanguage();
+
switch (tag) {
case DW_TAG_typedef:
case DW_TAG_base_type:
@@ -427,848 +479,895 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
case DW_TAG_const_type:
case DW_TAG_restrict_type:
case DW_TAG_volatile_type:
+ case DW_TAG_atomic_type:
case DW_TAG_unspecified_type: {
- if (tag == DW_TAG_typedef && attrs.type.IsValid()) {
- // Try to parse a typedef from the DWO file first as modules can
- // contain typedef'ed structures that have no names like:
- //
- // typedef struct { int a; } Foo;
- //
- // In this case we will have a structure with no name and a typedef
- // named "Foo" that points to this unnamed structure. The name in the
- // typedef is the only identifier for the struct, so always try to
- // get typedefs from DWO files if possible.
- //
- // The type_sp returned will be empty if the typedef doesn't exist in
- // a DWO file, so it is cheap to call this function just to check.
- //
- // If we don't do this we end up creating a TypeSP that says this is
- // a typedef to type 0x123 (the DW_AT_type value would be 0x123 in
- // the DW_TAG_typedef), and this is the unnamed structure type. We
- // will have a hard time tracking down an unnammed structure type in
- // the module DWO file, so we make sure we don't get into this
- // situation by always resolving typedefs from the DWO file.
- const DWARFDIE encoding_die = attrs.type.Reference();
-
- // First make sure that the die that this is typedef'ed to _is_ just
- // a declaration (DW_AT_declaration == 1), not a full definition
- // since template types can't be represented in modules since only
- // concrete instances of templates are ever emitted and modules won't
- // contain those
- if (encoding_die &&
- encoding_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) {
- type_sp = ParseTypeFromDWO(die, log);
- if (type_sp)
- return type_sp;
- }
- }
+ type_sp = ParseTypeModifier(sc, die, attrs);
+ break;
+ }
- DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n",
- die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr,
- encoding_uid.Reference());
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_class_type: {
+ type_sp = ParseStructureLikeDIE(sc, die, attrs);
+ break;
+ }
- switch (tag) {
- default:
- break;
+ case DW_TAG_enumeration_type: {
+ type_sp = ParseEnum(sc, die, attrs);
+ break;
+ }
- case DW_TAG_unspecified_type:
- if (attrs.name == "nullptr_t" || attrs.name == "decltype(nullptr)") {
- resolve_state = Type::eResolveStateFull;
- clang_type = m_ast.GetBasicType(eBasicTypeNullPtr);
- break;
- }
- // Fall through to base type below in case we can handle the type
- // there...
- LLVM_FALLTHROUGH;
-
- case DW_TAG_base_type:
- resolve_state = Type::eResolveStateFull;
- clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(
- attrs.name.GetCString(), attrs.encoding,
- attrs.byte_size.getValueOr(0) * 8);
- break;
+ case DW_TAG_inlined_subroutine:
+ case DW_TAG_subprogram:
+ case DW_TAG_subroutine_type: {
+ type_sp = ParseSubroutine(die, attrs);
+ break;
+ }
+ case DW_TAG_array_type: {
+ type_sp = ParseArrayType(die, attrs);
+ break;
+ }
+ case DW_TAG_ptr_to_member_type: {
+ type_sp = ParsePointerToMemberType(die, attrs);
+ break;
+ }
+ default:
+ dwarf->GetObjectFile()->GetModule()->ReportError(
+ "{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and "
+ "attach the file at the start of this error message",
+ die.GetOffset(), tag, DW_TAG_value_to_name(tag));
+ break;
+ }
- case DW_TAG_pointer_type:
- encoding_data_type = Type::eEncodingIsPointerUID;
- break;
- case DW_TAG_reference_type:
- encoding_data_type = Type::eEncodingIsLValueReferenceUID;
- break;
- case DW_TAG_rvalue_reference_type:
- encoding_data_type = Type::eEncodingIsRValueReferenceUID;
- break;
- case DW_TAG_typedef:
- encoding_data_type = Type::eEncodingIsTypedefUID;
- break;
- case DW_TAG_const_type:
- encoding_data_type = Type::eEncodingIsConstUID;
- break;
- case DW_TAG_restrict_type:
- encoding_data_type = Type::eEncodingIsRestrictUID;
- break;
- case DW_TAG_volatile_type:
- encoding_data_type = Type::eEncodingIsVolatileUID;
+ // TODO: We should consider making the switch above exhaustive to simplify
+ // control flow in ParseTypeFromDWARF. Then, we could simply replace this
+ // return statement with a call to llvm_unreachable.
+ return UpdateSymbolContextScopeForType(sc, die, type_sp);
+}
+
+lldb::TypeSP
+DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
+ const DWARFDIE &die,
+ ParsedDWARFTypeAttributes &attrs) {
+ Log *log(LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION |
+ DWARF_LOG_LOOKUPS));
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ const dw_tag_t tag = die.Tag();
+ LanguageType cu_language = die.GetLanguage();
+ Type::ResolveState resolve_state = Type::ResolveState::Unresolved;
+ Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
+ TypeSP type_sp;
+ CompilerType clang_type;
+
+ if (tag == DW_TAG_typedef && attrs.type.IsValid()) {
+ // Try to parse a typedef from the (DWARF embedded in the) Clang
+ // module file first as modules can contain typedef'ed
+ // structures that have no names like:
+ //
+ // typedef struct { int a; } Foo;
+ //
+ // In this case we will have a structure with no name and a
+ // typedef named "Foo" that points to this unnamed
+ // structure. The name in the typedef is the only identifier for
+ // the struct, so always try to get typedefs from Clang modules
+ // if possible.
+ //
+ // The type_sp returned will be empty if the typedef doesn't
+ // exist in a module file, so it is cheap to call this function
+ // just to check.
+ //
+ // If we don't do this we end up creating a TypeSP that says
+ // this is a typedef to type 0x123 (the DW_AT_type value would
+ // be 0x123 in the DW_TAG_typedef), and this is the unnamed
+ // structure type. We will have a hard time tracking down an
+ // unnammed structure type in the module debug info, so we make
+ // sure we don't get into this situation by always resolving
+ // typedefs from the module.
+ const DWARFDIE encoding_die = attrs.type.Reference();
+
+ // First make sure that the die that this is typedef'ed to _is_
+ // just a declaration (DW_AT_declaration == 1), not a full
+ // definition since template types can't be represented in
+ // modules since only concrete instances of templates are ever
+ // emitted and modules won't contain those
+ if (encoding_die &&
+ encoding_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) {
+ type_sp = ParseTypeFromClangModule(sc, die, log);
+ if (type_sp)
+ return type_sp;
+ }
+ }
+
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", die.GetID(),
+ DW_TAG_value_to_name(tag), type_name_cstr,
+ encoding_uid.Reference());
+
+ switch (tag) {
+ default:
+ break;
+
+ case DW_TAG_unspecified_type:
+ if (attrs.name == "nullptr_t" || attrs.name == "decltype(nullptr)") {
+ resolve_state = Type::ResolveState::Full;
+ clang_type = m_ast.GetBasicType(eBasicTypeNullPtr);
break;
}
+ // Fall through to base type below in case we can handle the type
+ // there...
+ LLVM_FALLTHROUGH;
- if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID ||
- encoding_data_type == Type::eEncodingIsTypedefUID)) {
- if (tag == DW_TAG_pointer_type) {
- DWARFDIE target_die = die.GetReferencedDIE(DW_AT_type);
-
- if (target_die.GetAttributeValueAsUnsigned(DW_AT_APPLE_block, 0)) {
- // Blocks have a __FuncPtr inside them which is a pointer to a
- // function of the proper type.
-
- for (DWARFDIE child_die = target_die.GetFirstChild();
- child_die.IsValid(); child_die = child_die.GetSibling()) {
- if (!strcmp(child_die.GetAttributeValueAsString(DW_AT_name, ""),
- "__FuncPtr")) {
- DWARFDIE function_pointer_type =
- child_die.GetReferencedDIE(DW_AT_type);
-
- if (function_pointer_type) {
- DWARFDIE function_type =
- function_pointer_type.GetReferencedDIE(DW_AT_type);
-
- bool function_type_is_new_pointer;
- TypeSP lldb_function_type_sp = ParseTypeFromDWARF(
- sc, function_type, &function_type_is_new_pointer);
-
- if (lldb_function_type_sp) {
- clang_type = m_ast.CreateBlockPointerType(
- lldb_function_type_sp->GetForwardCompilerType());
- encoding_data_type = Type::eEncodingIsUID;
- attrs.type.Clear();
- resolve_state = Type::eResolveStateFull;
- }
- }
+ case DW_TAG_base_type:
+ resolve_state = Type::ResolveState::Full;
+ clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(
+ attrs.name.GetStringRef(), attrs.encoding,
+ attrs.byte_size.getValueOr(0) * 8);
+ break;
- break;
+ case DW_TAG_pointer_type:
+ encoding_data_type = Type::eEncodingIsPointerUID;
+ break;
+ case DW_TAG_reference_type:
+ encoding_data_type = Type::eEncodingIsLValueReferenceUID;
+ break;
+ case DW_TAG_rvalue_reference_type:
+ encoding_data_type = Type::eEncodingIsRValueReferenceUID;
+ break;
+ case DW_TAG_typedef:
+ encoding_data_type = Type::eEncodingIsTypedefUID;
+ break;
+ case DW_TAG_const_type:
+ encoding_data_type = Type::eEncodingIsConstUID;
+ break;
+ case DW_TAG_restrict_type:
+ encoding_data_type = Type::eEncodingIsRestrictUID;
+ break;
+ case DW_TAG_volatile_type:
+ encoding_data_type = Type::eEncodingIsVolatileUID;
+ break;
+ case DW_TAG_atomic_type:
+ encoding_data_type = Type::eEncodingIsAtomicUID;
+ break;
+ }
+
+ if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID ||
+ encoding_data_type == Type::eEncodingIsTypedefUID)) {
+ if (tag == DW_TAG_pointer_type) {
+ DWARFDIE target_die = die.GetReferencedDIE(DW_AT_type);
+
+ if (target_die.GetAttributeValueAsUnsigned(DW_AT_APPLE_block, 0)) {
+ // Blocks have a __FuncPtr inside them which is a pointer to a
+ // function of the proper type.
+
+ for (DWARFDIE child_die = target_die.GetFirstChild();
+ child_die.IsValid(); child_die = child_die.GetSibling()) {
+ if (!strcmp(child_die.GetAttributeValueAsString(DW_AT_name, ""),
+ "__FuncPtr")) {
+ DWARFDIE function_pointer_type =
+ child_die.GetReferencedDIE(DW_AT_type);
+
+ if (function_pointer_type) {
+ DWARFDIE function_type =
+ function_pointer_type.GetReferencedDIE(DW_AT_type);
+
+ bool function_type_is_new_pointer;
+ TypeSP lldb_function_type_sp = ParseTypeFromDWARF(
+ sc, function_type, &function_type_is_new_pointer);
+
+ if (lldb_function_type_sp) {
+ clang_type = m_ast.CreateBlockPointerType(
+ lldb_function_type_sp->GetForwardCompilerType());
+ encoding_data_type = Type::eEncodingIsUID;
+ attrs.type.Clear();
+ resolve_state = Type::ResolveState::Full;
+ }
}
+
+ break;
}
}
}
+ }
- if (cu_language == eLanguageTypeObjC ||
- cu_language == eLanguageTypeObjC_plus_plus) {
- if (attrs.name) {
- static ConstString g_objc_type_name_id("id");
- static ConstString g_objc_type_name_Class("Class");
- static ConstString g_objc_type_name_selector("SEL");
+ if (cu_language == eLanguageTypeObjC ||
+ cu_language == eLanguageTypeObjC_plus_plus) {
+ if (attrs.name) {
+ if (attrs.name == "id") {
+ if (log)
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
+ "is Objective-C 'id' built-in type.",
+ die.GetOffset(), die.GetTagAsCString(), die.GetName());
+ clang_type = m_ast.GetBasicType(eBasicTypeObjCID);
+ encoding_data_type = Type::eEncodingIsUID;
+ attrs.type.Clear();
+ resolve_state = Type::ResolveState::Full;
+ } else if (attrs.name == "Class") {
+ if (log)
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
+ "is Objective-C 'Class' built-in type.",
+ die.GetOffset(), die.GetTagAsCString(), die.GetName());
+ clang_type = m_ast.GetBasicType(eBasicTypeObjCClass);
+ encoding_data_type = Type::eEncodingIsUID;
+ attrs.type.Clear();
+ resolve_state = Type::ResolveState::Full;
+ } else if (attrs.name == "SEL") {
+ if (log)
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
+ "is Objective-C 'selector' built-in type.",
+ die.GetOffset(), die.GetTagAsCString(), die.GetName());
+ clang_type = m_ast.GetBasicType(eBasicTypeObjCSel);
+ encoding_data_type = Type::eEncodingIsUID;
+ attrs.type.Clear();
+ resolve_state = Type::ResolveState::Full;
+ }
+ } else if (encoding_data_type == Type::eEncodingIsPointerUID &&
+ attrs.type.IsValid()) {
+ // Clang sometimes erroneously emits id as objc_object*. In that
+ // case we fix up the type to "id".
- if (attrs.name == g_objc_type_name_id) {
- if (log)
- dwarf->GetObjectFile()->GetModule()->LogMessage(
- log,
- "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
- "is Objective-C 'id' built-in type.",
- die.GetOffset(), die.GetTagAsCString(), die.GetName());
- clang_type = m_ast.GetBasicType(eBasicTypeObjCID);
- encoding_data_type = Type::eEncodingIsUID;
- attrs.type.Clear();
- resolve_state = Type::eResolveStateFull;
+ const DWARFDIE encoding_die = attrs.type.Reference();
- } else if (attrs.name == g_objc_type_name_Class) {
+ if (encoding_die && encoding_die.Tag() == DW_TAG_structure_type) {
+ llvm::StringRef struct_name = encoding_die.GetName();
+ if (struct_name == "objc_object") {
if (log)
dwarf->GetObjectFile()->GetModule()->LogMessage(
log,
- "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
- "is Objective-C 'Class' built-in type.",
+ "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s "
+ "'%s' is 'objc_object*', which we overrode to "
+ "'id'.",
die.GetOffset(), die.GetTagAsCString(), die.GetName());
- clang_type = m_ast.GetBasicType(eBasicTypeObjCClass);
- encoding_data_type = Type::eEncodingIsUID;
- attrs.type.Clear();
- resolve_state = Type::eResolveStateFull;
- } else if (attrs.name == g_objc_type_name_selector) {
- if (log)
- dwarf->GetObjectFile()->GetModule()->LogMessage(
- log,
- "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
- "is Objective-C 'selector' built-in type.",
- die.GetOffset(), die.GetTagAsCString(), die.GetName());
- clang_type = m_ast.GetBasicType(eBasicTypeObjCSel);
+ clang_type = m_ast.GetBasicType(eBasicTypeObjCID);
encoding_data_type = Type::eEncodingIsUID;
attrs.type.Clear();
- resolve_state = Type::eResolveStateFull;
- }
- } else if (encoding_data_type == Type::eEncodingIsPointerUID &&
- attrs.type.IsValid()) {
- // Clang sometimes erroneously emits id as objc_object*. In that
- // case we fix up the type to "id".
-
- const DWARFDIE encoding_die = attrs.type.Reference();
-
- if (encoding_die && encoding_die.Tag() == DW_TAG_structure_type) {
- if (const char *struct_name = encoding_die.GetName()) {
- if (!strcmp(struct_name, "objc_object")) {
- if (log)
- dwarf->GetObjectFile()->GetModule()->LogMessage(
- log,
- "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s "
- "'%s' is 'objc_object*', which we overrode to "
- "'id'.",
- die.GetOffset(), die.GetTagAsCString(), die.GetName());
- clang_type = m_ast.GetBasicType(eBasicTypeObjCID);
- encoding_data_type = Type::eEncodingIsUID;
- attrs.type.Clear();
- resolve_state = Type::eResolveStateFull;
- }
- }
+ resolve_state = Type::ResolveState::Full;
}
}
}
}
-
- type_sp = std::make_shared<Type>(
- die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr,
- dwarf->GetUID(attrs.type.Reference()), encoding_data_type, &attrs.decl,
- clang_type, resolve_state);
-
- dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
- } break;
-
- case DW_TAG_structure_type:
- case DW_TAG_union_type:
- case DW_TAG_class_type: {
- assert((!type_sp && !clang_type) &&
- "Did not expect partially computed structure-like type");
- TypeSP struct_like_type_sp = ParseStructureLikeDIE(die, attrs);
- return UpdateSymbolContextScopeForType(sc, die, struct_like_type_sp);
}
- case DW_TAG_enumeration_type: {
- if (attrs.is_forward_declaration) {
- type_sp = ParseTypeFromDWO(die, log);
- if (type_sp)
- return type_sp;
+ type_sp = std::make_shared<Type>(
+ die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr,
+ dwarf->GetUID(attrs.type.Reference()), encoding_data_type, &attrs.decl,
+ clang_type, resolve_state);
- DWARFDeclContext die_decl_ctx;
- die.GetDWARFDeclContext(die_decl_ctx);
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+ return type_sp;
+}
- type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx);
+TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc,
+ const DWARFDIE &die,
+ ParsedDWARFTypeAttributes &attrs) {
+ Log *log(LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION |
+ DWARF_LOG_LOOKUPS));
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ const dw_tag_t tag = die.Tag();
+ TypeSP type_sp;
- if (!type_sp) {
- SymbolFileDWARFDebugMap *debug_map_symfile =
- dwarf->GetDebugMapSymfile();
- if (debug_map_symfile) {
- // We weren't able to find a full declaration in this DWARF,
- // see if we have a declaration anywhere else...
- type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(
- die_decl_ctx);
- }
- }
+ if (attrs.is_forward_declaration) {
+ type_sp = ParseTypeFromClangModule(sc, die, log);
+ if (type_sp)
+ return type_sp;
- if (type_sp) {
- if (log) {
- dwarf->GetObjectFile()->GetModule()->LogMessage(
- log,
- "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a "
- "forward declaration, complete type is 0x%8.8" PRIx64,
- static_cast<void *>(this), die.GetOffset(),
- DW_TAG_value_to_name(tag), attrs.name.GetCString(),
- type_sp->GetID());
- }
+ DWARFDeclContext die_decl_ctx;
+ die.GetDWARFDeclContext(die_decl_ctx);
- // We found a real definition for this type elsewhere so lets use
- // it and cache the fact that we found a complete type for this
- // die
- dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
- clang::DeclContext *defn_decl_ctx =
- GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID()));
- if (defn_decl_ctx)
- LinkDeclContextToDIE(defn_decl_ctx, die);
- return type_sp;
+ type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx);
+
+ if (!type_sp) {
+ SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile();
+ if (debug_map_symfile) {
+ // We weren't able to find a full declaration in this DWARF,
+ // see if we have a declaration anywhere else...
+ type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(
+ die_decl_ctx);
}
}
- DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
- DW_TAG_value_to_name(tag), type_name_cstr);
-
- CompilerType enumerator_clang_type;
- clang_type.SetCompilerType(
- &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE()));
- if (!clang_type) {
- if (attrs.type.IsValid()) {
- Type *enumerator_type =
- dwarf->ResolveTypeUID(attrs.type.Reference(), true);
- if (enumerator_type)
- enumerator_clang_type = enumerator_type->GetFullCompilerType();
- }
- if (!enumerator_clang_type) {
- if (attrs.byte_size) {
- enumerator_clang_type =
- m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(
- NULL, DW_ATE_signed, *attrs.byte_size * 8);
- } else {
- enumerator_clang_type = m_ast.GetBasicType(eBasicTypeInt);
- }
+ if (type_sp) {
+ if (log) {
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a "
+ "forward declaration, complete type is 0x%8.8" PRIx64,
+ static_cast<void *>(this), die.GetOffset(),
+ DW_TAG_value_to_name(tag), attrs.name.GetCString(),
+ type_sp->GetID());
}
- clang_type = m_ast.CreateEnumerationType(
- attrs.name.GetCString(),
- GetClangDeclContextContainingDIE(die, nullptr), attrs.decl,
- enumerator_clang_type, attrs.is_scoped_enum);
- } else {
- enumerator_clang_type =
- m_ast.GetEnumerationIntegerType(clang_type.GetOpaqueQualType());
+ // We found a real definition for this type elsewhere so lets use
+ // it and cache the fact that we found a complete type for this
+ // die
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+ clang::DeclContext *defn_decl_ctx =
+ GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID()));
+ if (defn_decl_ctx)
+ LinkDeclContextToDIE(defn_decl_ctx, die);
+ return type_sp;
}
+ }
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
+ DW_TAG_value_to_name(tag), type_name_cstr);
- LinkDeclContextToDIE(ClangASTContext::GetDeclContextForType(clang_type),
- die);
-
- type_sp = std::make_shared<Type>(
- die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr,
- dwarf->GetUID(attrs.type.Reference()), Type::eEncodingIsUID,
- &attrs.decl, clang_type, Type::eResolveStateForward);
+ CompilerType enumerator_clang_type;
+ CompilerType clang_type;
+ clang_type.SetCompilerType(
+ &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE()));
+ if (!clang_type) {
+ if (attrs.type.IsValid()) {
+ Type *enumerator_type =
+ dwarf->ResolveTypeUID(attrs.type.Reference(), true);
+ if (enumerator_type)
+ enumerator_clang_type = enumerator_type->GetFullCompilerType();
+ }
- if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) {
- if (die.HasChildren()) {
- bool is_signed = false;
- enumerator_clang_type.IsIntegerType(is_signed);
- ParseChildEnumerators(clang_type, is_signed,
- type_sp->GetByteSize().getValueOr(0), die);
+ if (!enumerator_clang_type) {
+ if (attrs.byte_size) {
+ enumerator_clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(
+ "", DW_ATE_signed, *attrs.byte_size * 8);
+ } else {
+ enumerator_clang_type = m_ast.GetBasicType(eBasicTypeInt);
}
- ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
- } else {
- dwarf->GetObjectFile()->GetModule()->ReportError(
- "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its "
- "definition.\nPlease file a bug and attach the file at the "
- "start of this error message",
- die.GetOffset(), attrs.name.GetCString());
}
- } break;
- case DW_TAG_inlined_subroutine:
- case DW_TAG_subprogram:
- case DW_TAG_subroutine_type: {
- bool is_variadic = false;
- bool is_static = false;
- bool has_template_params = false;
+ clang_type = m_ast.CreateEnumerationType(
+ attrs.name.GetCString(), GetClangDeclContextContainingDIE(die, nullptr),
+ attrs.decl, enumerator_clang_type, attrs.is_scoped_enum);
+ } else {
+ enumerator_clang_type =
+ m_ast.GetEnumerationIntegerType(clang_type.GetOpaqueQualType());
+ }
- unsigned type_quals = 0;
+ LinkDeclContextToDIE(ClangASTContext::GetDeclContextForType(clang_type), die);
- std::string object_pointer_name;
- if (attrs.object_pointer) {
- const char *object_pointer_name_cstr = attrs.object_pointer.GetName();
- if (object_pointer_name_cstr)
- object_pointer_name = object_pointer_name_cstr;
- }
+ type_sp = std::make_shared<Type>(
+ die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr,
+ dwarf->GetUID(attrs.type.Reference()), Type::eEncodingIsUID, &attrs.decl,
+ clang_type, Type::ResolveState::Forward);
- DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
- DW_TAG_value_to_name(tag), type_name_cstr);
+ if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) {
+ if (die.HasChildren()) {
+ bool is_signed = false;
+ enumerator_clang_type.IsIntegerType(is_signed);
+ ParseChildEnumerators(clang_type, is_signed,
+ type_sp->GetByteSize().getValueOr(0), die);
+ }
+ ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
+ } else {
+ dwarf->GetObjectFile()->GetModule()->ReportError(
+ "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its "
+ "definition.\nPlease file a bug and attach the file at the "
+ "start of this error message",
+ die.GetOffset(), attrs.name.GetCString());
+ }
+ return type_sp;
+}
- CompilerType return_clang_type;
- Type *func_type = NULL;
+TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
+ ParsedDWARFTypeAttributes &attrs) {
+ Log *log(LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION |
+ DWARF_LOG_LOOKUPS));
- if (attrs.type.IsValid())
- func_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true);
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ const dw_tag_t tag = die.Tag();
- if (func_type)
- return_clang_type = func_type->GetForwardCompilerType();
- else
- return_clang_type = m_ast.GetBasicType(eBasicTypeVoid);
+ bool is_variadic = false;
+ bool is_static = false;
+ bool has_template_params = false;
- std::vector<CompilerType> function_param_types;
- std::vector<clang::ParmVarDecl *> function_param_decls;
+ unsigned type_quals = 0;
- // Parse the function children for the parameters
+ std::string object_pointer_name;
+ if (attrs.object_pointer) {
+ const char *object_pointer_name_cstr = attrs.object_pointer.GetName();
+ if (object_pointer_name_cstr)
+ object_pointer_name = object_pointer_name_cstr;
+ }
- DWARFDIE decl_ctx_die;
- clang::DeclContext *containing_decl_ctx =
- GetClangDeclContextContainingDIE(die, &decl_ctx_die);
- const clang::Decl::Kind containing_decl_kind =
- containing_decl_ctx->getDeclKind();
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
+ DW_TAG_value_to_name(tag), type_name_cstr);
- bool is_cxx_method = DeclKindIsCXXClass(containing_decl_kind);
- // Start off static. This will be set to false in
- // ParseChildParameters(...) if we find a "this" parameters as the
- // first parameter
- if (is_cxx_method) {
- is_static = true;
- }
+ CompilerType return_clang_type;
+ Type *func_type = NULL;
+
+ if (attrs.type.IsValid())
+ func_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true);
+
+ if (func_type)
+ return_clang_type = func_type->GetForwardCompilerType();
+ else
+ return_clang_type = m_ast.GetBasicType(eBasicTypeVoid);
+
+ std::vector<CompilerType> function_param_types;
+ std::vector<clang::ParmVarDecl *> function_param_decls;
+
+ // Parse the function children for the parameters
+
+ DWARFDIE decl_ctx_die;
+ clang::DeclContext *containing_decl_ctx =
+ GetClangDeclContextContainingDIE(die, &decl_ctx_die);
+ const clang::Decl::Kind containing_decl_kind =
+ containing_decl_ctx->getDeclKind();
+
+ bool is_cxx_method = DeclKindIsCXXClass(containing_decl_kind);
+ // Start off static. This will be set to false in
+ // ParseChildParameters(...) if we find a "this" parameters as the
+ // first parameter
+ if (is_cxx_method) {
+ is_static = true;
+ }
+
+ if (die.HasChildren()) {
+ bool skip_artificial = true;
+ ParseChildParameters(containing_decl_ctx, die, skip_artificial, is_static,
+ is_variadic, has_template_params,
+ function_param_types, function_param_decls,
+ type_quals);
+ }
+
+ bool ignore_containing_context = false;
+ // Check for templatized class member functions. If we had any
+ // DW_TAG_template_type_parameter or DW_TAG_template_value_parameter
+ // the DW_TAG_subprogram DIE, then we can't let this become a method in
+ // a class. Why? Because templatized functions are only emitted if one
+ // of the templatized methods is used in the current compile unit and
+ // we will end up with classes that may or may not include these member
+ // functions and this means one class won't match another class
+ // definition and it affects our ability to use a class in the clang
+ // expression parser. So for the greater good, we currently must not
+ // allow any template member functions in a class definition.
+ if (is_cxx_method && has_template_params) {
+ ignore_containing_context = true;
+ is_cxx_method = false;
+ }
+
+ // clang_type will get the function prototype clang type after this
+ // call
+ CompilerType clang_type = m_ast.CreateFunctionType(
+ return_clang_type, function_param_types.data(),
+ function_param_types.size(), is_variadic, type_quals);
- if (die.HasChildren()) {
- bool skip_artificial = true;
- ParseChildParameters(containing_decl_ctx, die, skip_artificial, is_static,
- is_variadic, has_template_params,
- function_param_types, function_param_decls,
- type_quals);
- }
-
- bool ignore_containing_context = false;
- // Check for templatized class member functions. If we had any
- // DW_TAG_template_type_parameter or DW_TAG_template_value_parameter
- // the DW_TAG_subprogram DIE, then we can't let this become a method in
- // a class. Why? Because templatized functions are only emitted if one
- // of the templatized methods is used in the current compile unit and
- // we will end up with classes that may or may not include these member
- // functions and this means one class won't match another class
- // definition and it affects our ability to use a class in the clang
- // expression parser. So for the greater good, we currently must not
- // allow any template member functions in a class definition.
- if (is_cxx_method && has_template_params) {
- ignore_containing_context = true;
- is_cxx_method = false;
- }
-
- // clang_type will get the function prototype clang type after this
- // call
- clang_type = m_ast.CreateFunctionType(
- return_clang_type, function_param_types.data(),
- function_param_types.size(), is_variadic, type_quals);
-
- if (attrs.name) {
- bool type_handled = false;
- if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) {
- ObjCLanguage::MethodName objc_method(attrs.name.GetStringRef(), true);
- if (objc_method.IsValid(true)) {
- CompilerType class_opaque_type;
- ConstString class_name(objc_method.GetClassName());
- if (class_name) {
- TypeSP complete_objc_class_type_sp(
- dwarf->FindCompleteObjCDefinitionTypeForDIE(DWARFDIE(),
- class_name, false));
-
- if (complete_objc_class_type_sp) {
- CompilerType type_clang_forward_type =
- complete_objc_class_type_sp->GetForwardCompilerType();
- if (ClangASTContext::IsObjCObjectOrInterfaceType(
- type_clang_forward_type))
- class_opaque_type = type_clang_forward_type;
- }
+ if (attrs.name) {
+ bool type_handled = false;
+ if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) {
+ ObjCLanguage::MethodName objc_method(attrs.name.GetStringRef(), true);
+ if (objc_method.IsValid(true)) {
+ CompilerType class_opaque_type;
+ ConstString class_name(objc_method.GetClassName());
+ if (class_name) {
+ TypeSP complete_objc_class_type_sp(
+ dwarf->FindCompleteObjCDefinitionTypeForDIE(DWARFDIE(),
+ class_name, false));
+
+ if (complete_objc_class_type_sp) {
+ CompilerType type_clang_forward_type =
+ complete_objc_class_type_sp->GetForwardCompilerType();
+ if (ClangASTContext::IsObjCObjectOrInterfaceType(
+ type_clang_forward_type))
+ class_opaque_type = type_clang_forward_type;
}
+ }
- if (class_opaque_type) {
- // If accessibility isn't set to anything valid, assume public
- // for now...
- if (attrs.accessibility == eAccessNone)
- attrs.accessibility = eAccessPublic;
-
- clang::ObjCMethodDecl *objc_method_decl =
- m_ast.AddMethodToObjCObjectType(
- class_opaque_type, attrs.name.GetCString(), clang_type,
- attrs.accessibility, attrs.is_artificial, is_variadic);
- type_handled = objc_method_decl != NULL;
- if (type_handled) {
- LinkDeclContextToDIE(
- ClangASTContext::GetAsDeclContext(objc_method_decl), die);
- m_ast.SetMetadataAsUserID(objc_method_decl, die.GetID());
- } else {
- dwarf->GetObjectFile()->GetModule()->ReportError(
- "{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), "
- "please file a bug and attach the file at the start of "
- "this error message",
- die.GetOffset(), tag, DW_TAG_value_to_name(tag));
- }
+ if (class_opaque_type) {
+ // If accessibility isn't set to anything valid, assume public
+ // for now...
+ if (attrs.accessibility == eAccessNone)
+ attrs.accessibility = eAccessPublic;
+
+ clang::ObjCMethodDecl *objc_method_decl =
+ m_ast.AddMethodToObjCObjectType(
+ class_opaque_type, attrs.name.GetCString(), clang_type,
+ attrs.accessibility, attrs.is_artificial, is_variadic,
+ attrs.is_objc_direct_call);
+ type_handled = objc_method_decl != NULL;
+ if (type_handled) {
+ LinkDeclContextToDIE(objc_method_decl, die);
+ m_ast.SetMetadataAsUserID(objc_method_decl, die.GetID());
+ } else {
+ dwarf->GetObjectFile()->GetModule()->ReportError(
+ "{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), "
+ "please file a bug and attach the file at the start of "
+ "this error message",
+ die.GetOffset(), tag, DW_TAG_value_to_name(tag));
}
- } else if (is_cxx_method) {
- // Look at the parent of this DIE and see if is is a class or
- // struct and see if this is actually a C++ method
- Type *class_type = dwarf->ResolveType(decl_ctx_die);
- if (class_type) {
- bool alternate_defn = false;
- if (class_type->GetID() != decl_ctx_die.GetID() ||
- decl_ctx_die.GetContainingDWOModuleDIE()) {
- alternate_defn = true;
-
- // We uniqued the parent class of this function to another
- // class so we now need to associate all dies under
- // "decl_ctx_die" to DIEs in the DIE for "class_type"...
- DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID());
-
- if (class_type_die) {
- std::vector<DWARFDIE> failures;
-
- CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die,
- class_type, failures);
-
- // FIXME do something with these failures that's smarter
- // than
- // just dropping them on the ground. Unfortunately classes
- // don't like having stuff added to them after their
- // definitions are complete...
-
- type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
- if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) {
- type_sp = type_ptr->shared_from_this();
- break;
- }
+ }
+ } else if (is_cxx_method) {
+ // Look at the parent of this DIE and see if is is a class or
+ // struct and see if this is actually a C++ method
+ Type *class_type = dwarf->ResolveType(decl_ctx_die);
+ if (class_type) {
+ bool alternate_defn = false;
+ if (class_type->GetID() != decl_ctx_die.GetID() ||
+ IsClangModuleFwdDecl(decl_ctx_die)) {
+ alternate_defn = true;
+
+ // We uniqued the parent class of this function to another
+ // class so we now need to associate all dies under
+ // "decl_ctx_die" to DIEs in the DIE for "class_type"...
+ DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID());
+
+ if (class_type_die) {
+ std::vector<DWARFDIE> failures;
+
+ CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die,
+ class_type, failures);
+
+ // FIXME do something with these failures that's
+ // smarter than just dropping them on the ground.
+ // Unfortunately classes don't like having stuff added
+ // to them after their definitions are complete...
+
+ Type *type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
+ if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) {
+ return type_ptr->shared_from_this();
}
}
+ }
- if (attrs.specification.IsValid()) {
- // We have a specification which we are going to base our
- // function prototype off of, so we need this type to be
- // completed so that the m_die_to_decl_ctx for the method in
- // the specification has a valid clang decl context.
- class_type->GetForwardCompilerType();
- // If we have a specification, then the function type should
- // have been made with the specification and not with this
- // die.
- DWARFDIE spec_die = attrs.specification.Reference();
- clang::DeclContext *spec_clang_decl_ctx =
- GetClangDeclContextForDIE(spec_die);
- if (spec_clang_decl_ctx) {
- LinkDeclContextToDIE(spec_clang_decl_ctx, die);
- } else {
- dwarf->GetObjectFile()->GetModule()->ReportWarning(
- "0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8x"
- ") has no decl\n",
- die.GetID(), spec_die.GetOffset());
- }
- type_handled = true;
- } else if (attrs.abstract_origin.IsValid()) {
- // We have a specification which we are going to base our
- // function prototype off of, so we need this type to be
- // completed so that the m_die_to_decl_ctx for the method in
- // the abstract origin has a valid clang decl context.
- class_type->GetForwardCompilerType();
-
- DWARFDIE abs_die = attrs.abstract_origin.Reference();
- clang::DeclContext *abs_clang_decl_ctx =
- GetClangDeclContextForDIE(abs_die);
- if (abs_clang_decl_ctx) {
- LinkDeclContextToDIE(abs_clang_decl_ctx, die);
- } else {
- dwarf->GetObjectFile()->GetModule()->ReportWarning(
- "0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8x"
- ") has no decl\n",
- die.GetID(), abs_die.GetOffset());
- }
- type_handled = true;
+ if (attrs.specification.IsValid()) {
+ // We have a specification which we are going to base our
+ // function prototype off of, so we need this type to be
+ // completed so that the m_die_to_decl_ctx for the method in
+ // the specification has a valid clang decl context.
+ class_type->GetForwardCompilerType();
+ // If we have a specification, then the function type should
+ // have been made with the specification and not with this
+ // die.
+ DWARFDIE spec_die = attrs.specification.Reference();
+ clang::DeclContext *spec_clang_decl_ctx =
+ GetClangDeclContextForDIE(spec_die);
+ if (spec_clang_decl_ctx) {
+ LinkDeclContextToDIE(spec_clang_decl_ctx, die);
+ } else {
+ dwarf->GetObjectFile()->GetModule()->ReportWarning(
+ "0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8x"
+ ") has no decl\n",
+ die.GetID(), spec_die.GetOffset());
+ }
+ type_handled = true;
+ } else if (attrs.abstract_origin.IsValid()) {
+ // We have a specification which we are going to base our
+ // function prototype off of, so we need this type to be
+ // completed so that the m_die_to_decl_ctx for the method in
+ // the abstract origin has a valid clang decl context.
+ class_type->GetForwardCompilerType();
+
+ DWARFDIE abs_die = attrs.abstract_origin.Reference();
+ clang::DeclContext *abs_clang_decl_ctx =
+ GetClangDeclContextForDIE(abs_die);
+ if (abs_clang_decl_ctx) {
+ LinkDeclContextToDIE(abs_clang_decl_ctx, die);
} else {
- CompilerType class_opaque_type =
- class_type->GetForwardCompilerType();
- if (ClangASTContext::IsCXXClassType(class_opaque_type)) {
- if (class_opaque_type.IsBeingDefined() || alternate_defn) {
- if (!is_static && !die.HasChildren()) {
- // We have a C++ member function with no children (this
- // pointer!) and clang will get mad if we try and make
- // a function that isn't well formed in the DWARF, so
- // we will just skip it...
- type_handled = true;
- } else {
- bool add_method = true;
- if (alternate_defn) {
- // If an alternate definition for the class exists,
- // then add the method only if an equivalent is not
- // already present.
- clang::CXXRecordDecl *record_decl =
- m_ast.GetAsCXXRecordDecl(
- class_opaque_type.GetOpaqueQualType());
- if (record_decl) {
- for (auto method_iter = record_decl->method_begin();
- method_iter != record_decl->method_end();
- method_iter++) {
- clang::CXXMethodDecl *method_decl = *method_iter;
- if (method_decl->getNameInfo().getAsString() ==
- attrs.name.GetStringRef()) {
- if (method_decl->getType() ==
- ClangUtil::GetQualType(clang_type)) {
- add_method = false;
- LinkDeclContextToDIE(
- ClangASTContext::GetAsDeclContext(
- method_decl),
- die);
- type_handled = true;
-
- break;
- }
+ dwarf->GetObjectFile()->GetModule()->ReportWarning(
+ "0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8x"
+ ") has no decl\n",
+ die.GetID(), abs_die.GetOffset());
+ }
+ type_handled = true;
+ } else {
+ CompilerType class_opaque_type =
+ class_type->GetForwardCompilerType();
+ if (ClangASTContext::IsCXXClassType(class_opaque_type)) {
+ if (class_opaque_type.IsBeingDefined() || alternate_defn) {
+ if (!is_static && !die.HasChildren()) {
+ // We have a C++ member function with no children (this
+ // pointer!) and clang will get mad if we try and make
+ // a function that isn't well formed in the DWARF, so
+ // we will just skip it...
+ type_handled = true;
+ } else {
+ bool add_method = true;
+ if (alternate_defn) {
+ // If an alternate definition for the class exists,
+ // then add the method only if an equivalent is not
+ // already present.
+ clang::CXXRecordDecl *record_decl =
+ m_ast.GetAsCXXRecordDecl(
+ class_opaque_type.GetOpaqueQualType());
+ if (record_decl) {
+ for (auto method_iter = record_decl->method_begin();
+ method_iter != record_decl->method_end();
+ method_iter++) {
+ clang::CXXMethodDecl *method_decl = *method_iter;
+ if (method_decl->getNameInfo().getAsString() ==
+ attrs.name.GetStringRef()) {
+ if (method_decl->getType() ==
+ ClangUtil::GetQualType(clang_type)) {
+ add_method = false;
+ LinkDeclContextToDIE(method_decl, die);
+ type_handled = true;
+
+ break;
}
}
}
}
+ }
- if (add_method) {
- llvm::PrettyStackTraceFormat stack_trace(
- "SymbolFileDWARF::ParseType() is adding a method "
- "%s to class %s in DIE 0x%8.8" PRIx64 " from %s",
- attrs.name.GetCString(),
- class_type->GetName().GetCString(), die.GetID(),
- dwarf->GetObjectFile()
- ->GetFileSpec()
- .GetPath()
- .c_str());
-
- const bool is_attr_used = false;
- // Neither GCC 4.2 nor clang++ currently set a valid
- // accessibility in the DWARF for C++ methods...
- // Default to public for now...
- if (attrs.accessibility == eAccessNone)
- attrs.accessibility = eAccessPublic;
-
- clang::CXXMethodDecl *cxx_method_decl =
- m_ast.AddMethodToCXXRecordType(
- class_opaque_type.GetOpaqueQualType(),
- attrs.name.GetCString(), attrs.mangled_name,
- clang_type, attrs.accessibility, attrs.is_virtual,
- is_static, attrs.is_inline, attrs.is_explicit,
- is_attr_used, attrs.is_artificial);
-
- type_handled = cxx_method_decl != NULL;
- // Artificial methods are always handled even when we
- // don't create a new declaration for them.
- type_handled |= attrs.is_artificial;
-
- if (cxx_method_decl) {
- LinkDeclContextToDIE(
- ClangASTContext::GetAsDeclContext(cxx_method_decl),
- die);
-
- ClangASTMetadata metadata;
- metadata.SetUserID(die.GetID());
-
- if (!object_pointer_name.empty()) {
- metadata.SetObjectPtrName(
- object_pointer_name.c_str());
- LLDB_LOGF(log,
- "Setting object pointer name: %s on method "
- "object %p.\n",
- object_pointer_name.c_str(),
- static_cast<void *>(cxx_method_decl));
- }
- m_ast.SetMetadata(cxx_method_decl, metadata);
- } else {
- ignore_containing_context = true;
+ if (add_method) {
+ llvm::PrettyStackTraceFormat stack_trace(
+ "SymbolFileDWARF::ParseType() is adding a method "
+ "%s to class %s in DIE 0x%8.8" PRIx64 " from %s",
+ attrs.name.GetCString(),
+ class_type->GetName().GetCString(), die.GetID(),
+ dwarf->GetObjectFile()
+ ->GetFileSpec()
+ .GetPath()
+ .c_str());
+
+ const bool is_attr_used = false;
+ // Neither GCC 4.2 nor clang++ currently set a valid
+ // accessibility in the DWARF for C++ methods...
+ // Default to public for now...
+ if (attrs.accessibility == eAccessNone)
+ attrs.accessibility = eAccessPublic;
+
+ clang::CXXMethodDecl *cxx_method_decl =
+ m_ast.AddMethodToCXXRecordType(
+ class_opaque_type.GetOpaqueQualType(),
+ attrs.name.GetCString(), attrs.mangled_name,
+ clang_type, attrs.accessibility, attrs.is_virtual,
+ is_static, attrs.is_inline, attrs.is_explicit,
+ is_attr_used, attrs.is_artificial);
+
+ type_handled = cxx_method_decl != NULL;
+ // Artificial methods are always handled even when we
+ // don't create a new declaration for them.
+ type_handled |= attrs.is_artificial;
+
+ if (cxx_method_decl) {
+ LinkDeclContextToDIE(cxx_method_decl, die);
+
+ ClangASTMetadata metadata;
+ metadata.SetUserID(die.GetID());
+
+ if (!object_pointer_name.empty()) {
+ metadata.SetObjectPtrName(
+ object_pointer_name.c_str());
+ LLDB_LOGF(log,
+ "Setting object pointer name: %s on method "
+ "object %p.\n",
+ object_pointer_name.c_str(),
+ static_cast<void *>(cxx_method_decl));
}
+ m_ast.SetMetadata(cxx_method_decl, metadata);
+ } else {
+ ignore_containing_context = true;
}
}
- } else {
- // We were asked to parse the type for a method in a
- // class, yet the class hasn't been asked to complete
- // itself through the clang::ExternalASTSource protocol,
- // so we need to just have the class complete itself and
- // do things the right way, then our
- // DIE should then have an entry in the
- // dwarf->GetDIEToType() map. First
- // we need to modify the dwarf->GetDIEToType() so it
- // doesn't think we are trying to parse this DIE
- // anymore...
- dwarf->GetDIEToType()[die.GetDIE()] = NULL;
-
- // Now we get the full type to force our class type to
- // complete itself using the clang::ExternalASTSource
- // protocol which will parse all base classes and all
- // methods (including the method for this DIE).
- class_type->GetFullCompilerType();
-
- // The type for this DIE should have been filled in the
- // function call above
- type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
- if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) {
- type_sp = type_ptr->shared_from_this();
- break;
- }
-
- // FIXME This is fixing some even uglier behavior but we
- // really need to
- // uniq the methods of each class as well as the class
- // itself. <rdar://problem/11240464>
- type_handled = true;
}
+ } else {
+ // We were asked to parse the type for a method in a
+ // class, yet the class hasn't been asked to complete
+ // itself through the clang::ExternalASTSource protocol,
+ // so we need to just have the class complete itself and
+ // do things the right way, then our
+ // DIE should then have an entry in the
+ // dwarf->GetDIEToType() map. First
+ // we need to modify the dwarf->GetDIEToType() so it
+ // doesn't think we are trying to parse this DIE
+ // anymore...
+ dwarf->GetDIEToType()[die.GetDIE()] = NULL;
+
+ // Now we get the full type to force our class type to
+ // complete itself using the clang::ExternalASTSource
+ // protocol which will parse all base classes and all
+ // methods (including the method for this DIE).
+ class_type->GetFullCompilerType();
+
+ // The type for this DIE should have been filled in the
+ // function call above
+ Type *type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
+ if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) {
+ return type_ptr->shared_from_this();
+ }
+
+ // FIXME This is fixing some even uglier behavior but we
+ // really need to
+ // uniq the methods of each class as well as the class
+ // itself. <rdar://problem/11240464>
+ type_handled = true;
}
}
}
}
}
+ }
- if (!type_handled) {
- clang::FunctionDecl *function_decl = nullptr;
- clang::FunctionDecl *template_function_decl = nullptr;
+ if (!type_handled) {
+ clang::FunctionDecl *function_decl = nullptr;
+ clang::FunctionDecl *template_function_decl = nullptr;
- if (attrs.abstract_origin.IsValid()) {
- DWARFDIE abs_die = attrs.abstract_origin.Reference();
+ if (attrs.abstract_origin.IsValid()) {
+ DWARFDIE abs_die = attrs.abstract_origin.Reference();
- if (dwarf->ResolveType(abs_die)) {
- function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>(
- GetCachedClangDeclContextForDIE(abs_die));
+ if (dwarf->ResolveType(abs_die)) {
+ function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>(
+ GetCachedClangDeclContextForDIE(abs_die));
- if (function_decl) {
- LinkDeclContextToDIE(function_decl, die);
- }
+ if (function_decl) {
+ LinkDeclContextToDIE(function_decl, die);
}
}
+ }
- if (!function_decl) {
- // We just have a function that isn't part of a class
- function_decl = m_ast.CreateFunctionDeclaration(
+ if (!function_decl) {
+ // We just have a function that isn't part of a class
+ function_decl = m_ast.CreateFunctionDeclaration(
+ ignore_containing_context ? m_ast.GetTranslationUnitDecl()
+ : containing_decl_ctx,
+ attrs.name.GetCString(), clang_type, attrs.storage,
+ attrs.is_inline);
+
+ if (has_template_params) {
+ ClangASTContext::TemplateParameterInfos template_param_infos;
+ ParseTemplateParameterInfos(die, template_param_infos);
+ template_function_decl = m_ast.CreateFunctionDeclaration(
ignore_containing_context ? m_ast.GetTranslationUnitDecl()
: containing_decl_ctx,
attrs.name.GetCString(), clang_type, attrs.storage,
attrs.is_inline);
+ clang::FunctionTemplateDecl *func_template_decl =
+ m_ast.CreateFunctionTemplateDecl(
+ containing_decl_ctx, template_function_decl,
+ attrs.name.GetCString(), template_param_infos);
+ m_ast.CreateFunctionTemplateSpecializationInfo(
+ function_decl, func_template_decl, template_param_infos);
+ }
- if (has_template_params) {
- ClangASTContext::TemplateParameterInfos template_param_infos;
- ParseTemplateParameterInfos(die, template_param_infos);
- template_function_decl = m_ast.CreateFunctionDeclaration(
- ignore_containing_context ? m_ast.GetTranslationUnitDecl()
- : containing_decl_ctx,
- attrs.name.GetCString(), clang_type, attrs.storage,
- attrs.is_inline);
- clang::FunctionTemplateDecl *func_template_decl =
- m_ast.CreateFunctionTemplateDecl(
- containing_decl_ctx, template_function_decl,
- attrs.name.GetCString(), template_param_infos);
- m_ast.CreateFunctionTemplateSpecializationInfo(
- function_decl, func_template_decl, template_param_infos);
- }
-
- lldbassert(function_decl);
+ lldbassert(function_decl);
- if (function_decl) {
- LinkDeclContextToDIE(function_decl, die);
+ if (function_decl) {
+ LinkDeclContextToDIE(function_decl, die);
- if (!function_param_decls.empty()) {
- m_ast.SetFunctionParameters(function_decl,
+ if (!function_param_decls.empty()) {
+ m_ast.SetFunctionParameters(function_decl,
+ &function_param_decls.front(),
+ function_param_decls.size());
+ if (template_function_decl)
+ m_ast.SetFunctionParameters(template_function_decl,
&function_param_decls.front(),
function_param_decls.size());
- if (template_function_decl)
- m_ast.SetFunctionParameters(template_function_decl,
- &function_param_decls.front(),
- function_param_decls.size());
- }
+ }
- ClangASTMetadata metadata;
- metadata.SetUserID(die.GetID());
+ ClangASTMetadata metadata;
+ metadata.SetUserID(die.GetID());
- if (!object_pointer_name.empty()) {
- metadata.SetObjectPtrName(object_pointer_name.c_str());
- LLDB_LOGF(log,
- "Setting object pointer name: %s on function "
- "object %p.",
- object_pointer_name.c_str(),
- static_cast<void *>(function_decl));
- }
- m_ast.SetMetadata(function_decl, metadata);
+ if (!object_pointer_name.empty()) {
+ metadata.SetObjectPtrName(object_pointer_name.c_str());
+ LLDB_LOGF(log,
+ "Setting object pointer name: %s on function "
+ "object %p.",
+ object_pointer_name.c_str(),
+ static_cast<void *>(function_decl));
}
+ m_ast.SetMetadata(function_decl, metadata);
}
}
}
- type_sp = std::make_shared<Type>(
- die.GetID(), dwarf, attrs.name, llvm::None, nullptr, LLDB_INVALID_UID,
- Type::eEncodingIsUID, &attrs.decl, clang_type, Type::eResolveStateFull);
- assert(type_sp.get());
- } break;
+ }
+ return std::make_shared<Type>(
+ die.GetID(), dwarf, attrs.name, llvm::None, nullptr, LLDB_INVALID_UID,
+ Type::eEncodingIsUID, &attrs.decl, clang_type, Type::ResolveState::Full);
+}
- case DW_TAG_array_type: {
- DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
- DW_TAG_value_to_name(tag), type_name_cstr);
+TypeSP DWARFASTParserClang::ParseArrayType(const DWARFDIE &die,
+ ParsedDWARFTypeAttributes &attrs) {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
- DWARFDIE type_die = attrs.type.Reference();
- Type *element_type = dwarf->ResolveTypeUID(type_die, true);
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
+ DW_TAG_value_to_name(tag), type_name_cstr);
- if (element_type) {
- auto array_info = ParseChildArrayInfo(die);
- if (array_info) {
- attrs.byte_stride = array_info->byte_stride;
- attrs.bit_stride = array_info->bit_stride;
- }
- if (attrs.byte_stride == 0 && attrs.bit_stride == 0)
- attrs.byte_stride = element_type->GetByteSize().getValueOr(0);
- CompilerType array_element_type = element_type->GetForwardCompilerType();
-
- if (ClangASTContext::IsCXXClassType(array_element_type) &&
- !array_element_type.GetCompleteType()) {
- ModuleSP module_sp = die.GetModule();
- if (module_sp) {
- if (die.GetCU()->GetProducer() == eProducerClang)
- module_sp->ReportError(
- "DWARF DW_TAG_array_type DIE at 0x%8.8x has a "
- "class/union/struct element type DIE 0x%8.8x that is a "
- "forward declaration, not a complete definition.\nTry "
- "compiling the source file with -fstandalone-debug or "
- "disable -gmodules",
- die.GetOffset(), type_die.GetOffset());
- else
- module_sp->ReportError(
- "DWARF DW_TAG_array_type DIE at 0x%8.8x has a "
- "class/union/struct element type DIE 0x%8.8x that is a "
- "forward declaration, not a complete definition.\nPlease "
- "file a bug against the compiler and include the "
- "preprocessed output for %s",
- die.GetOffset(), type_die.GetOffset(),
- GetUnitName(die).c_str());
- }
+ DWARFDIE type_die = attrs.type.Reference();
+ Type *element_type = dwarf->ResolveTypeUID(type_die, true);
- // We have no choice other than to pretend that the element class
- // type is complete. If we don't do this, clang will crash when
- // trying to layout the class. Since we provide layout
- // assistance, all ivars in this class and other classes will be
- // fine, this is the best we can do short of crashing.
- if (ClangASTContext::StartTagDeclarationDefinition(
- array_element_type)) {
- ClangASTContext::CompleteTagDeclarationDefinition(array_element_type);
- } else {
- module_sp->ReportError("DWARF DIE at 0x%8.8x was not able to "
- "start its definition.\nPlease file a "
- "bug and attach the file at the start "
- "of this error message",
- type_die.GetOffset());
- }
- }
+ if (!element_type)
+ return nullptr;
- uint64_t array_element_bit_stride =
- attrs.byte_stride * 8 + attrs.bit_stride;
- if (array_info && array_info->element_orders.size() > 0) {
- uint64_t num_elements = 0;
- auto end = array_info->element_orders.rend();
- for (auto pos = array_info->element_orders.rbegin(); pos != end;
- ++pos) {
- num_elements = *pos;
- clang_type = m_ast.CreateArrayType(array_element_type, num_elements,
- attrs.is_vector);
- array_element_type = clang_type;
- array_element_bit_stride =
- num_elements ? array_element_bit_stride * num_elements
- : array_element_bit_stride;
- }
- } else {
- clang_type = m_ast.CreateArrayType(array_element_type, 0, attrs.is_vector);
- }
- ConstString empty_name;
- type_sp = std::make_shared<Type>(
- die.GetID(), dwarf, empty_name, array_element_bit_stride / 8, nullptr,
- dwarf->GetUID(type_die), Type::eEncodingIsUID, &attrs.decl,
- clang_type, Type::eResolveStateFull);
- type_sp->SetEncodingType(element_type);
- m_ast.SetMetadataAsUserID(clang_type.GetOpaqueQualType(), die.GetID());
+ llvm::Optional<SymbolFile::ArrayInfo> array_info = ParseChildArrayInfo(die);
+ if (array_info) {
+ attrs.byte_stride = array_info->byte_stride;
+ attrs.bit_stride = array_info->bit_stride;
+ }
+ if (attrs.byte_stride == 0 && attrs.bit_stride == 0)
+ attrs.byte_stride = element_type->GetByteSize().getValueOr(0);
+ CompilerType array_element_type = element_type->GetForwardCompilerType();
+
+ if (ClangASTContext::IsCXXClassType(array_element_type) &&
+ !array_element_type.GetCompleteType()) {
+ ModuleSP module_sp = die.GetModule();
+ if (module_sp) {
+ if (die.GetCU()->GetProducer() == eProducerClang)
+ module_sp->ReportError(
+ "DWARF DW_TAG_array_type DIE at 0x%8.8x has a "
+ "class/union/struct element type DIE 0x%8.8x that is a "
+ "forward declaration, not a complete definition.\nTry "
+ "compiling the source file with -fstandalone-debug or "
+ "disable -gmodules",
+ die.GetOffset(), type_die.GetOffset());
+ else
+ module_sp->ReportError(
+ "DWARF DW_TAG_array_type DIE at 0x%8.8x has a "
+ "class/union/struct element type DIE 0x%8.8x that is a "
+ "forward declaration, not a complete definition.\nPlease "
+ "file a bug against the compiler and include the "
+ "preprocessed output for %s",
+ die.GetOffset(), type_die.GetOffset(), GetUnitName(die).c_str());
+ }
+
+ // We have no choice other than to pretend that the element class
+ // type is complete. If we don't do this, clang will crash when
+ // trying to layout the class. Since we provide layout
+ // assistance, all ivars in this class and other classes will be
+ // fine, this is the best we can do short of crashing.
+ if (ClangASTContext::StartTagDeclarationDefinition(array_element_type)) {
+ ClangASTContext::CompleteTagDeclarationDefinition(array_element_type);
+ } else {
+ module_sp->ReportError("DWARF DIE at 0x%8.8x was not able to "
+ "start its definition.\nPlease file a "
+ "bug and attach the file at the start "
+ "of this error message",
+ type_die.GetOffset());
}
- } break;
+ }
- case DW_TAG_ptr_to_member_type: {
- Type *pointee_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true);
- Type *class_type =
- dwarf->ResolveTypeUID(attrs.containing_type.Reference(), true);
+ uint64_t array_element_bit_stride =
+ attrs.byte_stride * 8 + attrs.bit_stride;
+ CompilerType clang_type;
+ if (array_info && array_info->element_orders.size() > 0) {
+ uint64_t num_elements = 0;
+ auto end = array_info->element_orders.rend();
+ for (auto pos = array_info->element_orders.rbegin(); pos != end; ++pos) {
+ num_elements = *pos;
+ clang_type = m_ast.CreateArrayType(array_element_type, num_elements,
+ attrs.is_vector);
+ array_element_type = clang_type;
+ array_element_bit_stride = num_elements
+ ? array_element_bit_stride * num_elements
+ : array_element_bit_stride;
+ }
+ } else {
+ clang_type =
+ m_ast.CreateArrayType(array_element_type, 0, attrs.is_vector);
+ }
+ ConstString empty_name;
+ TypeSP type_sp = std::make_shared<Type>(
+ die.GetID(), dwarf, empty_name, array_element_bit_stride / 8, nullptr,
+ dwarf->GetUID(type_die), Type::eEncodingIsUID, &attrs.decl, clang_type,
+ Type::ResolveState::Full);
+ type_sp->SetEncodingType(element_type);
+ const clang::Type *type = ClangUtil::GetQualType(clang_type).getTypePtr();
+ m_ast.SetMetadataAsUserID(type, die.GetID());
+ return type_sp;
+}
- CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType();
- CompilerType class_clang_type = class_type->GetLayoutCompilerType();
+TypeSP DWARFASTParserClang::ParsePointerToMemberType(
+ const DWARFDIE &die, const ParsedDWARFTypeAttributes &attrs) {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ Type *pointee_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true);
+ Type *class_type =
+ dwarf->ResolveTypeUID(attrs.containing_type.Reference(), true);
- clang_type = ClangASTContext::CreateMemberPointerType(class_clang_type,
- pointee_clang_type);
+ CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType();
+ CompilerType class_clang_type = class_type->GetLayoutCompilerType();
- if (llvm::Optional<uint64_t> clang_type_size =
- clang_type.GetByteSize(nullptr)) {
- type_sp = std::make_shared<Type>(
- die.GetID(), dwarf, attrs.name, *clang_type_size, nullptr,
- LLDB_INVALID_UID, Type::eEncodingIsUID, nullptr, clang_type,
- Type::eResolveStateForward);
- }
+ CompilerType clang_type = ClangASTContext::CreateMemberPointerType(
+ class_clang_type, pointee_clang_type);
- break;
- }
- default:
- dwarf->GetObjectFile()->GetModule()->ReportError(
- "{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and "
- "attach the file at the start of this error message",
- die.GetOffset(), tag, DW_TAG_value_to_name(tag));
- break;
+ if (llvm::Optional<uint64_t> clang_type_size =
+ clang_type.GetByteSize(nullptr)) {
+ return std::make_shared<Type>(die.GetID(), dwarf, attrs.name,
+ *clang_type_size, nullptr, LLDB_INVALID_UID,
+ Type::eEncodingIsUID, nullptr, clang_type,
+ Type::ResolveState::Forward);
}
-
- // TODO: We should consider making the switch above exhaustive to simplify
- // control flow in ParseTypeFromDWARF. Then, we could simply replace this
- // return statement with a call to llvm_unreachable.
- return UpdateSymbolContextScopeForType(sc, die, type_sp);
+ return nullptr;
}
TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType(
@@ -1281,20 +1380,20 @@ TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType(
DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die);
dw_tag_t sc_parent_tag = sc_parent_die.Tag();
- SymbolContextScope *symbol_context_scope = NULL;
+ SymbolContextScope *symbol_context_scope = nullptr;
if (sc_parent_tag == DW_TAG_compile_unit ||
sc_parent_tag == DW_TAG_partial_unit) {
symbol_context_scope = sc.comp_unit;
- } else if (sc.function != NULL && sc_parent_die) {
+ } else if (sc.function != nullptr && sc_parent_die) {
symbol_context_scope =
sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
- if (symbol_context_scope == NULL)
+ if (symbol_context_scope == nullptr)
symbol_context_scope = sc.function;
} else {
symbol_context_scope = sc.module_sp.get();
}
- if (symbol_context_scope != NULL)
+ if (symbol_context_scope != nullptr)
type_sp->SetSymbolContextScope(symbol_context_scope);
// We are ready to put this type into the uniqued list up at the module
@@ -1306,7 +1405,8 @@ TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType(
}
TypeSP
-DWARFASTParserClang::ParseStructureLikeDIE(const DWARFDIE &die,
+DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
+ const DWARFDIE &die,
ParsedDWARFTypeAttributes &attrs) {
TypeSP type_sp;
CompilerType clang_type;
@@ -1438,9 +1538,9 @@ DWARFASTParserClang::ParseStructureLikeDIE(const DWARFDIE &die,
attrs.name.GetCString());
}
- // See if the type comes from a DWO module and if so, track down that
- // type.
- type_sp = ParseTypeFromDWO(die, log);
+ // See if the type comes from a Clang module and if so, track down
+ // that type.
+ type_sp = ParseTypeFromClangModule(sc, die, log);
if (type_sp)
return type_sp;
@@ -1495,7 +1595,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const DWARFDIE &die,
// backing the Decl is complete before adding children to it. This is
// not an issue in the non-gmodules case because the debug info will
// always contain a full definition of parent types in that case.
- CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die,
+ CompleteExternalTagDeclType(m_ast, GetClangASTImporter(), decl_ctx, die,
attrs.name.GetCString());
if (attrs.accessibility == eAccessNone && decl_ctx) {
@@ -1546,7 +1646,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const DWARFDIE &die,
clang_type_was_created = true;
clang_type = m_ast.CreateRecordType(
decl_ctx, attrs.accessibility, attrs.name.GetCString(), tag_decl_kind,
- attrs.class_language, &metadata);
+ attrs.class_language, &metadata, attrs.exports_symbols);
}
}
@@ -1557,7 +1657,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const DWARFDIE &die,
type_sp = std::make_shared<Type>(die.GetID(), dwarf, attrs.name,
attrs.byte_size, nullptr, LLDB_INVALID_UID,
Type::eEncodingIsUID, &attrs.decl,
- clang_type, Type::eResolveStateForward);
+ clang_type, Type::ResolveState::Forward);
type_sp->SetIsCompleteObjCClass(attrs.is_complete_objc_class);
@@ -1621,7 +1721,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const DWARFDIE &die,
ClangASTContext::GetAsRecordDecl(clang_type);
if (record_decl) {
- GetClangASTImporter().InsertRecordDecl(
+ GetClangASTImporter().SetRecordLayout(
record_decl, ClangASTImporter::LayoutInfo());
}
}
@@ -1810,7 +1910,7 @@ bool DWARFASTParserClang::ParseTemplateDIE(
}
}
- clang::ASTContext *ast = m_ast.getASTContext();
+ clang::ASTContext &ast = m_ast.getASTContext();
if (!clang_type)
clang_type = m_ast.GetBasicType(eBasicTypeVoid);
@@ -1830,7 +1930,7 @@ bool DWARFASTParserClang::ParseTemplateDIE(
return false;
llvm::APInt apint(*size, uval64, is_signed);
template_param_infos.args.push_back(
- clang::TemplateArgument(*ast, llvm::APSInt(apint, !is_signed),
+ clang::TemplateArgument(ast, llvm::APSInt(apint, !is_signed),
ClangUtil::GetQualType(clang_type)));
} else {
template_param_infos.args.push_back(
@@ -1880,6 +1980,182 @@ bool DWARFASTParserClang::ParseTemplateParameterInfos(
return template_param_infos.args.size() == template_param_infos.names.size();
}
+bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,
+ lldb_private::Type *type,
+ CompilerType &clang_type) {
+ const dw_tag_t tag = die.Tag();
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+
+ ClangASTImporter::LayoutInfo layout_info;
+
+ {
+ if (die.HasChildren()) {
+ LanguageType class_language = eLanguageTypeUnknown;
+ if (ClangASTContext::IsObjCObjectOrInterfaceType(clang_type)) {
+ class_language = eLanguageTypeObjC;
+ // For objective C we don't start the definition when the class is
+ // created.
+ ClangASTContext::StartTagDeclarationDefinition(clang_type);
+ }
+
+ int tag_decl_kind = -1;
+ AccessType default_accessibility = eAccessNone;
+ if (tag == DW_TAG_structure_type) {
+ tag_decl_kind = clang::TTK_Struct;
+ default_accessibility = eAccessPublic;
+ } else if (tag == DW_TAG_union_type) {
+ tag_decl_kind = clang::TTK_Union;
+ default_accessibility = eAccessPublic;
+ } else if (tag == DW_TAG_class_type) {
+ tag_decl_kind = clang::TTK_Class;
+ default_accessibility = eAccessPrivate;
+ }
+
+ std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
+ std::vector<int> member_accessibilities;
+ bool is_a_class = false;
+ // Parse members and base classes first
+ std::vector<DWARFDIE> member_function_dies;
+
+ DelayedPropertyList delayed_properties;
+ ParseChildMembers(die, clang_type, class_language, bases,
+ member_accessibilities, member_function_dies,
+ delayed_properties, default_accessibility, is_a_class,
+ layout_info);
+
+ // Now parse any methods if there were any...
+ for (const DWARFDIE &die : member_function_dies)
+ dwarf->ResolveType(die);
+
+ if (class_language == eLanguageTypeObjC) {
+ ConstString class_name(clang_type.GetTypeName());
+ if (class_name) {
+ DIEArray method_die_offsets;
+ dwarf->GetObjCMethodDIEOffsets(class_name, method_die_offsets);
+
+ if (!method_die_offsets.empty()) {
+ DWARFDebugInfo *debug_info = dwarf->DebugInfo();
+
+ const size_t num_matches = method_die_offsets.size();
+ for (size_t i = 0; i < num_matches; ++i) {
+ const DIERef &die_ref = method_die_offsets[i];
+ DWARFDIE method_die = debug_info->GetDIE(die_ref);
+
+ if (method_die)
+ method_die.ResolveType();
+ }
+ }
+
+ for (DelayedPropertyList::iterator pi = delayed_properties.begin(),
+ pe = delayed_properties.end();
+ pi != pe; ++pi)
+ pi->Finalize();
+ }
+ }
+
+ // If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we
+ // need to tell the clang type it is actually a class.
+ if (class_language != eLanguageTypeObjC) {
+ if (is_a_class && tag_decl_kind != clang::TTK_Class)
+ m_ast.SetTagTypeKind(ClangUtil::GetQualType(clang_type),
+ clang::TTK_Class);
+ }
+
+ // Since DW_TAG_structure_type gets used for both classes and
+ // structures, we may need to set any DW_TAG_member fields to have a
+ // "private" access if none was specified. When we parsed the child
+ // members we tracked that actual accessibility value for each
+ // DW_TAG_member in the "member_accessibilities" array. If the value
+ // for the member is zero, then it was set to the
+ // "default_accessibility" which for structs was "public". Below we
+ // correct this by setting any fields to "private" that weren't
+ // correctly set.
+ if (is_a_class && !member_accessibilities.empty()) {
+ // This is a class and all members that didn't have their access
+ // specified are private.
+ m_ast.SetDefaultAccessForRecordFields(
+ m_ast.GetAsRecordDecl(clang_type), eAccessPrivate,
+ &member_accessibilities.front(), member_accessibilities.size());
+ }
+
+ if (!bases.empty()) {
+ // Make sure all base classes refer to complete types and not forward
+ // declarations. If we don't do this, clang will crash with an
+ // assertion in the call to clang_type.TransferBaseClasses()
+ for (const auto &base_class : bases) {
+ clang::TypeSourceInfo *type_source_info =
+ base_class->getTypeSourceInfo();
+ if (type_source_info) {
+ CompilerType base_class_type =
+ m_ast.GetType(type_source_info->getType());
+ if (!base_class_type.GetCompleteType()) {
+ auto module = dwarf->GetObjectFile()->GetModule();
+ module->ReportError(":: Class '%s' has a base class '%s' which "
+ "does not have a complete definition.",
+ die.GetName(),
+ base_class_type.GetTypeName().GetCString());
+ if (die.GetCU()->GetProducer() == eProducerClang)
+ module->ReportError(":: Try compiling the source file with "
+ "-fstandalone-debug.");
+
+ // We have no choice other than to pretend that the base class
+ // is complete. If we don't do this, clang will crash when we
+ // call setBases() inside of
+ // "clang_type.TransferBaseClasses()" below. Since we
+ // provide layout assistance, all ivars in this class and other
+ // classes will be fine, this is the best we can do short of
+ // crashing.
+ if (ClangASTContext::StartTagDeclarationDefinition(
+ base_class_type)) {
+ ClangASTContext::CompleteTagDeclarationDefinition(
+ base_class_type);
+ }
+ }
+ }
+ }
+
+ m_ast.TransferBaseClasses(clang_type.GetOpaqueQualType(),
+ std::move(bases));
+ }
+ }
+ }
+
+ m_ast.AddMethodOverridesForCXXRecordType(clang_type.GetOpaqueQualType());
+ ClangASTContext::BuildIndirectFields(clang_type);
+ ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
+
+ if (!layout_info.field_offsets.empty() || !layout_info.base_offsets.empty() ||
+ !layout_info.vbase_offsets.empty()) {
+ if (type)
+ layout_info.bit_size = type->GetByteSize().getValueOr(0) * 8;
+ if (layout_info.bit_size == 0)
+ layout_info.bit_size =
+ die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
+
+ clang::CXXRecordDecl *record_decl =
+ m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
+ if (record_decl)
+ GetClangASTImporter().SetRecordLayout(record_decl, layout_info);
+ }
+
+ return (bool)clang_type;
+}
+
+bool DWARFASTParserClang::CompleteEnumType(const DWARFDIE &die,
+ lldb_private::Type *type,
+ CompilerType &clang_type) {
+ if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) {
+ if (die.HasChildren()) {
+ bool is_signed = false;
+ clang_type.IsIntegerType(is_signed);
+ ParseChildEnumerators(clang_type, is_signed,
+ type->GetByteSize().getValueOr(0), die);
+ }
+ ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
+ }
+ return (bool)clang_type;
+}
+
bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
lldb_private::Type *type,
CompilerType &clang_type) {
@@ -1895,39 +2171,6 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
if (!die)
return false;
-#if defined LLDB_CONFIGURATION_DEBUG
- // For debugging purposes, the LLDB_DWARF_DONT_COMPLETE_TYPENAMES environment
- // variable can be set with one or more typenames separated by ';'
- // characters. This will cause this function to not complete any types whose
- // names match.
- //
- // Examples of setting this environment variable:
- //
- // LLDB_DWARF_DONT_COMPLETE_TYPENAMES=Foo
- // LLDB_DWARF_DONT_COMPLETE_TYPENAMES=Foo;Bar;Baz
- const char *dont_complete_typenames_cstr =
- getenv("LLDB_DWARF_DONT_COMPLETE_TYPENAMES");
- if (dont_complete_typenames_cstr && dont_complete_typenames_cstr[0]) {
- const char *die_name = die.GetName();
- if (die_name && die_name[0]) {
- const char *match = strstr(dont_complete_typenames_cstr, die_name);
- if (match) {
- size_t die_name_length = strlen(die_name);
- while (match) {
- const char separator_char = ';';
- const char next_char = match[die_name_length];
- if (next_char == '\0' || next_char == separator_char) {
- if (match == dont_complete_typenames_cstr ||
- match[-1] == separator_char)
- return false;
- }
- match = strstr(match + 1, die_name);
- }
- }
- }
- }
-#endif
-
const dw_tag_t tag = die.Tag();
Log *log =
@@ -1941,239 +2184,10 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
switch (tag) {
case DW_TAG_structure_type:
case DW_TAG_union_type:
- case DW_TAG_class_type: {
- ClangASTImporter::LayoutInfo layout_info;
-
- {
- if (die.HasChildren()) {
- LanguageType class_language = eLanguageTypeUnknown;
- if (ClangASTContext::IsObjCObjectOrInterfaceType(clang_type)) {
- class_language = eLanguageTypeObjC;
- // For objective C we don't start the definition when the class is
- // created.
- ClangASTContext::StartTagDeclarationDefinition(clang_type);
- }
-
- int tag_decl_kind = -1;
- AccessType default_accessibility = eAccessNone;
- if (tag == DW_TAG_structure_type) {
- tag_decl_kind = clang::TTK_Struct;
- default_accessibility = eAccessPublic;
- } else if (tag == DW_TAG_union_type) {
- tag_decl_kind = clang::TTK_Union;
- default_accessibility = eAccessPublic;
- } else if (tag == DW_TAG_class_type) {
- tag_decl_kind = clang::TTK_Class;
- default_accessibility = eAccessPrivate;
- }
-
- std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
- std::vector<int> member_accessibilities;
- bool is_a_class = false;
- // Parse members and base classes first
- std::vector<DWARFDIE> member_function_dies;
-
- DelayedPropertyList delayed_properties;
- ParseChildMembers(die, clang_type, class_language, bases,
- member_accessibilities, member_function_dies,
- delayed_properties, default_accessibility, is_a_class,
- layout_info);
-
- // Now parse any methods if there were any...
- for (const DWARFDIE &die : member_function_dies)
- dwarf->ResolveType(die);
-
- if (class_language == eLanguageTypeObjC) {
- ConstString class_name(clang_type.GetTypeName());
- if (class_name) {
- DIEArray method_die_offsets;
- dwarf->GetObjCMethodDIEOffsets(class_name, method_die_offsets);
-
- if (!method_die_offsets.empty()) {
- DWARFDebugInfo *debug_info = dwarf->DebugInfo();
-
- const size_t num_matches = method_die_offsets.size();
- for (size_t i = 0; i < num_matches; ++i) {
- const DIERef &die_ref = method_die_offsets[i];
- DWARFDIE method_die = debug_info->GetDIE(die_ref);
-
- if (method_die)
- method_die.ResolveType();
- }
- }
-
- for (DelayedPropertyList::iterator pi = delayed_properties.begin(),
- pe = delayed_properties.end();
- pi != pe; ++pi)
- pi->Finalize();
- }
- }
-
- // If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we
- // need to tell the clang type it is actually a class.
- if (class_language != eLanguageTypeObjC) {
- if (is_a_class && tag_decl_kind != clang::TTK_Class)
- m_ast.SetTagTypeKind(ClangUtil::GetQualType(clang_type),
- clang::TTK_Class);
- }
-
- // Since DW_TAG_structure_type gets used for both classes and
- // structures, we may need to set any DW_TAG_member fields to have a
- // "private" access if none was specified. When we parsed the child
- // members we tracked that actual accessibility value for each
- // DW_TAG_member in the "member_accessibilities" array. If the value
- // for the member is zero, then it was set to the
- // "default_accessibility" which for structs was "public". Below we
- // correct this by setting any fields to "private" that weren't
- // correctly set.
- if (is_a_class && !member_accessibilities.empty()) {
- // This is a class and all members that didn't have their access
- // specified are private.
- m_ast.SetDefaultAccessForRecordFields(
- m_ast.GetAsRecordDecl(clang_type), eAccessPrivate,
- &member_accessibilities.front(), member_accessibilities.size());
- }
-
- if (!bases.empty()) {
- // Make sure all base classes refer to complete types and not forward
- // declarations. If we don't do this, clang will crash with an
- // assertion in the call to clang_type.TransferBaseClasses()
- for (const auto &base_class : bases) {
- clang::TypeSourceInfo *type_source_info =
- base_class->getTypeSourceInfo();
- if (type_source_info) {
- CompilerType base_class_type(
- &m_ast, type_source_info->getType().getAsOpaquePtr());
- if (!base_class_type.GetCompleteType()) {
- auto module = dwarf->GetObjectFile()->GetModule();
- module->ReportError(":: Class '%s' has a base class '%s' which "
- "does not have a complete definition.",
- die.GetName(),
- base_class_type.GetTypeName().GetCString());
- if (die.GetCU()->GetProducer() == eProducerClang)
- module->ReportError(":: Try compiling the source file with "
- "-fstandalone-debug.");
-
- // We have no choice other than to pretend that the base class
- // is complete. If we don't do this, clang will crash when we
- // call setBases() inside of
- // "clang_type.TransferBaseClasses()" below. Since we
- // provide layout assistance, all ivars in this class and other
- // classes will be fine, this is the best we can do short of
- // crashing.
- if (ClangASTContext::StartTagDeclarationDefinition(
- base_class_type)) {
- ClangASTContext::CompleteTagDeclarationDefinition(
- base_class_type);
- }
- }
- }
- }
-
- m_ast.TransferBaseClasses(clang_type.GetOpaqueQualType(),
- std::move(bases));
- }
- }
- }
-
- m_ast.AddMethodOverridesForCXXRecordType(clang_type.GetOpaqueQualType());
- ClangASTContext::BuildIndirectFields(clang_type);
- ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
-
- if (!layout_info.field_offsets.empty() ||
- !layout_info.base_offsets.empty() ||
- !layout_info.vbase_offsets.empty()) {
- if (type)
- layout_info.bit_size = type->GetByteSize().getValueOr(0) * 8;
- if (layout_info.bit_size == 0)
- layout_info.bit_size =
- die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
-
- clang::CXXRecordDecl *record_decl =
- m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
- if (record_decl) {
- if (log) {
- ModuleSP module_sp = dwarf->GetObjectFile()->GetModule();
-
- if (module_sp) {
- module_sp->LogMessage(
- log,
- "ClangASTContext::CompleteTypeFromDWARF (clang_type = %p) "
- "caching layout info for record_decl = %p, bit_size = %" PRIu64
- ", alignment = %" PRIu64
- ", field_offsets[%u], base_offsets[%u], vbase_offsets[%u])",
- static_cast<void *>(clang_type.GetOpaqueQualType()),
- static_cast<void *>(record_decl), layout_info.bit_size,
- layout_info.alignment,
- static_cast<uint32_t>(layout_info.field_offsets.size()),
- static_cast<uint32_t>(layout_info.base_offsets.size()),
- static_cast<uint32_t>(layout_info.vbase_offsets.size()));
-
- uint32_t idx;
- {
- llvm::DenseMap<const clang::FieldDecl *, uint64_t>::const_iterator
- pos,
- end = layout_info.field_offsets.end();
- for (idx = 0, pos = layout_info.field_offsets.begin(); pos != end;
- ++pos, ++idx) {
- module_sp->LogMessage(
- log, "ClangASTContext::CompleteTypeFromDWARF (clang_type = "
- "%p) field[%u] = { bit_offset=%u, name='%s' }",
- static_cast<void *>(clang_type.GetOpaqueQualType()), idx,
- static_cast<uint32_t>(pos->second),
- pos->first->getNameAsString().c_str());
- }
- }
-
- {
- llvm::DenseMap<const clang::CXXRecordDecl *,
- clang::CharUnits>::const_iterator base_pos,
- base_end = layout_info.base_offsets.end();
- for (idx = 0, base_pos = layout_info.base_offsets.begin();
- base_pos != base_end; ++base_pos, ++idx) {
- module_sp->LogMessage(
- log, "ClangASTContext::CompleteTypeFromDWARF (clang_type = "
- "%p) base[%u] = { byte_offset=%u, name='%s' }",
- clang_type.GetOpaqueQualType(), idx,
- (uint32_t)base_pos->second.getQuantity(),
- base_pos->first->getNameAsString().c_str());
- }
- }
- {
- llvm::DenseMap<const clang::CXXRecordDecl *,
- clang::CharUnits>::const_iterator vbase_pos,
- vbase_end = layout_info.vbase_offsets.end();
- for (idx = 0, vbase_pos = layout_info.vbase_offsets.begin();
- vbase_pos != vbase_end; ++vbase_pos, ++idx) {
- module_sp->LogMessage(
- log, "ClangASTContext::CompleteTypeFromDWARF (clang_type = "
- "%p) vbase[%u] = { byte_offset=%u, name='%s' }",
- static_cast<void *>(clang_type.GetOpaqueQualType()), idx,
- static_cast<uint32_t>(vbase_pos->second.getQuantity()),
- vbase_pos->first->getNameAsString().c_str());
- }
- }
- }
- }
- GetClangASTImporter().InsertRecordDecl(record_decl, layout_info);
- }
- }
- }
-
- return (bool)clang_type;
-
+ case DW_TAG_class_type:
+ return CompleteRecordType(die, type, clang_type);
case DW_TAG_enumeration_type:
- if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) {
- if (die.HasChildren()) {
- bool is_signed = false;
- clang_type.IsIntegerType(is_signed);
- ParseChildEnumerators(clang_type, is_signed,
- type->GetByteSize().getValueOr(0), die);
- }
- ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
- }
- return (bool)clang_type;
-
+ return CompleteEnumType(die, type, clang_type);
default:
assert(false && "not a forward clang type decl!");
break;
@@ -2205,7 +2219,7 @@ CompilerDeclContext
DWARFASTParserClang::GetDeclContextForUIDFromDWARF(const DWARFDIE &die) {
clang::DeclContext *clang_decl_ctx = GetClangDeclContextForDIE(die);
if (clang_decl_ctx)
- return CompilerDeclContext(&m_ast, clang_decl_ctx);
+ return m_ast.CreateDeclContext(clang_decl_ctx);
return CompilerDeclContext();
}
@@ -2214,7 +2228,7 @@ DWARFASTParserClang::GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) {
clang::DeclContext *clang_decl_ctx =
GetClangDeclContextContainingDIE(die, nullptr);
if (clang_decl_ctx)
- return CompilerDeclContext(&m_ast, clang_decl_ctx);
+ return m_ast.CreateDeclContext(clang_decl_ctx);
return CompilerDeclContext();
}
@@ -2284,54 +2298,6 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
return enumerators_added;
}
-#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
-
-class DIEStack {
-public:
- void Push(const DWARFDIE &die) { m_dies.push_back(die); }
-
- void LogDIEs(Log *log) {
- StreamString log_strm;
- const size_t n = m_dies.size();
- log_strm.Printf("DIEStack[%" PRIu64 "]:\n", (uint64_t)n);
- for (size_t i = 0; i < n; i++) {
- std::string qualified_name;
- const DWARFDIE &die = m_dies[i];
- die.GetQualifiedName(qualified_name);
- log_strm.Printf("[%" PRIu64 "] 0x%8.8x: %s name='%s'\n", (uint64_t)i,
- die.GetOffset(), die.GetTagAsCString(),
- qualified_name.c_str());
- }
- log->PutCString(log_strm.GetData());
- }
- void Pop() { m_dies.pop_back(); }
-
- class ScopedPopper {
- public:
- ScopedPopper(DIEStack &die_stack)
- : m_die_stack(die_stack), m_valid(false) {}
-
- void Push(const DWARFDIE &die) {
- m_valid = true;
- m_die_stack.Push(die);
- }
-
- ~ScopedPopper() {
- if (m_valid)
- m_die_stack.Pop();
- }
-
- protected:
- DIEStack &m_die_stack;
- bool m_valid;
- };
-
-protected:
- typedef std::vector<DWARFDIE> Stack;
- Stack m_dies;
-};
-#endif
-
Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit,
const DWARFDIE &die) {
DWARFRangeList func_ranges;
@@ -2445,495 +2411,499 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit,
return nullptr;
}
-bool DWARFASTParserClang::ParseChildMembers(
- const DWARFDIE &parent_die, CompilerType &class_clang_type,
- const LanguageType class_language,
- std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,
+void DWARFASTParserClang::ParseSingleMember(
+ const DWARFDIE &die, const DWARFDIE &parent_die,
+ lldb_private::CompilerType &class_clang_type,
+ const lldb::LanguageType class_language,
std::vector<int> &member_accessibilities,
- std::vector<DWARFDIE> &member_function_dies,
- DelayedPropertyList &delayed_properties, AccessType &default_accessibility,
- bool &is_a_class, ClangASTImporter::LayoutInfo &layout_info) {
- if (!parent_die)
- return false;
-
+ lldb::AccessType &default_accessibility,
+ DelayedPropertyList &delayed_properties,
+ lldb_private::ClangASTImporter::LayoutInfo &layout_info,
+ BitfieldInfo &last_field_info) {
+ ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
+ const dw_tag_t tag = die.Tag();
// Get the parent byte size so we can verify any members will fit
const uint64_t parent_byte_size =
parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size, UINT64_MAX);
const uint64_t parent_bit_size =
parent_byte_size == UINT64_MAX ? UINT64_MAX : parent_byte_size * 8;
- uint32_t member_idx = 0;
- BitfieldInfo last_field_info;
-
- ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
- ClangASTContext *ast =
- llvm::dyn_cast_or_null<ClangASTContext>(class_clang_type.GetTypeSystem());
- if (ast == nullptr)
- return false;
-
- for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
- die = die.GetSibling()) {
- dw_tag_t tag = die.Tag();
-
- switch (tag) {
- case DW_TAG_member:
- case DW_TAG_APPLE_property: {
- DWARFAttributes attributes;
- const size_t num_attributes = die.GetAttributes(attributes);
- if (num_attributes > 0) {
- const char *name = nullptr;
- const char *prop_name = nullptr;
- const char *prop_getter_name = nullptr;
- const char *prop_setter_name = nullptr;
- uint32_t prop_attributes = 0;
-
- bool is_artificial = false;
- DWARFFormValue encoding_form;
- AccessType accessibility = eAccessNone;
- uint32_t member_byte_offset =
- (parent_die.Tag() == DW_TAG_union_type) ? 0 : UINT32_MAX;
- llvm::Optional<uint64_t> byte_size;
- int64_t bit_offset = 0;
- uint64_t data_bit_offset = UINT64_MAX;
- size_t bit_size = 0;
- bool is_external =
- false; // On DW_TAG_members, this means the member is static
- uint32_t i;
- for (i = 0; i < num_attributes && !is_artificial; ++i) {
- const dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(i, form_value)) {
- switch (attr) {
- case DW_AT_name:
- name = form_value.AsCString();
- break;
- case DW_AT_type:
- encoding_form = form_value;
- break;
- case DW_AT_bit_offset:
- bit_offset = form_value.Signed();
- break;
- case DW_AT_bit_size:
- bit_size = form_value.Unsigned();
- break;
- case DW_AT_byte_size:
- byte_size = form_value.Unsigned();
- break;
- case DW_AT_data_bit_offset:
- data_bit_offset = form_value.Unsigned();
- break;
- case DW_AT_data_member_location:
- if (form_value.BlockData()) {
- Value initialValue(0);
- Value memberOffset(0);
- const DWARFDataExtractor &debug_info_data = die.GetData();
- uint32_t block_length = form_value.Unsigned();
- uint32_t block_offset =
- form_value.BlockData() - debug_info_data.GetDataStart();
- if (DWARFExpression::Evaluate(
- nullptr, // ExecutionContext *
- nullptr, // RegisterContext *
- module_sp,
- DataExtractor(debug_info_data, block_offset,
- block_length),
- die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr,
- memberOffset, nullptr)) {
- member_byte_offset =
- memberOffset.ResolveValue(nullptr).UInt();
- }
- } else {
- // With DWARF 3 and later, if the value is an integer constant,
- // this form value is the offset in bytes from the beginning of
- // the containing entity.
- member_byte_offset = form_value.Unsigned();
- }
- break;
-
- case DW_AT_accessibility:
- accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
- break;
- case DW_AT_artificial:
- is_artificial = form_value.Boolean();
- break;
- case DW_AT_APPLE_property_name:
- prop_name = form_value.AsCString();
- break;
- case DW_AT_APPLE_property_getter:
- prop_getter_name = form_value.AsCString();
- break;
- case DW_AT_APPLE_property_setter:
- prop_setter_name = form_value.AsCString();
- break;
- case DW_AT_APPLE_property_attribute:
- prop_attributes = form_value.Unsigned();
- break;
- case DW_AT_external:
- is_external = form_value.Boolean();
- break;
-
- default:
- case DW_AT_declaration:
- case DW_AT_description:
- case DW_AT_mutable:
- case DW_AT_visibility:
- case DW_AT_sibling:
- break;
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes(attributes);
+ if (num_attributes > 0) {
+ const char *name = nullptr;
+ const char *prop_name = nullptr;
+ const char *prop_getter_name = nullptr;
+ const char *prop_setter_name = nullptr;
+ uint32_t prop_attributes = 0;
+
+ bool is_artificial = false;
+ DWARFFormValue encoding_form;
+ AccessType accessibility = eAccessNone;
+ uint32_t member_byte_offset =
+ (parent_die.Tag() == DW_TAG_union_type) ? 0 : UINT32_MAX;
+ llvm::Optional<uint64_t> byte_size;
+ int64_t bit_offset = 0;
+ uint64_t data_bit_offset = UINT64_MAX;
+ size_t bit_size = 0;
+ bool is_external =
+ false; // On DW_TAG_members, this means the member is static
+ uint32_t i;
+ for (i = 0; i < num_attributes && !is_artificial; ++i) {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value)) {
+ switch (attr) {
+ case DW_AT_name:
+ name = form_value.AsCString();
+ break;
+ case DW_AT_type:
+ encoding_form = form_value;
+ break;
+ case DW_AT_bit_offset:
+ bit_offset = form_value.Signed();
+ break;
+ case DW_AT_bit_size:
+ bit_size = form_value.Unsigned();
+ break;
+ case DW_AT_byte_size:
+ byte_size = form_value.Unsigned();
+ break;
+ case DW_AT_data_bit_offset:
+ data_bit_offset = form_value.Unsigned();
+ break;
+ case DW_AT_data_member_location:
+ if (form_value.BlockData()) {
+ Value initialValue(0);
+ Value memberOffset(0);
+ const DWARFDataExtractor &debug_info_data = die.GetData();
+ uint32_t block_length = form_value.Unsigned();
+ uint32_t block_offset =
+ form_value.BlockData() - debug_info_data.GetDataStart();
+ if (DWARFExpression::Evaluate(
+ nullptr, // ExecutionContext *
+ nullptr, // RegisterContext *
+ module_sp,
+ DataExtractor(debug_info_data, block_offset, block_length),
+ die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr,
+ memberOffset, nullptr)) {
+ member_byte_offset = memberOffset.ResolveValue(nullptr).UInt();
}
+ } else {
+ // With DWARF 3 and later, if the value is an integer constant,
+ // this form value is the offset in bytes from the beginning of
+ // the containing entity.
+ member_byte_offset = form_value.Unsigned();
}
- }
-
- if (prop_name) {
- ConstString fixed_getter;
- ConstString fixed_setter;
-
- // Check if the property getter/setter were provided as full names.
- // We want basenames, so we extract them.
-
- if (prop_getter_name && prop_getter_name[0] == '-') {
- ObjCLanguage::MethodName prop_getter_method(prop_getter_name, true);
- prop_getter_name = prop_getter_method.GetSelector().GetCString();
- }
+ break;
- if (prop_setter_name && prop_setter_name[0] == '-') {
- ObjCLanguage::MethodName prop_setter_method(prop_setter_name, true);
- prop_setter_name = prop_setter_method.GetSelector().GetCString();
- }
+ case DW_AT_accessibility:
+ accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
+ break;
+ case DW_AT_artificial:
+ is_artificial = form_value.Boolean();
+ break;
+ case DW_AT_APPLE_property_name:
+ prop_name = form_value.AsCString();
+ break;
+ case DW_AT_APPLE_property_getter:
+ prop_getter_name = form_value.AsCString();
+ break;
+ case DW_AT_APPLE_property_setter:
+ prop_setter_name = form_value.AsCString();
+ break;
+ case DW_AT_APPLE_property_attribute:
+ prop_attributes = form_value.Unsigned();
+ break;
+ case DW_AT_external:
+ is_external = form_value.Boolean();
+ break;
- // If the names haven't been provided, they need to be filled in.
+ default:
+ case DW_AT_declaration:
+ case DW_AT_description:
+ case DW_AT_mutable:
+ case DW_AT_visibility:
+ case DW_AT_sibling:
+ break;
+ }
+ }
+ }
- if (!prop_getter_name) {
- prop_getter_name = prop_name;
- }
- if (!prop_setter_name && prop_name[0] &&
- !(prop_attributes & DW_APPLE_PROPERTY_readonly)) {
- StreamString ss;
+ if (prop_name) {
+ ConstString fixed_setter;
- ss.Printf("set%c%s:", toupper(prop_name[0]), &prop_name[1]);
+ // Check if the property getter/setter were provided as full names.
+ // We want basenames, so we extract them.
- fixed_setter.SetString(ss.GetString());
- prop_setter_name = fixed_setter.GetCString();
- }
- }
+ if (prop_getter_name && prop_getter_name[0] == '-') {
+ ObjCLanguage::MethodName prop_getter_method(prop_getter_name, true);
+ prop_getter_name = prop_getter_method.GetSelector().GetCString();
+ }
- // Clang has a DWARF generation bug where sometimes it represents
- // fields that are references with bad byte size and bit size/offset
- // information such as:
- //
- // DW_AT_byte_size( 0x00 )
- // DW_AT_bit_size( 0x40 )
- // DW_AT_bit_offset( 0xffffffffffffffc0 )
- //
- // So check the bit offset to make sure it is sane, and if the values
- // are not sane, remove them. If we don't do this then we will end up
- // with a crash if we try to use this type in an expression when clang
- // becomes unhappy with its recycled debug info.
-
- if (byte_size.getValueOr(0) == 0 && bit_offset < 0) {
- bit_size = 0;
- bit_offset = 0;
- }
+ if (prop_setter_name && prop_setter_name[0] == '-') {
+ ObjCLanguage::MethodName prop_setter_method(prop_setter_name, true);
+ prop_setter_name = prop_setter_method.GetSelector().GetCString();
+ }
- // FIXME: Make Clang ignore Objective-C accessibility for expressions
- if (class_language == eLanguageTypeObjC ||
- class_language == eLanguageTypeObjC_plus_plus)
- accessibility = eAccessNone;
-
- // Handle static members
- if (is_external && member_byte_offset == UINT32_MAX) {
- Type *var_type = die.ResolveTypeUID(encoding_form.Reference());
-
- if (var_type) {
- if (accessibility == eAccessNone)
- accessibility = eAccessPublic;
- ClangASTContext::AddVariableToRecordType(
- class_clang_type, name, var_type->GetLayoutCompilerType(),
- accessibility);
- }
- break;
- }
+ // If the names haven't been provided, they need to be filled in.
- if (!is_artificial) {
- Type *member_type = die.ResolveTypeUID(encoding_form.Reference());
-
- clang::FieldDecl *field_decl = nullptr;
- if (tag == DW_TAG_member) {
- if (member_type) {
- if (accessibility == eAccessNone)
- accessibility = default_accessibility;
- member_accessibilities.push_back(accessibility);
-
- uint64_t field_bit_offset =
- (member_byte_offset == UINT32_MAX ? 0
- : (member_byte_offset * 8));
- if (bit_size > 0) {
-
- BitfieldInfo this_field_info;
- this_field_info.bit_offset = field_bit_offset;
- this_field_info.bit_size = bit_size;
-
- /////////////////////////////////////////////////////////////
- // How to locate a field given the DWARF debug information
- //
- // AT_byte_size indicates the size of the word in which the bit
- // offset must be interpreted.
- //
- // AT_data_member_location indicates the byte offset of the
- // word from the base address of the structure.
- //
- // AT_bit_offset indicates how many bits into the word
- // (according to the host endianness) the low-order bit of the
- // field starts. AT_bit_offset can be negative.
- //
- // AT_bit_size indicates the size of the field in bits.
- /////////////////////////////////////////////////////////////
-
- if (data_bit_offset != UINT64_MAX) {
- this_field_info.bit_offset = data_bit_offset;
- } else {
- if (!byte_size)
- byte_size = member_type->GetByteSize();
-
- ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
- if (objfile->GetByteOrder() == eByteOrderLittle) {
- this_field_info.bit_offset += byte_size.getValueOr(0) * 8;
- this_field_info.bit_offset -= (bit_offset + bit_size);
- } else {
- this_field_info.bit_offset += bit_offset;
- }
- }
+ if (!prop_getter_name) {
+ prop_getter_name = prop_name;
+ }
+ if (!prop_setter_name && prop_name[0] &&
+ !(prop_attributes & DW_APPLE_PROPERTY_readonly)) {
+ StreamString ss;
- if ((this_field_info.bit_offset >= parent_bit_size) ||
- !last_field_info.NextBitfieldOffsetIsValid(
- this_field_info.bit_offset)) {
- ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
- objfile->GetModule()->ReportWarning(
- "0x%8.8" PRIx64 ": %s bitfield named \"%s\" has invalid "
- "bit offset (0x%8.8" PRIx64
- ") member will be ignored. Please file a bug against the "
- "compiler and include the preprocessed output for %s\n",
- die.GetID(), DW_TAG_value_to_name(tag), name,
- this_field_info.bit_offset,
- GetUnitName(parent_die).c_str());
- this_field_info.Clear();
- continue;
- }
+ ss.Printf("set%c%s:", toupper(prop_name[0]), &prop_name[1]);
- // Update the field bit offset we will report for layout
- field_bit_offset = this_field_info.bit_offset;
-
- // If the member to be emitted did not start on a character
- // boundary and there is empty space between the last field and
- // this one, then we need to emit an anonymous member filling
- // up the space up to its start. There are three cases here:
- //
- // 1 If the previous member ended on a character boundary, then
- // we can emit an
- // anonymous member starting at the most recent character
- // boundary.
- //
- // 2 If the previous member did not end on a character boundary
- // and the distance
- // from the end of the previous member to the current member
- // is less than a
- // word width, then we can emit an anonymous member starting
- // right after the
- // previous member and right before this member.
- //
- // 3 If the previous member did not end on a character boundary
- // and the distance
- // from the end of the previous member to the current member
- // is greater than
- // or equal a word width, then we act as in Case 1.
-
- const uint64_t character_width = 8;
- const uint64_t word_width = 32;
-
- // Objective-C has invalid DW_AT_bit_offset values in older
- // versions of clang, so we have to be careful and only insert
- // unnamed bitfields if we have a new enough clang.
- bool detect_unnamed_bitfields = true;
-
- if (class_language == eLanguageTypeObjC ||
- class_language == eLanguageTypeObjC_plus_plus)
- detect_unnamed_bitfields =
- die.GetCU()->Supports_unnamed_objc_bitfields();
-
- if (detect_unnamed_bitfields) {
- BitfieldInfo anon_field_info;
-
- if ((this_field_info.bit_offset % character_width) !=
- 0) // not char aligned
- {
- uint64_t last_field_end = 0;
-
- if (last_field_info.IsValid())
- last_field_end =
- last_field_info.bit_offset + last_field_info.bit_size;
-
- if (this_field_info.bit_offset != last_field_end) {
- if (((last_field_end % character_width) == 0) || // case 1
- (this_field_info.bit_offset - last_field_end >=
- word_width)) // case 3
- {
- anon_field_info.bit_size =
- this_field_info.bit_offset % character_width;
- anon_field_info.bit_offset =
- this_field_info.bit_offset -
- anon_field_info.bit_size;
- } else // case 2
- {
- anon_field_info.bit_size =
- this_field_info.bit_offset - last_field_end;
- anon_field_info.bit_offset = last_field_end;
- }
- }
- }
+ fixed_setter.SetString(ss.GetString());
+ prop_setter_name = fixed_setter.GetCString();
+ }
+ }
- if (anon_field_info.IsValid()) {
- clang::FieldDecl *unnamed_bitfield_decl =
- ClangASTContext::AddFieldToRecordType(
- class_clang_type, llvm::StringRef(),
- m_ast.GetBuiltinTypeForEncodingAndBitSize(
- eEncodingSint, word_width),
- accessibility, anon_field_info.bit_size);
+ // Clang has a DWARF generation bug where sometimes it represents
+ // fields that are references with bad byte size and bit size/offset
+ // information such as:
+ //
+ // DW_AT_byte_size( 0x00 )
+ // DW_AT_bit_size( 0x40 )
+ // DW_AT_bit_offset( 0xffffffffffffffc0 )
+ //
+ // So check the bit offset to make sure it is sane, and if the values
+ // are not sane, remove them. If we don't do this then we will end up
+ // with a crash if we try to use this type in an expression when clang
+ // becomes unhappy with its recycled debug info.
+
+ if (byte_size.getValueOr(0) == 0 && bit_offset < 0) {
+ bit_size = 0;
+ bit_offset = 0;
+ }
+
+ // FIXME: Make Clang ignore Objective-C accessibility for expressions
+ if (class_language == eLanguageTypeObjC ||
+ class_language == eLanguageTypeObjC_plus_plus)
+ accessibility = eAccessNone;
+
+ // Handle static members
+ if (is_external && member_byte_offset == UINT32_MAX) {
+ Type *var_type = die.ResolveTypeUID(encoding_form.Reference());
+
+ if (var_type) {
+ if (accessibility == eAccessNone)
+ accessibility = eAccessPublic;
+ ClangASTContext::AddVariableToRecordType(
+ class_clang_type, name, var_type->GetLayoutCompilerType(),
+ accessibility);
+ }
+ return;
+ }
+
+ if (!is_artificial) {
+ Type *member_type = die.ResolveTypeUID(encoding_form.Reference());
+
+ clang::FieldDecl *field_decl = nullptr;
+ if (tag == DW_TAG_member) {
+ if (member_type) {
+ if (accessibility == eAccessNone)
+ accessibility = default_accessibility;
+ member_accessibilities.push_back(accessibility);
+
+ uint64_t field_bit_offset =
+ (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8));
+ if (bit_size > 0) {
+
+ BitfieldInfo this_field_info;
+ this_field_info.bit_offset = field_bit_offset;
+ this_field_info.bit_size = bit_size;
+
+ /////////////////////////////////////////////////////////////
+ // How to locate a field given the DWARF debug information
+ //
+ // AT_byte_size indicates the size of the word in which the bit
+ // offset must be interpreted.
+ //
+ // AT_data_member_location indicates the byte offset of the
+ // word from the base address of the structure.
+ //
+ // AT_bit_offset indicates how many bits into the word
+ // (according to the host endianness) the low-order bit of the
+ // field starts. AT_bit_offset can be negative.
+ //
+ // AT_bit_size indicates the size of the field in bits.
+ /////////////////////////////////////////////////////////////
+
+ if (data_bit_offset != UINT64_MAX) {
+ this_field_info.bit_offset = data_bit_offset;
+ } else {
+ if (!byte_size)
+ byte_size = member_type->GetByteSize();
- layout_info.field_offsets.insert(std::make_pair(
- unnamed_bitfield_decl, anon_field_info.bit_offset));
- }
- }
- last_field_info = this_field_info;
+ ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
+ if (objfile->GetByteOrder() == eByteOrderLittle) {
+ this_field_info.bit_offset += byte_size.getValueOr(0) * 8;
+ this_field_info.bit_offset -= (bit_offset + bit_size);
} else {
- last_field_info.Clear();
+ this_field_info.bit_offset += bit_offset;
}
+ }
- CompilerType member_clang_type =
- member_type->GetLayoutCompilerType();
- if (!member_clang_type.IsCompleteType())
- member_clang_type.GetCompleteType();
+ if ((this_field_info.bit_offset >= parent_bit_size) ||
+ !last_field_info.NextBitfieldOffsetIsValid(
+ this_field_info.bit_offset)) {
+ ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
+ objfile->GetModule()->ReportWarning(
+ "0x%8.8" PRIx64 ": %s bitfield named \"%s\" has invalid "
+ "bit offset (0x%8.8" PRIx64
+ ") member will be ignored. Please file a bug against the "
+ "compiler and include the preprocessed output for %s\n",
+ die.GetID(), DW_TAG_value_to_name(tag), name,
+ this_field_info.bit_offset, GetUnitName(parent_die).c_str());
+ this_field_info.Clear();
+ return;
+ }
+ // Update the field bit offset we will report for layout
+ field_bit_offset = this_field_info.bit_offset;
+
+ // If the member to be emitted did not start on a character
+ // boundary and there is empty space between the last field and
+ // this one, then we need to emit an anonymous member filling
+ // up the space up to its start. There are three cases here:
+ //
+ // 1 If the previous member ended on a character boundary, then
+ // we can emit an
+ // anonymous member starting at the most recent character
+ // boundary.
+ //
+ // 2 If the previous member did not end on a character boundary
+ // and the distance
+ // from the end of the previous member to the current member
+ // is less than a
+ // word width, then we can emit an anonymous member starting
+ // right after the
+ // previous member and right before this member.
+ //
+ // 3 If the previous member did not end on a character boundary
+ // and the distance
+ // from the end of the previous member to the current member
+ // is greater than
+ // or equal a word width, then we act as in Case 1.
+
+ const uint64_t character_width = 8;
+ const uint64_t word_width = 32;
+
+ // Objective-C has invalid DW_AT_bit_offset values in older
+ // versions of clang, so we have to be careful and only insert
+ // unnamed bitfields if we have a new enough clang.
+ bool detect_unnamed_bitfields = true;
+
+ if (class_language == eLanguageTypeObjC ||
+ class_language == eLanguageTypeObjC_plus_plus)
+ detect_unnamed_bitfields =
+ die.GetCU()->Supports_unnamed_objc_bitfields();
+
+ if (detect_unnamed_bitfields) {
+ BitfieldInfo anon_field_info;
+
+ if ((this_field_info.bit_offset % character_width) !=
+ 0) // not char aligned
{
- // Older versions of clang emit array[0] and array[1] in the
- // same way (<rdar://problem/12566646>). If the current field
- // is at the end of the structure, then there is definitely no
- // room for extra elements and we override the type to
- // array[0].
-
- CompilerType member_array_element_type;
- uint64_t member_array_size;
- bool member_array_is_incomplete;
-
- if (member_clang_type.IsArrayType(
- &member_array_element_type, &member_array_size,
- &member_array_is_incomplete) &&
- !member_array_is_incomplete) {
- uint64_t parent_byte_size =
- parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size,
- UINT64_MAX);
-
- if (member_byte_offset >= parent_byte_size) {
- if (member_array_size != 1 &&
- (member_array_size != 0 ||
- member_byte_offset > parent_byte_size)) {
- module_sp->ReportError(
- "0x%8.8" PRIx64
- ": DW_TAG_member '%s' refers to type 0x%8.8x"
- " which extends beyond the bounds of 0x%8.8" PRIx64,
- die.GetID(), name,
- encoding_form.Reference().GetOffset(),
- parent_die.GetID());
- }
+ uint64_t last_field_end = 0;
+
+ if (last_field_info.IsValid())
+ last_field_end =
+ last_field_info.bit_offset + last_field_info.bit_size;
- member_clang_type = m_ast.CreateArrayType(
- member_array_element_type, 0, false);
+ if (this_field_info.bit_offset != last_field_end) {
+ if (((last_field_end % character_width) == 0) || // case 1
+ (this_field_info.bit_offset - last_field_end >=
+ word_width)) // case 3
+ {
+ anon_field_info.bit_size =
+ this_field_info.bit_offset % character_width;
+ anon_field_info.bit_offset =
+ this_field_info.bit_offset - anon_field_info.bit_size;
+ } else // case 2
+ {
+ anon_field_info.bit_size =
+ this_field_info.bit_offset - last_field_end;
+ anon_field_info.bit_offset = last_field_end;
}
}
}
- if (ClangASTContext::IsCXXClassType(member_clang_type) &&
- !member_clang_type.GetCompleteType()) {
- if (die.GetCU()->GetProducer() == eProducerClang)
- module_sp->ReportError(
- "DWARF DIE at 0x%8.8x (class %s) has a member variable "
- "0x%8.8x (%s) whose type is a forward declaration, not a "
- "complete definition.\nTry compiling the source file "
- "with -fstandalone-debug",
- parent_die.GetOffset(), parent_die.GetName(),
- die.GetOffset(), name);
- else
- module_sp->ReportError(
- "DWARF DIE at 0x%8.8x (class %s) has a member variable "
- "0x%8.8x (%s) whose type is a forward declaration, not a "
- "complete definition.\nPlease file a bug against the "
- "compiler and include the preprocessed output for %s",
- parent_die.GetOffset(), parent_die.GetName(),
- die.GetOffset(), name, GetUnitName(parent_die).c_str());
- // We have no choice other than to pretend that the member
- // class is complete. If we don't do this, clang will crash
- // when trying to layout the class. Since we provide layout
- // assistance, all ivars in this class and other classes will
- // be fine, this is the best we can do short of crashing.
- if (ClangASTContext::StartTagDeclarationDefinition(
- member_clang_type)) {
- ClangASTContext::CompleteTagDeclarationDefinition(
- member_clang_type);
- } else {
- module_sp->ReportError(
- "DWARF DIE at 0x%8.8x (class %s) has a member variable "
- "0x%8.8x (%s) whose type claims to be a C++ class but we "
- "were not able to start its definition.\nPlease file a "
- "bug and attach the file at the start of this error "
- "message",
- parent_die.GetOffset(), parent_die.GetName(),
- die.GetOffset(), name);
- }
+ if (anon_field_info.IsValid()) {
+ clang::FieldDecl *unnamed_bitfield_decl =
+ ClangASTContext::AddFieldToRecordType(
+ class_clang_type, llvm::StringRef(),
+ m_ast.GetBuiltinTypeForEncodingAndBitSize(eEncodingSint,
+ word_width),
+ accessibility, anon_field_info.bit_size);
+
+ layout_info.field_offsets.insert(std::make_pair(
+ unnamed_bitfield_decl, anon_field_info.bit_offset));
}
+ }
+ last_field_info = this_field_info;
+ } else {
+ last_field_info.Clear();
+ }
- field_decl = ClangASTContext::AddFieldToRecordType(
- class_clang_type, name, member_clang_type, accessibility,
- bit_size);
+ CompilerType member_clang_type = member_type->GetLayoutCompilerType();
+ if (!member_clang_type.IsCompleteType())
+ member_clang_type.GetCompleteType();
+
+ {
+ // Older versions of clang emit array[0] and array[1] in the
+ // same way (<rdar://problem/12566646>). If the current field
+ // is at the end of the structure, then there is definitely no
+ // room for extra elements and we override the type to
+ // array[0].
+
+ CompilerType member_array_element_type;
+ uint64_t member_array_size;
+ bool member_array_is_incomplete;
+
+ if (member_clang_type.IsArrayType(&member_array_element_type,
+ &member_array_size,
+ &member_array_is_incomplete) &&
+ !member_array_is_incomplete) {
+ uint64_t parent_byte_size =
+ parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size,
+ UINT64_MAX);
+
+ if (member_byte_offset >= parent_byte_size) {
+ if (member_array_size != 1 &&
+ (member_array_size != 0 ||
+ member_byte_offset > parent_byte_size)) {
+ module_sp->ReportError(
+ "0x%8.8" PRIx64
+ ": DW_TAG_member '%s' refers to type 0x%8.8x"
+ " which extends beyond the bounds of 0x%8.8" PRIx64,
+ die.GetID(), name, encoding_form.Reference().GetOffset(),
+ parent_die.GetID());
+ }
- m_ast.SetMetadataAsUserID(field_decl, die.GetID());
+ member_clang_type =
+ m_ast.CreateArrayType(member_array_element_type, 0, false);
+ }
+ }
+ }
- layout_info.field_offsets.insert(
- std::make_pair(field_decl, field_bit_offset));
+ if (ClangASTContext::IsCXXClassType(member_clang_type) &&
+ !member_clang_type.GetCompleteType()) {
+ if (die.GetCU()->GetProducer() == eProducerClang)
+ module_sp->ReportError(
+ "DWARF DIE at 0x%8.8x (class %s) has a member variable "
+ "0x%8.8x (%s) whose type is a forward declaration, not a "
+ "complete definition.\nTry compiling the source file "
+ "with -fstandalone-debug",
+ parent_die.GetOffset(), parent_die.GetName(), die.GetOffset(),
+ name);
+ else
+ module_sp->ReportError(
+ "DWARF DIE at 0x%8.8x (class %s) has a member variable "
+ "0x%8.8x (%s) whose type is a forward declaration, not a "
+ "complete definition.\nPlease file a bug against the "
+ "compiler and include the preprocessed output for %s",
+ parent_die.GetOffset(), parent_die.GetName(), die.GetOffset(),
+ name, GetUnitName(parent_die).c_str());
+ // We have no choice other than to pretend that the member
+ // class is complete. If we don't do this, clang will crash
+ // when trying to layout the class. Since we provide layout
+ // assistance, all ivars in this class and other classes will
+ // be fine, this is the best we can do short of crashing.
+ if (ClangASTContext::StartTagDeclarationDefinition(
+ member_clang_type)) {
+ ClangASTContext::CompleteTagDeclarationDefinition(
+ member_clang_type);
} else {
- if (name)
- module_sp->ReportError(
- "0x%8.8" PRIx64
- ": DW_TAG_member '%s' refers to type 0x%8.8x"
- " which was unable to be parsed",
- die.GetID(), name, encoding_form.Reference().GetOffset());
- else
- module_sp->ReportError(
- "0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8x"
- " which was unable to be parsed",
- die.GetID(), encoding_form.Reference().GetOffset());
+ module_sp->ReportError(
+ "DWARF DIE at 0x%8.8x (class %s) has a member variable "
+ "0x%8.8x (%s) whose type claims to be a C++ class but we "
+ "were not able to start its definition.\nPlease file a "
+ "bug and attach the file at the start of this error "
+ "message",
+ parent_die.GetOffset(), parent_die.GetName(), die.GetOffset(),
+ name);
}
}
- if (prop_name != nullptr && member_type) {
- clang::ObjCIvarDecl *ivar_decl = nullptr;
+ field_decl = ClangASTContext::AddFieldToRecordType(
+ class_clang_type, name, member_clang_type, accessibility,
+ bit_size);
- if (field_decl) {
- ivar_decl = clang::dyn_cast<clang::ObjCIvarDecl>(field_decl);
- assert(ivar_decl != nullptr);
- }
+ m_ast.SetMetadataAsUserID(field_decl, die.GetID());
- ClangASTMetadata metadata;
- metadata.SetUserID(die.GetID());
- delayed_properties.push_back(DelayedAddObjCClassProperty(
- class_clang_type, prop_name,
- member_type->GetLayoutCompilerType(), ivar_decl,
- prop_setter_name, prop_getter_name, prop_attributes,
- &metadata));
+ layout_info.field_offsets.insert(
+ std::make_pair(field_decl, field_bit_offset));
+ } else {
+ if (name)
+ module_sp->ReportError(
+ "0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8x"
+ " which was unable to be parsed",
+ die.GetID(), name, encoding_form.Reference().GetOffset());
+ else
+ module_sp->ReportError(
+ "0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8x"
+ " which was unable to be parsed",
+ die.GetID(), encoding_form.Reference().GetOffset());
+ }
+ }
- if (ivar_decl)
- m_ast.SetMetadataAsUserID(ivar_decl, die.GetID());
- }
+ if (prop_name != nullptr && member_type) {
+ clang::ObjCIvarDecl *ivar_decl = nullptr;
+
+ if (field_decl) {
+ ivar_decl = clang::dyn_cast<clang::ObjCIvarDecl>(field_decl);
+ assert(ivar_decl != nullptr);
}
+
+ ClangASTMetadata metadata;
+ metadata.SetUserID(die.GetID());
+ delayed_properties.push_back(DelayedAddObjCClassProperty(
+ class_clang_type, prop_name, member_type->GetLayoutCompilerType(),
+ ivar_decl, prop_setter_name, prop_getter_name, prop_attributes,
+ &metadata));
+
+ if (ivar_decl)
+ m_ast.SetMetadataAsUserID(ivar_decl, die.GetID());
}
- ++member_idx;
- } break;
+ }
+ }
+}
+
+bool DWARFASTParserClang::ParseChildMembers(
+ const DWARFDIE &parent_die, CompilerType &class_clang_type,
+ const LanguageType class_language,
+ std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,
+ std::vector<int> &member_accessibilities,
+ std::vector<DWARFDIE> &member_function_dies,
+ DelayedPropertyList &delayed_properties, AccessType &default_accessibility,
+ bool &is_a_class, ClangASTImporter::LayoutInfo &layout_info) {
+ if (!parent_die)
+ return false;
+
+ BitfieldInfo last_field_info;
+
+ ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
+ ClangASTContext *ast =
+ llvm::dyn_cast_or_null<ClangASTContext>(class_clang_type.GetTypeSystem());
+ if (ast == nullptr)
+ return false;
+
+ for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
+ die = die.GetSibling()) {
+ dw_tag_t tag = die.Tag();
+
+ switch (tag) {
+ case DW_TAG_member:
+ case DW_TAG_APPLE_property:
+ ParseSingleMember(die, parent_die, class_clang_type, class_language,
+ member_accessibilities, default_accessibility,
+ delayed_properties, layout_info, last_field_info);
+ break;
case DW_TAG_subprogram:
// Let the type parsing code handle this one for us.
@@ -3552,18 +3522,20 @@ DWARFASTParserClang::ResolveNamespaceDIE(const DWARFDIE &die) {
SymbolFileDWARF *dwarf = die.GetDWARF();
if (namespace_name) {
dwarf->GetObjectFile()->GetModule()->LogMessage(
- log, "ASTContext => %p: 0x%8.8" PRIx64
- ": DW_TAG_namespace with DW_AT_name(\"%s\") => "
- "clang::NamespaceDecl *%p (original = %p)",
- static_cast<void *>(m_ast.getASTContext()), die.GetID(),
+ log,
+ "ASTContext => %p: 0x%8.8" PRIx64
+ ": DW_TAG_namespace with DW_AT_name(\"%s\") => "
+ "clang::NamespaceDecl *%p (original = %p)",
+ static_cast<void *>(&m_ast.getASTContext()), die.GetID(),
namespace_name, static_cast<void *>(namespace_decl),
static_cast<void *>(namespace_decl->getOriginalNamespace()));
} else {
dwarf->GetObjectFile()->GetModule()->LogMessage(
- log, "ASTContext => %p: 0x%8.8" PRIx64
- ": DW_TAG_namespace (anonymous) => clang::NamespaceDecl *%p "
- "(original = %p)",
- static_cast<void *>(m_ast.getASTContext()), die.GetID(),
+ log,
+ "ASTContext => %p: 0x%8.8" PRIx64
+ ": DW_TAG_namespace (anonymous) => clang::NamespaceDecl *%p "
+ "(original = %p)",
+ static_cast<void *>(&m_ast.getASTContext()), die.GetID(),
static_cast<void *>(namespace_decl),
static_cast<void *>(namespace_decl->getOriginalNamespace()));
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index 106f9254a449..4ad757247c3e 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -128,7 +128,8 @@ protected:
const DWARFDIE &parent_die);
/// Parse a structure, class, or union type DIE.
- lldb::TypeSP ParseStructureLikeDIE(const DWARFDIE &die,
+ lldb::TypeSP ParseStructureLikeDIE(const lldb_private::SymbolContext &sc,
+ const DWARFDIE &die,
ParsedDWARFTypeAttributes &attrs);
lldb_private::Type *GetTypeForDIE(const DWARFDIE &die);
@@ -159,11 +160,73 @@ protected:
UpdateSymbolContextScopeForType(const lldb_private::SymbolContext &sc,
const DWARFDIE &die, lldb::TypeSP type_sp);
- lldb::TypeSP ParseTypeFromDWO(const DWARFDIE &die, lldb_private::Log *log);
+ /// Follow Clang Module Skeleton CU references to find a type definition.
+ lldb::TypeSP ParseTypeFromClangModule(const lldb_private::SymbolContext &sc,
+ const DWARFDIE &die,
+ lldb_private::Log *log);
// Return true if this type is a declaration to a type in an external
// module.
lldb::ModuleSP GetModuleForType(const DWARFDIE &die);
+
+private:
+ struct BitfieldInfo {
+ uint64_t bit_size;
+ uint64_t bit_offset;
+
+ BitfieldInfo()
+ : bit_size(LLDB_INVALID_ADDRESS), bit_offset(LLDB_INVALID_ADDRESS) {}
+
+ void Clear() {
+ bit_size = LLDB_INVALID_ADDRESS;
+ bit_offset = LLDB_INVALID_ADDRESS;
+ }
+
+ bool IsValid() const {
+ return (bit_size != LLDB_INVALID_ADDRESS) &&
+ (bit_offset != LLDB_INVALID_ADDRESS);
+ }
+
+ bool NextBitfieldOffsetIsValid(const uint64_t next_bit_offset) const {
+ if (IsValid()) {
+ // This bitfield info is valid, so any subsequent bitfields must not
+ // overlap and must be at a higher bit offset than any previous bitfield
+ // + size.
+ return (bit_size + bit_offset) <= next_bit_offset;
+ } else {
+ // If the this BitfieldInfo is not valid, then any offset isOK
+ return true;
+ }
+ }
+ };
+
+ void
+ ParseSingleMember(const DWARFDIE &die, const DWARFDIE &parent_die,
+ lldb_private::CompilerType &class_clang_type,
+ const lldb::LanguageType class_language,
+ std::vector<int> &member_accessibilities,
+ lldb::AccessType &default_accessibility,
+ DelayedPropertyList &delayed_properties,
+ lldb_private::ClangASTImporter::LayoutInfo &layout_info,
+ BitfieldInfo &last_field_info);
+
+ bool CompleteRecordType(const DWARFDIE &die, lldb_private::Type *type,
+ lldb_private::CompilerType &clang_type);
+ bool CompleteEnumType(const DWARFDIE &die, lldb_private::Type *type,
+ lldb_private::CompilerType &clang_type);
+
+ lldb::TypeSP ParseTypeModifier(const lldb_private::SymbolContext &sc,
+ const DWARFDIE &die,
+ ParsedDWARFTypeAttributes &attrs);
+ lldb::TypeSP ParseEnum(const lldb_private::SymbolContext &sc,
+ const DWARFDIE &die, ParsedDWARFTypeAttributes &attrs);
+ lldb::TypeSP ParseSubroutine(const DWARFDIE &die,
+ ParsedDWARFTypeAttributes &attrs);
+ // FIXME: attrs should be passed as a const reference.
+ lldb::TypeSP ParseArrayType(const DWARFDIE &die,
+ ParsedDWARFTypeAttributes &attrs);
+ lldb::TypeSP ParsePointerToMemberType(const DWARFDIE &die,
+ const ParsedDWARFTypeAttributes &attrs);
};
/// Parsed form of all attributes that are relevant for type reconstruction.
@@ -181,6 +244,8 @@ struct ParsedDWARFTypeAttributes {
bool is_scoped_enum = false;
bool is_vector = false;
bool is_virtual = false;
+ bool is_objc_direct_call = false;
+ bool exports_symbols = false;
clang::StorageClass storage = clang::SC_None;
const char *mangled_name = nullptr;
lldb_private::ConstString name;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
index 75647dbb082f..454637ef981c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
@@ -24,8 +24,8 @@ private:
DWARFCompileUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
const DWARFUnitHeader &header,
const DWARFAbbreviationDeclarationSet &abbrevs,
- DIERef::Section section)
- : DWARFUnit(dwarf, uid, header, abbrevs, section) {}
+ DIERef::Section section, bool is_dwo)
+ : DWARFUnit(dwarf, uid, header, abbrevs, section, is_dwo) {}
DISALLOW_COPY_AND_ASSIGN(DWARFCompileUnit);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp
index eb307ce1cce1..5052b825fea6 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp
@@ -70,6 +70,17 @@ const DWARFDataExtractor &DWARFContext::getOrLoadLineStrData() {
m_data_debug_line_str);
}
+const DWARFDataExtractor &DWARFContext::getOrLoadLocData() {
+ return LoadOrGetSection(eSectionTypeDWARFDebugLoc,
+ eSectionTypeDWARFDebugLocDwo, m_data_debug_loc);
+}
+
+const DWARFDataExtractor &DWARFContext::getOrLoadLocListsData() {
+ return LoadOrGetSection(eSectionTypeDWARFDebugLocLists,
+ eSectionTypeDWARFDebugLocListsDwo,
+ m_data_debug_loclists);
+}
+
const DWARFDataExtractor &DWARFContext::getOrLoadMacroData() {
return LoadOrGetSection(eSectionTypeDWARFDebugMacro, llvm::None,
m_data_debug_macro);
@@ -81,7 +92,8 @@ const DWARFDataExtractor &DWARFContext::getOrLoadRangesData() {
}
const DWARFDataExtractor &DWARFContext::getOrLoadRngListsData() {
- return LoadOrGetSection(eSectionTypeDWARFDebugRngLists, llvm::None,
+ return LoadOrGetSection(eSectionTypeDWARFDebugRngLists,
+ eSectionTypeDWARFDebugRngListsDwo,
m_data_debug_rnglists);
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h
index add042384039..8691001b1b76 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h
@@ -34,6 +34,8 @@ private:
SectionData m_data_debug_info;
SectionData m_data_debug_line;
SectionData m_data_debug_line_str;
+ SectionData m_data_debug_loc;
+ SectionData m_data_debug_loclists;
SectionData m_data_debug_macro;
SectionData m_data_debug_ranges;
SectionData m_data_debug_rnglists;
@@ -41,8 +43,6 @@ private:
SectionData m_data_debug_str_offsets;
SectionData m_data_debug_types;
- bool isDwo() { return m_dwo_section_list != nullptr; }
-
const DWARFDataExtractor &
LoadOrGetSection(lldb::SectionType main_section_type,
llvm::Optional<lldb::SectionType> dwo_section_type,
@@ -60,6 +60,8 @@ public:
const DWARFDataExtractor &getOrLoadDebugInfoData();
const DWARFDataExtractor &getOrLoadLineData();
const DWARFDataExtractor &getOrLoadLineStrData();
+ const DWARFDataExtractor &getOrLoadLocData();
+ const DWARFDataExtractor &getOrLoadLocListsData();
const DWARFDataExtractor &getOrLoadMacroData();
const DWARFDataExtractor &getOrLoadRangesData();
const DWARFDataExtractor &getOrLoadRngListsData();
@@ -67,6 +69,8 @@ public:
const DWARFDataExtractor &getOrLoadStrOffsetsData();
const DWARFDataExtractor &getOrLoadDebugTypesData();
+ bool isDwo() { return m_dwo_section_list != nullptr; }
+
llvm::DWARFContext &GetAsLLVM();
};
} // namespace lldb_private
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
index 5ee0687995a1..c5411a17f274 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -406,39 +406,6 @@ bool DWARFDIE::IsMethod() const {
return false;
}
-DWARFDIE
-DWARFDIE::GetContainingDWOModuleDIE() const {
- if (IsValid()) {
- DWARFDIE top_module_die;
- // Now make sure this DIE is scoped in a DW_TAG_module tag and return true
- // if so
- for (DWARFDIE parent = GetParent(); parent.IsValid();
- parent = parent.GetParent()) {
- const dw_tag_t tag = parent.Tag();
- if (tag == DW_TAG_module)
- top_module_die = parent;
- else if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
- break;
- }
-
- return top_module_die;
- }
- return DWARFDIE();
-}
-
-lldb::ModuleSP DWARFDIE::GetContainingDWOModule() const {
- if (IsValid()) {
- DWARFDIE dwo_module_die = GetContainingDWOModuleDIE();
-
- if (dwo_module_die) {
- const char *module_name = dwo_module_die.GetName();
- if (module_name)
- return GetDWARF()->GetDWOModule(lldb_private::ConstString(module_name));
- }
- }
- return lldb::ModuleSP();
-}
-
bool DWARFDIE::GetDIENamesAndRanges(
const char *&name, const char *&mangled, DWARFRangeList &ranges,
int &decl_file, int &decl_line, int &decl_column, int &call_file,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
index a779c589611a..87d52eee9dd9 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -22,10 +22,6 @@ public:
bool IsMethod() const;
// Accessors
- lldb::ModuleSP GetContainingDWOModule() const;
-
- DWARFDIE
- GetContainingDWOModuleDIE() const;
// Accessing information about a DIE
const char *GetMangledName() const;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
index d1b066ffe80c..056cf33a202f 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
@@ -16,7 +16,6 @@
#include "DWARFTypeUnit.h"
#include "DWARFUnit.h"
#include "SymbolFileDWARF.h"
-#include "lldb/Core/STLUtils.h"
#include "lldb/lldb-private.h"
#include "llvm/Support/Error.h"
@@ -24,11 +23,6 @@ namespace lldb_private {
class DWARFContext;
}
-typedef std::multimap<const char *, dw_offset_t, CStringCompareFunctionObject>
- CStringToDIEMap;
-typedef CStringToDIEMap::iterator CStringToDIEMapIter;
-typedef CStringToDIEMap::const_iterator CStringToDIEMapConstIter;
-
class DWARFDebugInfo {
public:
typedef dw_offset_t (*Callback)(SymbolFileDWARF *dwarf2Data,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
index 8c0fbeb4b717..320500fe608d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -156,6 +156,7 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data,
// signed or unsigned LEB 128 values
case DW_FORM_addrx:
+ case DW_FORM_loclistx:
case DW_FORM_rnglistx:
case DW_FORM_sdata:
case DW_FORM_udata:
@@ -200,7 +201,7 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data,
return false;
}
-static DWARFRangeList GetRangesOrReportError(const DWARFUnit &unit,
+static DWARFRangeList GetRangesOrReportError(DWARFUnit &unit,
const DWARFDebugInfoEntry &die,
const DWARFFormValue &value) {
llvm::Expected<DWARFRangeList> expected_ranges =
@@ -223,7 +224,7 @@ static DWARFRangeList GetRangesOrReportError(const DWARFUnit &unit,
// Gets the valid address ranges for a given DIE by looking for a
// DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges attributes.
bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
- const DWARFUnit *cu, const char *&name, const char *&mangled,
+ DWARFUnit *cu, const char *&name, const char *&mangled,
DWARFRangeList &ranges, int &decl_file, int &decl_line, int &decl_column,
int &call_file, int &call_line, int &call_column,
DWARFExpression *frame_base) const {
@@ -343,15 +344,15 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
*frame_base = DWARFExpression(
module, DataExtractor(data, block_offset, block_length), cu);
} else {
- DataExtractor data = dwarf.DebugLocData();
+ DataExtractor data = cu->GetLocationData();
const dw_offset_t offset = form_value.Unsigned();
if (data.ValidOffset(offset)) {
data = DataExtractor(data, offset, data.GetByteSize() - offset);
*frame_base = DWARFExpression(module, data, cu);
if (lo_pc != LLDB_INVALID_ADDRESS) {
assert(lo_pc >= cu->GetBaseAddress());
- frame_base->SetLocationListSlide(lo_pc -
- cu->GetBaseAddress());
+ frame_base->SetLocationListAddresses(cu->GetBaseAddress(),
+ lo_pc);
} else {
set_frame_base_loclist_addr = true;
}
@@ -379,7 +380,7 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
if (set_frame_base_loclist_addr) {
dw_addr_t lowest_range_pc = ranges.GetMinRangeBase(0);
assert(lowest_range_pc >= cu->GetBaseAddress());
- frame_base->SetLocationListSlide(lowest_range_pc - cu->GetBaseAddress());
+ frame_base->SetLocationListAddresses(cu->GetBaseAddress(), lowest_range_pc);
}
if (ranges.IsEmpty() || name == nullptr || mangled == nullptr) {
@@ -477,8 +478,6 @@ void DWARFDebugInfoEntry::DumpAttribute(
s.PutCString("( ");
- SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF();
-
// Check to see if we have any special attribute formatters
switch (attr) {
case DW_AT_stmt_list:
@@ -508,7 +507,7 @@ void DWARFDebugInfoEntry::DumpAttribute(
// We have a location list offset as the value that is the offset into
// the .debug_loc section that describes the value over it's lifetime
uint64_t debug_loc_offset = form_value.Unsigned();
- DWARFExpression::PrintDWARFLocationList(s, cu, dwarf.DebugLocData(),
+ DWARFExpression::PrintDWARFLocationList(s, cu, cu->GetLocationData(),
debug_loc_offset);
}
} break;
@@ -646,25 +645,7 @@ dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
}
}
}
-
- // If we're a unit DIE, also check the attributes of the dwo unit (if any).
- if (GetParent())
- return 0;
- SymbolFileDWARFDwo *dwo_symbol_file = cu->GetDwoSymbolFile();
- if (!dwo_symbol_file)
- return 0;
-
- DWARFCompileUnit *dwo_cu = dwo_symbol_file->GetCompileUnit();
- if (!dwo_cu)
- return 0;
-
- DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly();
- if (!dwo_cu_die.IsValid())
- return 0;
-
- return dwo_cu_die.GetDIE()->GetAttributeValue(
- dwo_cu, attr, form_value, end_attr_offset_ptr,
- check_specification_or_abstract_origin);
+ return 0;
}
// GetAttributeValueAsString
@@ -766,7 +747,7 @@ bool DWARFDebugInfoEntry::GetAttributeAddressRange(
}
size_t DWARFDebugInfoEntry::GetAttributeAddressRanges(
- const DWARFUnit *cu, DWARFRangeList &ranges, bool check_hi_lo_pc,
+ DWARFUnit *cu, DWARFRangeList &ranges, bool check_hi_lo_pc,
bool check_specification_or_abstract_origin) const {
ranges.Clear();
@@ -1012,8 +993,7 @@ DWARFDebugInfoEntry::GetQualifiedName(DWARFUnit *cu,
return storage.c_str();
}
-bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address,
- const DWARFUnit *cu,
+bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, DWARFUnit *cu,
DWARFDebugInfoEntry **function_die,
DWARFDebugInfoEntry **block_die) {
bool found_address = false;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
index 25c885608d85..f35af6e7d498 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
@@ -23,6 +23,10 @@ class DWARFDeclContext;
#define DIE_SIBLING_IDX_BITSIZE 31
+/// DWARFDebugInfoEntry objects assume that they are living in one big
+/// vector and do pointer arithmetic on their this pointers. Don't
+/// pass them by value. Due to the way they are constructed in a
+/// std::vector, we cannot delete the copy constructor.
class DWARFDebugInfoEntry {
public:
typedef std::vector<DWARFDebugInfoEntry> collection;
@@ -46,7 +50,7 @@ public:
bool Extract(const lldb_private::DWARFDataExtractor &data,
const DWARFUnit *cu, lldb::offset_t *offset_ptr);
- bool LookupAddress(const dw_addr_t address, const DWARFUnit *cu,
+ bool LookupAddress(const dw_addr_t address, DWARFUnit *cu,
DWARFDebugInfoEntry **function_die,
DWARFDebugInfoEntry **block_die);
@@ -87,7 +91,7 @@ public:
bool check_specification_or_abstract_origin = false) const;
size_t GetAttributeAddressRanges(
- const DWARFUnit *cu, DWARFRangeList &ranges, bool check_hi_lo_pc,
+ DWARFUnit *cu, DWARFRangeList &ranges, bool check_hi_lo_pc,
bool check_specification_or_abstract_origin = false) const;
const char *GetName(const DWARFUnit *cu) const;
@@ -112,7 +116,7 @@ public:
dw_attr_t attr, DWARFFormValue &form_value);
bool GetDIENamesAndRanges(
- const DWARFUnit *cu, const char *&name, const char *&mangled,
+ DWARFUnit *cu, const char *&name, const char *&mangled,
DWARFRangeList &rangeList, int &decl_file, int &decl_line,
int &decl_column, int &call_file, int &call_line, int &call_column,
lldb_private::DWARFExpression *frame_base = nullptr) const;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
index 0b08fa09f906..6c074002cb20 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
@@ -95,13 +95,15 @@ void DWARFDebugRanges::Dump(Stream &s,
} else if (begin == LLDB_INVALID_ADDRESS) {
// A base address selection entry
base_addr = end;
- s.Address(base_addr, sizeof(dw_addr_t), " Base address = ");
+ DumpAddress(s.AsRawOstream(), base_addr, sizeof(dw_addr_t),
+ " Base address = ");
} else {
// Convert from offset to an address
dw_addr_t begin_addr = begin + base_addr;
dw_addr_t end_addr = end + base_addr;
- s.AddressRange(begin_addr, end_addr, sizeof(dw_addr_t), nullptr);
+ DumpAddressRange(s.AsRawOstream(), begin_addr, end_addr,
+ sizeof(dw_addr_t), nullptr);
}
}
}
@@ -122,164 +124,3 @@ bool DWARFDebugRanges::FindRanges(const DWARFUnit *cu,
}
return false;
}
-
-bool DWARFDebugRngLists::ExtractRangeList(
- const DWARFDataExtractor &data, uint8_t addrSize,
- lldb::offset_t *offset_ptr, std::vector<RngListEntry> &rangeList) {
- rangeList.clear();
-
- bool error = false;
- while (!error) {
- switch (data.GetU8(offset_ptr)) {
- case DW_RLE_end_of_list:
- return true;
-
- case DW_RLE_start_length: {
- dw_addr_t begin = data.GetMaxU64(offset_ptr, addrSize);
- dw_addr_t len = data.GetULEB128(offset_ptr);
- rangeList.push_back({DW_RLE_start_length, begin, len});
- break;
- }
-
- case DW_RLE_start_end: {
- dw_addr_t begin = data.GetMaxU64(offset_ptr, addrSize);
- dw_addr_t end = data.GetMaxU64(offset_ptr, addrSize);
- rangeList.push_back({DW_RLE_start_end, begin, end});
- break;
- }
-
- case DW_RLE_base_address: {
- dw_addr_t base = data.GetMaxU64(offset_ptr, addrSize);
- rangeList.push_back({DW_RLE_base_address, base, 0});
- break;
- }
-
- case DW_RLE_offset_pair: {
- dw_addr_t begin = data.GetULEB128(offset_ptr);
- dw_addr_t end = data.GetULEB128(offset_ptr);
- rangeList.push_back({DW_RLE_offset_pair, begin, end});
- break;
- }
-
- case DW_RLE_base_addressx: {
- dw_addr_t base = data.GetULEB128(offset_ptr);
- rangeList.push_back({DW_RLE_base_addressx, base, 0});
- break;
- }
-
- case DW_RLE_startx_endx: {
- dw_addr_t start = data.GetULEB128(offset_ptr);
- dw_addr_t end = data.GetULEB128(offset_ptr);
- rangeList.push_back({DW_RLE_startx_endx, start, end});
- break;
- }
-
- case DW_RLE_startx_length: {
- dw_addr_t start = data.GetULEB128(offset_ptr);
- dw_addr_t length = data.GetULEB128(offset_ptr);
- rangeList.push_back({DW_RLE_startx_length, start, length});
- break;
- }
-
- default:
- lldbassert(0 && "unknown range list entry encoding");
- error = true;
- }
- }
-
- return false;
-}
-
-static uint64_t ReadAddressFromDebugAddrSection(const DWARFUnit *cu,
- uint32_t index) {
- uint32_t index_size = cu->GetAddressByteSize();
- dw_offset_t addr_base = cu->GetAddrBase();
- lldb::offset_t offset = addr_base + index * index_size;
- return cu->GetSymbolFileDWARF()
- .GetDWARFContext()
- .getOrLoadAddrData()
- .GetMaxU64(&offset, index_size);
-}
-
-bool DWARFDebugRngLists::FindRanges(const DWARFUnit *cu,
- dw_offset_t debug_ranges_offset,
- DWARFRangeList &range_list) const {
- range_list.Clear();
- dw_addr_t debug_ranges_address = cu->GetRangesBase() + debug_ranges_offset;
- auto pos = m_range_map.find(debug_ranges_address);
- if (pos != m_range_map.end()) {
- dw_addr_t BaseAddr = cu->GetBaseAddress();
- for (const RngListEntry &E : pos->second) {
- switch (E.encoding) {
- case DW_RLE_start_length:
- range_list.Append(DWARFRangeList::Entry(E.value0, E.value1));
- break;
- case DW_RLE_base_address:
- BaseAddr = E.value0;
- break;
- case DW_RLE_start_end:
- range_list.Append(DWARFRangeList::Entry(E.value0, E.value1 - E.value0));
- break;
- case DW_RLE_offset_pair:
- range_list.Append(
- DWARFRangeList::Entry(BaseAddr + E.value0, E.value1 - E.value0));
- break;
- case DW_RLE_base_addressx: {
- BaseAddr = ReadAddressFromDebugAddrSection(cu, E.value0);
- break;
- }
- case DW_RLE_startx_endx: {
- dw_addr_t start = ReadAddressFromDebugAddrSection(cu, E.value0);
- dw_addr_t end = ReadAddressFromDebugAddrSection(cu, E.value1);
- range_list.Append(DWARFRangeList::Entry(start, end - start));
- break;
- }
- case DW_RLE_startx_length: {
- dw_addr_t start = ReadAddressFromDebugAddrSection(cu, E.value0);
- range_list.Append(DWARFRangeList::Entry(start, E.value1));
- break;
- }
- default:
- llvm_unreachable("unexpected encoding");
- }
- }
- return true;
- }
- return false;
-}
-
-void DWARFDebugRngLists::Extract(DWARFContext &context) {
- const DWARFDataExtractor &data = context.getOrLoadRngListsData();
- lldb::offset_t offset = 0;
-
- uint64_t length = data.GetU32(&offset);
- // FIXME: Handle DWARF64.
- lldb::offset_t end = offset + length;
-
- // Check version.
- if (data.GetU16(&offset) < 5)
- return;
-
- uint8_t addrSize = data.GetU8(&offset);
-
- // We do not support non-zero segment selector size.
- if (data.GetU8(&offset) != 0) {
- lldbassert(0 && "not implemented");
- return;
- }
-
- uint32_t offsetsAmount = data.GetU32(&offset);
- for (uint32_t i = 0; i < offsetsAmount; ++i)
- Offsets.push_back(data.GetMaxU64(&offset, 4));
-
- lldb::offset_t listOffset = offset;
- std::vector<RngListEntry> rangeList;
- while (offset < end && ExtractRangeList(data, addrSize, &offset, rangeList)) {
- m_range_map[listOffset] = rangeList;
- listOffset = offset;
- }
-}
-
-uint64_t DWARFDebugRngLists::GetOffset(size_t Index) const {
- return Offsets[Index];
-}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
index c398259056b3..1888a7760f27 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
@@ -17,22 +17,13 @@ namespace lldb_private {
class DWARFContext;
}
-class DWARFDebugRangesBase {
-public:
- virtual ~DWARFDebugRangesBase(){};
-
- virtual void Extract(lldb_private::DWARFContext &context) = 0;
- virtual bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset,
- DWARFRangeList &range_list) const = 0;
-};
-
-class DWARFDebugRanges final : public DWARFDebugRangesBase {
+class DWARFDebugRanges {
public:
DWARFDebugRanges();
- void Extract(lldb_private::DWARFContext &context) override;
+ void Extract(lldb_private::DWARFContext &context);
bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset,
- DWARFRangeList &range_list) const override;
+ DWARFRangeList &range_list) const;
static void Dump(lldb_private::Stream &s,
const lldb_private::DWARFDataExtractor &debug_ranges_data,
@@ -48,27 +39,4 @@ protected:
range_map m_range_map;
};
-// DWARF v5 .debug_rnglists section.
-class DWARFDebugRngLists final : public DWARFDebugRangesBase {
- struct RngListEntry {
- uint8_t encoding;
- uint64_t value0;
- uint64_t value1;
- };
-
-public:
- void Extract(lldb_private::DWARFContext &context) override;
- bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset,
- DWARFRangeList &range_list) const override;
- uint64_t GetOffset(size_t Index) const;
-
-protected:
- bool ExtractRangeList(const lldb_private::DWARFDataExtractor &data,
- uint8_t addrSize, lldb::offset_t *offset_ptr,
- std::vector<RngListEntry> &list);
-
- std::vector<uint64_t> Offsets;
- std::map<dw_offset_t, std::vector<RngListEntry>> m_range_map;
-};
-
#endif // SymbolFileDWARF_DWARFDebugRanges_h_
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
index 6501ac27f27d..348b33464a54 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
@@ -63,7 +63,7 @@ public:
const char *GetQualifiedName() const;
- // Same as GetQaulifiedName, but the life time of the returned string will
+ // Same as GetQualifiedName, but the life time of the returned string will
// be that of the LLDB session.
lldb_private::ConstString GetQualifiedNameAsConstString() const {
return lldb_private::ConstString(GetQualifiedName());
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index 046ae67446af..f660cc32b3f8 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -107,6 +107,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
m_value.value.uval = data.GetU64(offset_ptr);
break;
case DW_FORM_addrx:
+ case DW_FORM_loclistx:
case DW_FORM_rnglistx:
case DW_FORM_strx:
case DW_FORM_udata:
@@ -305,6 +306,7 @@ bool DWARFFormValue::SkipValue(dw_form_t form,
// signed or unsigned LEB 128 values
case DW_FORM_addrx:
+ case DW_FORM_loclistx:
case DW_FORM_rnglistx:
case DW_FORM_sdata:
case DW_FORM_udata:
@@ -333,7 +335,7 @@ void DWARFFormValue::Dump(Stream &s) const {
switch (m_form) {
case DW_FORM_addr:
- s.Address(uvalue, sizeof(uint64_t));
+ DumpAddress(s.AsRawOstream(), uvalue, sizeof(uint64_t));
break;
case DW_FORM_flag:
case DW_FORM_data1:
@@ -409,10 +411,11 @@ void DWARFFormValue::Dump(Stream &s) const {
assert(m_unit); // Unit must be valid for DW_FORM_ref_addr objects or we
// will get this wrong
if (m_unit->GetVersion() <= 2)
- s.Address(uvalue, sizeof(uint64_t) * 2);
+ DumpAddress(s.AsRawOstream(), uvalue, sizeof(uint64_t) * 2);
else
- s.Address(uvalue, 4 * 2); // 4 for DWARF32, 8 for DWARF64, but we don't
- // support DWARF64 yet
+ DumpAddress(s.AsRawOstream(), uvalue,
+ 4 * 2); // 4 for DWARF32, 8 for DWARF64, but we don't
+ // support DWARF64 yet
break;
}
case DW_FORM_ref1:
@@ -599,105 +602,11 @@ bool DWARFFormValue::IsDataForm(const dw_form_t form) {
return false;
}
-int DWARFFormValue::Compare(const DWARFFormValue &a_value,
- const DWARFFormValue &b_value) {
- dw_form_t a_form = a_value.Form();
- dw_form_t b_form = b_value.Form();
- if (a_form < b_form)
- return -1;
- if (a_form > b_form)
- return 1;
- switch (a_form) {
- case DW_FORM_addr:
- case DW_FORM_addrx:
- case DW_FORM_flag:
- case DW_FORM_data1:
- case DW_FORM_data2:
- case DW_FORM_data4:
- case DW_FORM_data8:
- case DW_FORM_udata:
- case DW_FORM_ref_addr:
- case DW_FORM_sec_offset:
- case DW_FORM_flag_present:
- case DW_FORM_ref_sig8:
- case DW_FORM_GNU_addr_index: {
- uint64_t a = a_value.Unsigned();
- uint64_t b = b_value.Unsigned();
- if (a < b)
- return -1;
- if (a > b)
- return 1;
- return 0;
- }
-
- case DW_FORM_sdata: {
- int64_t a = a_value.Signed();
- int64_t b = b_value.Signed();
- if (a < b)
- return -1;
- if (a > b)
- return 1;
- return 0;
- }
-
- case DW_FORM_string:
- case DW_FORM_strp:
- case DW_FORM_GNU_str_index: {
- const char *a_string = a_value.AsCString();
- const char *b_string = b_value.AsCString();
- if (a_string == b_string)
- return 0;
- else if (a_string && b_string)
- return strcmp(a_string, b_string);
- else if (a_string == nullptr)
- return -1; // A string is NULL, and B is valid
- else
- return 1; // A string valid, and B is NULL
- }
-
- case DW_FORM_block:
- case DW_FORM_block1:
- case DW_FORM_block2:
- case DW_FORM_block4:
- case DW_FORM_exprloc: {
- uint64_t a_len = a_value.Unsigned();
- uint64_t b_len = b_value.Unsigned();
- if (a_len < b_len)
- return -1;
- if (a_len > b_len)
- return 1;
- // The block lengths are the same
- return memcmp(a_value.BlockData(), b_value.BlockData(), a_value.Unsigned());
- } break;
-
- case DW_FORM_ref1:
- case DW_FORM_ref2:
- case DW_FORM_ref4:
- case DW_FORM_ref8:
- case DW_FORM_ref_udata: {
- uint64_t a = a_value.m_value.value.uval;
- uint64_t b = b_value.m_value.value.uval;
- if (a < b)
- return -1;
- if (a > b)
- return 1;
- return 0;
- }
-
- case DW_FORM_indirect:
- llvm_unreachable(
- "This shouldn't happen after the form has been extracted...");
-
- default:
- llvm_unreachable("Unhandled DW_FORM");
- }
- return -1;
-}
-
bool DWARFFormValue::FormIsSupported(dw_form_t form) {
switch (form) {
case DW_FORM_addr:
case DW_FORM_addrx:
+ case DW_FORM_loclistx:
case DW_FORM_rnglistx:
case DW_FORM_block2:
case DW_FORM_block4:
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h
index 6ff73ecd8efa..8967509c081a 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h
@@ -28,8 +28,8 @@ private:
DWARFTypeUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
const DWARFUnitHeader &header,
const DWARFAbbreviationDeclarationSet &abbrevs,
- DIERef::Section section)
- : DWARFUnit(dwarf, uid, header, abbrevs, section) {}
+ DIERef::Section section, bool is_dwo)
+ : DWARFUnit(dwarf, uid, header, abbrevs, section, is_dwo) {}
friend class DWARFUnit;
};
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 9964cf4b893c..22e3e40dac93 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -32,9 +32,9 @@ extern int g_verbose;
DWARFUnit::DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
const DWARFUnitHeader &header,
const DWARFAbbreviationDeclarationSet &abbrevs,
- DIERef::Section section)
+ DIERef::Section section, bool is_dwo)
: UserID(uid), m_dwarf(dwarf), m_header(header), m_abbrevs(&abbrevs),
- m_cancel_scopes(false), m_section(section) {}
+ m_cancel_scopes(false), m_section(section), m_is_dwo(is_dwo) {}
DWARFUnit::~DWARFUnit() = default;
@@ -287,15 +287,27 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
DWARFAttributes attributes;
size_t num_attributes = cu_die.GetAttributes(this, attributes);
+
+ // Extract DW_AT_addr_base first, as other attributes may need it.
+ for (size_t i = 0; i < num_attributes; ++i) {
+ if (attributes.AttributeAtIndex(i) != DW_AT_addr_base)
+ continue;
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value)) {
+ addr_base = form_value.Unsigned();
+ SetAddrBase(*addr_base);
+ break;
+ }
+ }
+
for (size_t i = 0; i < num_attributes; ++i) {
dw_attr_t attr = attributes.AttributeAtIndex(i);
DWARFFormValue form_value;
if (!attributes.ExtractFormValueAtIndex(i, form_value))
continue;
switch (attr) {
- case DW_AT_addr_base:
- addr_base = form_value.Unsigned();
- SetAddrBase(*addr_base);
+ case DW_AT_loclists_base:
+ SetLoclistsBase(form_value.Unsigned());
break;
case DW_AT_rnglists_base:
ranges_base = form_value.Unsigned();
@@ -324,6 +336,9 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
}
}
+ if (m_is_dwo)
+ return;
+
std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
m_dwarf.GetDwoSymbolFileForCompileUnit(*this, cu_die);
if (!dwo_symbol_file)
@@ -358,10 +373,18 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
else if (gnu_addr_base)
dwo_cu->SetAddrBase(*gnu_addr_base);
- if (ranges_base)
- dwo_cu->SetRangesBase(*ranges_base);
- else if (gnu_ranges_base)
+ if (GetVersion() <= 4 && gnu_ranges_base)
dwo_cu->SetRangesBase(*gnu_ranges_base);
+ else if (m_dwo_symbol_file->GetDWARFContext()
+ .getOrLoadRngListsData()
+ .GetByteSize() > 0)
+ dwo_cu->SetRangesBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
+
+ if (GetVersion() >= 5 && m_dwo_symbol_file->GetDWARFContext()
+ .getOrLoadLocListsData()
+ .GetByteSize() > 0)
+ dwo_cu->SetLoclistsBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
+ dwo_cu->SetBaseAddress(GetBaseAddress());
for (size_t i = 0; i < m_dwo_symbol_file->DebugInfo()->GetNumUnits(); ++i) {
DWARFUnit *unit = m_dwo_symbol_file->DebugInfo()->GetUnitAtIndex(i);
@@ -380,24 +403,6 @@ DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) {
return DWARFDIE();
}
-size_t DWARFUnit::AppendDIEsWithTag(const dw_tag_t tag,
- std::vector<DWARFDIE> &dies,
- uint32_t depth) const {
- size_t old_size = dies.size();
- {
- llvm::sys::ScopedReader lock(m_die_array_mutex);
- DWARFDebugInfoEntry::const_iterator pos;
- DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
- for (pos = m_die_array.begin(); pos != end; ++pos) {
- if (pos->Tag() == tag)
- dies.emplace_back(this, &(*pos));
- }
- }
-
- // Return the number of DIEs added to the collection
- return dies.size() - old_size;
-}
-
size_t DWARFUnit::GetDebugInfoSize() const {
return GetLengthByteSize() + GetLength() - GetHeaderByteSize();
}
@@ -417,8 +422,79 @@ dw_offset_t DWARFUnit::GetLineTableOffset() {
void DWARFUnit::SetAddrBase(dw_addr_t addr_base) { m_addr_base = addr_base; }
+// Parse the rangelist table header, including the optional array of offsets
+// following it (DWARF v5 and later).
+template <typename ListTableType>
+static llvm::Expected<ListTableType>
+ParseListTableHeader(const llvm::DWARFDataExtractor &data, uint64_t offset,
+ DwarfFormat format) {
+ // We are expected to be called with Offset 0 or pointing just past the table
+ // header. Correct Offset in the latter case so that it points to the start
+ // of the header.
+ if (offset > 0) {
+ uint64_t HeaderSize = llvm::DWARFListTableHeader::getHeaderSize(format);
+ if (offset < HeaderSize)
+ return llvm::createStringError(errc::invalid_argument,
+ "did not detect a valid"
+ " list table with base = 0x%" PRIx64 "\n",
+ offset);
+ offset -= HeaderSize;
+ }
+ ListTableType Table;
+ if (llvm::Error E = Table.extractHeaderAndOffsets(data, &offset))
+ return std::move(E);
+ return Table;
+}
+
+void DWARFUnit::SetLoclistsBase(dw_addr_t loclists_base) {
+ m_loclists_base = loclists_base;
+
+ uint64_t header_size = llvm::DWARFListTableHeader::getHeaderSize(DWARF32);
+ if (loclists_base < header_size)
+ return;
+
+ m_loclist_table_header.emplace(".debug_loclists", "locations");
+ uint64_t offset = loclists_base - header_size;
+ if (llvm::Error E = m_loclist_table_header->extract(
+ m_dwarf.GetDWARFContext().getOrLoadLocListsData().GetAsLLVM(),
+ &offset)) {
+ GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
+ "Failed to extract location list table at offset 0x%" PRIx64 ": %s",
+ loclists_base, toString(std::move(E)).c_str());
+ }
+}
+
+std::unique_ptr<llvm::DWARFLocationTable>
+DWARFUnit::GetLocationTable(const DataExtractor &data) const {
+ llvm::DWARFDataExtractor llvm_data(
+ toStringRef(data.GetData()),
+ data.GetByteOrder() == lldb::eByteOrderLittle, data.GetAddressByteSize());
+
+ if (m_is_dwo || GetVersion() >= 5)
+ return std::make_unique<llvm::DWARFDebugLoclists>(llvm_data, GetVersion());
+ return std::make_unique<llvm::DWARFDebugLoc>(llvm_data);
+}
+
+const DWARFDataExtractor &DWARFUnit::GetLocationData() const {
+ DWARFContext &Ctx = GetSymbolFileDWARF().GetDWARFContext();
+ return GetVersion() >= 5 ? Ctx.getOrLoadLocListsData()
+ : Ctx.getOrLoadLocData();
+}
+
void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) {
m_ranges_base = ranges_base;
+
+ if (GetVersion() < 5)
+ return;
+
+ if (auto table_or_error = ParseListTableHeader<llvm::DWARFDebugRnglistTable>(
+ m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(),
+ ranges_base, DWARF32))
+ m_rnglist_table = std::move(table_or_error.get());
+ else
+ GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
+ "Failed to extract range list table at offset 0x%" PRIx64 ": %s",
+ ranges_base, toString(table_or_error.takeError()).c_str());
}
void DWARFUnit::SetStrOffsetsBase(dw_offset_t str_offsets_base) {
@@ -646,6 +722,8 @@ FileSpec DWARFUnit::GetFile(size_t file_idx) {
// Remove the host part if present.
static llvm::StringRef
removeHostnameFromPathname(llvm::StringRef path_from_dwarf) {
+ if (!path_from_dwarf.contains(':'))
+ return path_from_dwarf;
llvm::StringRef host, path;
std::tie(host, path) = path_from_dwarf.split(':');
@@ -715,7 +793,8 @@ void DWARFUnit::ComputeAbsolutePath() {
m_file_spec->MakeAbsolute(GetCompilationDirectory());
}
-SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const {
+SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() {
+ ExtractUnitDIEIfNeeded();
return m_dwo_symbol_file.get();
}
@@ -816,11 +895,12 @@ DWARFUnit::extract(SymbolFileDWARF &dwarf, user_id_t uid,
return llvm::make_error<llvm::object::GenericBinaryError>(
"No abbrev exists at the specified offset.");
+ bool is_dwo = dwarf.GetDWARFContext().isDwo();
if (expected_header->IsTypeUnit())
- return DWARFUnitSP(
- new DWARFTypeUnit(dwarf, uid, *expected_header, *abbrevs, section));
- return DWARFUnitSP(
- new DWARFCompileUnit(dwarf, uid, *expected_header, *abbrevs, section));
+ return DWARFUnitSP(new DWARFTypeUnit(dwarf, uid, *expected_header, *abbrevs,
+ section, is_dwo));
+ return DWARFUnitSP(new DWARFCompileUnit(dwarf, uid, *expected_header,
+ *abbrevs, section, is_dwo));
}
const lldb_private::DWARFDataExtractor &DWARFUnit::GetData() const {
@@ -845,30 +925,56 @@ uint32_t DWARFUnit::GetHeaderByteSize() const {
}
llvm::Expected<DWARFRangeList>
-DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) const {
- const DWARFDebugRangesBase *debug_ranges;
- llvm::StringRef section;
+DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) {
if (GetVersion() <= 4) {
- debug_ranges = m_dwarf.GetDebugRanges();
- section = "debug_ranges";
- } else {
- debug_ranges = m_dwarf.GetDebugRngLists();
- section = "debug_rnglists";
+ const DWARFDebugRanges *debug_ranges = m_dwarf.GetDebugRanges();
+ if (!debug_ranges)
+ return llvm::make_error<llvm::object::GenericBinaryError>(
+ "No debug_ranges section");
+ DWARFRangeList ranges;
+ debug_ranges->FindRanges(this, offset, ranges);
+ return ranges;
}
- if (!debug_ranges)
- return llvm::make_error<llvm::object::GenericBinaryError>("No " + section +
- " section");
+
+ if (!m_rnglist_table)
+ return llvm::createStringError(errc::invalid_argument,
+ "missing or invalid range list table");
+
+ auto range_list_or_error = m_rnglist_table->findList(
+ m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(), offset);
+ if (!range_list_or_error)
+ return range_list_or_error.takeError();
+
+ llvm::Expected<llvm::DWARFAddressRangesVector> llvm_ranges =
+ range_list_or_error->getAbsoluteRanges(
+ llvm::object::SectionedAddress{GetBaseAddress()},
+ [&](uint32_t index) {
+ uint32_t index_size = GetAddressByteSize();
+ dw_offset_t addr_base = GetAddrBase();
+ lldb::offset_t offset = addr_base + index * index_size;
+ return llvm::object::SectionedAddress{
+ m_dwarf.GetDWARFContext().getOrLoadAddrData().GetMaxU64(
+ &offset, index_size)};
+ });
+ if (!llvm_ranges)
+ return llvm_ranges.takeError();
DWARFRangeList ranges;
- debug_ranges->FindRanges(this, offset, ranges);
+ for (const llvm::DWARFAddressRange &llvm_range : *llvm_ranges) {
+ ranges.Append(DWARFRangeList::Entry(llvm_range.LowPC,
+ llvm_range.HighPC - llvm_range.LowPC));
+ }
return ranges;
}
llvm::Expected<DWARFRangeList>
-DWARFUnit::FindRnglistFromIndex(uint32_t index) const {
- const DWARFDebugRngLists *debug_rnglists = m_dwarf.GetDebugRngLists();
- if (!debug_rnglists)
- return llvm::make_error<llvm::object::GenericBinaryError>(
- "No debug_rnglists section");
- return FindRnglistFromOffset(debug_rnglists->GetOffset(index));
+DWARFUnit::FindRnglistFromIndex(uint32_t index) {
+ if (llvm::Optional<uint64_t> offset = GetRnglistOffset(index))
+ return FindRnglistFromOffset(*offset);
+ if (m_rnglist_table)
+ return llvm::createStringError(errc::invalid_argument,
+ "invalid range list table index %d", index);
+
+ return llvm::createStringError(errc::invalid_argument,
+ "missing or invalid range list table");
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index 87e0de283de4..217f9bb89ace 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -95,8 +95,6 @@ public:
ScopedExtractDIEs ExtractDIEsScoped();
DWARFDIE LookupAddress(const dw_addr_t address);
- size_t AppendDIEsWithTag(const dw_tag_t tag, std::vector<DWARFDIE> &dies,
- uint32_t depth = UINT32_MAX) const;
bool Verify(lldb_private::Stream *s) const;
virtual void Dump(lldb_private::Stream *s) const = 0;
/// Get the data that contains the DIE information for this unit.
@@ -147,6 +145,7 @@ public:
dw_addr_t GetRangesBase() const { return m_ranges_base; }
dw_addr_t GetStrOffsetsBase() const { return m_str_offsets_base; }
void SetAddrBase(dw_addr_t addr_base);
+ void SetLoclistsBase(dw_addr_t loclists_base);
void SetRangesBase(dw_addr_t ranges_base);
void SetStrOffsetsBase(dw_offset_t str_offsets_base);
virtual void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) = 0;
@@ -202,7 +201,7 @@ public:
lldb_private::FileSpec GetFile(size_t file_idx);
lldb_private::FileSpec::Style GetPathStyle();
- SymbolFileDWARFDwo *GetDwoSymbolFile() const;
+ SymbolFileDWARFDwo *GetDwoSymbolFile();
die_iterator_range dies() {
ExtractDIEsIfNeeded();
@@ -216,18 +215,46 @@ public:
/// Return a list of address ranges resulting from a (possibly encoded)
/// range list starting at a given offset in the appropriate ranges section.
- llvm::Expected<DWARFRangeList> FindRnglistFromOffset(dw_offset_t offset) const;
+ llvm::Expected<DWARFRangeList> FindRnglistFromOffset(dw_offset_t offset);
/// Return a list of address ranges retrieved from an encoded range
/// list whose offset is found via a table lookup given an index (DWARF v5
/// and later).
- llvm::Expected<DWARFRangeList> FindRnglistFromIndex(uint32_t index) const;
+ llvm::Expected<DWARFRangeList> FindRnglistFromIndex(uint32_t index);
+
+ /// Return a rangelist's offset based on an index. The index designates
+ /// an entry in the rangelist table's offset array and is supplied by
+ /// DW_FORM_rnglistx.
+ llvm::Optional<uint64_t> GetRnglistOffset(uint32_t Index) const {
+ if (!m_rnglist_table)
+ return llvm::None;
+ if (llvm::Optional<uint64_t> off = m_rnglist_table->getOffsetEntry(Index))
+ return *off + m_ranges_base;
+ return llvm::None;
+ }
+
+ llvm::Optional<uint64_t> GetLoclistOffset(uint32_t Index) {
+ if (!m_loclist_table_header)
+ return llvm::None;
+
+ llvm::Optional<uint64_t> Offset = m_loclist_table_header->getOffsetEntry(Index);
+ if (!Offset)
+ return llvm::None;
+ return *Offset + m_loclists_base;
+ }
+
+ /// Return the location table for parsing the given location list data. The
+ /// format is chosen according to the unit type. Never returns null.
+ std::unique_ptr<llvm::DWARFLocationTable>
+ GetLocationTable(const lldb_private::DataExtractor &data) const;
+
+ const lldb_private::DWARFDataExtractor &GetLocationData() const;
protected:
DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
const DWARFUnitHeader &header,
const DWARFAbbreviationDeclarationSet &abbrevs,
- DIERef::Section section);
+ DIERef::Section section, bool is_dwo);
llvm::Error ExtractHeader(SymbolFileDWARF &dwarf,
const lldb_private::DWARFDataExtractor &data,
@@ -281,14 +308,20 @@ protected:
lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate;
llvm::Optional<lldb_private::FileSpec> m_comp_dir;
llvm::Optional<lldb_private::FileSpec> m_file_spec;
- dw_addr_t m_addr_base = 0; // Value of DW_AT_addr_base
- dw_addr_t m_ranges_base = 0; // Value of DW_AT_ranges_base
+ dw_addr_t m_addr_base = 0; ///< Value of DW_AT_addr_base.
+ dw_addr_t m_loclists_base = 0; ///< Value of DW_AT_loclists_base.
+ dw_addr_t m_ranges_base = 0; ///< Value of DW_AT_rnglists_base.
/// Value of DW_AT_stmt_list.
dw_offset_t m_line_table_offset = DW_INVALID_OFFSET;
dw_offset_t m_str_offsets_base = 0; // Value of DW_AT_str_offsets_base.
+
+ llvm::Optional<llvm::DWARFDebugRnglistTable> m_rnglist_table;
+ llvm::Optional<llvm::DWARFListTableHeader> m_loclist_table_header;
+
const DIERef::Section m_section;
+ bool m_is_dwo;
private:
void ParseProducerInfo();
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
index aff8b5d8c15f..1e5927bd14f0 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -401,8 +401,6 @@ void ManualDWARFIndex::GetFunctions(ConstString name, SymbolFileDWARF &dwarf,
if (name_type_mask & eFunctionNameTypeFull) {
DIEArray offsets;
- m_set.function_basenames.Find(name, offsets);
- m_set.function_methods.Find(name, offsets);
m_set.function_fullnames.Find(name, offsets);
for (const DIERef &die_ref: offsets) {
DWARFDIE die = dwarf.GetDIE(die_ref);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index c982d59c2830..d45a8b56efe4 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -94,6 +94,8 @@
using namespace lldb;
using namespace lldb_private;
+char SymbolFileDWARF::ID;
+
// static inline bool
// child_requires_parent_class_union_or_struct_to_be_completed (dw_tag_t tag)
//{
@@ -179,36 +181,46 @@ ParseLLVMLineTable(lldb_private::DWARFContext &context,
return *line_table;
}
-static FileSpecList ParseSupportFilesFromPrologue(
- const lldb::ModuleSP &module,
- const llvm::DWARFDebugLine::Prologue &prologue, FileSpec::Style style,
- llvm::StringRef compile_dir = {}, FileSpec first_file = {}) {
+static llvm::Optional<std::string>
+GetFileByIndex(const llvm::DWARFDebugLine::Prologue &prologue, size_t idx,
+ llvm::StringRef compile_dir, FileSpec::Style style) {
+ // Try to get an absolute path first.
+ std::string abs_path;
+ auto absolute = llvm::DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath;
+ if (prologue.getFileNameByIndex(idx, compile_dir, absolute, abs_path, style))
+ return std::move(abs_path);
+
+ // Otherwise ask for a relative path.
+ std::string rel_path;
+ auto relative = llvm::DILineInfoSpecifier::FileLineInfoKind::Default;
+ if (!prologue.getFileNameByIndex(idx, compile_dir, relative, rel_path, style))
+ return {};
+ return std::move(rel_path);
+}
+
+static FileSpecList
+ParseSupportFilesFromPrologue(const lldb::ModuleSP &module,
+ const llvm::DWARFDebugLine::Prologue &prologue,
+ FileSpec::Style style,
+ llvm::StringRef compile_dir = {}) {
FileSpecList support_files;
- support_files.Append(first_file);
+ size_t first_file = 0;
+ if (prologue.getVersion() <= 4) {
+ // File index 0 is not valid before DWARF v5. Add a dummy entry to ensure
+ // support file list indices match those we get from the debug info and line
+ // tables.
+ support_files.Append(FileSpec());
+ first_file = 1;
+ }
const size_t number_of_files = prologue.FileNames.size();
- for (size_t idx = 1; idx <= number_of_files; ++idx) {
- std::string original_file;
- if (!prologue.getFileNameByIndex(
- idx, compile_dir,
- llvm::DILineInfoSpecifier::FileLineInfoKind::Default, original_file,
- style)) {
- // Always add an entry so the indexes remain correct.
- support_files.EmplaceBack();
- continue;
- }
-
+ for (size_t idx = first_file; idx <= number_of_files; ++idx) {
std::string remapped_file;
- if (!prologue.getFileNameByIndex(
- idx, compile_dir,
- llvm::DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
- remapped_file, style)) {
- // Always add an entry so the indexes remain correct.
- support_files.EmplaceBack(original_file, style);
- continue;
- }
+ if (auto file_path = GetFileByIndex(prologue, idx, compile_dir, style))
+ if (!module->RemapSourceFile(llvm::StringRef(*file_path), remapped_file))
+ remapped_file = std::move(*file_path);
- module->RemapSourceFile(llvm::StringRef(original_file), remapped_file);
+ // Unconditionally add an entry, so the indices match up.
support_files.EmplaceBack(remapped_file, style);
}
@@ -585,22 +597,6 @@ void SymbolFileDWARF::LoadSectionData(lldb::SectionType sect_type,
m_objfile_sp->ReadSectionData(section_sp.get(), data);
}
-const DWARFDataExtractor &SymbolFileDWARF::DebugLocData() {
- const DWARFDataExtractor &debugLocData = get_debug_loc_data();
- if (debugLocData.GetByteSize() > 0)
- return debugLocData;
- return get_debug_loclists_data();
-}
-
-const DWARFDataExtractor &SymbolFileDWARF::get_debug_loc_data() {
- return GetCachedSectionData(eSectionTypeDWARFDebugLoc, m_data_debug_loc);
-}
-
-const DWARFDataExtractor &SymbolFileDWARF::get_debug_loclists_data() {
- return GetCachedSectionData(eSectionTypeDWARFDebugLocLists,
- m_data_debug_loclists);
-}
-
DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() {
if (m_abbr)
return m_abbr.get();
@@ -672,21 +668,6 @@ DWARFDebugRanges *SymbolFileDWARF::GetDebugRanges() {
return m_ranges.get();
}
-DWARFDebugRngLists *SymbolFileDWARF::GetDebugRngLists() {
- if (!m_rnglists) {
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION,
- static_cast<void *>(this));
-
- if (m_context.getOrLoadRngListsData().GetByteSize() > 0)
- m_rnglists.reset(new DWARFDebugRngLists());
-
- if (m_rnglists)
- m_rnglists->Extract(m_context);
- }
- return m_rnglists.get();
-}
-
lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
CompUnitSP cu_sp;
CompileUnit *comp_unit = (CompileUnit *)dwarf_cu.GetUserData();
@@ -703,7 +684,8 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
} else {
ModuleSP module_sp(m_objfile_sp->GetModule());
if (module_sp) {
- const DWARFDIE cu_die = dwarf_cu.DIE();
+ const DWARFBaseDIE cu_die =
+ dwarf_cu.GetNonSkeletonUnit().GetUnitDIEOnly();
if (cu_die) {
FileSpec cu_file_spec(cu_die.GetName(), dwarf_cu.GetPathStyle());
if (cu_file_spec) {
@@ -721,7 +703,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
LanguageType cu_language = DWARFUnit::LanguageTypeFromDWARF(
cu_die.GetAttributeValueAsUnsigned(DW_AT_language, 0));
- bool is_optimized = dwarf_cu.GetIsOptimized();
+ bool is_optimized = dwarf_cu.GetNonSkeletonUnit().GetIsOptimized();
BuildCuTranslationTable();
cu_sp = std::make_shared<CompileUnit>(
module_sp, &dwarf_cu, cu_file_spec,
@@ -828,15 +810,20 @@ lldb::LanguageType SymbolFileDWARF::ParseLanguage(CompileUnit &comp_unit) {
}
size_t SymbolFileDWARF::ParseFunctions(CompileUnit &comp_unit) {
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "SymbolFileDWARF::ParseFunctions");
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
if (!dwarf_cu)
return 0;
size_t functions_added = 0;
- std::vector<DWARFDIE> function_dies;
- dwarf_cu->AppendDIEsWithTag(DW_TAG_subprogram, function_dies);
- for (const DWARFDIE &die : function_dies) {
+ dwarf_cu = &dwarf_cu->GetNonSkeletonUnit();
+ for (DWARFDebugInfoEntry &entry : dwarf_cu->dies()) {
+ if (entry.Tag() != DW_TAG_subprogram)
+ continue;
+
+ DWARFDIE die(dwarf_cu, &entry);
if (comp_unit.FindFunctionByUID(die.GetID()))
continue;
if (ParseFunction(comp_unit, die))
@@ -846,16 +833,32 @@ size_t SymbolFileDWARF::ParseFunctions(CompileUnit &comp_unit) {
return functions_added;
}
-void SymbolFileDWARF::ForEachExternalModule(
- CompileUnit &comp_unit, llvm::function_ref<void(ModuleSP)> f) {
- UpdateExternalModuleListIfNeeded();
+bool SymbolFileDWARF::ForEachExternalModule(
+ CompileUnit &comp_unit,
+ llvm::DenseSet<lldb_private::SymbolFile *> &visited_symbol_files,
+ llvm::function_ref<bool(Module &)> lambda) {
+ // Only visit each symbol file once.
+ if (!visited_symbol_files.insert(this).second)
+ return false;
+ UpdateExternalModuleListIfNeeded();
for (auto &p : m_external_type_modules) {
ModuleSP module = p.second;
- f(module);
- for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i)
- module->GetCompileUnitAtIndex(i)->ForEachExternalModule(f);
+ if (!module)
+ continue;
+
+ // Invoke the action and potentially early-exit.
+ if (lambda(*module))
+ return true;
+
+ for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i) {
+ auto cu = module->GetCompileUnitAtIndex(i);
+ bool early_exit = cu->ForEachExternalModule(visited_symbol_files, lambda);
+ if (early_exit)
+ return true;
+ }
}
+ return false;
}
bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit,
@@ -961,7 +964,7 @@ bool SymbolFileDWARF::ParseImportedModules(
DW_AT_LLVM_include_path, nullptr))
module.search_path = ConstString(include_path);
if (const char *sysroot = module_die.GetAttributeValueAsString(
- DW_AT_LLVM_isysroot, nullptr))
+ DW_AT_LLVM_sysroot, nullptr))
module.sysroot = ConstString(sysroot);
imported_modules.push_back(module);
}
@@ -1023,7 +1026,7 @@ bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) {
comp_unit.SetSupportFiles(ParseSupportFilesFromPrologue(
comp_unit.GetModule(), line_table->Prologue, dwarf_cu->GetPathStyle(),
- dwarf_cu->GetCompilationDirectory().GetCString(), FileSpec(comp_unit)));
+ dwarf_cu->GetCompilationDirectory().GetCString()));
return true;
}
@@ -1507,7 +1510,7 @@ bool SymbolFileDWARF::GetFunction(const DWARFDIE &die, SymbolContext &sc) {
return false;
}
-lldb::ModuleSP SymbolFileDWARF::GetDWOModule(ConstString name) {
+lldb::ModuleSP SymbolFileDWARF::GetExternalModule(ConstString name) {
UpdateExternalModuleListIfNeeded();
const auto &pos = m_external_type_modules.find(name);
if (pos != m_external_type_modules.end())
@@ -1532,12 +1535,48 @@ SymbolFileDWARF::GetDIE(const DIERef &die_ref) {
return DWARFDIE();
}
+/// Return the DW_AT_(GNU_)dwo_name.
+static const char *GetDWOName(DWARFCompileUnit &dwarf_cu,
+ const DWARFDebugInfoEntry &cu_die) {
+ const char *dwo_name =
+ cu_die.GetAttributeValueAsString(&dwarf_cu, DW_AT_GNU_dwo_name, nullptr);
+ if (!dwo_name)
+ dwo_name =
+ cu_die.GetAttributeValueAsString(&dwarf_cu, DW_AT_dwo_name, nullptr);
+ return dwo_name;
+}
+
+/// Return the DW_AT_(GNU_)dwo_id.
+/// FIXME: Technically 0 is a valid hash.
+static uint64_t GetDWOId(DWARFCompileUnit &dwarf_cu,
+ const DWARFDebugInfoEntry &cu_die) {
+ uint64_t dwo_id =
+ cu_die.GetAttributeValueAsUnsigned(&dwarf_cu, DW_AT_GNU_dwo_id, 0);
+ if (!dwo_id)
+ dwo_id = cu_die.GetAttributeValueAsUnsigned(&dwarf_cu, DW_AT_dwo_id, 0);
+ return dwo_id;
+}
+
+llvm::Optional<uint64_t> SymbolFileDWARF::GetDWOId() {
+ if (GetNumCompileUnits() == 1) {
+ if (auto comp_unit = GetCompileUnitAtIndex(0))
+ if (DWARFCompileUnit *cu = llvm::dyn_cast_or_null<DWARFCompileUnit>(
+ GetDWARFCompileUnit(comp_unit.get())))
+ if (DWARFDebugInfoEntry *cu_die = cu->DIE().GetDIE())
+ if (uint64_t dwo_id = ::GetDWOId(*cu, *cu_die))
+ return dwo_id;
+ }
+ return {};
+}
+
std::unique_ptr<SymbolFileDWARFDwo>
SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
DWARFUnit &unit, const DWARFDebugInfoEntry &cu_die) {
- // If we are using a dSYM file, we never want the standard DWO files since
- // the -gmodules support uses the same DWO machanism to specify full debug
- // info files for modules.
+ // If this is a Darwin-style debug map (non-.dSYM) symbol file,
+ // never attempt to load ELF-style DWO files since the -gmodules
+ // support uses the same DWO machanism to specify full debug info
+ // files for modules. This is handled in
+ // UpdateExternalModuleListIfNeeded().
if (GetDebugMapSymfile())
return nullptr;
@@ -1546,15 +1585,13 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
if (!dwarf_cu)
return nullptr;
- const char *dwo_name =
- cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_GNU_dwo_name, nullptr);
+ const char *dwo_name = GetDWOName(*dwarf_cu, cu_die);
if (!dwo_name)
return nullptr;
SymbolFileDWARFDwp *dwp_symfile = GetDwpSymbolFile();
if (dwp_symfile) {
- uint64_t dwo_id =
- cu_die.GetAttributeValueAsUnsigned(dwarf_cu, DW_AT_GNU_dwo_id, 0);
+ uint64_t dwo_id = ::GetDWOId(*dwarf_cu, cu_die);
std::unique_ptr<SymbolFileDWARFDwo> dwo_symfile =
dwp_symfile->GetSymbolFileForDwoId(*dwarf_cu, dwo_id);
if (dwo_symfile)
@@ -1594,76 +1631,101 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() {
if (m_fetched_external_modules)
return;
m_fetched_external_modules = true;
-
DWARFDebugInfo *debug_info = DebugInfo();
+ // Follow DWO skeleton unit breadcrumbs.
const uint32_t num_compile_units = GetNumCompileUnits();
for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
- DWARFUnit *dwarf_cu = debug_info->GetUnitAtIndex(cu_idx);
+ auto *dwarf_cu =
+ llvm::dyn_cast<DWARFCompileUnit>(debug_info->GetUnitAtIndex(cu_idx));
+ if (!dwarf_cu)
+ continue;
const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly();
- if (die && !die.HasChildren()) {
- const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr);
-
- if (name) {
- ConstString const_name(name);
- if (m_external_type_modules.find(const_name) ==
- m_external_type_modules.end()) {
- ModuleSP module_sp;
- const char *dwo_path =
- die.GetAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr);
- if (dwo_path) {
- ModuleSpec dwo_module_spec;
- dwo_module_spec.GetFileSpec().SetFile(dwo_path,
- FileSpec::Style::native);
- if (dwo_module_spec.GetFileSpec().IsRelative()) {
- const char *comp_dir =
- die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr);
- if (comp_dir) {
- dwo_module_spec.GetFileSpec().SetFile(comp_dir,
- FileSpec::Style::native);
- FileSystem::Instance().Resolve(dwo_module_spec.GetFileSpec());
- dwo_module_spec.GetFileSpec().AppendPathComponent(dwo_path);
- }
- }
- dwo_module_spec.GetArchitecture() =
- m_objfile_sp->GetModule()->GetArchitecture();
-
- // When LLDB loads "external" modules it looks at the presence of
- // DW_AT_GNU_dwo_name. However, when the already created module
- // (corresponding to .dwo itself) is being processed, it will see
- // the presence of DW_AT_GNU_dwo_name (which contains the name of
- // dwo file) and will try to call ModuleList::GetSharedModule
- // again. In some cases (i.e. for empty files) Clang 4.0 generates
- // a *.dwo file which has DW_AT_GNU_dwo_name, but no
- // DW_AT_comp_dir. In this case the method
- // ModuleList::GetSharedModule will fail and the warning will be
- // printed. However, as one can notice in this case we don't
- // actually need to try to load the already loaded module
- // (corresponding to .dwo) so we simply skip it.
- if (m_objfile_sp->GetFileSpec().GetFileNameExtension() == ".dwo" &&
- llvm::StringRef(m_objfile_sp->GetFileSpec().GetPath())
- .endswith(dwo_module_spec.GetFileSpec().GetPath())) {
- continue;
- }
+ if (!die || die.HasChildren() || !die.GetDIE())
+ continue;
- Status error = ModuleList::GetSharedModule(
- dwo_module_spec, module_sp, nullptr, nullptr, nullptr);
- if (!module_sp) {
- GetObjectFile()->GetModule()->ReportWarning(
- "0x%8.8x: unable to locate module needed for external types: "
- "%s\nerror: %s\nDebugging will be degraded due to missing "
- "types. Rebuilding your project will regenerate the needed "
- "module files.",
- die.GetOffset(),
- dwo_module_spec.GetFileSpec().GetPath().c_str(),
- error.AsCString("unknown error"));
- }
- }
- m_external_type_modules[const_name] = module_sp;
- }
+ const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr);
+ if (!name)
+ continue;
+
+ ConstString const_name(name);
+ ModuleSP &module_sp = m_external_type_modules[const_name];
+ if (module_sp)
+ continue;
+
+ const char *dwo_path = GetDWOName(*dwarf_cu, *die.GetDIE());
+ if (!dwo_path)
+ continue;
+
+ ModuleSpec dwo_module_spec;
+ dwo_module_spec.GetFileSpec().SetFile(dwo_path, FileSpec::Style::native);
+ if (dwo_module_spec.GetFileSpec().IsRelative()) {
+ const char *comp_dir =
+ die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr);
+ if (comp_dir) {
+ dwo_module_spec.GetFileSpec().SetFile(comp_dir,
+ FileSpec::Style::native);
+ FileSystem::Instance().Resolve(dwo_module_spec.GetFileSpec());
+ dwo_module_spec.GetFileSpec().AppendPathComponent(dwo_path);
}
}
+ dwo_module_spec.GetArchitecture() =
+ m_objfile_sp->GetModule()->GetArchitecture();
+
+ // When LLDB loads "external" modules it looks at the presence of
+ // DW_AT_dwo_name. However, when the already created module
+ // (corresponding to .dwo itself) is being processed, it will see
+ // the presence of DW_AT_dwo_name (which contains the name of dwo
+ // file) and will try to call ModuleList::GetSharedModule
+ // again. In some cases (i.e., for empty files) Clang 4.0
+ // generates a *.dwo file which has DW_AT_dwo_name, but no
+ // DW_AT_comp_dir. In this case the method
+ // ModuleList::GetSharedModule will fail and the warning will be
+ // printed. However, as one can notice in this case we don't
+ // actually need to try to load the already loaded module
+ // (corresponding to .dwo) so we simply skip it.
+ if (m_objfile_sp->GetFileSpec().GetFileNameExtension() == ".dwo" &&
+ llvm::StringRef(m_objfile_sp->GetFileSpec().GetPath())
+ .endswith(dwo_module_spec.GetFileSpec().GetPath())) {
+ continue;
+ }
+
+ Status error = ModuleList::GetSharedModule(dwo_module_spec, module_sp,
+ nullptr, nullptr, nullptr);
+ if (!module_sp) {
+ GetObjectFile()->GetModule()->ReportWarning(
+ "0x%8.8x: unable to locate module needed for external types: "
+ "%s\nerror: %s\nDebugging will be degraded due to missing "
+ "types. Rebuilding the project will regenerate the needed "
+ "module files.",
+ die.GetOffset(), dwo_module_spec.GetFileSpec().GetPath().c_str(),
+ error.AsCString("unknown error"));
+ continue;
+ }
+
+ // Verify the DWO hash.
+ // FIXME: Technically "0" is a valid hash.
+ uint64_t dwo_id = ::GetDWOId(*dwarf_cu, *die.GetDIE());
+ if (!dwo_id)
+ continue;
+
+ auto *dwo_symfile =
+ llvm::dyn_cast_or_null<SymbolFileDWARF>(module_sp->GetSymbolFile());
+ if (!dwo_symfile)
+ continue;
+ llvm::Optional<uint64_t> dwo_dwo_id = dwo_symfile->GetDWOId();
+ if (!dwo_dwo_id)
+ continue;
+
+ if (dwo_id != dwo_dwo_id) {
+ GetObjectFile()->GetModule()->ReportWarning(
+ "0x%8.8x: Module %s is out-of-date (hash mismatch). Type information "
+ "from this module may be incomplete or inconsistent with the rest of "
+ "the program. Rebuilding the project will regenerate the needed "
+ "module files.",
+ die.GetOffset(), dwo_module_spec.GetFileSpec().GetPath().c_str());
+ }
}
}
@@ -1867,9 +1929,8 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
if (!dc_cu)
continue;
- const bool full_match = (bool)file_spec.GetDirectory();
bool file_spec_matches_cu_file_spec =
- FileSpec::Equal(file_spec, *dc_cu, full_match);
+ FileSpec::Match(file_spec, dc_cu->GetPrimaryFile());
if (check_inlines || file_spec_matches_cu_file_spec) {
SymbolContext sc(m_objfile_sp->GetModule());
sc.comp_unit = dc_cu;
@@ -2208,9 +2269,12 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die,
addr = sc.function->GetAddressRange().GetBaseAddress();
}
- if (addr.IsValid()) {
- sc_list.Append(sc);
- return true;
+
+ if (auto section_sp = addr.GetSection()) {
+ if (section_sp->GetPermissions() & ePermissionsExecutable) {
+ sc_list.Append(sc);
+ return true;
+ }
}
}
@@ -2364,12 +2428,10 @@ void SymbolFileDWARF::FindTypes(
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
- // Make sure we haven't already searched this SymbolFile before...
- if (searched_symbol_files.count(this))
+ // Make sure we haven't already searched this SymbolFile before.
+ if (!searched_symbol_files.insert(this).second)
return;
- searched_symbol_files.insert(this);
-
DWARFDebugInfo *info = DebugInfo();
if (!info)
return;
@@ -2451,8 +2513,13 @@ void SymbolFileDWARF::FindTypes(
}
}
-void SymbolFileDWARF::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
- LanguageSet languages, TypeMap &types) {
+void SymbolFileDWARF::FindTypes(
+ llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {
+ // Make sure we haven't already searched this SymbolFile before.
+ if (!searched_symbol_files.insert(this).second)
+ return;
+
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
if (pattern.empty())
return;
@@ -2482,11 +2549,22 @@ void SymbolFileDWARF::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
if (!contextMatches(die_context, pattern))
continue;
- if (Type *matching_type = ResolveType(die, true, true))
+ if (Type *matching_type = ResolveType(die, true, true)) {
// We found a type pointer, now find the shared pointer form our type
// list.
types.InsertUnique(matching_type->shared_from_this());
+ }
}
+
+ // Next search through the reachable Clang modules. This only applies for
+ // DWARF objects compiled with -gmodules that haven't been processed by
+ // dsymutil.
+ UpdateExternalModuleListIfNeeded();
+
+ for (const auto &pair : m_external_type_modules)
+ if (ModuleSP external_module_sp = pair.second)
+ external_module_sp->FindTypes(pattern, languages, searched_symbol_files,
+ types);
}
CompilerDeclContext
@@ -3268,15 +3346,17 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
module, DataExtractor(data, block_offset, block_length),
die.GetCU());
} else {
- DataExtractor data = DebugLocData();
- const dw_offset_t offset = form_value.Unsigned();
+ DataExtractor data = die.GetCU()->GetLocationData();
+ dw_offset_t offset = form_value.Unsigned();
+ if (form_value.Form() == DW_FORM_loclistx)
+ offset = die.GetCU()->GetLoclistOffset(offset).getValueOr(-1);
if (data.ValidOffset(offset)) {
data = DataExtractor(data, offset, data.GetByteSize() - offset);
location = DWARFExpression(module, data, die.GetCU());
assert(func_low_pc != LLDB_INVALID_ADDRESS);
- location.SetLocationListSlide(
- func_low_pc -
- attributes.CompileUnitAtIndex(i)->GetBaseAddress());
+ location.SetLocationListAddresses(
+ attributes.CompileUnitAtIndex(i)->GetBaseAddress(),
+ func_low_pc);
}
}
} break;
@@ -3685,8 +3765,8 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) {
if (child.Tag() != DW_TAG_call_site_parameter)
continue;
- llvm::Optional<DWARFExpression> LocationInCallee = {};
- llvm::Optional<DWARFExpression> LocationInCaller = {};
+ llvm::Optional<DWARFExpression> LocationInCallee;
+ llvm::Optional<DWARFExpression> LocationInCaller;
DWARFAttributes attributes;
const size_t num_attributes = child.GetAttributes(attributes);
@@ -3725,7 +3805,7 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) {
}
/// Collect call graph edges present in a function DIE.
-static std::vector<lldb_private::CallEdge>
+static std::vector<std::unique_ptr<lldb_private::CallEdge>>
CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
// Check if the function has a supported call site-related attribute.
// TODO: In the future it may be worthwhile to support call_all_source_calls.
@@ -3743,32 +3823,87 @@ CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
// to be DWARF5-compliant. This may need to be done lazily to be performant.
// For now, assume that all entries are nested directly under the subprogram
// (this is the kind of DWARF LLVM produces) and parse them eagerly.
- std::vector<CallEdge> call_edges;
+ std::vector<std::unique_ptr<CallEdge>> call_edges;
for (DWARFDIE child = function_die.GetFirstChild(); child.IsValid();
child = child.GetSibling()) {
if (child.Tag() != DW_TAG_call_site)
continue;
- // Extract DW_AT_call_origin (the call target's DIE).
- DWARFDIE call_origin = child.GetReferencedDIE(DW_AT_call_origin);
- if (!call_origin.IsValid()) {
- LLDB_LOG(log, "CollectCallEdges: Invalid call origin in {0}",
- function_die.GetPubname());
+ llvm::Optional<DWARFDIE> call_origin;
+ llvm::Optional<DWARFExpression> call_target;
+ addr_t return_pc = LLDB_INVALID_ADDRESS;
+
+ DWARFAttributes attributes;
+ const size_t num_attributes = child.GetAttributes(attributes);
+ for (size_t i = 0; i < num_attributes; ++i) {
+ DWARFFormValue form_value;
+ if (!attributes.ExtractFormValueAtIndex(i, form_value)) {
+ LLDB_LOG(log, "CollectCallEdges: Could not extract TAG_call_site form");
+ break;
+ }
+
+ dw_attr_t attr = attributes.AttributeAtIndex(i);
+
+ // Extract DW_AT_call_origin (the call target's DIE).
+ if (attr == DW_AT_call_origin) {
+ call_origin = form_value.Reference();
+ if (!call_origin->IsValid()) {
+ LLDB_LOG(log, "CollectCallEdges: Invalid call origin in {0}",
+ function_die.GetPubname());
+ break;
+ }
+ }
+
+ // Extract DW_AT_call_return_pc (the PC the call returns to) if it's
+ // available. It should only ever be unavailable for tail call edges, in
+ // which case use LLDB_INVALID_ADDRESS.
+ if (attr == DW_AT_call_return_pc)
+ return_pc = form_value.Address();
+
+ // Extract DW_AT_call_target (the location of the address of the indirect
+ // call).
+ if (attr == DW_AT_call_target) {
+ if (!DWARFFormValue::IsBlockForm(form_value.Form())) {
+ LLDB_LOG(log,
+ "CollectCallEdges: AT_call_target does not have block form");
+ break;
+ }
+
+ auto data = child.GetData();
+ uint32_t block_offset = form_value.BlockData() - data.GetDataStart();
+ uint32_t block_length = form_value.Unsigned();
+ call_target = DWARFExpression(
+ module, DataExtractor(data, block_offset, block_length),
+ child.GetCU());
+ }
+ }
+ if (!call_origin && !call_target) {
+ LLDB_LOG(log, "CollectCallEdges: call site without any call target");
continue;
}
- // Extract DW_AT_call_return_pc (the PC the call returns to) if it's
- // available. It should only ever be unavailable for tail call edges, in
- // which case use LLDB_INVALID_ADDRESS.
- addr_t return_pc = child.GetAttributeValueAsAddress(DW_AT_call_return_pc,
- LLDB_INVALID_ADDRESS);
-
// Extract call site parameters.
CallSiteParameterArray parameters =
CollectCallSiteParameters(module, child);
- LLDB_LOG(log, "CollectCallEdges: Found call origin: {0} (retn-PC: {1:x})",
- call_origin.GetPubname(), return_pc);
+ std::unique_ptr<CallEdge> edge;
+ if (call_origin) {
+ LLDB_LOG(log, "CollectCallEdges: Found call origin: {0} (retn-PC: {1:x})",
+ call_origin->GetPubname(), return_pc);
+ edge = std::make_unique<DirectCallEdge>(call_origin->GetMangledName(),
+ return_pc, std::move(parameters));
+ } else {
+ if (log) {
+ StreamString call_target_desc;
+ call_target->GetDescription(&call_target_desc, eDescriptionLevelBrief,
+ LLDB_INVALID_ADDRESS, nullptr);
+ LLDB_LOG(log, "CollectCallEdges: Found indirect call target: {0}",
+ call_target_desc.GetString());
+ }
+ edge = std::make_unique<IndirectCallEdge>(*call_target, return_pc,
+ std::move(parameters));
+ }
+
if (log && parameters.size()) {
for (const CallSiteParameter &param : parameters) {
StreamString callee_loc_desc, caller_loc_desc;
@@ -3783,13 +3918,12 @@ CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
}
}
- call_edges.emplace_back(call_origin.GetMangledName(), return_pc,
- std::move(parameters));
+ call_edges.push_back(std::move(edge));
}
return call_edges;
}
-std::vector<lldb_private::CallEdge>
+std::vector<std::unique_ptr<lldb_private::CallEdge>>
SymbolFileDWARF::ParseCallEdgesInFunction(UserID func_id) {
DWARFDIE func_die = GetDIE(func_id.GetID());
if (func_die.IsValid())
@@ -3829,13 +3963,6 @@ SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() {
return m_debug_map_symfile;
}
-DWARFExpression::LocationListFormat
-SymbolFileDWARF::GetLocationListFormat() const {
- if (m_data_debug_loclists.m_data.GetByteSize() > 0)
- return DWARFExpression::LocLists;
- return DWARFExpression::RegularLocationList;
-}
-
SymbolFileDWARFDwp *SymbolFileDWARF::GetDwpSymbolFile() {
llvm::call_once(m_dwp_symfile_once_flag, [this]() {
ModuleSpec module_spec;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 04cb11d426be..23e26732453f 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -21,7 +21,6 @@
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/Core/dwarf.h"
-#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Symbol/DebugMacros.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolFile.h"
@@ -47,7 +46,6 @@ class DWARFDebugInfo;
class DWARFDebugInfoEntry;
class DWARFDebugLine;
class DWARFDebugRanges;
-class DWARFDebugRngLists;
class DWARFDeclContext;
class DWARFFormValue;
class DWARFTypeUnit;
@@ -59,7 +57,18 @@ class SymbolFileDWARFDwp;
class SymbolFileDWARF : public lldb_private::SymbolFile,
public lldb_private::UserID {
+ /// LLVM RTTI support.
+ static char ID;
+
public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFile::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
+
friend class SymbolFileDWARFDebugMap;
friend class SymbolFileDWARFDwo;
friend class DebugMapModule;
@@ -105,9 +114,9 @@ public:
bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override;
- void
- ForEachExternalModule(lldb_private::CompileUnit &comp_unit,
- llvm::function_ref<void(lldb::ModuleSP)> f) override;
+ bool ForEachExternalModule(
+ lldb_private::CompileUnit &, llvm::DenseSet<lldb_private::SymbolFile *> &,
+ llvm::function_ref<bool(lldb_private::Module &)>) override;
bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit,
lldb_private::FileSpecList &support_files) override;
@@ -190,6 +199,7 @@ public:
void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern,
lldb_private::LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files,
lldb_private::TypeMap &types) override;
void GetTypes(lldb_private::SymbolContextScope *sc_scope,
@@ -212,9 +222,6 @@ public:
uint32_t GetPluginVersion() override;
- const lldb_private::DWARFDataExtractor &get_debug_loc_data();
- const lldb_private::DWARFDataExtractor &get_debug_loclists_data();
-
DWARFDebugAbbrev *DebugAbbrev();
const DWARFDebugAbbrev *DebugAbbrev() const;
@@ -224,9 +231,6 @@ public:
const DWARFDebugInfo *DebugInfo() const;
DWARFDebugRanges *GetDebugRanges();
- DWARFDebugRngLists *GetDebugRngLists();
-
- const lldb_private::DWARFDataExtractor &DebugLocData();
static bool SupportedVersion(uint16_t version);
@@ -250,10 +254,7 @@ public:
virtual lldb::CompUnitSP ParseCompileUnit(DWARFCompileUnit &dwarf_cu);
- virtual lldb_private::DWARFExpression::LocationListFormat
- GetLocationListFormat() const;
-
- lldb::ModuleSP GetDWOModule(lldb_private::ConstString name);
+ lldb::ModuleSP GetExternalModule(lldb_private::ConstString name);
typedef std::map<lldb_private::ConstString, lldb::ModuleSP>
ExternalTypeModuleMap;
@@ -277,7 +278,7 @@ public:
lldb::user_id_t GetUID(DIERef ref);
- virtual std::unique_ptr<SymbolFileDWARFDwo>
+ std::unique_ptr<SymbolFileDWARFDwo>
GetDwoSymbolFileForCompileUnit(DWARFUnit &dwarf_cu,
const DWARFDebugInfoEntry &cu_die);
@@ -288,11 +289,14 @@ public:
virtual llvm::Optional<uint32_t> GetDwoNum() { return llvm::None; }
+ /// If this is a DWARF object with a single CU, return its DW_AT_dwo_id.
+ llvm::Optional<uint64_t> GetDWOId();
+
static bool
DIEInDeclContext(const lldb_private::CompilerDeclContext *parent_decl_ctx,
const DWARFDIE &die);
- std::vector<lldb_private::CallEdge>
+ std::vector<std::unique_ptr<lldb_private::CallEdge>>
ParseCallEdgesInFunction(UserID func_id) override;
void Dump(lldb_private::Stream &s) override;
@@ -484,7 +488,6 @@ protected:
typedef llvm::StringMap<DIERefSet> NameToOffsetMap;
NameToOffsetMap m_function_scope_qualified_name_map;
std::unique_ptr<DWARFDebugRanges> m_ranges;
- std::unique_ptr<DWARFDebugRngLists> m_rnglists;
UniqueDWARFASTTypeMap m_unique_ast_type_map;
DIEToTypePtr m_die_to_type;
DIEToVariableSP m_die_to_variable_sp;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index a50d4e460bae..cce666a222d0 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -39,6 +39,8 @@
using namespace lldb;
using namespace lldb_private;
+char SymbolFileDWARFDebugMap::ID;
+
// Subclass lldb_private::Module so we can intercept the
// "Module::GetObjectFile()" (so we can fixup the object file sections) and
// also for "Module::GetSymbolFile()" (so we can fixup the symbol file id.
@@ -602,7 +604,7 @@ SymbolFileDWARFDebugMap::CompileUnitInfo *
SymbolFileDWARFDebugMap::GetCompUnitInfo(const CompileUnit &comp_unit) {
const uint32_t cu_count = GetNumCompileUnits();
for (uint32_t i = 0; i < cu_count; ++i) {
- if (comp_unit == m_compile_unit_infos[i].compile_unit_sp.get())
+ if (&comp_unit == m_compile_unit_infos[i].compile_unit_sp.get())
return &m_compile_unit_infos[i];
}
return nullptr;
@@ -652,12 +654,15 @@ bool SymbolFileDWARFDebugMap::ParseDebugMacros(CompileUnit &comp_unit) {
return false;
}
-void SymbolFileDWARFDebugMap::ForEachExternalModule(
- CompileUnit &comp_unit, llvm::function_ref<void(ModuleSP)> f) {
+bool SymbolFileDWARFDebugMap::ForEachExternalModule(
+ CompileUnit &comp_unit,
+ llvm::DenseSet<lldb_private::SymbolFile *> &visited_symbol_files,
+ llvm::function_ref<bool(Module &)> f) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
if (oso_dwarf)
- oso_dwarf->ForEachExternalModule(comp_unit, f);
+ return oso_dwarf->ForEachExternalModule(comp_unit, visited_symbol_files, f);
+ return false;
}
bool SymbolFileDWARFDebugMap::ParseSupportFiles(CompileUnit &comp_unit,
@@ -807,12 +812,8 @@ uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext(
if (!resolve) {
FileSpec so_file_spec;
- if (GetFileSpecForSO(i, so_file_spec)) {
- // Match the full path if the incoming file_spec has a directory (not
- // just a basename)
- const bool full_match = (bool)file_spec.GetDirectory();
- resolve = FileSpec::Equal(file_spec, so_file_spec, full_match);
- }
+ if (GetFileSpecForSO(i, so_file_spec))
+ resolve = FileSpec::Match(file_spec, so_file_spec);
}
if (resolve) {
SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(i);
@@ -1071,7 +1072,7 @@ void SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope,
}
}
-std::vector<lldb_private::CallEdge>
+std::vector<std::unique_ptr<lldb_private::CallEdge>>
SymbolFileDWARFDebugMap::ParseCallEdgesInFunction(UserID func_id) {
uint32_t oso_idx = GetOSOIndexFromUserID(func_id.GetID());
SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
@@ -1183,6 +1184,16 @@ void SymbolFileDWARFDebugMap::FindTypes(
});
}
+void SymbolFileDWARFDebugMap::FindTypes(
+ llvm::ArrayRef<CompilerContext> context, LanguageSet languages,
+ llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
+ TypeMap &types) {
+ ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
+ oso_dwarf->FindTypes(context, languages, searched_symbol_files, types);
+ return false;
+ });
+}
+
//
// uint32_t
// SymbolFileDWARFDebugMap::FindTypes (const SymbolContext& sc, const
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index 7adee1b356ce..035a902498be 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -23,7 +23,18 @@ class DWARFDebugAranges;
class DWARFDeclContext;
class SymbolFileDWARFDebugMap : public lldb_private::SymbolFile {
+ /// LLVM RTTI support.
+ static char ID;
+
public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFile::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
+
// Static Functions
static void Initialize();
@@ -53,9 +64,9 @@ public:
bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override;
- void
- ForEachExternalModule(lldb_private::CompileUnit &comp_unit,
- llvm::function_ref<void(lldb::ModuleSP)> f) override;
+ bool ForEachExternalModule(
+ lldb_private::CompileUnit &, llvm::DenseSet<lldb_private::SymbolFile *> &,
+ llvm::function_ref<bool(lldb_private::Module &)>) override;
bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit,
lldb_private::FileSpecList &support_files) override;
@@ -114,13 +125,18 @@ public:
uint32_t max_matches,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
lldb_private::TypeMap &types) override;
+ void
+ FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> context,
+ lldb_private::LanguageSet languages,
+ llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
+ lldb_private::TypeMap &types) override;
lldb_private::CompilerDeclContext FindNamespace(
lldb_private::ConstString name,
const lldb_private::CompilerDeclContext *parent_decl_ctx) override;
void GetTypes(lldb_private::SymbolContextScope *sc_scope,
lldb::TypeClass type_mask,
lldb_private::TypeList &type_list) override;
- std::vector<lldb_private::CallEdge>
+ std::vector<std::unique_ptr<lldb_private::CallEdge>>
ParseCallEdgesInFunction(lldb_private::UserID func_id) override;
void DumpClangAST(lldb_private::Stream &s) override;
@@ -348,8 +364,8 @@ protected:
/// \param[in] oso_symfile
/// The DWARF symbol file that produced the \a line_table
///
- /// \param[in] addr
- /// A section offset address from a .o file
+ /// \param[in] line_table
+ /// A pointer to the line table.
///
/// \return
/// Returns a valid line table full of linked addresses, or NULL
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
index b0f7e813d4f8..f75f06f31e2d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
@@ -21,6 +21,8 @@
using namespace lldb;
using namespace lldb_private;
+char SymbolFileDWARFDwo::ID;
+
SymbolFileDWARFDwo::SymbolFileDWARFDwo(ObjectFileSP objfile,
DWARFCompileUnit &dwarf_cu)
: SymbolFileDWARF(objfile, objfile->GetSectionList(
@@ -135,11 +137,6 @@ SymbolFileDWARF &SymbolFileDWARFDwo::GetBaseSymbolFile() {
return m_base_dwarf_cu.GetSymbolFileDWARF();
}
-DWARFExpression::LocationListFormat
-SymbolFileDWARFDwo::GetLocationListFormat() const {
- return DWARFExpression::SplitDwarfLocationList;
-}
-
llvm::Expected<TypeSystem &>
SymbolFileDWARFDwo::GetTypeSystemForLanguage(LanguageType language) {
return GetBaseSymbolFile().GetTypeSystemForLanguage(language);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
index ad290cdcf65e..0855dba044e4 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
@@ -12,7 +12,18 @@
#include "SymbolFileDWARF.h"
class SymbolFileDWARFDwo : public SymbolFileDWARF {
+ /// LLVM RTTI support.
+ static char ID;
+
public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFileDWARF::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
+
SymbolFileDWARFDwo(lldb::ObjectFileSP objfile, DWARFCompileUnit &dwarf_cu);
~SymbolFileDWARFDwo() override = default;
@@ -24,9 +35,6 @@ public:
DWARFUnit *
GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) override;
- lldb_private::DWARFExpression::LocationListFormat
- GetLocationListFormat() const override;
-
size_t GetObjCMethodDIEOffsets(lldb_private::ConstString class_name,
DIEArray &method_die_offsets) override;
@@ -36,12 +44,6 @@ public:
DWARFDIE
GetDIE(const DIERef &die_ref) override;
- std::unique_ptr<SymbolFileDWARFDwo>
- GetDwoSymbolFileForCompileUnit(DWARFUnit &dwarf_cu,
- const DWARFDebugInfoEntry &cu_die) override {
- return nullptr;
- }
-
DWARFCompileUnit *GetBaseCompileUnit() override { return &m_base_dwarf_cu; }
llvm::Optional<uint32_t> GetDwoNum() override { return GetID() >> 32; }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp
index efea192b17ce..4288dcb5c9bd 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp
@@ -19,6 +19,8 @@
using namespace lldb;
using namespace lldb_private;
+char SymbolFileDWARFDwoDwp::ID;
+
SymbolFileDWARFDwoDwp::SymbolFileDWARFDwoDwp(SymbolFileDWARFDwp *dwp_symfile,
ObjectFileSP objfile,
DWARFCompileUnit &dwarf_cu,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h
index 2105e1a8f6cb..a55795ba5950 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h
@@ -13,7 +13,17 @@
#include "SymbolFileDWARFDwp.h"
class SymbolFileDWARFDwoDwp : public SymbolFileDWARFDwo {
+ /// LLVM RTTI support.
+ static char ID;
+
public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFileDWARFDwo::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
SymbolFileDWARFDwoDwp(SymbolFileDWARFDwp *dwp_symfile,
lldb::ObjectFileSP objfile, DWARFCompileUnit &dwarf_cu,
uint64_t dwo_id);
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
index 986b0b785d87..4588c80aa1b1 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -17,7 +17,7 @@
#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/ClangASTMetadata.h"
#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/LLDBAssert.h"
@@ -655,7 +655,7 @@ bool PdbAstBuilder::CompleteTagDecl(clang::TagDecl &tag) {
lldbassert(IsTagRecord(type_id, m_index.tpi()));
- clang::QualType tag_qt = m_clang.getASTContext()->getTypeDeclType(&tag);
+ clang::QualType tag_qt = m_clang.getASTContext().getTypeDeclType(&tag);
ClangASTContext::SetHasExternalStorage(tag_qt.getAsOpaquePtr(), false);
TypeIndex tag_ti = type_id.index;
@@ -700,7 +700,7 @@ clang::QualType PdbAstBuilder::CreateSimpleType(TypeIndex ti) {
if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
clang::QualType direct_type = GetOrCreateType(ti.makeDirect());
- return m_clang.getASTContext()->getPointerType(direct_type);
+ return m_clang.getASTContext().getPointerType(direct_type);
}
if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated)
@@ -725,19 +725,17 @@ clang::QualType PdbAstBuilder::CreatePointerType(const PointerRecord &pointer) {
MemberPointerInfo mpi = pointer.getMemberInfo();
clang::QualType class_type = GetOrCreateType(mpi.ContainingType);
- return m_clang.getASTContext()->getMemberPointerType(
+ return m_clang.getASTContext().getMemberPointerType(
pointee_type, class_type.getTypePtr());
}
clang::QualType pointer_type;
if (pointer.getMode() == PointerMode::LValueReference)
- pointer_type =
- m_clang.getASTContext()->getLValueReferenceType(pointee_type);
+ pointer_type = m_clang.getASTContext().getLValueReferenceType(pointee_type);
else if (pointer.getMode() == PointerMode::RValueReference)
- pointer_type =
- m_clang.getASTContext()->getRValueReferenceType(pointee_type);
+ pointer_type = m_clang.getASTContext().getRValueReferenceType(pointee_type);
else
- pointer_type = m_clang.getASTContext()->getPointerType(pointee_type);
+ pointer_type = m_clang.getASTContext().getPointerType(pointee_type);
if ((pointer.getOptions() & PointerOptions::Const) != PointerOptions::None)
pointer_type.addConst();
@@ -778,9 +776,8 @@ clang::QualType PdbAstBuilder::CreateRecordType(PdbTypeSymId id,
metadata.SetUserID(toOpaqueUid(id));
metadata.SetIsDynamicCXXType(false);
- CompilerType ct =
- m_clang.CreateRecordType(context, access, uname.c_str(), ttk,
- lldb::eLanguageTypeC_plus_plus, &metadata);
+ CompilerType ct = m_clang.CreateRecordType(
+ context, access, uname, ttk, lldb::eLanguageTypeC_plus_plus, &metadata);
lldbassert(ct.IsValid());
@@ -1081,7 +1078,7 @@ void PdbAstBuilder::CreateFunctionParameters(PdbCompilandSymId func_id,
PdbCompilandSymId param_uid(func_id.modi, record_offset);
clang::QualType qt = GetOrCreateType(param_type);
- CompilerType param_type_ct(&m_clang, qt.getAsOpaquePtr());
+ CompilerType param_type_ct = m_clang.GetType(qt);
clang::ParmVarDecl *param = m_clang.CreateParameterDeclaration(
&function_decl, param_name.str().c_str(), param_type_ct,
clang::SC_None, true);
@@ -1346,7 +1343,7 @@ CompilerType PdbAstBuilder::ToCompilerType(clang::QualType qt) {
CompilerDeclContext
PdbAstBuilder::ToCompilerDeclContext(clang::DeclContext &context) {
- return {&m_clang, &context};
+ return m_clang.CreateDeclContext(&context);
}
clang::Decl * PdbAstBuilder::FromCompilerDecl(CompilerDecl decl) {
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 33b8da3b543b..370c339fb74b 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -20,7 +20,6 @@
#include "lldb/Core/StreamBuffer.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/LineTable.h"
@@ -67,6 +66,8 @@ using namespace npdb;
using namespace llvm::codeview;
using namespace llvm::pdb;
+char SymbolFileNativePDB::ID;
+
static lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
switch (lang) {
case PDB_Lang::Cpp:
@@ -460,7 +461,7 @@ lldb::TypeSP SymbolFileNativePDB::CreateModifierType(PdbTypeSymId type_id,
return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(name),
modified_type->GetByteSize(), nullptr,
LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
- ct, Type::eResolveStateFull);
+ ct, Type::ResolveState::Full);
}
lldb::TypeSP
@@ -480,7 +481,7 @@ SymbolFileNativePDB::CreatePointerType(PdbTypeSymId type_id,
return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(),
pr.getSize(), nullptr, LLDB_INVALID_UID,
Type::eEncodingIsUID, decl, ct,
- Type::eResolveStateFull);
+ Type::ResolveState::Full);
}
lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
@@ -490,7 +491,7 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
Declaration decl;
return std::make_shared<Type>(
uid, this, ConstString("std::nullptr_t"), 0, nullptr, LLDB_INVALID_UID,
- Type::eEncodingIsUID, decl, ct, Type::eResolveStateFull);
+ Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);
}
if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
@@ -511,7 +512,7 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
Declaration decl;
return std::make_shared<Type>(
uid, this, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID,
- Type::eEncodingIsUID, decl, ct, Type::eResolveStateFull);
+ Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);
}
if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated)
@@ -523,7 +524,7 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
Declaration decl;
return std::make_shared<Type>(uid, this, ConstString(type_name), size,
nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID,
- decl, ct, Type::eResolveStateFull);
+ decl, ct, Type::ResolveState::Full);
}
static std::string GetUnqualifiedTypeName(const TagRecord &record) {
@@ -557,7 +558,7 @@ SymbolFileNativePDB::CreateClassStructUnion(PdbTypeSymId type_id,
return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(uname),
size, nullptr, LLDB_INVALID_UID,
Type::eEncodingIsUID, decl, ct,
- Type::eResolveStateForward);
+ Type::ResolveState::Forward);
}
lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
@@ -584,7 +585,7 @@ lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
toOpaqueUid(type_id), this, ConstString(uname),
underlying_type->GetByteSize(), nullptr, LLDB_INVALID_UID,
lldb_private::Type::eEncodingIsUID, decl, ct,
- lldb_private::Type::eResolveStateForward);
+ lldb_private::Type::ResolveState::Forward);
}
TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id,
@@ -596,7 +597,7 @@ TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id,
TypeSP array_sp = std::make_shared<lldb_private::Type>(
toOpaqueUid(type_id), this, ConstString(), ar.Size, nullptr,
LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct,
- lldb_private::Type::eResolveStateFull);
+ lldb_private::Type::ResolveState::Full);
array_sp->SetEncodingType(element_type.get());
return array_sp;
}
@@ -609,7 +610,7 @@ TypeSP SymbolFileNativePDB::CreateFunctionType(PdbTypeSymId type_id,
return std::make_shared<lldb_private::Type>(
toOpaqueUid(type_id), this, ConstString(), 0, nullptr, LLDB_INVALID_UID,
lldb_private::Type::eEncodingIsUID, decl, ct,
- lldb_private::Type::eResolveStateFull);
+ lldb_private::Type::ResolveState::Full);
}
TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id,
@@ -619,7 +620,7 @@ TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id,
return std::make_shared<lldb_private::Type>(
toOpaqueUid(type_id), this, ConstString(), 0, nullptr, LLDB_INVALID_UID,
lldb_private::Type::eEncodingIsUID, decl, ct,
- lldb_private::Type::eResolveStateFull);
+ lldb_private::Type::ResolveState::Full);
}
TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) {
@@ -1108,9 +1109,7 @@ bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) {
// LLDB wants the index of the file in the list of support files.
auto fn_iter = llvm::find(cci->m_file_list, *efn);
lldbassert(fn_iter != cci->m_file_list.end());
- // LLDB support file indices are 1-based.
- uint32_t file_index =
- 1 + std::distance(cci->m_file_list.begin(), fn_iter);
+ uint32_t file_index = std::distance(cci->m_file_list.begin(), fn_iter);
std::unique_ptr<LineSequence> sequence(
line_table->CreateLineSequenceContainer());
@@ -1153,14 +1152,6 @@ bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit,
FileSpec spec(f, style);
support_files.Append(spec);
}
-
- llvm::SmallString<64> main_source_file =
- m_index->compilands().GetMainSourceFile(*cci);
- FileSpec::Style style = main_source_file.startswith("/")
- ? FileSpec::Style::posix
- : FileSpec::Style::windows;
- FileSpec spec(main_source_file, style);
- support_files.Insert(0, spec);
return true;
}
@@ -1259,8 +1250,9 @@ void SymbolFileNativePDB::FindTypes(
FindTypesByName(name.GetStringRef(), max_matches, types);
}
-void SymbolFileNativePDB::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
- LanguageSet languages, TypeMap &types) {}
+void SymbolFileNativePDB::FindTypes(
+ llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {}
void SymbolFileNativePDB::FindTypesByName(llvm::StringRef name,
uint32_t max_matches,
@@ -1386,7 +1378,7 @@ TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) {
toOpaqueUid(id), this, ConstString(udt.Name), target_type->GetByteSize(),
nullptr, target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID,
decl, target_type->GetForwardCompilerType(),
- lldb_private::Type::eResolveStateForward);
+ lldb_private::Type::ResolveState::Forward);
}
TypeSP SymbolFileNativePDB::GetOrCreateTypedef(PdbGlobalSymId id) {
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
index ca7de0e7d1ed..a37de0f58ef3 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -41,7 +41,18 @@ class PdbAstBuilder;
class SymbolFileNativePDB : public SymbolFile {
friend class UdtRecordCompleter;
+ /// LLVM RTTI support.
+ static char ID;
+
public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFile::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
+
// Static Functions
static void Initialize();
@@ -131,6 +142,7 @@ public:
TypeMap &types) override;
void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files,
TypeMap &types) override;
llvm::Expected<TypeSystem &>
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
index 3c494dc83986..7221144407c1 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
@@ -231,6 +231,6 @@ void UdtRecordCompleter::complete() {
ClangASTContext::CompleteTagDeclarationDefinition(m_derived_ct);
if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) {
- m_ast_builder.importer().InsertRecordDecl(record_decl, m_layout);
+ m_ast_builder.importer().SetRecordLayout(record_decl, m_layout);
}
}
diff --git a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
index 47c4ad088494..6b2dbd9e1e5a 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
+++ b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
@@ -16,7 +16,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/ClangASTMetadata.h"
#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Symbol/Declaration.h"
#include "lldb/Symbol/SymbolFile.h"
@@ -103,9 +103,7 @@ static CompilerType
GetBuiltinTypeForPDBEncodingAndBitSize(ClangASTContext &clang_ast,
const PDBSymbolTypeBuiltin &pdb_type,
Encoding encoding, uint32_t width) {
- auto *ast = clang_ast.getASTContext();
- if (!ast)
- return CompilerType();
+ clang::ASTContext &ast = clang_ast.getASTContext();
switch (pdb_type.getBuiltinType()) {
default:
@@ -119,32 +117,25 @@ GetBuiltinTypeForPDBEncodingAndBitSize(ClangASTContext &clang_ast,
case PDB_BuiltinType::Bool:
return clang_ast.GetBasicType(eBasicTypeBool);
case PDB_BuiltinType::Long:
- if (width == ast->getTypeSize(ast->LongTy))
- return CompilerType(ClangASTContext::GetASTContext(ast),
- ast->LongTy.getAsOpaquePtr());
- if (width == ast->getTypeSize(ast->LongLongTy))
- return CompilerType(ClangASTContext::GetASTContext(ast),
- ast->LongLongTy.getAsOpaquePtr());
+ if (width == ast.getTypeSize(ast.LongTy))
+ return CompilerType(&clang_ast, ast.LongTy.getAsOpaquePtr());
+ if (width == ast.getTypeSize(ast.LongLongTy))
+ return CompilerType(&clang_ast, ast.LongLongTy.getAsOpaquePtr());
break;
case PDB_BuiltinType::ULong:
- if (width == ast->getTypeSize(ast->UnsignedLongTy))
- return CompilerType(ClangASTContext::GetASTContext(ast),
- ast->UnsignedLongTy.getAsOpaquePtr());
- if (width == ast->getTypeSize(ast->UnsignedLongLongTy))
- return CompilerType(ClangASTContext::GetASTContext(ast),
- ast->UnsignedLongLongTy.getAsOpaquePtr());
+ if (width == ast.getTypeSize(ast.UnsignedLongTy))
+ return CompilerType(&clang_ast, ast.UnsignedLongTy.getAsOpaquePtr());
+ if (width == ast.getTypeSize(ast.UnsignedLongLongTy))
+ return CompilerType(&clang_ast, ast.UnsignedLongLongTy.getAsOpaquePtr());
break;
case PDB_BuiltinType::WCharT:
- if (width == ast->getTypeSize(ast->WCharTy))
- return CompilerType(ClangASTContext::GetASTContext(ast),
- ast->WCharTy.getAsOpaquePtr());
+ if (width == ast.getTypeSize(ast.WCharTy))
+ return CompilerType(&clang_ast, ast.WCharTy.getAsOpaquePtr());
break;
case PDB_BuiltinType::Char16:
- return CompilerType(ClangASTContext::GetASTContext(ast),
- ast->Char16Ty.getAsOpaquePtr());
+ return CompilerType(&clang_ast, ast.Char16Ty.getAsOpaquePtr());
case PDB_BuiltinType::Char32:
- return CompilerType(ClangASTContext::GetASTContext(ast),
- ast->Char32Ty.getAsOpaquePtr());
+ return CompilerType(&clang_ast, ast.Char32Ty.getAsOpaquePtr());
case PDB_BuiltinType::Float:
// Note: types `long double` and `double` have same bit size in MSVC and
// there is no information in the PDB to distinguish them. So when falling
@@ -405,7 +396,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
// This may occur with const or volatile types. There are separate type
// symbols in PDB for types with const or volatile modifiers, but we need
// to create only one declaration for them all.
- Type::ResolveStateTag type_resolve_state_tag;
+ Type::ResolveState type_resolve_state;
CompilerType clang_type = m_ast.GetTypeForIdentifier<clang::CXXRecordDecl>(
ConstString(name), decl_context);
if (!clang_type.IsValid()) {
@@ -417,9 +408,9 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
metadata.SetUserID(type.getSymIndexId());
metadata.SetIsDynamicCXXType(false);
- clang_type = m_ast.CreateRecordType(
- decl_context, access, name.c_str(), tag_type_kind,
- lldb::eLanguageTypeC_plus_plus, &metadata);
+ clang_type =
+ m_ast.CreateRecordType(decl_context, access, name, tag_type_kind,
+ lldb::eLanguageTypeC_plus_plus, &metadata);
assert(clang_type.IsValid());
auto record_decl =
@@ -428,7 +419,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
m_uid_to_decl[type.getSymIndexId()] = record_decl;
auto inheritance_attr = clang::MSInheritanceAttr::CreateImplicit(
- *m_ast.getASTContext(), GetMSInheritance(*udt));
+ m_ast.getASTContext(), GetMSInheritance(*udt));
record_decl->addAttr(inheritance_attr);
ClangASTContext::StartTagDeclarationDefinition(clang_type);
@@ -442,7 +433,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
ClangASTContext::SetHasExternalStorage(clang_type.GetOpaqueQualType(),
false);
- type_resolve_state_tag = Type::eResolveStateFull;
+ type_resolve_state = Type::ResolveState::Full;
} else {
// Add the type to the forward declarations. It will help us to avoid
// an endless recursion in CompleteTypeFromUdt function.
@@ -451,10 +442,10 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
ClangASTContext::SetHasExternalStorage(clang_type.GetOpaqueQualType(),
true);
- type_resolve_state_tag = Type::eResolveStateForward;
+ type_resolve_state = Type::ResolveState::Forward;
}
} else
- type_resolve_state_tag = Type::eResolveStateForward;
+ type_resolve_state = Type::ResolveState::Forward;
if (udt->isConstType())
clang_type = clang_type.AddConstModifier();
@@ -467,7 +458,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name),
udt->getLength(), nullptr, LLDB_INVALID_UID,
lldb_private::Type::eEncodingIsUID, decl, clang_type,
- type_resolve_state_tag);
+ type_resolve_state);
} break;
case PDB_SymType::Enum: {
auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(&type);
@@ -535,7 +526,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
return std::make_shared<lldb_private::Type>(
type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), bytes,
nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
- ast_enum, lldb_private::Type::eResolveStateFull);
+ ast_enum, lldb_private::Type::ResolveState::Full);
} break;
case PDB_SymType::Typedef: {
auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type);
@@ -558,7 +549,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
CompilerType target_ast_type = target_type->GetFullCompilerType();
ast_typedef = m_ast.CreateTypedefType(
- target_ast_type, name.c_str(), CompilerDeclContext(&m_ast, decl_ctx));
+ target_ast_type, name.c_str(), m_ast.CreateDeclContext(decl_ctx));
if (!ast_typedef)
return nullptr;
@@ -581,7 +572,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
type_def->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name),
size, nullptr, target_type->GetID(),
lldb_private::Type::eEncodingIsTypedefUID, decl, ast_typedef,
- lldb_private::Type::eResolveStateFull);
+ lldb_private::Type::ResolveState::Full);
} break;
case PDB_SymType::Function:
case PDB_SymType::FunctionSig: {
@@ -649,7 +640,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name),
llvm::None, nullptr, LLDB_INVALID_UID,
lldb_private::Type::eEncodingIsUID, decl, func_sig_ast_type,
- lldb_private::Type::eResolveStateFull);
+ lldb_private::Type::ResolveState::Full);
} break;
case PDB_SymType::ArrayType: {
auto array_type = llvm::dyn_cast<PDBSymbolTypeArray>(&type);
@@ -683,7 +674,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
TypeSP type_sp = std::make_shared<lldb_private::Type>(
array_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(),
bytes, nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID,
- decl, array_ast_type, lldb_private::Type::eResolveStateFull);
+ decl, array_ast_type, lldb_private::Type::ResolveState::Full);
type_sp->SetEncodingType(element_type);
return type_sp;
} break;
@@ -712,7 +703,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
return std::make_shared<lldb_private::Type>(
builtin_type->getSymIndexId(), m_ast.GetSymbolFile(), type_name, bytes,
nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
- builtin_ast_type, lldb_private::Type::eResolveStateFull);
+ builtin_ast_type, lldb_private::Type::ResolveState::Full);
} break;
case PDB_SymType::PointerType: {
auto *pointer_type = llvm::dyn_cast<PDBSymbolTypePointer>(&type);
@@ -739,7 +730,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
pointer_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(),
pointer_type->getLength(), nullptr, LLDB_INVALID_UID,
lldb_private::Type::eEncodingIsUID, decl, pointer_ast_type,
- lldb_private::Type::eResolveStateForward);
+ lldb_private::Type::ResolveState::Forward);
}
CompilerType pointer_ast_type;
@@ -764,7 +755,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
pointer_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(),
pointer_type->getLength(), nullptr, LLDB_INVALID_UID,
lldb_private::Type::eEncodingIsUID, decl, pointer_ast_type,
- lldb_private::Type::eResolveStateFull);
+ lldb_private::Type::ResolveState::Full);
} break;
default:
break;
@@ -900,7 +891,7 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) {
// Check if the current context already contains the symbol with the name.
clang::Decl *decl =
- GetDeclFromContextByName(*m_ast.getASTContext(), *decl_context, name);
+ GetDeclFromContextByName(m_ast.getASTContext(), *decl_context, name);
if (!decl) {
auto type = symbol_file->ResolveTypeUID(data->getTypeId());
if (!type)
@@ -1160,7 +1151,7 @@ bool PDBASTParser::AddEnumValue(CompilerType enum_type,
}
CompilerType underlying_type =
m_ast.GetEnumerationIntegerType(enum_type.GetOpaqueQualType());
- uint32_t byte_size = m_ast.getASTContext()->getTypeSize(
+ uint32_t byte_size = m_ast.getASTContext().getTypeSize(
ClangUtil::GetQualType(underlying_type));
auto enum_constant_decl = m_ast.AddEnumerationValueToEnumerationType(
enum_type, decl, name.c_str(), raw_value, byte_size * 8);
@@ -1207,7 +1198,7 @@ bool PDBASTParser::CompleteTypeFromUDT(
if (!record_decl)
return static_cast<bool>(compiler_type);
- GetClangASTImporter().InsertRecordDecl(record_decl, layout_info);
+ GetClangASTImporter().SetRecordLayout(record_decl, layout_info);
return static_cast<bool>(compiler_type);
}
diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
index 854e735b5f83..917ab68af418 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -58,6 +58,8 @@ using namespace lldb;
using namespace lldb_private;
using namespace llvm::pdb;
+char SymbolFilePDB::ID;
+
namespace {
lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
switch (lang) {
@@ -369,10 +371,6 @@ bool SymbolFilePDB::ParseSupportFiles(
support_files.AppendIfUnique(spec);
}
- // LLDB uses the DWARF-like file numeration (one based),
- // the zeroth file is the compile unit itself
- support_files.Insert(0, comp_unit);
-
return true;
}
@@ -668,7 +666,7 @@ SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) {
if (!decl_context)
return GetDeclContextContainingUID(uid);
- return CompilerDeclContext(clang_ast_ctx, decl_context);
+ return clang_ast_ctx->CreateDeclContext(decl_context);
}
lldb_private::CompilerDeclContext
@@ -697,7 +695,7 @@ SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
auto decl_context = pdb->GetDeclContextContainingSymbol(*symbol);
assert(decl_context);
- return CompilerDeclContext(clang_ast_ctx, decl_context);
+ return clang_ast_ctx->CreateDeclContext(decl_context);
}
void SymbolFilePDB::ParseDeclsForContext(
@@ -1562,9 +1560,10 @@ void SymbolFilePDB::FindTypesByName(
}
}
-void SymbolFilePDB::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
- LanguageSet languages,
- lldb_private::TypeMap &types) {}
+void SymbolFilePDB::FindTypes(
+ llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files,
+ lldb_private::TypeMap &types) {}
void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol,
uint32_t type_mask,
@@ -1704,8 +1703,7 @@ lldb_private::CompilerDeclContext SymbolFilePDB::FindNamespace(
if (!namespace_decl)
return CompilerDeclContext();
- return CompilerDeclContext(clang_type_system,
- static_cast<clang::DeclContext *>(namespace_decl));
+ return clang_type_system->CreateDeclContext(namespace_decl);
}
lldb_private::ConstString SymbolFilePDB::GetPluginName() {
@@ -1777,7 +1775,6 @@ bool SymbolFilePDB::ParseCompileUnitLineTable(CompileUnit &comp_unit,
auto line_table = std::make_unique<LineTable>(&comp_unit);
// Find contributions to `compiland` from all source and header files.
- std::string path = comp_unit.GetPath();
auto files = m_session_up->getSourceFilesForCompiland(*compiland_up);
if (!files)
return false;
@@ -1879,9 +1876,7 @@ void SymbolFilePDB::BuildSupportFileIdToSupportFileIndexMap(
if (!source_files)
return;
- // LLDB uses the DWARF-like file numeration (one based)
- int index = 1;
-
+ int index = 0;
while (auto file = source_files->getNext()) {
uint32_t source_id = file->getUniqueId();
index_map[source_id] = index++;
diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
index df717bbbbdb0..7a4eee48771a 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
+++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
@@ -22,7 +22,18 @@
class PDBASTParser;
class SymbolFilePDB : public lldb_private::SymbolFile {
+ /// LLVM RTTI support.
+ static char ID;
+
public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFile::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
+
// Static Functions
static void Initialize();
@@ -134,6 +145,7 @@ public:
void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern,
lldb_private::LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files,
lldb_private::TypeMap &types) override;
void FindTypesByRegex(const lldb_private::RegularExpression &regex,
diff --git a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
index 62da76581c3e..305efea1afab 100644
--- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
+++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
@@ -25,6 +25,8 @@
using namespace lldb;
using namespace lldb_private;
+char SymbolFileSymtab::ID;
+
void SymbolFileSymtab::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
GetPluginDescriptionStatic(), CreateInstance);
diff --git a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
index 2ac4660f0125..1fff8188433e 100644
--- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
+++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
@@ -16,7 +16,18 @@
#include "lldb/Symbol/Symtab.h"
class SymbolFileSymtab : public lldb_private::SymbolFile {
+ /// LLVM RTTI support.
+ static char ID;
+
public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFile::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
+
// Constructors and Destructors
SymbolFileSymtab(lldb::ObjectFileSP objfile_sp);
diff --git a/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
index e61e5763fabb..d4d7a8937c12 100644
--- a/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
+++ b/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
@@ -119,14 +119,17 @@ SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp,
SectionList *objfile_section_list = dsym_objfile_sp->GetSectionList();
static const SectionType g_sections[] = {
- eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr,
- eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugCuIndex,
- eSectionTypeDWARFDebugFrame, eSectionTypeDWARFDebugInfo,
- eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLoc,
- eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugPubNames,
- eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges,
- eSectionTypeDWARFDebugStr, eSectionTypeDWARFDebugStrOffsets,
- eSectionTypeELFSymbolTable, eSectionTypeDWARFGNUDebugAltLink,
+ eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr,
+ eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugCuIndex,
+ eSectionTypeDWARFDebugFrame, eSectionTypeDWARFDebugInfo,
+ eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLineStr,
+ eSectionTypeDWARFDebugLoc, eSectionTypeDWARFDebugLocLists,
+ eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugMacro,
+ eSectionTypeDWARFDebugNames, eSectionTypeDWARFDebugPubNames,
+ eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges,
+ eSectionTypeDWARFDebugRngLists, eSectionTypeDWARFDebugStr,
+ eSectionTypeDWARFDebugStrOffsets, eSectionTypeDWARFDebugTypes,
+ eSectionTypeELFSymbolTable, eSectionTypeDWARFGNUDebugAltLink,
};
for (SectionType section_type : g_sections) {
if (SectionSP section_sp =
diff --git a/lldb/source/Symbol/Block.cpp b/lldb/source/Symbol/Block.cpp
index 77a4830dea7c..bf380064200a 100644
--- a/lldb/source/Symbol/Block.cpp
+++ b/lldb/source/Symbol/Block.cpp
@@ -44,8 +44,8 @@ void Block::GetDescription(Stream *s, Function *function,
s->Printf(", range%s = ", num_ranges > 1 ? "s" : "");
for (size_t i = 0; i < num_ranges; ++i) {
const Range &range = m_ranges.GetEntryRef(i);
- s->AddressRange(base_addr + range.GetRangeBase(),
- base_addr + range.GetRangeEnd(), 4);
+ DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),
+ base_addr + range.GetRangeEnd(), 4);
}
}
@@ -87,8 +87,8 @@ void Block::Dump(Stream *s, addr_t base_addr, int32_t depth,
*s << '!';
else
*s << ' ';
- s->AddressRange(base_addr + range.GetRangeBase(),
- base_addr + range.GetRangeEnd(), 4);
+ DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),
+ base_addr + range.GetRangeEnd(), 4);
}
}
s->EOL();
@@ -160,8 +160,8 @@ void Block::DumpAddressRanges(Stream *s, lldb::addr_t base_addr) {
size_t num_ranges = m_ranges.GetSize();
for (size_t i = 0; i < num_ranges; ++i) {
const Range &range = m_ranges.GetEntryRef(i);
- s->AddressRange(base_addr + range.GetRangeBase(),
- base_addr + range.GetRangeEnd(), 4);
+ DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),
+ base_addr + range.GetRangeEnd(), 4);
}
}
}
@@ -406,11 +406,10 @@ Block::AppendBlockVariables(bool can_create, bool get_child_block_variables,
uint32_t num_variables_added = 0;
VariableList *block_var_list = GetBlockVariableList(can_create).get();
if (block_var_list) {
- for (size_t i = 0; i < block_var_list->GetSize(); ++i) {
- VariableSP variable = block_var_list->GetVariableAtIndex(i);
- if (filter(variable.get())) {
+ for (const VariableSP &var_sp : *block_var_list) {
+ if (filter(var_sp.get())) {
num_variables_added++;
- variable_list->AddVariable(variable);
+ variable_list->AddVariable(var_sp);
}
}
}
diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp
index 565b15a007da..ac3bce179d9e 100644
--- a/lldb/source/Symbol/ClangASTContext.cpp
+++ b/lldb/source/Symbol/ClangASTContext.cpp
@@ -15,24 +15,6 @@
#include <string>
#include <vector>
-
-// Clang headers like to use NDEBUG inside of them to enable/disable debug
-// related features using "#ifndef NDEBUG" preprocessor blocks to do one thing
-// or another. This is bad because it means that if clang was built in release
-// mode, it assumes that you are building in release mode which is not always
-// the case. You can end up with functions that are defined as empty in header
-// files when NDEBUG is not defined, and this can cause link errors with the
-// clang .a files that you have since you might be missing functions in the .a
-// file. So we have to define NDEBUG when including clang headers to avoid any
-// mismatches. This is covered by rdar://problem/8691220
-
-#if !defined(NDEBUG) && !defined(LLVM_NDEBUG_OFF)
-#define LLDB_DEFINED_NDEBUG_FOR_CLANG
-#define NDEBUG
-// Need to include assert.h so it is as clang would expect it to be (disabled)
-#include <assert.h>
-#endif
-
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTImporter.h"
#include "clang/AST/Attr.h"
@@ -54,13 +36,6 @@
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Sema/Sema.h"
-#ifdef LLDB_DEFINED_NDEBUG_FOR_CLANG
-#undef NDEBUG
-#undef LLDB_DEFINED_NDEBUG_FOR_CLANG
-// Need to re-include assert.h so it is as _we_ would expect it to be (enabled)
-#include <assert.h>
-#endif
-
#include "llvm/Support/Signals.h"
#include "llvm/Support/Threading.h"
@@ -78,8 +53,8 @@
#include "lldb/Core/ThreadSafeDenseMap.h"
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/Symbol/ClangASTImporter.h"
+#include "lldb/Symbol/ClangASTMetadata.h"
#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolFile.h"
@@ -337,6 +312,8 @@ static ClangASTMap &GetASTMap() {
return *g_map_ptr;
}
+char ClangASTContext::ID;
+
bool ClangASTContext::IsOperator(llvm::StringRef name,
clang::OverloadedOperatorKind &op_kind) {
// All operators have to start with "operator".
@@ -522,25 +499,15 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) {
Opts.NoInlineDefine = !Opt;
}
-ClangASTContext::ClangASTContext(llvm::StringRef target_triple)
- : TypeSystem(TypeSystem::eKindClang) {
- if (!target_triple.empty())
- SetTargetTriple(target_triple);
- // The caller didn't pass an ASTContext so create a new one for this
- // ClangASTContext.
- CreateASTContext();
-}
-
-ClangASTContext::ClangASTContext(ArchSpec arch)
- : TypeSystem(TypeSystem::eKindClang) {
- SetTargetTriple(arch.GetTriple().str());
+ClangASTContext::ClangASTContext(llvm::Triple target_triple) {
+ if (!target_triple.str().empty())
+ SetTargetTriple(target_triple.str());
// The caller didn't pass an ASTContext so create a new one for this
// ClangASTContext.
CreateASTContext();
}
-ClangASTContext::ClangASTContext(ASTContext &existing_ctxt)
- : TypeSystem(TypeSystem::eKindClang) {
+ClangASTContext::ClangASTContext(ASTContext &existing_ctxt) {
SetTargetTriple(existing_ctxt.getTargetInfo().getTriple().str());
m_ast_up.reset(&existing_ctxt);
@@ -563,48 +530,36 @@ uint32_t ClangASTContext::GetPluginVersion() { return 1; }
lldb::TypeSystemSP ClangASTContext::CreateInstance(lldb::LanguageType language,
lldb_private::Module *module,
Target *target) {
- if (ClangASTContextSupportsLanguage(language)) {
- ArchSpec arch;
- if (module)
- arch = module->GetArchitecture();
- else if (target)
- arch = target->GetArchitecture();
-
- if (arch.IsValid()) {
- ArchSpec fixed_arch = arch;
- // LLVM wants this to be set to iOS or MacOSX; if we're working on
- // a bare-boards type image, change the triple for llvm's benefit.
- if (fixed_arch.GetTriple().getVendor() == llvm::Triple::Apple &&
- fixed_arch.GetTriple().getOS() == llvm::Triple::UnknownOS) {
- if (fixed_arch.GetTriple().getArch() == llvm::Triple::arm ||
- fixed_arch.GetTriple().getArch() == llvm::Triple::aarch64 ||
- fixed_arch.GetTriple().getArch() == llvm::Triple::aarch64_32 ||
- fixed_arch.GetTriple().getArch() == llvm::Triple::thumb) {
- fixed_arch.GetTriple().setOS(llvm::Triple::IOS);
- } else {
- fixed_arch.GetTriple().setOS(llvm::Triple::MacOSX);
- }
- }
-
- if (module) {
- std::shared_ptr<ClangASTContext> ast_sp(
- new ClangASTContext(fixed_arch));
- return ast_sp;
- } else if (target && target->IsValid()) {
- std::shared_ptr<ClangASTContextForExpressions> ast_sp(
- new ClangASTContextForExpressions(*target, fixed_arch));
- ast_sp->m_scratch_ast_source_up.reset(
- new ClangASTSource(target->shared_from_this()));
- lldbassert(ast_sp->getFileManager());
- ast_sp->m_scratch_ast_source_up->InstallASTContext(
- *ast_sp->getASTContext(), *ast_sp->getFileManager(), true);
- llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source(
- ast_sp->m_scratch_ast_source_up->CreateProxy());
- ast_sp->SetExternalSource(proxy_ast_source);
- return ast_sp;
- }
+ if (!ClangASTContextSupportsLanguage(language))
+ return lldb::TypeSystemSP();
+ ArchSpec arch;
+ if (module)
+ arch = module->GetArchitecture();
+ else if (target)
+ arch = target->GetArchitecture();
+
+ if (!arch.IsValid())
+ return lldb::TypeSystemSP();
+
+ llvm::Triple triple = arch.GetTriple();
+ // LLVM wants this to be set to iOS or MacOSX; if we're working on
+ // a bare-boards type image, change the triple for llvm's benefit.
+ if (triple.getVendor() == llvm::Triple::Apple &&
+ triple.getOS() == llvm::Triple::UnknownOS) {
+ if (triple.getArch() == llvm::Triple::arm ||
+ triple.getArch() == llvm::Triple::aarch64 ||
+ triple.getArch() == llvm::Triple::aarch64_32 ||
+ triple.getArch() == llvm::Triple::thumb) {
+ triple.setOS(llvm::Triple::IOS);
+ } else {
+ triple.setOS(llvm::Triple::MacOSX);
}
}
+
+ if (module)
+ return std::make_shared<ClangASTContext>(triple);
+ else if (target && target->IsValid())
+ return std::make_shared<ClangASTContextForExpressions>(*target, triple);
return lldb::TypeSystemSP();
}
@@ -658,7 +613,6 @@ void ClangASTContext::Finalize() {
m_diagnostics_engine_up.reset();
m_source_manager_up.reset();
m_language_options_up.reset();
- m_scratch_ast_source_up.reset();
}
void ClangASTContext::setSema(Sema *s) {
@@ -677,26 +631,70 @@ void ClangASTContext::SetTargetTriple(llvm::StringRef target_triple) {
void ClangASTContext::SetExternalSource(
llvm::IntrusiveRefCntPtr<ExternalASTSource> &ast_source_up) {
- ASTContext *ast = getASTContext();
- if (ast) {
- ast->setExternalSource(ast_source_up);
- ast->getTranslationUnitDecl()->setHasExternalLexicalStorage(true);
- }
+ ASTContext &ast = getASTContext();
+ ast.setExternalSource(ast_source_up);
+ ast.getTranslationUnitDecl()->setHasExternalLexicalStorage(true);
}
-ASTContext *ClangASTContext::getASTContext() {
+ASTContext &ClangASTContext::getASTContext() {
assert(m_ast_up);
- return m_ast_up.get();
+ return *m_ast_up;
}
+class NullDiagnosticConsumer : public DiagnosticConsumer {
+public:
+ NullDiagnosticConsumer() {
+ m_log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
+ }
+
+ void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const clang::Diagnostic &info) override {
+ if (m_log) {
+ llvm::SmallVector<char, 32> diag_str(10);
+ info.FormatDiagnostic(diag_str);
+ diag_str.push_back('\0');
+ LLDB_LOGF(m_log, "Compiler diagnostic: %s\n", diag_str.data());
+ }
+ }
+
+ DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
+ return new NullDiagnosticConsumer();
+ }
+
+private:
+ Log *m_log;
+};
+
void ClangASTContext::CreateASTContext() {
assert(!m_ast_up);
m_ast_owned = true;
- m_ast_up.reset(new ASTContext(*getLanguageOptions(), *getSourceManager(),
- *getIdentifierTable(), *getSelectorTable(),
- *getBuiltinContext()));
- m_ast_up->getDiagnostics().setClient(getDiagnosticConsumer(), false);
+ m_language_options_up.reset(new LangOptions());
+ ParseLangArgs(*m_language_options_up, clang::Language::ObjCXX,
+ GetTargetTriple());
+
+ m_identifier_table_up.reset(
+ new IdentifierTable(*m_language_options_up, nullptr));
+ m_builtins_up.reset(new Builtin::Context());
+
+ m_selector_table_up.reset(new SelectorTable());
+
+ clang::FileSystemOptions file_system_options;
+ m_file_manager_up.reset(new clang::FileManager(
+ file_system_options, FileSystem::Instance().GetVirtualFileSystem()));
+
+ llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_id_sp(new DiagnosticIDs());
+ m_diagnostics_engine_up.reset(
+ new DiagnosticsEngine(diag_id_sp, new DiagnosticOptions()));
+
+ m_source_manager_up.reset(
+ new clang::SourceManager(*m_diagnostics_engine_up, *m_file_manager_up));
+ m_ast_up.reset(new ASTContext(*m_language_options_up, *m_source_manager_up,
+ *m_identifier_table_up, *m_selector_table_up,
+ *m_builtins_up));
+
+ m_diagnostic_consumer_up.reset(new NullDiagnosticConsumer);
+ m_ast_up->getDiagnostics().setClient(m_diagnostic_consumer_up.get(), false);
// This can be NULL if we don't know anything about the architecture or if
// the target for an architecture isn't enabled in the llvm/clang that we
@@ -705,18 +703,10 @@ void ClangASTContext::CreateASTContext() {
if (target_info)
m_ast_up->InitBuiltinTypes(*target_info);
- if ((m_callback_tag_decl || m_callback_objc_decl) && m_callback_baton) {
- m_ast_up->getTranslationUnitDecl()->setHasExternalLexicalStorage();
- // m_ast_up->getTranslationUnitDecl()->setHasExternalVisibleStorage();
- }
-
GetASTMap().Insert(m_ast_up.get(), this);
llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_up(
- new ClangExternalASTSourceCallbacks(
- ClangASTContext::CompleteTagDecl,
- ClangASTContext::CompleteObjCInterfaceDecl, nullptr,
- ClangASTContext::LayoutRecordType, this));
+ new ClangExternalASTSourceCallbacks(*this));
SetExternalSource(ast_source_up);
}
@@ -725,97 +715,12 @@ ClangASTContext *ClangASTContext::GetASTContext(clang::ASTContext *ast) {
return clang_ast;
}
-Builtin::Context *ClangASTContext::getBuiltinContext() {
- if (m_builtins_up == nullptr)
- m_builtins_up.reset(new Builtin::Context());
- return m_builtins_up.get();
-}
-
-IdentifierTable *ClangASTContext::getIdentifierTable() {
- if (m_identifier_table_up == nullptr)
- m_identifier_table_up.reset(
- new IdentifierTable(*ClangASTContext::getLanguageOptions(), nullptr));
- return m_identifier_table_up.get();
-}
-
-LangOptions *ClangASTContext::getLanguageOptions() {
- if (m_language_options_up == nullptr) {
- m_language_options_up.reset(new LangOptions());
- ParseLangArgs(*m_language_options_up, clang::Language::ObjCXX,
- GetTargetTriple());
- // InitializeLangOptions(*m_language_options_up, Language::ObjCXX);
- }
- return m_language_options_up.get();
-}
-
-SelectorTable *ClangASTContext::getSelectorTable() {
- if (m_selector_table_up == nullptr)
- m_selector_table_up.reset(new SelectorTable());
- return m_selector_table_up.get();
-}
-
-clang::FileManager *ClangASTContext::getFileManager() {
- if (m_file_manager_up == nullptr) {
- clang::FileSystemOptions file_system_options;
- m_file_manager_up.reset(new clang::FileManager(
- file_system_options, FileSystem::Instance().GetVirtualFileSystem()));
- }
- return m_file_manager_up.get();
-}
-
-clang::SourceManager *ClangASTContext::getSourceManager() {
- if (m_source_manager_up == nullptr)
- m_source_manager_up.reset(
- new clang::SourceManager(*getDiagnosticsEngine(), *getFileManager()));
- return m_source_manager_up.get();
-}
-
-clang::DiagnosticsEngine *ClangASTContext::getDiagnosticsEngine() {
- if (m_diagnostics_engine_up == nullptr) {
- llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_id_sp(new DiagnosticIDs());
- m_diagnostics_engine_up.reset(
- new DiagnosticsEngine(diag_id_sp, new DiagnosticOptions()));
- }
- return m_diagnostics_engine_up.get();
-}
-
clang::MangleContext *ClangASTContext::getMangleContext() {
if (m_mangle_ctx_up == nullptr)
- m_mangle_ctx_up.reset(getASTContext()->createMangleContext());
+ m_mangle_ctx_up.reset(getASTContext().createMangleContext());
return m_mangle_ctx_up.get();
}
-class NullDiagnosticConsumer : public DiagnosticConsumer {
-public:
- NullDiagnosticConsumer() {
- m_log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
- }
-
- void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
- const clang::Diagnostic &info) override {
- if (m_log) {
- llvm::SmallVector<char, 32> diag_str(10);
- info.FormatDiagnostic(diag_str);
- diag_str.push_back('\0');
- LLDB_LOGF(m_log, "Compiler diagnostic: %s\n", diag_str.data());
- }
- }
-
- DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
- return new NullDiagnosticConsumer();
- }
-
-private:
- Log *m_log;
-};
-
-DiagnosticConsumer *ClangASTContext::getDiagnosticConsumer() {
- if (m_diagnostic_consumer_up == nullptr)
- m_diagnostic_consumer_up.reset(new NullDiagnosticConsumer);
-
- return m_diagnostic_consumer_up.get();
-}
-
std::shared_ptr<clang::TargetOptions> &ClangASTContext::getTargetOptions() {
if (m_target_options_rp == nullptr && !m_target_triple.empty()) {
m_target_options_rp = std::make_shared<clang::TargetOptions>();
@@ -828,93 +733,74 @@ std::shared_ptr<clang::TargetOptions> &ClangASTContext::getTargetOptions() {
TargetInfo *ClangASTContext::getTargetInfo() {
// target_triple should be something like "x86_64-apple-macosx"
if (m_target_info_up == nullptr && !m_target_triple.empty())
- m_target_info_up.reset(TargetInfo::CreateTargetInfo(*getDiagnosticsEngine(),
- getTargetOptions()));
+ m_target_info_up.reset(TargetInfo::CreateTargetInfo(
+ getASTContext().getDiagnostics(), getTargetOptions()));
return m_target_info_up.get();
}
#pragma mark Basic Types
static inline bool QualTypeMatchesBitSize(const uint64_t bit_size,
- ASTContext *ast, QualType qual_type) {
- uint64_t qual_type_bit_size = ast->getTypeSize(qual_type);
+ ASTContext &ast, QualType qual_type) {
+ uint64_t qual_type_bit_size = ast.getTypeSize(qual_type);
return qual_type_bit_size == bit_size;
}
CompilerType
ClangASTContext::GetBuiltinTypeForEncodingAndBitSize(Encoding encoding,
size_t bit_size) {
- return ClangASTContext::GetBuiltinTypeForEncodingAndBitSize(
- getASTContext(), encoding, bit_size);
-}
-
-CompilerType ClangASTContext::GetBuiltinTypeForEncodingAndBitSize(
- ASTContext *ast, Encoding encoding, uint32_t bit_size) {
- auto *clang_ast_context = ClangASTContext::GetASTContext(ast);
- if (!ast)
- return CompilerType();
+ ASTContext &ast = getASTContext();
switch (encoding) {
case eEncodingInvalid:
- if (QualTypeMatchesBitSize(bit_size, ast, ast->VoidPtrTy))
- return CompilerType(clang_ast_context, ast->VoidPtrTy.getAsOpaquePtr());
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.VoidPtrTy))
+ return GetType(ast.VoidPtrTy);
break;
case eEncodingUint:
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy))
- return CompilerType(clang_ast_context,
- ast->UnsignedCharTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy))
- return CompilerType(clang_ast_context,
- ast->UnsignedShortTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedIntTy))
- return CompilerType(clang_ast_context,
- ast->UnsignedIntTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongTy))
- return CompilerType(clang_ast_context,
- ast->UnsignedLongTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongLongTy))
- return CompilerType(clang_ast_context,
- ast->UnsignedLongLongTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedInt128Ty))
- return CompilerType(clang_ast_context,
- ast->UnsignedInt128Ty.getAsOpaquePtr());
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
+ return GetType(ast.UnsignedCharTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
+ return GetType(ast.UnsignedShortTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedIntTy))
+ return GetType(ast.UnsignedIntTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongTy))
+ return GetType(ast.UnsignedLongTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongLongTy))
+ return GetType(ast.UnsignedLongLongTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedInt128Ty))
+ return GetType(ast.UnsignedInt128Ty);
break;
case eEncodingSint:
- if (QualTypeMatchesBitSize(bit_size, ast, ast->SignedCharTy))
- return CompilerType(clang_ast_context,
- ast->SignedCharTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->ShortTy))
- return CompilerType(clang_ast_context, ast->ShortTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->IntTy))
- return CompilerType(clang_ast_context, ast->IntTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->LongTy))
- return CompilerType(clang_ast_context, ast->LongTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->LongLongTy))
- return CompilerType(clang_ast_context, ast->LongLongTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->Int128Ty))
- return CompilerType(clang_ast_context, ast->Int128Ty.getAsOpaquePtr());
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.SignedCharTy))
+ return GetType(ast.SignedCharTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.ShortTy))
+ return GetType(ast.ShortTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.IntTy))
+ return GetType(ast.IntTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.LongTy))
+ return GetType(ast.LongTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.LongLongTy))
+ return GetType(ast.LongLongTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.Int128Ty))
+ return GetType(ast.Int128Ty);
break;
case eEncodingIEEE754:
- if (QualTypeMatchesBitSize(bit_size, ast, ast->FloatTy))
- return CompilerType(clang_ast_context, ast->FloatTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->DoubleTy))
- return CompilerType(clang_ast_context, ast->DoubleTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->LongDoubleTy))
- return CompilerType(clang_ast_context,
- ast->LongDoubleTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->HalfTy))
- return CompilerType(clang_ast_context, ast->HalfTy.getAsOpaquePtr());
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.FloatTy))
+ return GetType(ast.FloatTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.DoubleTy))
+ return GetType(ast.DoubleTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleTy))
+ return GetType(ast.LongDoubleTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.HalfTy))
+ return GetType(ast.HalfTy);
break;
case eEncodingVector:
// Sanity check that bit_size is a multiple of 8's.
if (bit_size && !(bit_size & 0x7u))
- return CompilerType(
- clang_ast_context,
- ast->getExtVectorType(ast->UnsignedCharTy, bit_size / 8)
- .getAsOpaquePtr());
+ return GetType(ast.getExtVectorType(ast.UnsignedCharTy, bit_size / 8));
break;
}
@@ -987,15 +873,6 @@ ClangASTContext::GetBasicTypeEnumeration(ConstString name) {
return eBasicTypeInvalid;
}
-CompilerType ClangASTContext::GetBasicType(ASTContext *ast,
- ConstString name) {
- if (ast) {
- lldb::BasicType basic_type = ClangASTContext::GetBasicTypeEnumeration(name);
- return ClangASTContext::GetBasicType(ast, basic_type);
- }
- return CompilerType();
-}
-
uint32_t ClangASTContext::GetPointerByteSize() {
if (m_pointer_byte_size == 0)
if (auto size = GetBasicType(lldb::eBasicTypeVoid)
@@ -1006,236 +883,220 @@ uint32_t ClangASTContext::GetPointerByteSize() {
}
CompilerType ClangASTContext::GetBasicType(lldb::BasicType basic_type) {
- return GetBasicType(getASTContext(), basic_type);
-}
+ clang::ASTContext &ast = getASTContext();
-CompilerType ClangASTContext::GetBasicType(ASTContext *ast,
- lldb::BasicType basic_type) {
- if (!ast)
- return CompilerType();
lldb::opaque_compiler_type_t clang_type =
- GetOpaqueCompilerType(ast, basic_type);
+ GetOpaqueCompilerType(&ast, basic_type);
if (clang_type)
- return CompilerType(GetASTContext(ast), clang_type);
+ return CompilerType(this, clang_type);
return CompilerType();
}
CompilerType ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize(
- const char *type_name, uint32_t dw_ate, uint32_t bit_size) {
- ASTContext *ast = getASTContext();
+ llvm::StringRef type_name, uint32_t dw_ate, uint32_t bit_size) {
+ ASTContext &ast = getASTContext();
-#define streq(a, b) strcmp(a, b) == 0
- assert(ast != nullptr);
- if (ast) {
- switch (dw_ate) {
- default:
- break;
+ switch (dw_ate) {
+ default:
+ break;
- case DW_ATE_address:
- if (QualTypeMatchesBitSize(bit_size, ast, ast->VoidPtrTy))
- return CompilerType(this, ast->VoidPtrTy.getAsOpaquePtr());
- break;
+ case DW_ATE_address:
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.VoidPtrTy))
+ return GetType(ast.VoidPtrTy);
+ break;
- case DW_ATE_boolean:
- if (QualTypeMatchesBitSize(bit_size, ast, ast->BoolTy))
- return CompilerType(this, ast->BoolTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy))
- return CompilerType(this, ast->UnsignedCharTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy))
- return CompilerType(this, ast->UnsignedShortTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedIntTy))
- return CompilerType(this, ast->UnsignedIntTy.getAsOpaquePtr());
- break;
+ case DW_ATE_boolean:
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.BoolTy))
+ return GetType(ast.BoolTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
+ return GetType(ast.UnsignedCharTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
+ return GetType(ast.UnsignedShortTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedIntTy))
+ return GetType(ast.UnsignedIntTy);
+ break;
- case DW_ATE_lo_user:
- // This has been seen to mean DW_AT_complex_integer
- if (type_name) {
- if (::strstr(type_name, "complex")) {
- CompilerType complex_int_clang_type =
- GetBuiltinTypeForDWARFEncodingAndBitSize("int", DW_ATE_signed,
- bit_size / 2);
- return CompilerType(
- this, ast->getComplexType(
- ClangUtil::GetQualType(complex_int_clang_type))
- .getAsOpaquePtr());
- }
- }
- break;
+ case DW_ATE_lo_user:
+ // This has been seen to mean DW_AT_complex_integer
+ if (type_name.contains("complex")) {
+ CompilerType complex_int_clang_type =
+ GetBuiltinTypeForDWARFEncodingAndBitSize("int", DW_ATE_signed,
+ bit_size / 2);
+ return GetType(
+ ast.getComplexType(ClangUtil::GetQualType(complex_int_clang_type)));
+ }
+ break;
- case DW_ATE_complex_float:
- if (QualTypeMatchesBitSize(bit_size, ast, ast->FloatComplexTy))
- return CompilerType(this, ast->FloatComplexTy.getAsOpaquePtr());
- else if (QualTypeMatchesBitSize(bit_size, ast, ast->DoubleComplexTy))
- return CompilerType(this, ast->DoubleComplexTy.getAsOpaquePtr());
- else if (QualTypeMatchesBitSize(bit_size, ast, ast->LongDoubleComplexTy))
- return CompilerType(this, ast->LongDoubleComplexTy.getAsOpaquePtr());
- else {
- CompilerType complex_float_clang_type =
- GetBuiltinTypeForDWARFEncodingAndBitSize("float", DW_ATE_float,
- bit_size / 2);
- return CompilerType(
- this, ast->getComplexType(
- ClangUtil::GetQualType(complex_float_clang_type))
- .getAsOpaquePtr());
- }
- break;
+ case DW_ATE_complex_float:
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.FloatComplexTy))
+ return GetType(ast.FloatComplexTy);
+ else if (QualTypeMatchesBitSize(bit_size, ast, ast.DoubleComplexTy))
+ return GetType(ast.DoubleComplexTy);
+ else if (QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleComplexTy))
+ return GetType(ast.LongDoubleComplexTy);
+ else {
+ CompilerType complex_float_clang_type =
+ GetBuiltinTypeForDWARFEncodingAndBitSize("float", DW_ATE_float,
+ bit_size / 2);
+ return GetType(
+ ast.getComplexType(ClangUtil::GetQualType(complex_float_clang_type)));
+ }
+ break;
- case DW_ATE_float:
- if (streq(type_name, "float") &&
- QualTypeMatchesBitSize(bit_size, ast, ast->FloatTy))
- return CompilerType(this, ast->FloatTy.getAsOpaquePtr());
- if (streq(type_name, "double") &&
- QualTypeMatchesBitSize(bit_size, ast, ast->DoubleTy))
- return CompilerType(this, ast->DoubleTy.getAsOpaquePtr());
- if (streq(type_name, "long double") &&
- QualTypeMatchesBitSize(bit_size, ast, ast->LongDoubleTy))
- return CompilerType(this, ast->LongDoubleTy.getAsOpaquePtr());
- // Fall back to not requiring a name match
- if (QualTypeMatchesBitSize(bit_size, ast, ast->FloatTy))
- return CompilerType(this, ast->FloatTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->DoubleTy))
- return CompilerType(this, ast->DoubleTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->LongDoubleTy))
- return CompilerType(this, ast->LongDoubleTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->HalfTy))
- return CompilerType(this, ast->HalfTy.getAsOpaquePtr());
- break;
+ case DW_ATE_float:
+ if (type_name == "float" &&
+ QualTypeMatchesBitSize(bit_size, ast, ast.FloatTy))
+ return GetType(ast.FloatTy);
+ if (type_name == "double" &&
+ QualTypeMatchesBitSize(bit_size, ast, ast.DoubleTy))
+ return GetType(ast.DoubleTy);
+ if (type_name == "long double" &&
+ QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleTy))
+ return GetType(ast.LongDoubleTy);
+ // Fall back to not requiring a name match
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.FloatTy))
+ return GetType(ast.FloatTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.DoubleTy))
+ return GetType(ast.DoubleTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleTy))
+ return GetType(ast.LongDoubleTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.HalfTy))
+ return GetType(ast.HalfTy);
+ break;
- case DW_ATE_signed:
- if (type_name) {
- if (streq(type_name, "wchar_t") &&
- QualTypeMatchesBitSize(bit_size, ast, ast->WCharTy) &&
- (getTargetInfo() &&
- TargetInfo::isTypeSigned(getTargetInfo()->getWCharType())))
- return CompilerType(this, ast->WCharTy.getAsOpaquePtr());
- if (streq(type_name, "void") &&
- QualTypeMatchesBitSize(bit_size, ast, ast->VoidTy))
- return CompilerType(this, ast->VoidTy.getAsOpaquePtr());
- if (strstr(type_name, "long long") &&
- QualTypeMatchesBitSize(bit_size, ast, ast->LongLongTy))
- return CompilerType(this, ast->LongLongTy.getAsOpaquePtr());
- if (strstr(type_name, "long") &&
- QualTypeMatchesBitSize(bit_size, ast, ast->LongTy))
- return CompilerType(this, ast->LongTy.getAsOpaquePtr());
- if (strstr(type_name, "short") &&
- QualTypeMatchesBitSize(bit_size, ast, ast->ShortTy))
- return CompilerType(this, ast->ShortTy.getAsOpaquePtr());
- if (strstr(type_name, "char")) {
- if (QualTypeMatchesBitSize(bit_size, ast, ast->CharTy))
- return CompilerType(this, ast->CharTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->SignedCharTy))
- return CompilerType(this, ast->SignedCharTy.getAsOpaquePtr());
- }
- if (strstr(type_name, "int")) {
- if (QualTypeMatchesBitSize(bit_size, ast, ast->IntTy))
- return CompilerType(this, ast->IntTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->Int128Ty))
- return CompilerType(this, ast->Int128Ty.getAsOpaquePtr());
- }
+ case DW_ATE_signed:
+ if (!type_name.empty()) {
+ if (type_name == "wchar_t" &&
+ QualTypeMatchesBitSize(bit_size, ast, ast.WCharTy) &&
+ (getTargetInfo() &&
+ TargetInfo::isTypeSigned(getTargetInfo()->getWCharType())))
+ return GetType(ast.WCharTy);
+ if (type_name == "void" &&
+ QualTypeMatchesBitSize(bit_size, ast, ast.VoidTy))
+ return GetType(ast.VoidTy);
+ if (type_name.contains("long long") &&
+ QualTypeMatchesBitSize(bit_size, ast, ast.LongLongTy))
+ return GetType(ast.LongLongTy);
+ if (type_name.contains("long") &&
+ QualTypeMatchesBitSize(bit_size, ast, ast.LongTy))
+ return GetType(ast.LongTy);
+ if (type_name.contains("short") &&
+ QualTypeMatchesBitSize(bit_size, ast, ast.ShortTy))
+ return GetType(ast.ShortTy);
+ if (type_name.contains("char")) {
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.CharTy))
+ return GetType(ast.CharTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.SignedCharTy))
+ return GetType(ast.SignedCharTy);
}
- // We weren't able to match up a type name, just search by size
- if (QualTypeMatchesBitSize(bit_size, ast, ast->CharTy))
- return CompilerType(this, ast->CharTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->ShortTy))
- return CompilerType(this, ast->ShortTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->IntTy))
- return CompilerType(this, ast->IntTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->LongTy))
- return CompilerType(this, ast->LongTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->LongLongTy))
- return CompilerType(this, ast->LongLongTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->Int128Ty))
- return CompilerType(this, ast->Int128Ty.getAsOpaquePtr());
- break;
-
- case DW_ATE_signed_char:
- if (ast->getLangOpts().CharIsSigned && type_name &&
- streq(type_name, "char")) {
- if (QualTypeMatchesBitSize(bit_size, ast, ast->CharTy))
- return CompilerType(this, ast->CharTy.getAsOpaquePtr());
+ if (type_name.contains("int")) {
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.IntTy))
+ return GetType(ast.IntTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.Int128Ty))
+ return GetType(ast.Int128Ty);
}
- if (QualTypeMatchesBitSize(bit_size, ast, ast->SignedCharTy))
- return CompilerType(this, ast->SignedCharTy.getAsOpaquePtr());
- break;
+ }
+ // We weren't able to match up a type name, just search by size
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.CharTy))
+ return GetType(ast.CharTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.ShortTy))
+ return GetType(ast.ShortTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.IntTy))
+ return GetType(ast.IntTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.LongTy))
+ return GetType(ast.LongTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.LongLongTy))
+ return GetType(ast.LongLongTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.Int128Ty))
+ return GetType(ast.Int128Ty);
+ break;
- case DW_ATE_unsigned:
- if (type_name) {
- if (streq(type_name, "wchar_t")) {
- if (QualTypeMatchesBitSize(bit_size, ast, ast->WCharTy)) {
- if (!(getTargetInfo() &&
- TargetInfo::isTypeSigned(getTargetInfo()->getWCharType())))
- return CompilerType(this, ast->WCharTy.getAsOpaquePtr());
- }
- }
- if (strstr(type_name, "long long")) {
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongLongTy))
- return CompilerType(this, ast->UnsignedLongLongTy.getAsOpaquePtr());
- } else if (strstr(type_name, "long")) {
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongTy))
- return CompilerType(this, ast->UnsignedLongTy.getAsOpaquePtr());
- } else if (strstr(type_name, "short")) {
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy))
- return CompilerType(this, ast->UnsignedShortTy.getAsOpaquePtr());
- } else if (strstr(type_name, "char")) {
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy))
- return CompilerType(this, ast->UnsignedCharTy.getAsOpaquePtr());
- } else if (strstr(type_name, "int")) {
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedIntTy))
- return CompilerType(this, ast->UnsignedIntTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedInt128Ty))
- return CompilerType(this, ast->UnsignedInt128Ty.getAsOpaquePtr());
+ case DW_ATE_signed_char:
+ if (ast.getLangOpts().CharIsSigned && type_name == "char") {
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.CharTy))
+ return GetType(ast.CharTy);
+ }
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.SignedCharTy))
+ return GetType(ast.SignedCharTy);
+ break;
+
+ case DW_ATE_unsigned:
+ if (!type_name.empty()) {
+ if (type_name == "wchar_t") {
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.WCharTy)) {
+ if (!(getTargetInfo() &&
+ TargetInfo::isTypeSigned(getTargetInfo()->getWCharType())))
+ return GetType(ast.WCharTy);
}
}
- // We weren't able to match up a type name, just search by size
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy))
- return CompilerType(this, ast->UnsignedCharTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy))
- return CompilerType(this, ast->UnsignedShortTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedIntTy))
- return CompilerType(this, ast->UnsignedIntTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongTy))
- return CompilerType(this, ast->UnsignedLongTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongLongTy))
- return CompilerType(this, ast->UnsignedLongLongTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedInt128Ty))
- return CompilerType(this, ast->UnsignedInt128Ty.getAsOpaquePtr());
- break;
-
- case DW_ATE_unsigned_char:
- if (!ast->getLangOpts().CharIsSigned && type_name &&
- streq(type_name, "char")) {
- if (QualTypeMatchesBitSize(bit_size, ast, ast->CharTy))
- return CompilerType(this, ast->CharTy.getAsOpaquePtr());
+ if (type_name.contains("long long")) {
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongLongTy))
+ return GetType(ast.UnsignedLongLongTy);
+ } else if (type_name.contains("long")) {
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongTy))
+ return GetType(ast.UnsignedLongTy);
+ } else if (type_name.contains("short")) {
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
+ return GetType(ast.UnsignedShortTy);
+ } else if (type_name.contains("char")) {
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
+ return GetType(ast.UnsignedCharTy);
+ } else if (type_name.contains("int")) {
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedIntTy))
+ return GetType(ast.UnsignedIntTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedInt128Ty))
+ return GetType(ast.UnsignedInt128Ty);
}
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy))
- return CompilerType(this, ast->UnsignedCharTy.getAsOpaquePtr());
- if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy))
- return CompilerType(this, ast->UnsignedShortTy.getAsOpaquePtr());
- break;
+ }
+ // We weren't able to match up a type name, just search by size
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
+ return GetType(ast.UnsignedCharTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
+ return GetType(ast.UnsignedShortTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedIntTy))
+ return GetType(ast.UnsignedIntTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongTy))
+ return GetType(ast.UnsignedLongTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongLongTy))
+ return GetType(ast.UnsignedLongLongTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedInt128Ty))
+ return GetType(ast.UnsignedInt128Ty);
+ break;
- case DW_ATE_imaginary_float:
- break;
+ case DW_ATE_unsigned_char:
+ if (!ast.getLangOpts().CharIsSigned && type_name == "char") {
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.CharTy))
+ return GetType(ast.CharTy);
+ }
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
+ return GetType(ast.UnsignedCharTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
+ return GetType(ast.UnsignedShortTy);
+ break;
- case DW_ATE_UTF:
- if (type_name) {
- if (streq(type_name, "char16_t"))
- return CompilerType(this, ast->Char16Ty.getAsOpaquePtr());
- if (streq(type_name, "char32_t"))
- return CompilerType(this, ast->Char32Ty.getAsOpaquePtr());
- if (streq(type_name, "char8_t"))
- return CompilerType(this, ast->Char8Ty.getAsOpaquePtr());
- }
- break;
+ case DW_ATE_imaginary_float:
+ break;
+
+ case DW_ATE_UTF:
+ if (!type_name.empty()) {
+ if (type_name == "char16_t")
+ return GetType(ast.Char16Ty);
+ if (type_name == "char32_t")
+ return GetType(ast.Char32Ty);
+ if (type_name == "char8_t")
+ return GetType(ast.Char8Ty);
}
+ break;
}
// This assert should fire for anything that we don't catch above so we know
// to fix any issues we run into.
- if (type_name) {
- Host::SystemLog(Host::eSystemLogError, "error: need to add support for "
- "DW_TAG_base_type '%s' encoded with "
- "DW_ATE = 0x%x, bit_size = %u\n",
- type_name, dw_ate, bit_size);
+ if (!type_name.empty()) {
+ std::string type_name_str = type_name.str();
+ Host::SystemLog(Host::eSystemLogError,
+ "error: need to add support for DW_TAG_base_type '%s' "
+ "encoded with DW_ATE = 0x%x, bit_size = %u\n",
+ type_name_str.c_str(), dw_ate, bit_size);
} else {
Host::SystemLog(Host::eSystemLogError, "error: need to add support for "
"DW_TAG_base_type encoded with "
@@ -1245,42 +1106,14 @@ CompilerType ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize(
return CompilerType();
}
-CompilerType ClangASTContext::GetUnknownAnyType(clang::ASTContext *ast) {
- if (ast)
- return CompilerType(ClangASTContext::GetASTContext(ast),
- ast->UnknownAnyTy.getAsOpaquePtr());
- return CompilerType();
-}
-
CompilerType ClangASTContext::GetCStringType(bool is_const) {
- ASTContext *ast = getASTContext();
- QualType char_type(ast->CharTy);
+ ASTContext &ast = getASTContext();
+ QualType char_type(ast.CharTy);
if (is_const)
char_type.addConst();
- return CompilerType(this, ast->getPointerType(char_type).getAsOpaquePtr());
-}
-
-clang::DeclContext *
-ClangASTContext::GetTranslationUnitDecl(clang::ASTContext *ast) {
- return ast->getTranslationUnitDecl();
-}
-
-clang::Decl *ClangASTContext::CopyDecl(ASTContext *dst_ast, ASTContext *src_ast,
- clang::Decl *source_decl) {
- FileSystemOptions file_system_options;
- FileManager file_manager(file_system_options);
- ASTImporter importer(*dst_ast, file_manager, *src_ast, file_manager, false);
-
- if (llvm::Expected<clang::Decl *> ret_or_error =
- importer.Import(source_decl)) {
- return *ret_or_error;
- } else {
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
- LLDB_LOG_ERROR(log, ret_or_error.takeError(), "Couldn't import decl: {0}");
- return nullptr;
- }
+ return GetType(ast.getPointerType(char_type));
}
bool ClangASTContext::AreTypesSame(CompilerType type1, CompilerType type2,
@@ -1301,7 +1134,7 @@ bool ClangASTContext::AreTypesSame(CompilerType type1, CompilerType type2,
type2_qual = type2_qual.getUnqualifiedType();
}
- return ast->getASTContext()->hasSameType(type1_qual, type2_qual);
+ return ast->getASTContext().hasSameType(type1_qual, type2_qual);
}
CompilerType ClangASTContext::GetTypeForDecl(void *opaque_decl) {
@@ -1314,9 +1147,15 @@ CompilerType ClangASTContext::GetTypeForDecl(void *opaque_decl) {
return CompilerType();
}
+CompilerDeclContext ClangASTContext::CreateDeclContext(DeclContext *ctx) {
+ // Check that the DeclContext actually belongs to this ASTContext.
+ assert(&ctx->getParentASTContext() == &getASTContext());
+ return CompilerDeclContext(this, ctx);
+}
+
CompilerType ClangASTContext::GetTypeForDecl(clang::NamedDecl *decl) {
if (clang::ObjCInterfaceDecl *interface_decl =
- llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl))
+ llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl))
return GetTypeForDecl(interface_decl);
if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl))
return GetTypeForDecl(tag_decl);
@@ -1324,39 +1163,25 @@ CompilerType ClangASTContext::GetTypeForDecl(clang::NamedDecl *decl) {
}
CompilerType ClangASTContext::GetTypeForDecl(TagDecl *decl) {
- // No need to call the getASTContext() accessor (which can create the AST if
- // it isn't created yet, because we can't have created a decl in this
- // AST if our AST didn't already exist...
- ASTContext *ast = &decl->getASTContext();
- if (ast)
- return CompilerType(ClangASTContext::GetASTContext(ast),
- ast->getTagDeclType(decl).getAsOpaquePtr());
- return CompilerType();
+ return GetType(getASTContext().getTagDeclType(decl));
}
CompilerType ClangASTContext::GetTypeForDecl(ObjCInterfaceDecl *decl) {
- // No need to call the getASTContext() accessor (which can create the AST if
- // it isn't created yet, because we can't have created a decl in this
- // AST if our AST didn't already exist...
- ASTContext *ast = &decl->getASTContext();
- if (ast)
- return CompilerType(ClangASTContext::GetASTContext(ast),
- ast->getObjCInterfaceType(decl).getAsOpaquePtr());
- return CompilerType();
+ return GetType(getASTContext().getObjCInterfaceType(decl));
}
#pragma mark Structure, Unions, Classes
CompilerType ClangASTContext::CreateRecordType(DeclContext *decl_ctx,
AccessType access_type,
- const char *name, int kind,
+ llvm::StringRef name, int kind,
LanguageType language,
- ClangASTMetadata *metadata) {
- ASTContext *ast = getASTContext();
- assert(ast != nullptr);
+ ClangASTMetadata *metadata,
+ bool exports_symbols) {
+ ASTContext &ast = getASTContext();
if (decl_ctx == nullptr)
- decl_ctx = ast->getTranslationUnitDecl();
+ decl_ctx = ast.getTranslationUnitDecl();
if (language == eLanguageTypeObjC ||
language == eLanguageTypeObjC_plus_plus) {
@@ -1371,11 +1196,11 @@ CompilerType ClangASTContext::CreateRecordType(DeclContext *decl_ctx,
// something is struct or a class, so we default to always use the more
// complete definition just in case.
- bool has_name = name && name[0];
+ bool has_name = !name.empty();
CXXRecordDecl *decl = CXXRecordDecl::Create(
- *ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(),
- SourceLocation(), has_name ? &ast->Idents.get(name) : nullptr);
+ ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(), SourceLocation(),
+ has_name ? &ast.Idents.get(name) : nullptr);
if (!has_name) {
// In C++ a lambda is also represented as an unnamed class. This is
@@ -1402,16 +1227,13 @@ CompilerType ClangASTContext::CreateRecordType(DeclContext *decl_ctx,
// Anonymous classes is a GNU/MSVC extension that clang supports. It
// requires the anonymous class be embedded within a class. So the new
// heuristic verifies this condition.
- //
- // FIXME: An unnamed class within a class is also wrongly recognized as an
- // anonymous struct.
- if (isa<CXXRecordDecl>(decl_ctx))
+ if (isa<CXXRecordDecl>(decl_ctx) && exports_symbols)
decl->setAnonymousStructOrUnion(true);
}
if (decl) {
if (metadata)
- SetMetadata(ast, decl, *metadata);
+ SetMetadata(decl, *metadata);
if (access_type != eAccessNone)
decl->setAccess(ConvertAccessTypeToAccessSpecifier(access_type));
@@ -1419,7 +1241,7 @@ CompilerType ClangASTContext::CreateRecordType(DeclContext *decl_ctx,
if (decl_ctx)
decl_ctx->addDecl(decl);
- return CompilerType(this, ast->getTagDeclType(decl).getAsOpaquePtr());
+ return GetType(ast.getTagDeclType(decl));
}
return CompilerType();
}
@@ -1492,14 +1314,14 @@ clang::FunctionTemplateDecl *ClangASTContext::CreateFunctionTemplateDecl(
clang::DeclContext *decl_ctx, clang::FunctionDecl *func_decl,
const char *name, const TemplateParameterInfos &template_param_infos) {
// /// Create a function template node.
- ASTContext *ast = getASTContext();
+ ASTContext &ast = getASTContext();
llvm::SmallVector<NamedDecl *, 8> template_param_decls;
TemplateParameterList *template_param_list = CreateTemplateParameterList(
- ast, template_param_infos, template_param_decls);
+ &ast, template_param_infos, template_param_decls);
FunctionTemplateDecl *func_tmpl_decl = FunctionTemplateDecl::Create(
- *ast, decl_ctx, func_decl->getLocation(), func_decl->getDeclName(),
+ ast, decl_ctx, func_decl->getLocation(), func_decl->getDeclName(),
template_param_list, func_decl);
for (size_t i = 0, template_param_decl_count = template_param_decls.size();
@@ -1507,6 +1329,11 @@ clang::FunctionTemplateDecl *ClangASTContext::CreateFunctionTemplateDecl(
// TODO: verify which decl context we should put template_param_decls into..
template_param_decls[i]->setDeclContext(func_decl);
}
+ // Function templates inside a record need to have an access specifier.
+ // It doesn't matter what access specifier we give the template as LLDB
+ // anyway allows accessing everything inside a record.
+ if (decl_ctx->isRecord())
+ func_tmpl_decl->setAccess(clang::AccessSpecifier::AS_public);
return func_tmpl_decl;
}
@@ -1524,13 +1351,13 @@ void ClangASTContext::CreateFunctionTemplateSpecializationInfo(
ClassTemplateDecl *ClangASTContext::CreateClassTemplateDecl(
DeclContext *decl_ctx, lldb::AccessType access_type, const char *class_name,
int kind, const TemplateParameterInfos &template_param_infos) {
- ASTContext *ast = getASTContext();
+ ASTContext &ast = getASTContext();
ClassTemplateDecl *class_template_decl = nullptr;
if (decl_ctx == nullptr)
- decl_ctx = ast->getTranslationUnitDecl();
+ decl_ctx = ast.getTranslationUnitDecl();
- IdentifierInfo &identifier_info = ast->Idents.get(class_name);
+ IdentifierInfo &identifier_info = ast.Idents.get(class_name);
DeclarationName decl_name(&identifier_info);
clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name);
@@ -1544,10 +1371,10 @@ ClassTemplateDecl *ClangASTContext::CreateClassTemplateDecl(
llvm::SmallVector<NamedDecl *, 8> template_param_decls;
TemplateParameterList *template_param_list = CreateTemplateParameterList(
- ast, template_param_infos, template_param_decls);
+ &ast, template_param_infos, template_param_decls);
CXXRecordDecl *template_cxx_decl = CXXRecordDecl::Create(
- *ast, (TagDecl::TagKind)kind,
+ ast, (TagDecl::TagKind)kind,
decl_ctx, // What decl context do we use here? TU? The actual decl
// context?
SourceLocation(), SourceLocation(), &identifier_info);
@@ -1563,7 +1390,7 @@ ClassTemplateDecl *ClangASTContext::CreateClassTemplateDecl(
// template_cxx_decl->completeDefinition();
class_template_decl = ClassTemplateDecl::Create(
- *ast,
+ ast,
decl_ctx, // What decl context do we use here? TU? The actual decl
// context?
SourceLocation(), decl_name, template_param_list, template_cxx_decl);
@@ -1589,23 +1416,23 @@ ClassTemplateDecl *ClangASTContext::CreateClassTemplateDecl(
TemplateTemplateParmDecl *
ClangASTContext::CreateTemplateTemplateParmDecl(const char *template_name) {
- ASTContext *ast = getASTContext();
+ ASTContext &ast = getASTContext();
- auto *decl_ctx = ast->getTranslationUnitDecl();
+ auto *decl_ctx = ast.getTranslationUnitDecl();
- IdentifierInfo &identifier_info = ast->Idents.get(template_name);
+ IdentifierInfo &identifier_info = ast.Idents.get(template_name);
llvm::SmallVector<NamedDecl *, 8> template_param_decls;
ClangASTContext::TemplateParameterInfos template_param_infos;
TemplateParameterList *template_param_list = CreateTemplateParameterList(
- ast, template_param_infos, template_param_decls);
+ &ast, template_param_infos, template_param_decls);
// LLDB needs to create those decls only to be able to display a
// type that includes a template template argument. Only the name matters for
// this purpose, so we use dummy values for the other characterisitcs of the
// type.
return TemplateTemplateParmDecl::Create(
- *ast, decl_ctx, SourceLocation(),
+ ast, decl_ctx, SourceLocation(),
/*Depth*/ 0, /*Position*/ 0,
/*IsParameterPack*/ false, &identifier_info, template_param_list);
}
@@ -1614,7 +1441,7 @@ ClassTemplateSpecializationDecl *
ClangASTContext::CreateClassTemplateSpecializationDecl(
DeclContext *decl_ctx, ClassTemplateDecl *class_template_decl, int kind,
const TemplateParameterInfos &template_param_infos) {
- ASTContext *ast = getASTContext();
+ ASTContext &ast = getASTContext();
llvm::SmallVector<clang::TemplateArgument, 2> args(
template_param_infos.args.size() +
(template_param_infos.packed_args ? 1 : 0));
@@ -1622,13 +1449,12 @@ ClangASTContext::CreateClassTemplateSpecializationDecl(
args.begin());
if (template_param_infos.packed_args) {
args[args.size() - 1] = TemplateArgument::CreatePackCopy(
- *ast, template_param_infos.packed_args->args);
+ ast, template_param_infos.packed_args->args);
}
ClassTemplateSpecializationDecl *class_template_specialization_decl =
ClassTemplateSpecializationDecl::Create(
- *ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(),
- SourceLocation(), class_template_decl, args,
- nullptr);
+ ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(),
+ SourceLocation(), class_template_decl, args, nullptr);
class_template_specialization_decl->setSpecializationKind(
TSK_ExplicitSpecialization);
@@ -1639,11 +1465,8 @@ ClangASTContext::CreateClassTemplateSpecializationDecl(
CompilerType ClangASTContext::CreateClassTemplateSpecializationType(
ClassTemplateSpecializationDecl *class_template_specialization_decl) {
if (class_template_specialization_decl) {
- ASTContext *ast = getASTContext();
- if (ast)
- return CompilerType(
- this, ast->getTagDeclType(class_template_specialization_decl)
- .getAsOpaquePtr());
+ ASTContext &ast = getASTContext();
+ return GetType(ast.getTagDeclType(class_template_specialization_decl));
}
return CompilerType();
}
@@ -1708,19 +1531,15 @@ ClangASTContext::UnifyAccessSpecifiers(clang::AccessSpecifier lhs,
bool ClangASTContext::FieldIsBitfield(FieldDecl *field,
uint32_t &bitfield_bit_size) {
- return FieldIsBitfield(getASTContext(), field, bitfield_bit_size);
-}
-
-bool ClangASTContext::FieldIsBitfield(ASTContext *ast, FieldDecl *field,
- uint32_t &bitfield_bit_size) {
- if (ast == nullptr || field == nullptr)
+ ASTContext &ast = getASTContext();
+ if (field == nullptr)
return false;
if (field->isBitField()) {
Expr *bit_width_expr = field->getBitWidth();
if (bit_width_expr) {
llvm::APSInt bit_width_apsint;
- if (bit_width_expr->isIntegerConstantExpr(bit_width_apsint, *ast)) {
+ if (bit_width_expr->isIntegerConstantExpr(bit_width_apsint, ast)) {
bitfield_bit_size = bit_width_apsint.getLimitedValue(UINT32_MAX);
return true;
}
@@ -1754,27 +1573,26 @@ bool ClangASTContext::RecordHasFields(const RecordDecl *record_decl) {
#pragma mark Objective-C Classes
-CompilerType ClangASTContext::CreateObjCClass(const char *name,
+CompilerType ClangASTContext::CreateObjCClass(llvm::StringRef name,
DeclContext *decl_ctx,
bool isForwardDecl,
bool isInternal,
ClangASTMetadata *metadata) {
- ASTContext *ast = getASTContext();
- assert(ast != nullptr);
- assert(name && name[0]);
+ ASTContext &ast = getASTContext();
+ assert(!name.empty());
if (decl_ctx == nullptr)
- decl_ctx = ast->getTranslationUnitDecl();
+ decl_ctx = ast.getTranslationUnitDecl();
ObjCInterfaceDecl *decl = ObjCInterfaceDecl::Create(
- *ast, decl_ctx, SourceLocation(), &ast->Idents.get(name), nullptr,
- nullptr, SourceLocation(),
+ ast, decl_ctx, SourceLocation(), &ast.Idents.get(name), nullptr, nullptr,
+ SourceLocation(),
/*isForwardDecl,*/
isInternal);
if (decl && metadata)
- SetMetadata(ast, decl, *metadata);
+ SetMetadata(decl, *metadata);
- return CompilerType(this, ast->getObjCInterfaceType(decl).getAsOpaquePtr());
+ return GetType(ast.getObjCInterfaceType(decl));
}
static inline bool BaseSpecifierIsEmpty(const CXXBaseSpecifier *b) {
@@ -1809,13 +1627,13 @@ ClangASTContext::GetNumBaseClasses(const CXXRecordDecl *cxx_record_decl,
NamespaceDecl *ClangASTContext::GetUniqueNamespaceDeclaration(
const char *name, DeclContext *decl_ctx, bool is_inline) {
NamespaceDecl *namespace_decl = nullptr;
- ASTContext *ast = getASTContext();
- TranslationUnitDecl *translation_unit_decl = ast->getTranslationUnitDecl();
+ ASTContext &ast = getASTContext();
+ TranslationUnitDecl *translation_unit_decl = ast.getTranslationUnitDecl();
if (decl_ctx == nullptr)
decl_ctx = translation_unit_decl;
if (name) {
- IdentifierInfo &identifier_info = ast->Idents.get(name);
+ IdentifierInfo &identifier_info = ast.Idents.get(name);
DeclarationName decl_name(&identifier_info);
clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name);
for (NamedDecl *decl : result) {
@@ -1825,7 +1643,7 @@ NamespaceDecl *ClangASTContext::GetUniqueNamespaceDeclaration(
}
namespace_decl =
- NamespaceDecl::Create(*ast, decl_ctx, is_inline, SourceLocation(),
+ NamespaceDecl::Create(ast, decl_ctx, is_inline, SourceLocation(),
SourceLocation(), &identifier_info, nullptr);
decl_ctx->addDecl(namespace_decl);
@@ -1836,7 +1654,7 @@ NamespaceDecl *ClangASTContext::GetUniqueNamespaceDeclaration(
return namespace_decl;
namespace_decl =
- NamespaceDecl::Create(*ast, decl_ctx, false, SourceLocation(),
+ NamespaceDecl::Create(ast, decl_ctx, false, SourceLocation(),
SourceLocation(), nullptr, nullptr);
translation_unit_decl->setAnonymousNamespace(namespace_decl);
translation_unit_decl->addDecl(namespace_decl);
@@ -1848,7 +1666,7 @@ NamespaceDecl *ClangASTContext::GetUniqueNamespaceDeclaration(
if (namespace_decl)
return namespace_decl;
namespace_decl =
- NamespaceDecl::Create(*ast, decl_ctx, false, SourceLocation(),
+ NamespaceDecl::Create(ast, decl_ctx, false, SourceLocation(),
SourceLocation(), nullptr, nullptr);
parent_namespace_decl->setAnonymousNamespace(namespace_decl);
parent_namespace_decl->addDecl(namespace_decl);
@@ -1866,21 +1684,11 @@ NamespaceDecl *ClangASTContext::GetUniqueNamespaceDeclaration(
return namespace_decl;
}
-NamespaceDecl *ClangASTContext::GetUniqueNamespaceDeclaration(
- clang::ASTContext *ast, const char *name, clang::DeclContext *decl_ctx,
- bool is_inline) {
- ClangASTContext *ast_ctx = ClangASTContext::GetASTContext(ast);
- if (ast_ctx == nullptr)
- return nullptr;
-
- return ast_ctx->GetUniqueNamespaceDeclaration(name, decl_ctx, is_inline);
-}
-
clang::BlockDecl *
ClangASTContext::CreateBlockDeclaration(clang::DeclContext *ctx) {
if (ctx != nullptr) {
- clang::BlockDecl *decl = clang::BlockDecl::Create(*getASTContext(), ctx,
- clang::SourceLocation());
+ clang::BlockDecl *decl =
+ clang::BlockDecl::Create(getASTContext(), ctx, clang::SourceLocation());
ctx->addDecl(decl);
return decl;
}
@@ -1907,10 +1715,9 @@ clang::DeclContext *FindLCABetweenDecls(clang::DeclContext *left,
clang::UsingDirectiveDecl *ClangASTContext::CreateUsingDirectiveDeclaration(
clang::DeclContext *decl_ctx, clang::NamespaceDecl *ns_decl) {
if (decl_ctx != nullptr && ns_decl != nullptr) {
- clang::TranslationUnitDecl *translation_unit =
- (clang::TranslationUnitDecl *)GetTranslationUnitDecl(getASTContext());
+ auto *translation_unit = getASTContext().getTranslationUnitDecl();
clang::UsingDirectiveDecl *using_decl = clang::UsingDirectiveDecl::Create(
- *getASTContext(), decl_ctx, clang::SourceLocation(),
+ getASTContext(), decl_ctx, clang::SourceLocation(),
clang::SourceLocation(), clang::NestedNameSpecifierLoc(),
clang::SourceLocation(), ns_decl,
FindLCABetweenDecls(decl_ctx, ns_decl, translation_unit));
@@ -1925,10 +1732,10 @@ ClangASTContext::CreateUsingDeclaration(clang::DeclContext *current_decl_ctx,
clang::NamedDecl *target) {
if (current_decl_ctx != nullptr && target != nullptr) {
clang::UsingDecl *using_decl = clang::UsingDecl::Create(
- *getASTContext(), current_decl_ctx, clang::SourceLocation(),
+ getASTContext(), current_decl_ctx, clang::SourceLocation(),
clang::NestedNameSpecifierLoc(), clang::DeclarationNameInfo(), false);
clang::UsingShadowDecl *shadow_decl = clang::UsingShadowDecl::Create(
- *getASTContext(), current_decl_ctx, clang::SourceLocation(), using_decl,
+ getASTContext(), current_decl_ctx, clang::SourceLocation(), using_decl,
target);
using_decl->addShadowDecl(shadow_decl);
current_decl_ctx->addDecl(using_decl);
@@ -1941,9 +1748,9 @@ clang::VarDecl *ClangASTContext::CreateVariableDeclaration(
clang::DeclContext *decl_context, const char *name, clang::QualType type) {
if (decl_context != nullptr) {
clang::VarDecl *var_decl = clang::VarDecl::Create(
- *getASTContext(), decl_context, clang::SourceLocation(),
+ getASTContext(), decl_context, clang::SourceLocation(),
clang::SourceLocation(),
- name && name[0] ? &getASTContext()->Idents.getOwn(name) : nullptr, type,
+ name && name[0] ? &getASTContext().Idents.getOwn(name) : nullptr, type,
nullptr, clang::SC_None);
var_decl->setAccess(clang::AS_public);
decl_context->addDecl(var_decl);
@@ -2033,7 +1840,7 @@ ClangASTContext::GetDeclarationName(const char *name,
clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
if (!IsOperator(name, op_kind) || op_kind == clang::NUM_OVERLOADED_OPERATORS)
- return DeclarationName(&getASTContext()->Idents.get(
+ return DeclarationName(&getASTContext().Idents.get(
name)); // Not operator, but a regular function.
// Check the number of operator parameters. Sometimes we have seen bad DWARF
@@ -2052,16 +1859,16 @@ ClangASTContext::GetDeclarationName(const char *name,
is_method, op_kind, num_params))
return clang::DeclarationName();
- return getASTContext()->DeclarationNames.getCXXOperatorName(op_kind);
+ return getASTContext().DeclarationNames.getCXXOperatorName(op_kind);
}
FunctionDecl *ClangASTContext::CreateFunctionDeclaration(
DeclContext *decl_ctx, const char *name,
const CompilerType &function_clang_type, int storage, bool is_inline) {
FunctionDecl *func_decl = nullptr;
- ASTContext *ast = getASTContext();
+ ASTContext &ast = getASTContext();
if (decl_ctx == nullptr)
- decl_ctx = ast->getTranslationUnitDecl();
+ decl_ctx = ast.getTranslationUnitDecl();
const bool hasWrittenPrototype = true;
const bool isConstexprSpecified = false;
@@ -2069,7 +1876,7 @@ FunctionDecl *ClangASTContext::CreateFunctionDeclaration(
clang::DeclarationName declarationName =
GetDeclarationName(name, function_clang_type);
func_decl = FunctionDecl::Create(
- *ast, decl_ctx, SourceLocation(), SourceLocation(), declarationName,
+ ast, decl_ctx, SourceLocation(), SourceLocation(), declarationName,
ClangUtil::GetQualType(function_clang_type), nullptr,
(clang::StorageClass)storage, is_inline, hasWrittenPrototype,
isConstexprSpecified ? CSK_constexpr : CSK_unspecified);
@@ -2083,13 +1890,11 @@ FunctionDecl *ClangASTContext::CreateFunctionDeclaration(
return func_decl;
}
-CompilerType ClangASTContext::CreateFunctionType(
- ASTContext *ast, const CompilerType &result_type, const CompilerType *args,
- unsigned num_args, bool is_variadic, unsigned type_quals,
- clang::CallingConv cc) {
- if (ast == nullptr)
- return CompilerType(); // invalid AST
-
+CompilerType
+ClangASTContext::CreateFunctionType(const CompilerType &result_type,
+ const CompilerType *args, unsigned num_args,
+ bool is_variadic, unsigned type_quals,
+ clang::CallingConv cc) {
if (!result_type || !ClangUtil::IsClangType(result_type))
return CompilerType(); // invalid return type
@@ -2120,19 +1925,17 @@ CompilerType ClangASTContext::CreateFunctionType(
proto_info.TypeQuals = clang::Qualifiers::fromFastMask(type_quals);
proto_info.RefQualifier = RQ_None;
- return CompilerType(ClangASTContext::GetASTContext(ast),
- ast->getFunctionType(ClangUtil::GetQualType(result_type),
- qual_type_args, proto_info).getAsOpaquePtr());
+ return GetType(getASTContext().getFunctionType(
+ ClangUtil::GetQualType(result_type), qual_type_args, proto_info));
}
ParmVarDecl *ClangASTContext::CreateParameterDeclaration(
clang::DeclContext *decl_ctx, const char *name,
const CompilerType &param_type, int storage, bool add_decl) {
- ASTContext *ast = getASTContext();
- assert(ast != nullptr);
+ ASTContext &ast = getASTContext();
auto *decl =
- ParmVarDecl::Create(*ast, decl_ctx, SourceLocation(), SourceLocation(),
- name && name[0] ? &ast->Idents.get(name) : nullptr,
+ ParmVarDecl::Create(ast, decl_ctx, SourceLocation(), SourceLocation(),
+ name && name[0] ? &ast.Idents.get(name) : nullptr,
ClangUtil::GetQualType(param_type), nullptr,
(clang::StorageClass)storage, nullptr);
if (add_decl)
@@ -2153,7 +1956,7 @@ ClangASTContext::CreateBlockPointerType(const CompilerType &function_type) {
QualType block_type = m_ast_up->getBlockPointerType(
clang::QualType::getFromOpaquePtr(function_type.GetOpaqueQualType()));
- return CompilerType(this, block_type.getAsOpaquePtr());
+ return GetType(block_type);
}
#pragma mark Array Types
@@ -2162,28 +1965,21 @@ CompilerType ClangASTContext::CreateArrayType(const CompilerType &element_type,
size_t element_count,
bool is_vector) {
if (element_type.IsValid()) {
- ASTContext *ast = getASTContext();
- assert(ast != nullptr);
+ ASTContext &ast = getASTContext();
if (is_vector) {
- return CompilerType(
- this, ast->getExtVectorType(ClangUtil::GetQualType(element_type),
- element_count)
- .getAsOpaquePtr());
+ return GetType(ast.getExtVectorType(ClangUtil::GetQualType(element_type),
+ element_count));
} else {
llvm::APInt ap_element_count(64, element_count);
if (element_count == 0) {
- return CompilerType(this, ast->getIncompleteArrayType(
- ClangUtil::GetQualType(element_type),
- clang::ArrayType::Normal, 0)
- .getAsOpaquePtr());
+ return GetType(ast.getIncompleteArrayType(
+ ClangUtil::GetQualType(element_type), clang::ArrayType::Normal, 0));
} else {
- return CompilerType(this, ast->getConstantArrayType(
- ClangUtil::GetQualType(element_type),
- ap_element_count, nullptr,
- clang::ArrayType::Normal, 0)
- .getAsOpaquePtr());
+ return GetType(ast.getConstantArrayType(
+ ClangUtil::GetQualType(element_type), ap_element_count, nullptr,
+ clang::ArrayType::Normal, 0));
}
}
}
@@ -2236,14 +2032,14 @@ ClangASTContext::CreateEnumerationType(const char *name, DeclContext *decl_ctx,
bool is_scoped) {
// TODO: Do something intelligent with the Declaration object passed in
// like maybe filling in the SourceLocation with it...
- ASTContext *ast = getASTContext();
+ ASTContext &ast = getASTContext();
// TODO: ask about these...
// const bool IsFixed = false;
EnumDecl *enum_decl = EnumDecl::Create(
- *ast, decl_ctx, SourceLocation(), SourceLocation(),
- name && name[0] ? &ast->Idents.get(name) : nullptr, nullptr,
+ ast, decl_ctx, SourceLocation(), SourceLocation(),
+ name && name[0] ? &ast.Idents.get(name) : nullptr, nullptr,
is_scoped, // IsScoped
is_scoped, // IsScopedUsingClassTag
false); // IsFixed
@@ -2257,71 +2053,58 @@ ClangASTContext::CreateEnumerationType(const char *name, DeclContext *decl_ctx,
enum_decl->setAccess(AS_public); // TODO respect what's in the debug info
- return CompilerType(this, ast->getTagDeclType(enum_decl).getAsOpaquePtr());
+ return GetType(ast.getTagDeclType(enum_decl));
}
return CompilerType();
}
-CompilerType ClangASTContext::GetIntTypeFromBitSize(clang::ASTContext *ast,
- size_t bit_size,
+CompilerType ClangASTContext::GetIntTypeFromBitSize(size_t bit_size,
bool is_signed) {
- if (ast) {
- auto *clang_ast_context = ClangASTContext::GetASTContext(ast);
- if (is_signed) {
- if (bit_size == ast->getTypeSize(ast->SignedCharTy))
- return CompilerType(clang_ast_context,
- ast->SignedCharTy.getAsOpaquePtr());
+ clang::ASTContext &ast = getASTContext();
- if (bit_size == ast->getTypeSize(ast->ShortTy))
- return CompilerType(clang_ast_context, ast->ShortTy.getAsOpaquePtr());
+ if (is_signed) {
+ if (bit_size == ast.getTypeSize(ast.SignedCharTy))
+ return GetType(ast.SignedCharTy);
- if (bit_size == ast->getTypeSize(ast->IntTy))
- return CompilerType(clang_ast_context, ast->IntTy.getAsOpaquePtr());
+ if (bit_size == ast.getTypeSize(ast.ShortTy))
+ return GetType(ast.ShortTy);
- if (bit_size == ast->getTypeSize(ast->LongTy))
- return CompilerType(clang_ast_context, ast->LongTy.getAsOpaquePtr());
+ if (bit_size == ast.getTypeSize(ast.IntTy))
+ return GetType(ast.IntTy);
- if (bit_size == ast->getTypeSize(ast->LongLongTy))
- return CompilerType(clang_ast_context,
- ast->LongLongTy.getAsOpaquePtr());
+ if (bit_size == ast.getTypeSize(ast.LongTy))
+ return GetType(ast.LongTy);
- if (bit_size == ast->getTypeSize(ast->Int128Ty))
- return CompilerType(clang_ast_context, ast->Int128Ty.getAsOpaquePtr());
- } else {
- if (bit_size == ast->getTypeSize(ast->UnsignedCharTy))
- return CompilerType(clang_ast_context,
- ast->UnsignedCharTy.getAsOpaquePtr());
+ if (bit_size == ast.getTypeSize(ast.LongLongTy))
+ return GetType(ast.LongLongTy);
- if (bit_size == ast->getTypeSize(ast->UnsignedShortTy))
- return CompilerType(clang_ast_context,
- ast->UnsignedShortTy.getAsOpaquePtr());
+ if (bit_size == ast.getTypeSize(ast.Int128Ty))
+ return GetType(ast.Int128Ty);
+ } else {
+ if (bit_size == ast.getTypeSize(ast.UnsignedCharTy))
+ return GetType(ast.UnsignedCharTy);
- if (bit_size == ast->getTypeSize(ast->UnsignedIntTy))
- return CompilerType(clang_ast_context,
- ast->UnsignedIntTy.getAsOpaquePtr());
+ if (bit_size == ast.getTypeSize(ast.UnsignedShortTy))
+ return GetType(ast.UnsignedShortTy);
- if (bit_size == ast->getTypeSize(ast->UnsignedLongTy))
- return CompilerType(clang_ast_context,
- ast->UnsignedLongTy.getAsOpaquePtr());
+ if (bit_size == ast.getTypeSize(ast.UnsignedIntTy))
+ return GetType(ast.UnsignedIntTy);
- if (bit_size == ast->getTypeSize(ast->UnsignedLongLongTy))
- return CompilerType(clang_ast_context,
- ast->UnsignedLongLongTy.getAsOpaquePtr());
+ if (bit_size == ast.getTypeSize(ast.UnsignedLongTy))
+ return GetType(ast.UnsignedLongTy);
- if (bit_size == ast->getTypeSize(ast->UnsignedInt128Ty))
- return CompilerType(clang_ast_context,
- ast->UnsignedInt128Ty.getAsOpaquePtr());
- }
+ if (bit_size == ast.getTypeSize(ast.UnsignedLongLongTy))
+ return GetType(ast.UnsignedLongLongTy);
+
+ if (bit_size == ast.getTypeSize(ast.UnsignedInt128Ty))
+ return GetType(ast.UnsignedInt128Ty);
}
return CompilerType();
}
-CompilerType ClangASTContext::GetPointerSizedIntType(clang::ASTContext *ast,
- bool is_signed) {
- if (ast)
- return GetIntTypeFromBitSize(ast, ast->getTypeSize(ast->VoidPtrTy),
- is_signed);
- return CompilerType();
+CompilerType ClangASTContext::GetPointerSizedIntType(bool is_signed) {
+ return GetIntTypeFromBitSize(
+ getASTContext().getTypeSize(getASTContext().VoidPtrTy), is_signed);
}
void ClangASTContext::DumpDeclContextHiearchy(clang::DeclContext *decl_ctx) {
@@ -2479,41 +2262,42 @@ bool ClangASTContext::GetCompleteDecl(clang::ASTContext *ast,
}
}
-void ClangASTContext::SetMetadataAsUserID(const void *object,
+void ClangASTContext::SetMetadataAsUserID(const clang::Decl *decl,
user_id_t user_id) {
ClangASTMetadata meta_data;
meta_data.SetUserID(user_id);
- SetMetadata(object, meta_data);
+ SetMetadata(decl, meta_data);
}
-void ClangASTContext::SetMetadata(clang::ASTContext *ast, const void *object,
- ClangASTMetadata &metadata) {
- ClangExternalASTSourceCommon *external_source =
- ClangExternalASTSourceCommon::Lookup(ast->getExternalSource());
-
- if (external_source)
- external_source->SetMetadata(object, metadata);
+void ClangASTContext::SetMetadataAsUserID(const clang::Type *type,
+ user_id_t user_id) {
+ ClangASTMetadata meta_data;
+ meta_data.SetUserID(user_id);
+ SetMetadata(type, meta_data);
}
-ClangASTMetadata *ClangASTContext::GetMetadata(clang::ASTContext *ast,
- const void *object) {
- ClangExternalASTSourceCommon *external_source =
- ClangExternalASTSourceCommon::Lookup(ast->getExternalSource());
+void ClangASTContext::SetMetadata(const clang::Decl *object,
+ ClangASTMetadata &metadata) {
+ m_decl_metadata[object] = metadata;
+}
- if (external_source && external_source->HasMetadata(object))
- return external_source->GetMetadata(object);
- else
- return nullptr;
+void ClangASTContext::SetMetadata(const clang::Type *object,
+ ClangASTMetadata &metadata) {
+ m_type_metadata[object] = metadata;
}
-clang::DeclContext *
-ClangASTContext::GetAsDeclContext(clang::CXXMethodDecl *cxx_method_decl) {
- return llvm::dyn_cast<clang::DeclContext>(cxx_method_decl);
+ClangASTMetadata *ClangASTContext::GetMetadata(const clang::Decl *object) {
+ auto It = m_decl_metadata.find(object);
+ if (It != m_decl_metadata.end())
+ return &It->second;
+ return nullptr;
}
-clang::DeclContext *
-ClangASTContext::GetAsDeclContext(clang::ObjCMethodDecl *objc_method_decl) {
- return llvm::dyn_cast<clang::DeclContext>(objc_method_decl);
+ClangASTMetadata *ClangASTContext::GetMetadata(const clang::Type *object) {
+ auto It = m_type_metadata.find(object);
+ if (It != m_type_metadata.end())
+ return &It->second;
+ return nullptr;
}
bool ClangASTContext::SetTagTypeKind(clang::QualType tag_qual_type,
@@ -2557,12 +2341,42 @@ ClangASTContext::GetDeclContextForType(const CompilerType &type) {
return GetDeclContextForType(ClangUtil::GetQualType(type));
}
+/// Aggressively desugar the provided type, skipping past various kinds of
+/// syntactic sugar and other constructs one typically wants to ignore.
+/// The \p mask argument allows one to skip certain kinds of simplifications,
+/// when one wishes to handle a certain kind of type directly.
+static QualType
+RemoveWrappingTypes(QualType type, ArrayRef<clang::Type::TypeClass> mask = {}) {
+ while (true) {
+ if (find(mask, type->getTypeClass()) != mask.end())
+ return type;
+ switch (type->getTypeClass()) {
+ // This is not fully correct as _Atomic is more than sugar, but it is
+ // sufficient for the purposes we care about.
+ case clang::Type::Atomic:
+ type = cast<clang::AtomicType>(type)->getValueType();
+ break;
+ case clang::Type::Auto:
+ case clang::Type::Decltype:
+ case clang::Type::Elaborated:
+ case clang::Type::Paren:
+ case clang::Type::Typedef:
+ case clang::Type::TypeOf:
+ case clang::Type::TypeOfExpr:
+ type = type->getLocallyUnqualifiedSingleStepDesugaredType();
+ break;
+ default:
+ return type;
+ }
+ }
+}
+
clang::DeclContext *
ClangASTContext::GetDeclContextForType(clang::QualType type) {
if (type.isNull())
return nullptr;
- clang::QualType qual_type = type.getCanonicalType();
+ clang::QualType qual_type = RemoveWrappingTypes(type.getCanonicalType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
case clang::Type::ObjCInterface:
@@ -2576,19 +2390,6 @@ ClangASTContext::GetDeclContextForType(clang::QualType type) {
return llvm::cast<clang::RecordType>(qual_type)->getDecl();
case clang::Type::Enum:
return llvm::cast<clang::EnumType>(qual_type)->getDecl();
- case clang::Type::Typedef:
- return GetDeclContextForType(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType());
- case clang::Type::Auto:
- return GetDeclContextForType(
- llvm::cast<clang::AutoType>(qual_type)->getDeducedType());
- case clang::Type::Elaborated:
- return GetDeclContextForType(
- llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType());
- case clang::Type::Paren:
- return GetDeclContextForType(
- llvm::cast<clang::ParenType>(qual_type)->desugar());
default:
break;
}
@@ -2599,6 +2400,7 @@ ClangASTContext::GetDeclContextForType(clang::QualType type) {
static bool GetCompleteQualType(clang::ASTContext *ast,
clang::QualType qual_type,
bool allow_completion = true) {
+ qual_type = RemoveWrappingTypes(qual_type);
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
case clang::Type::ConstantArray:
@@ -2700,27 +2502,6 @@ static bool GetCompleteQualType(clang::ASTContext *ast,
}
} break;
- case clang::Type::Typedef:
- return GetCompleteQualType(ast, llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType(),
- allow_completion);
-
- case clang::Type::Auto:
- return GetCompleteQualType(
- ast, llvm::cast<clang::AutoType>(qual_type)->getDeducedType(),
- allow_completion);
-
- case clang::Type::Elaborated:
- return GetCompleteQualType(
- ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType(),
- allow_completion);
-
- case clang::Type::Paren:
- return GetCompleteQualType(
- ast, llvm::cast<clang::ParenType>(qual_type)->desugar(),
- allow_completion);
-
case clang::Type::Attributed:
return GetCompleteQualType(
ast, llvm::cast<clang::AttributedType>(qual_type)->getModifiedType(),
@@ -2753,7 +2534,7 @@ ConvertAccessTypeToObjCIvarAccessControl(AccessType access) {
// Tests
bool ClangASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) {
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
@@ -2766,22 +2547,6 @@ bool ClangASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) {
case clang::Type::ObjCObject:
case clang::Type::ObjCInterface:
return true;
- case clang::Type::Auto:
- return IsAggregateType(llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr());
- case clang::Type::Elaborated:
- return IsAggregateType(llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr());
- case clang::Type::Typedef:
- return IsAggregateType(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr());
- case clang::Type::Paren:
- return IsAggregateType(
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr());
default:
break;
}
@@ -2790,7 +2555,7 @@ bool ClangASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) {
}
bool ClangASTContext::IsAnonymousType(lldb::opaque_compiler_type_t type) {
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
@@ -2804,22 +2569,6 @@ bool ClangASTContext::IsAnonymousType(lldb::opaque_compiler_type_t type) {
}
break;
}
- case clang::Type::Auto:
- return IsAnonymousType(llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr());
- case clang::Type::Elaborated:
- return IsAnonymousType(llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr());
- case clang::Type::Typedef:
- return IsAnonymousType(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr());
- case clang::Type::Paren:
- return IsAnonymousType(
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr());
default:
break;
}
@@ -2830,7 +2579,7 @@ bool ClangASTContext::IsAnonymousType(lldb::opaque_compiler_type_t type) {
bool ClangASTContext::IsArrayType(lldb::opaque_compiler_type_t type,
CompilerType *element_type_ptr,
uint64_t *size, bool *is_incomplete) {
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
@@ -2886,27 +2635,6 @@ bool ClangASTContext::IsArrayType(lldb::opaque_compiler_type_t type,
if (is_incomplete)
*is_incomplete = false;
return true;
-
- case clang::Type::Typedef:
- return IsArrayType(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr(),
- element_type_ptr, size, is_incomplete);
- case clang::Type::Auto:
- return IsArrayType(llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr(),
- element_type_ptr, size, is_incomplete);
- case clang::Type::Elaborated:
- return IsArrayType(llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr(),
- element_type_ptr, size, is_incomplete);
- case clang::Type::Paren:
- return IsArrayType(
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(),
- element_type_ptr, size, is_incomplete);
}
if (element_type_ptr)
element_type_ptr->Clear();
@@ -2930,8 +2658,7 @@ bool ClangASTContext::IsVectorType(lldb::opaque_compiler_type_t type,
if (size)
*size = vector_type->getNumElements();
if (element_type)
- *element_type =
- CompilerType(this, vector_type->getElementType().getAsOpaquePtr());
+ *element_type = GetType(vector_type->getElementType());
}
return true;
} break;
@@ -2955,8 +2682,7 @@ bool ClangASTContext::IsVectorType(lldb::opaque_compiler_type_t type,
bool ClangASTContext::IsRuntimeGeneratedType(
lldb::opaque_compiler_type_t type) {
- clang::DeclContext *decl_ctx = ClangASTContext::GetASTContext(getASTContext())
- ->GetDeclContextForType(GetQualType(type));
+ clang::DeclContext *decl_ctx = GetDeclContextForType(GetQualType(type));
if (!decl_ctx)
return false;
@@ -2966,8 +2692,7 @@ bool ClangASTContext::IsRuntimeGeneratedType(
clang::ObjCInterfaceDecl *result_iface_decl =
llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx);
- ClangASTMetadata *ast_metadata =
- ClangASTContext::GetMetadata(getASTContext(), result_iface_decl);
+ ClangASTMetadata *ast_metadata = GetMetadata(result_iface_decl);
if (!ast_metadata)
return false;
return (ast_metadata->GetISAPtr() != 0);
@@ -2979,7 +2704,7 @@ bool ClangASTContext::IsCharType(lldb::opaque_compiler_type_t type) {
bool ClangASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) {
const bool allow_completion = false;
- return GetCompleteQualType(getASTContext(), GetQualType(type),
+ return GetCompleteQualType(&getASTContext(), GetQualType(type),
allow_completion);
}
@@ -3015,7 +2740,7 @@ bool ClangASTContext::IsCStringType(lldb::opaque_compiler_type_t type,
bool ClangASTContext::IsFunctionType(lldb::opaque_compiler_type_t type,
bool *is_variadic_ptr) {
if (type) {
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
if (qual_type->isFunctionType()) {
if (is_variadic_ptr) {
@@ -3033,26 +2758,6 @@ bool ClangASTContext::IsFunctionType(lldb::opaque_compiler_type_t type,
switch (type_class) {
default:
break;
- case clang::Type::Typedef:
- return IsFunctionType(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr(),
- nullptr);
- case clang::Type::Auto:
- return IsFunctionType(llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr(),
- nullptr);
- case clang::Type::Elaborated:
- return IsFunctionType(llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr(),
- nullptr);
- case clang::Type::Paren:
- return IsFunctionType(
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(),
- nullptr);
case clang::Type::LValueReference:
case clang::Type::RValueReference: {
const clang::ReferenceType *reference_type =
@@ -3073,7 +2778,7 @@ ClangASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
if (!type)
return 0;
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
case clang::Type::Record:
@@ -3101,7 +2806,7 @@ ClangASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
for (field_pos = record_decl->field_begin(); field_pos != field_end;
++field_pos) {
clang::QualType field_qual_type = field_pos->getType();
- uint64_t field_bitwidth = getASTContext()->getTypeSize(qual_type);
+ uint64_t field_bitwidth = getASTContext().getTypeSize(qual_type);
if (field_qual_type->isFloatingType()) {
if (field_qual_type->isComplexType())
return 0;
@@ -3143,24 +2848,6 @@ ClangASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
}
break;
- case clang::Type::Typedef:
- return IsHomogeneousAggregate(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr(),
- base_type_ptr);
-
- case clang::Type::Auto:
- return IsHomogeneousAggregate(llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr(),
- base_type_ptr);
-
- case clang::Type::Elaborated:
- return IsHomogeneousAggregate(llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr(),
- base_type_ptr);
default:
break;
}
@@ -3196,7 +2883,7 @@ ClangASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
bool ClangASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) {
if (type) {
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
if (qual_type->isFunctionPointerType())
return true;
@@ -3205,22 +2892,6 @@ bool ClangASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) {
switch (type_class) {
default:
break;
- case clang::Type::Typedef:
- return IsFunctionPointerType(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr());
- case clang::Type::Auto:
- return IsFunctionPointerType(llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr());
- case clang::Type::Elaborated:
- return IsFunctionPointerType(llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr());
- case clang::Type::Paren:
- return IsFunctionPointerType(
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr());
case clang::Type::LValueReference:
case clang::Type::RValueReference: {
@@ -3239,7 +2910,7 @@ bool ClangASTContext::IsBlockPointerType(
lldb::opaque_compiler_type_t type,
CompilerType *function_pointer_type_ptr) {
if (type) {
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
if (qual_type->isBlockPointerType()) {
if (function_pointer_type_ptr) {
@@ -3257,26 +2928,6 @@ bool ClangASTContext::IsBlockPointerType(
switch (type_class) {
default:
break;
- case clang::Type::Typedef:
- return IsBlockPointerType(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr(),
- function_pointer_type_ptr);
- case clang::Type::Auto:
- return IsBlockPointerType(llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr(),
- function_pointer_type_ptr);
- case clang::Type::Elaborated:
- return IsBlockPointerType(llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr(),
- function_pointer_type_ptr);
- case clang::Type::Paren:
- return IsBlockPointerType(
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(),
- function_pointer_type_ptr);
case clang::Type::LValueReference:
case clang::Type::RValueReference: {
@@ -3330,7 +2981,7 @@ bool ClangASTContext::IsEnumerationType(lldb::opaque_compiler_type_t type,
bool ClangASTContext::IsPointerType(lldb::opaque_compiler_type_t type,
CompilerType *pointee_type) {
if (type) {
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
case clang::Type::Builtin:
@@ -3370,26 +3021,6 @@ bool ClangASTContext::IsPointerType(lldb::opaque_compiler_type_t type,
->getPointeeType()
.getAsOpaquePtr());
return true;
- case clang::Type::Typedef:
- return IsPointerType(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr(),
- pointee_type);
- case clang::Type::Auto:
- return IsPointerType(llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr(),
- pointee_type);
- case clang::Type::Elaborated:
- return IsPointerType(llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr(),
- pointee_type);
- case clang::Type::Paren:
- return IsPointerType(
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(),
- pointee_type);
default:
break;
}
@@ -3402,7 +3033,7 @@ bool ClangASTContext::IsPointerType(lldb::opaque_compiler_type_t type,
bool ClangASTContext::IsPointerOrReferenceType(
lldb::opaque_compiler_type_t type, CompilerType *pointee_type) {
if (type) {
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
case clang::Type::Builtin:
@@ -3455,27 +3086,6 @@ bool ClangASTContext::IsPointerOrReferenceType(
->desugar()
.getAsOpaquePtr());
return true;
- case clang::Type::Typedef:
- return IsPointerOrReferenceType(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr(),
- pointee_type);
- case clang::Type::Auto:
- return IsPointerOrReferenceType(llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr(),
- pointee_type);
- case clang::Type::Elaborated:
- return IsPointerOrReferenceType(
- llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr(),
- pointee_type);
- case clang::Type::Paren:
- return IsPointerOrReferenceType(
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(),
- pointee_type);
default:
break;
}
@@ -3489,7 +3099,7 @@ bool ClangASTContext::IsReferenceType(lldb::opaque_compiler_type_t type,
CompilerType *pointee_type,
bool *is_rvalue) {
if (type) {
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
@@ -3511,26 +3121,6 @@ bool ClangASTContext::IsReferenceType(lldb::opaque_compiler_type_t type,
if (is_rvalue)
*is_rvalue = true;
return true;
- case clang::Type::Typedef:
- return IsReferenceType(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr(),
- pointee_type, is_rvalue);
- case clang::Type::Auto:
- return IsReferenceType(llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr(),
- pointee_type, is_rvalue);
- case clang::Type::Elaborated:
- return IsReferenceType(llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr(),
- pointee_type, is_rvalue);
- case clang::Type::Paren:
- return IsReferenceType(
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(),
- pointee_type, is_rvalue);
default:
break;
@@ -3606,7 +3196,7 @@ bool ClangASTContext::IsDefined(lldb::opaque_compiler_type_t type) {
}
bool ClangASTContext::IsObjCClassType(const CompilerType &type) {
- if (type) {
+ if (ClangUtil::IsClangType(type)) {
clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type));
const clang::ObjCObjectPointerType *obj_pointer_type =
@@ -3672,7 +3262,7 @@ bool ClangASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
bool check_objc) {
clang::QualType pointee_qual_type;
if (type) {
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
bool success = false;
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
@@ -3719,32 +3309,6 @@ bool ClangASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
success = true;
break;
- case clang::Type::Typedef:
- return IsPossibleDynamicType(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr(),
- dynamic_pointee_type, check_cplusplus,
- check_objc);
-
- case clang::Type::Auto:
- return IsPossibleDynamicType(llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr(),
- dynamic_pointee_type, check_cplusplus,
- check_objc);
-
- case clang::Type::Elaborated:
- return IsPossibleDynamicType(llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr(),
- dynamic_pointee_type, check_cplusplus,
- check_objc);
-
- case clang::Type::Paren:
- return IsPossibleDynamicType(
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(),
- dynamic_pointee_type, check_cplusplus, check_objc);
default:
break;
}
@@ -3779,14 +3343,11 @@ bool ClangASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
if (is_complete)
success = cxx_record_decl->isDynamicClass();
else {
- ClangASTMetadata *metadata = ClangASTContext::GetMetadata(
- getASTContext(), cxx_record_decl);
+ ClangASTMetadata *metadata = GetMetadata(cxx_record_decl);
if (metadata)
success = metadata->GetIsDynamicCXXType();
else {
- is_complete =
- CompilerType(this, pointee_qual_type.getAsOpaquePtr())
- .GetCompleteType();
+ is_complete = GetType(pointee_qual_type).GetCompleteType();
if (is_complete)
success = cxx_record_decl->isDynamicClass();
else
@@ -3855,20 +3416,20 @@ bool ClangASTContext::SupportsLanguage(lldb::LanguageType language) {
return ClangASTContextSupportsLanguage(language);
}
-bool ClangASTContext::GetCXXClassName(const CompilerType &type,
- std::string &class_name) {
- if (type) {
- clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type));
- if (!qual_type.isNull()) {
- clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl) {
- class_name.assign(cxx_record_decl->getIdentifier()->getNameStart());
- return true;
- }
- }
- }
- class_name.clear();
- return false;
+Optional<std::string>
+ClangASTContext::GetCXXClassName(const CompilerType &type) {
+ if (!type)
+ return llvm::None;
+
+ clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type));
+ if (qual_type.isNull())
+ return llvm::None;
+
+ clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ if (!cxx_record_decl)
+ return llvm::None;
+
+ return std::string(cxx_record_decl->getIdentifier()->getNameStart());
}
bool ClangASTContext::IsCXXClassType(const CompilerType &type) {
@@ -3891,7 +3452,7 @@ bool ClangASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) {
bool ClangASTContext::IsObjCObjectPointerType(const CompilerType &type,
CompilerType *class_type_ptr) {
- if (!type)
+ if (!ClangUtil::IsClangType(type))
return false;
clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type));
@@ -3923,14 +3484,14 @@ bool ClangASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) {
if (!type)
return false;
const bool allow_completion = true;
- return GetCompleteQualType(getASTContext(), GetQualType(type),
+ return GetCompleteQualType(&getASTContext(), GetQualType(type),
allow_completion);
}
ConstString ClangASTContext::GetTypeName(lldb::opaque_compiler_type_t type) {
std::string type_name;
if (type) {
- clang::PrintingPolicy printing_policy(getASTContext()->getPrintingPolicy());
+ clang::PrintingPolicy printing_policy(getASTContext().getPrintingPolicy());
clang::QualType qual_type(GetQualType(type));
printing_policy.SuppressTagKeyword = true;
const clang::TypedefType *typedef_type =
@@ -3954,7 +3515,8 @@ ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type,
if (pointee_or_element_clang_type)
pointee_or_element_clang_type->Clear();
- clang::QualType qual_type(GetQualType(type));
+ clang::QualType qual_type =
+ RemoveWrappingTypes(GetQualType(type), {clang::Type::Typedef});
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
@@ -3973,14 +3535,14 @@ ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type,
case clang::BuiltinType::ObjCClass:
if (pointee_or_element_clang_type)
pointee_or_element_clang_type->SetCompilerType(
- this, getASTContext()->ObjCBuiltinClassTy.getAsOpaquePtr());
+ this, getASTContext().ObjCBuiltinClassTy.getAsOpaquePtr());
builtin_type_flags |= eTypeIsPointer | eTypeIsObjC;
break;
case clang::BuiltinType::ObjCSel:
if (pointee_or_element_clang_type)
pointee_or_element_clang_type->SetCompilerType(
- this, getASTContext()->CharTy.getAsOpaquePtr());
+ this, getASTContext().CharTy.getAsOpaquePtr());
builtin_type_flags |= eTypeIsPointer | eTypeIsObjC;
break;
@@ -4058,11 +3620,6 @@ ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type,
return eTypeHasChildren | eTypeIsVector;
case clang::Type::DependentTemplateSpecialization:
return eTypeIsTemplate;
- case clang::Type::Decltype:
- return CompilerType(this, llvm::cast<clang::DecltypeType>(qual_type)
- ->getUnderlyingType()
- .getAsOpaquePtr())
- .GetTypeInfo(pointee_or_element_clang_type);
case clang::Type::Enum:
if (pointee_or_element_clang_type)
@@ -4073,22 +3630,6 @@ ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type,
.getAsOpaquePtr());
return eTypeIsEnumeration | eTypeHasValue;
- case clang::Type::Auto:
- return CompilerType(this, llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr())
- .GetTypeInfo(pointee_or_element_clang_type);
- case clang::Type::Elaborated:
- return CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr())
- .GetTypeInfo(pointee_or_element_clang_type);
- case clang::Type::Paren:
- return CompilerType(this, llvm::cast<clang::ParenType>(qual_type)
- ->desugar()
- .getAsOpaquePtr())
- .GetTypeInfo(pointee_or_element_clang_type);
-
case clang::Type::FunctionProto:
return eTypeIsFuncPrototype | eTypeHasValue;
case clang::Type::FunctionNoProto:
@@ -4140,23 +3681,10 @@ ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type,
return eTypeIsTemplate;
case clang::Type::Typedef:
- return eTypeIsTypedef |
- CompilerType(this, llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr())
- .GetTypeInfo(pointee_or_element_clang_type);
- case clang::Type::TypeOfExpr:
- return CompilerType(this, llvm::cast<clang::TypeOfExprType>(qual_type)
- ->getUnderlyingExpr()
- ->getType()
- .getAsOpaquePtr())
- .GetTypeInfo(pointee_or_element_clang_type);
- case clang::Type::TypeOf:
- return CompilerType(this, llvm::cast<clang::TypeOfType>(qual_type)
- ->getUnderlyingType()
- .getAsOpaquePtr())
- .GetTypeInfo(pointee_or_element_clang_type);
+ return eTypeIsTypedef | GetType(llvm::cast<clang::TypedefType>(qual_type)
+ ->getDecl()
+ ->getUnderlyingType())
+ .GetTypeInfo(pointee_or_element_clang_type);
case clang::Type::UnresolvedUsing:
return 0;
@@ -4200,7 +3728,7 @@ ClangASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) {
if (pointee_type->isObjCClassType())
return lldb::eLanguageTypeObjC;
if (pointee_type.getTypePtr() ==
- getASTContext()->ObjCBuiltinIdTy.getTypePtr())
+ getASTContext().ObjCBuiltinIdTy.getTypePtr())
return lldb::eLanguageTypeObjC;
} else {
if (qual_type->isObjCObjectOrInterfaceType())
@@ -4254,10 +3782,9 @@ ClangASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) {
}
break;
case clang::Type::Typedef:
- return CompilerType(this, llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr())
+ return GetType(llvm::cast<clang::TypedefType>(qual_type)
+ ->getDecl()
+ ->getUnderlyingType())
.GetMinimumLanguage();
}
}
@@ -4269,9 +3796,18 @@ ClangASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) {
if (!type)
return lldb::eTypeClassInvalid;
- clang::QualType qual_type(GetQualType(type));
+ clang::QualType qual_type =
+ RemoveWrappingTypes(GetQualType(type), {clang::Type::Typedef});
switch (qual_type->getTypeClass()) {
+ case clang::Type::Atomic:
+ case clang::Type::Auto:
+ case clang::Type::Decltype:
+ case clang::Type::Elaborated:
+ case clang::Type::Paren:
+ case clang::Type::TypeOf:
+ case clang::Type::TypeOfExpr:
+ llvm_unreachable("Handled in RemoveWrappingTypes!");
case clang::Type::UnaryTransform:
break;
case clang::Type::FunctionNoProto:
@@ -4334,21 +3870,6 @@ ClangASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) {
return lldb::eTypeClassTypedef;
case clang::Type::UnresolvedUsing:
break;
- case clang::Type::Paren:
- return CompilerType(this, llvm::cast<clang::ParenType>(qual_type)
- ->desugar()
- .getAsOpaquePtr())
- .GetTypeClass();
- case clang::Type::Auto:
- return CompilerType(this, llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr())
- .GetTypeClass();
- case clang::Type::Elaborated:
- return CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr())
- .GetTypeClass();
case clang::Type::Attributed:
break;
@@ -4367,28 +3888,10 @@ ClangASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) {
case clang::Type::PackExpansion:
break;
- case clang::Type::TypeOfExpr:
- return CompilerType(this, llvm::cast<clang::TypeOfExprType>(qual_type)
- ->getUnderlyingExpr()
- ->getType()
- .getAsOpaquePtr())
- .GetTypeClass();
- case clang::Type::TypeOf:
- return CompilerType(this, llvm::cast<clang::TypeOfType>(qual_type)
- ->getUnderlyingType()
- .getAsOpaquePtr())
- .GetTypeClass();
- case clang::Type::Decltype:
- return CompilerType(this, llvm::cast<clang::TypeOfType>(qual_type)
- ->getUnderlyingType()
- .getAsOpaquePtr())
- .GetTypeClass();
case clang::Type::TemplateSpecialization:
break;
case clang::Type::DeducedTemplateSpecialization:
break;
- case clang::Type::Atomic:
- break;
case clang::Type::Pipe:
break;
@@ -4421,7 +3924,7 @@ CompilerType
ClangASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type,
uint64_t *stride) {
if (type) {
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type(GetQualType(type));
const clang::Type *array_eletype =
qual_type.getTypePtr()->getArrayElementTypeNoTypeQual();
@@ -4429,8 +3932,7 @@ ClangASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type,
if (!array_eletype)
return CompilerType();
- CompilerType element_type(
- this, array_eletype->getCanonicalTypeUnqualified().getAsOpaquePtr());
+ CompilerType element_type = GetType(clang::QualType(array_eletype, 0));
// TODO: the real stride will be >= this value.. find the real one!
if (stride)
@@ -4446,22 +3948,14 @@ CompilerType ClangASTContext::GetArrayType(lldb::opaque_compiler_type_t type,
uint64_t size) {
if (type) {
clang::QualType qual_type(GetCanonicalQualType(type));
- if (clang::ASTContext *ast_ctx = getASTContext()) {
- if (size != 0)
- return CompilerType(
- this, ast_ctx
- ->getConstantArrayType(
- qual_type, llvm::APInt(64, size), nullptr,
- clang::ArrayType::ArraySizeModifier::Normal, 0)
- .getAsOpaquePtr());
- else
- return CompilerType(
- this,
- ast_ctx
- ->getIncompleteArrayType(
- qual_type, clang::ArrayType::ArraySizeModifier::Normal, 0)
- .getAsOpaquePtr());
- }
+ clang::ASTContext &ast_ctx = getASTContext();
+ if (size != 0)
+ return GetType(ast_ctx.getConstantArrayType(
+ qual_type, llvm::APInt(64, size), nullptr,
+ clang::ArrayType::ArraySizeModifier::Normal, 0));
+ else
+ return GetType(ast_ctx.getIncompleteArrayType(
+ qual_type, clang::ArrayType::ArraySizeModifier::Normal, 0));
}
return CompilerType();
@@ -4470,7 +3964,7 @@ CompilerType ClangASTContext::GetArrayType(lldb::opaque_compiler_type_t type,
CompilerType
ClangASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) {
if (type)
- return CompilerType(this, GetCanonicalQualType(type).getAsOpaquePtr());
+ return GetType(GetCanonicalQualType(type));
return CompilerType();
}
@@ -4490,9 +3984,8 @@ static clang::QualType GetFullyUnqualifiedType_Impl(clang::ASTContext *ast,
CompilerType
ClangASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) {
if (type)
- return CompilerType(
- this,
- GetFullyUnqualifiedType_Impl(getASTContext(), GetQualType(type)).getAsOpaquePtr());
+ return GetType(
+ GetFullyUnqualifiedType_Impl(&getASTContext(), GetQualType(type)));
return CompilerType();
}
@@ -4515,7 +4008,7 @@ CompilerType ClangASTContext::GetFunctionArgumentTypeAtIndex(
if (func) {
const uint32_t num_args = func->getNumParams();
if (idx < num_args)
- return CompilerType(this, func->getParamType(idx).getAsOpaquePtr());
+ return GetType(func->getParamType(idx));
}
}
return CompilerType();
@@ -4528,7 +4021,7 @@ ClangASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) {
const clang::FunctionProtoType *func =
llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
if (func)
- return CompilerType(this, func->getReturnType().getAsOpaquePtr());
+ return GetType(func->getReturnType());
}
return CompilerType();
}
@@ -4537,10 +4030,10 @@ size_t
ClangASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) {
size_t num_functions = 0;
if (type) {
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
switch (qual_type->getTypeClass()) {
case clang::Type::Record:
- if (GetCompleteQualType(getASTContext(), qual_type)) {
+ if (GetCompleteQualType(&getASTContext(), qual_type)) {
const clang::RecordType *record_type =
llvm::cast<clang::RecordType>(qual_type.getTypePtr());
const clang::RecordDecl *record_decl = record_type->getDecl();
@@ -4586,31 +4079,6 @@ ClangASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) {
}
break;
- case clang::Type::Typedef:
- return CompilerType(this, llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr())
- .GetNumMemberFunctions();
-
- case clang::Type::Auto:
- return CompilerType(this, llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr())
- .GetNumMemberFunctions();
-
- case clang::Type::Elaborated:
- return CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr())
- .GetNumMemberFunctions();
-
- case clang::Type::Paren:
- return CompilerType(this, llvm::cast<clang::ParenType>(qual_type)
- ->desugar()
- .getAsOpaquePtr())
- .GetNumMemberFunctions();
-
default:
break;
}
@@ -4626,10 +4094,10 @@ ClangASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
CompilerType clang_type;
CompilerDecl clang_decl;
if (type) {
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
switch (qual_type->getTypeClass()) {
case clang::Type::Record:
- if (GetCompleteQualType(getASTContext(), qual_type)) {
+ if (GetCompleteQualType(&getASTContext(), qual_type)) {
const clang::RecordType *record_type =
llvm::cast<clang::RecordType>(qual_type.getTypePtr());
const clang::RecordDecl *record_decl = record_type->getDecl();
@@ -4654,8 +4122,7 @@ ClangASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
kind = lldb::eMemberFunctionKindDestructor;
else
kind = lldb::eMemberFunctionKindInstanceMethod;
- clang_type = CompilerType(
- this, cxx_method_decl->getType().getAsOpaquePtr());
+ clang_type = GetType(cxx_method_decl->getType());
clang_decl = CompilerDecl(this, cxx_method_decl);
}
}
@@ -4725,31 +4192,6 @@ ClangASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
}
break;
- case clang::Type::Typedef:
- return GetMemberFunctionAtIndex(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr(),
- idx);
-
- case clang::Type::Auto:
- return GetMemberFunctionAtIndex(llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr(),
- idx);
-
- case clang::Type::Elaborated:
- return GetMemberFunctionAtIndex(
- llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr(),
- idx);
-
- case clang::Type::Paren:
- return GetMemberFunctionAtIndex(
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(),
- idx);
-
default:
break;
}
@@ -4764,8 +4206,7 @@ ClangASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
CompilerType
ClangASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) {
if (type)
- return CompilerType(
- this, GetQualType(type).getNonReferenceType().getAsOpaquePtr());
+ return GetType(GetQualType(type).getNonReferenceType());
return CompilerType();
}
@@ -4777,25 +4218,25 @@ CompilerType ClangASTContext::CreateTypedefType(
llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
if (!ast)
return CompilerType();
- clang::ASTContext *clang_ast = ast->getASTContext();
+ clang::ASTContext &clang_ast = ast->getASTContext();
clang::QualType qual_type(ClangUtil::GetQualType(type));
clang::DeclContext *decl_ctx =
ClangASTContext::DeclContextGetAsDeclContext(compiler_decl_ctx);
if (decl_ctx == nullptr)
- decl_ctx = ast->getASTContext()->getTranslationUnitDecl();
+ decl_ctx = ast->getASTContext().getTranslationUnitDecl();
clang::TypedefDecl *decl = clang::TypedefDecl::Create(
- *clang_ast, decl_ctx, clang::SourceLocation(), clang::SourceLocation(),
- &clang_ast->Idents.get(typedef_name),
- clang_ast->getTrivialTypeSourceInfo(qual_type));
+ clang_ast, decl_ctx, clang::SourceLocation(), clang::SourceLocation(),
+ &clang_ast.Idents.get(typedef_name),
+ clang_ast.getTrivialTypeSourceInfo(qual_type));
decl->setAccess(clang::AS_public); // TODO respect proper access specifier
decl_ctx->addDecl(decl);
// Get a uniqued clang::QualType for the typedef decl type
- return CompilerType(ast, clang_ast->getTypedefType(decl).getAsOpaquePtr());
+ return ast->GetType(clang_ast.getTypedefType(decl));
}
return CompilerType();
}
@@ -4804,8 +4245,7 @@ CompilerType
ClangASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) {
if (type) {
clang::QualType qual_type(GetQualType(type));
- return CompilerType(
- this, qual_type.getTypePtr()->getPointeeType().getAsOpaquePtr());
+ return GetType(qual_type.getTypePtr()->getPointeeType());
}
return CompilerType();
}
@@ -4819,13 +4259,10 @@ ClangASTContext::GetPointerType(lldb::opaque_compiler_type_t type) {
switch (type_class) {
case clang::Type::ObjCObject:
case clang::Type::ObjCInterface:
- return CompilerType(this, getASTContext()
- ->getObjCObjectPointerType(qual_type)
- .getAsOpaquePtr());
+ return GetType(getASTContext().getObjCObjectPointerType(qual_type));
default:
- return CompilerType(
- this, getASTContext()->getPointerType(qual_type).getAsOpaquePtr());
+ return GetType(getASTContext().getPointerType(qual_type));
}
}
return CompilerType();
@@ -4834,9 +4271,7 @@ ClangASTContext::GetPointerType(lldb::opaque_compiler_type_t type) {
CompilerType
ClangASTContext::GetLValueReferenceType(lldb::opaque_compiler_type_t type) {
if (type)
- return CompilerType(this, getASTContext()
- ->getLValueReferenceType(GetQualType(type))
- .getAsOpaquePtr());
+ return GetType(getASTContext().getLValueReferenceType(GetQualType(type)));
else
return CompilerType();
}
@@ -4844,19 +4279,23 @@ ClangASTContext::GetLValueReferenceType(lldb::opaque_compiler_type_t type) {
CompilerType
ClangASTContext::GetRValueReferenceType(lldb::opaque_compiler_type_t type) {
if (type)
- return CompilerType(this, getASTContext()
- ->getRValueReferenceType(GetQualType(type))
- .getAsOpaquePtr());
+ return GetType(getASTContext().getRValueReferenceType(GetQualType(type)));
else
return CompilerType();
}
+CompilerType ClangASTContext::GetAtomicType(lldb::opaque_compiler_type_t type) {
+ if (!type)
+ return CompilerType();
+ return GetType(getASTContext().getAtomicType(GetQualType(type)));
+}
+
CompilerType
ClangASTContext::AddConstModifier(lldb::opaque_compiler_type_t type) {
if (type) {
clang::QualType result(GetQualType(type));
result.addConst();
- return CompilerType(this, result.getAsOpaquePtr());
+ return GetType(result);
}
return CompilerType();
}
@@ -4866,7 +4305,7 @@ ClangASTContext::AddVolatileModifier(lldb::opaque_compiler_type_t type) {
if (type) {
clang::QualType result(GetQualType(type));
result.addVolatile();
- return CompilerType(this, result.getAsOpaquePtr());
+ return GetType(result);
}
return CompilerType();
}
@@ -4876,7 +4315,7 @@ ClangASTContext::AddRestrictModifier(lldb::opaque_compiler_type_t type) {
if (type) {
clang::QualType result(GetQualType(type));
result.addRestrict();
- return CompilerType(this, result.getAsOpaquePtr());
+ return GetType(result);
}
return CompilerType();
}
@@ -4886,18 +4325,18 @@ ClangASTContext::CreateTypedef(lldb::opaque_compiler_type_t type,
const char *typedef_name,
const CompilerDeclContext &compiler_decl_ctx) {
if (type) {
- clang::ASTContext *clang_ast = getASTContext();
+ clang::ASTContext &clang_ast = getASTContext();
clang::QualType qual_type(GetQualType(type));
clang::DeclContext *decl_ctx =
ClangASTContext::DeclContextGetAsDeclContext(compiler_decl_ctx);
if (decl_ctx == nullptr)
- decl_ctx = getASTContext()->getTranslationUnitDecl();
+ decl_ctx = getASTContext().getTranslationUnitDecl();
clang::TypedefDecl *decl = clang::TypedefDecl::Create(
- *clang_ast, decl_ctx, clang::SourceLocation(), clang::SourceLocation(),
- &clang_ast->Idents.get(typedef_name),
- clang_ast->getTrivialTypeSourceInfo(qual_type));
+ clang_ast, decl_ctx, clang::SourceLocation(), clang::SourceLocation(),
+ &clang_ast.Idents.get(typedef_name),
+ clang_ast.getTrivialTypeSourceInfo(qual_type));
clang::TagDecl *tdecl = nullptr;
if (!qual_type.isNull()) {
@@ -4916,7 +4355,7 @@ ClangASTContext::CreateTypedef(lldb::opaque_compiler_type_t type,
decl->setAccess(clang::AS_public); // TODO respect proper access specifier
// Get a uniqued clang::QualType for the typedef decl type
- return CompilerType(this, clang_ast->getTypedefType(decl).getAsOpaquePtr());
+ return GetType(clang_ast.getTypedefType(decl));
}
return CompilerType();
}
@@ -4927,8 +4366,7 @@ ClangASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) {
const clang::TypedefType *typedef_type =
llvm::dyn_cast<clang::TypedefType>(GetQualType(type));
if (typedef_type)
- return CompilerType(
- this, typedef_type->getDecl()->getUnderlyingType().getAsOpaquePtr());
+ return GetType(typedef_type->getDecl()->getUnderlyingType());
}
return CompilerType();
}
@@ -4936,23 +4374,22 @@ ClangASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) {
// Create related types using the current type's AST
CompilerType ClangASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) {
- return ClangASTContext::GetBasicType(getASTContext(), basic_type);
+ return ClangASTContext::GetBasicType(basic_type);
}
// Exploring the type
const llvm::fltSemantics &
ClangASTContext::GetFloatTypeSemantics(size_t byte_size) {
- if (auto *ast = getASTContext()) {
- const size_t bit_size = byte_size * 8;
- if (bit_size == ast->getTypeSize(ast->FloatTy))
- return ast->getFloatTypeSemantics(ast->FloatTy);
- else if (bit_size == ast->getTypeSize(ast->DoubleTy))
- return ast->getFloatTypeSemantics(ast->DoubleTy);
- else if (bit_size == ast->getTypeSize(ast->LongDoubleTy))
- return ast->getFloatTypeSemantics(ast->LongDoubleTy);
- else if (bit_size == ast->getTypeSize(ast->HalfTy))
- return ast->getFloatTypeSemantics(ast->HalfTy);
- }
+ clang::ASTContext &ast = getASTContext();
+ const size_t bit_size = byte_size * 8;
+ if (bit_size == ast.getTypeSize(ast.FloatTy))
+ return ast.getFloatTypeSemantics(ast.FloatTy);
+ else if (bit_size == ast.getTypeSize(ast.DoubleTy))
+ return ast.getFloatTypeSemantics(ast.DoubleTy);
+ else if (bit_size == ast.getTypeSize(ast.LongDoubleTy))
+ return ast.getFloatTypeSemantics(ast.LongDoubleTy);
+ else if (bit_size == ast.getTypeSize(ast.HalfTy))
+ return ast.getFloatTypeSemantics(ast.HalfTy);
return llvm::APFloatBase::Bogus();
}
@@ -4965,7 +4402,7 @@ ClangASTContext::GetBitSize(lldb::opaque_compiler_type_t type,
switch (type_class) {
case clang::Type::Record:
if (GetCompleteType(type))
- return getASTContext()->getTypeSize(qual_type);
+ return getASTContext().getTypeSize(qual_type);
else
return None;
break;
@@ -4978,8 +4415,7 @@ ClangASTContext::GetBitSize(lldb::opaque_compiler_type_t type,
ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process);
if (objc_runtime) {
uint64_t bit_size = 0;
- if (objc_runtime->GetTypeBitSize(
- CompilerType(this, qual_type.getAsOpaquePtr()), bit_size))
+ if (objc_runtime->GetTypeBitSize(GetType(qual_type), bit_size))
return bit_size;
}
} else {
@@ -5001,17 +4437,16 @@ ClangASTContext::GetBitSize(lldb::opaque_compiler_type_t type,
}
LLVM_FALLTHROUGH;
default:
- const uint32_t bit_size = getASTContext()->getTypeSize(qual_type);
+ const uint32_t bit_size = getASTContext().getTypeSize(qual_type);
if (bit_size == 0) {
if (qual_type->isIncompleteArrayType())
- return getASTContext()->getTypeSize(
+ return getASTContext().getTypeSize(
qual_type->getArrayElementTypeNoTypeQual()
->getCanonicalTypeUnqualified());
}
if (qual_type->isObjCObjectOrInterfaceType())
return bit_size +
- getASTContext()->getTypeSize(
- getASTContext()->ObjCBuiltinClassTy);
+ getASTContext().getTypeSize(getASTContext().ObjCBuiltinClassTy);
// Function types actually have a size of 0, that's not an error.
if (qual_type->isFunctionProtoType())
return bit_size;
@@ -5026,7 +4461,7 @@ llvm::Optional<size_t>
ClangASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type,
ExecutionContextScope *exe_scope) {
if (GetCompleteType(type))
- return getASTContext()->getTypeAlign(GetQualType(type));
+ return getASTContext().getTypeAlign(GetQualType(type));
return {};
}
@@ -5036,9 +4471,19 @@ lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
return lldb::eEncodingInvalid;
count = 1;
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
switch (qual_type->getTypeClass()) {
+ case clang::Type::Atomic:
+ case clang::Type::Auto:
+ case clang::Type::Decltype:
+ case clang::Type::Elaborated:
+ case clang::Type::Paren:
+ case clang::Type::Typedef:
+ case clang::Type::TypeOf:
+ case clang::Type::TypeOfExpr:
+ llvm_unreachable("Handled in RemoveWrappingTypes!");
+
case clang::Type::UnaryTransform:
break;
@@ -5228,9 +4673,7 @@ lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
const clang::ComplexType *complex_type =
qual_type->getAsComplexIntegerType();
if (complex_type)
- encoding =
- CompilerType(this, complex_type->getElementType().getAsOpaquePtr())
- .GetEncoding(count);
+ encoding = GetType(complex_type->getElementType()).GetEncoding(count);
else
encoding = lldb::eEncodingSint;
}
@@ -5244,46 +4687,6 @@ lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
break;
case clang::Type::Enum:
return lldb::eEncodingSint;
- case clang::Type::Typedef:
- return CompilerType(this, llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr())
- .GetEncoding(count);
-
- case clang::Type::Auto:
- return CompilerType(this, llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr())
- .GetEncoding(count);
-
- case clang::Type::Elaborated:
- return CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr())
- .GetEncoding(count);
-
- case clang::Type::Paren:
- return CompilerType(this, llvm::cast<clang::ParenType>(qual_type)
- ->desugar()
- .getAsOpaquePtr())
- .GetEncoding(count);
- case clang::Type::TypeOfExpr:
- return CompilerType(this, llvm::cast<clang::TypeOfExprType>(qual_type)
- ->getUnderlyingExpr()
- ->getType()
- .getAsOpaquePtr())
- .GetEncoding(count);
- case clang::Type::TypeOf:
- return CompilerType(this, llvm::cast<clang::TypeOfType>(qual_type)
- ->getUnderlyingType()
- .getAsOpaquePtr())
- .GetEncoding(count);
- case clang::Type::Decltype:
- return CompilerType(this, llvm::cast<clang::DecltypeType>(qual_type)
- ->getUnderlyingType()
- .getAsOpaquePtr())
- .GetEncoding(count);
case clang::Type::DependentSizedArray:
case clang::Type::DependentSizedExtVector:
case clang::Type::UnresolvedUsing:
@@ -5299,7 +4702,6 @@ lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
case clang::Type::TemplateSpecialization:
case clang::Type::DeducedTemplateSpecialization:
- case clang::Type::Atomic:
case clang::Type::Adjusted:
case clang::Type::Pipe:
break;
@@ -5323,9 +4725,18 @@ lldb::Format ClangASTContext::GetFormat(lldb::opaque_compiler_type_t type) {
if (!type)
return lldb::eFormatDefault;
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
switch (qual_type->getTypeClass()) {
+ case clang::Type::Atomic:
+ case clang::Type::Auto:
+ case clang::Type::Decltype:
+ case clang::Type::Elaborated:
+ case clang::Type::Paren:
+ case clang::Type::Typedef:
+ case clang::Type::TypeOf:
+ case clang::Type::TypeOfExpr:
+ llvm_unreachable("Handled in RemoveWrappingTypes!");
case clang::Type::UnaryTransform:
break;
@@ -5418,43 +4829,6 @@ lldb::Format ClangASTContext::GetFormat(lldb::opaque_compiler_type_t type) {
break;
case clang::Type::Enum:
return lldb::eFormatEnum;
- case clang::Type::Typedef:
- return CompilerType(this, llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr())
- .GetFormat();
- case clang::Type::Auto:
- return CompilerType(this, llvm::cast<clang::AutoType>(qual_type)
- ->desugar()
- .getAsOpaquePtr())
- .GetFormat();
- case clang::Type::Paren:
- return CompilerType(this, llvm::cast<clang::ParenType>(qual_type)
- ->desugar()
- .getAsOpaquePtr())
- .GetFormat();
- case clang::Type::Elaborated:
- return CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr())
- .GetFormat();
- case clang::Type::TypeOfExpr:
- return CompilerType(this, llvm::cast<clang::TypeOfExprType>(qual_type)
- ->getUnderlyingExpr()
- ->getType()
- .getAsOpaquePtr())
- .GetFormat();
- case clang::Type::TypeOf:
- return CompilerType(this, llvm::cast<clang::TypeOfType>(qual_type)
- ->getUnderlyingType()
- .getAsOpaquePtr())
- .GetFormat();
- case clang::Type::Decltype:
- return CompilerType(this, llvm::cast<clang::DecltypeType>(qual_type)
- ->getUnderlyingType()
- .getAsOpaquePtr())
- .GetFormat();
case clang::Type::DependentSizedArray:
case clang::Type::DependentSizedExtVector:
case clang::Type::UnresolvedUsing:
@@ -5470,7 +4844,6 @@ lldb::Format ClangASTContext::GetFormat(lldb::opaque_compiler_type_t type) {
case clang::Type::TemplateSpecialization:
case clang::Type::DeducedTemplateSpecialization:
- case clang::Type::Atomic:
case clang::Type::Adjusted:
case clang::Type::Pipe:
break;
@@ -5509,7 +4882,7 @@ GetDynamicArrayInfo(ClangASTContext &ast, SymbolFile *sym_file,
clang::QualType qual_type,
const ExecutionContext *exe_ctx) {
if (qual_type->isIncompleteArrayType())
- if (auto *metadata = ast.GetMetadata(qual_type.getAsOpaquePtr()))
+ if (auto *metadata = ast.GetMetadata(qual_type.getTypePtr()))
return sym_file->GetDynamicArrayInfoForUID(metadata->GetUserID(),
exe_ctx);
return llvm::None;
@@ -5522,7 +4895,7 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
return 0;
uint32_t num_children = 0;
- clang::QualType qual_type(GetQualType(type));
+ clang::QualType qual_type(RemoveWrappingTypes(GetQualType(type)));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
case clang::Type::Builtin:
@@ -5540,7 +4913,7 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
case clang::Type::Complex:
return 0;
case clang::Type::Record:
- if (GetCompleteQualType(getASTContext(), qual_type)) {
+ if (GetCompleteQualType(&getASTContext(), qual_type)) {
const clang::RecordType *record_type =
llvm::cast<clang::RecordType>(qual_type.getTypePtr());
const clang::RecordDecl *record_decl = record_type->getDecl();
@@ -5584,7 +4957,7 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
case clang::Type::ObjCObject:
case clang::Type::ObjCInterface:
- if (GetCompleteQualType(getASTContext(), qual_type)) {
+ if (GetCompleteQualType(&getASTContext(), qual_type)) {
const clang::ObjCObjectType *objc_class_type =
llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
assert(objc_class_type);
@@ -5615,8 +4988,7 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr());
clang::QualType pointee_type = pointer_type->getPointeeType();
uint32_t num_pointee_children =
- CompilerType(this, pointee_type.getAsOpaquePtr())
- .GetNumChildren(omit_empty_base_classes, exe_ctx);
+ GetType(pointee_type).GetNumChildren(omit_empty_base_classes, exe_ctx);
// If this type points to a simple type, then it has 1 child
if (num_pointee_children == 0)
num_children = 1;
@@ -5649,8 +5021,7 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
llvm::cast<clang::PointerType>(qual_type.getTypePtr());
clang::QualType pointee_type(pointer_type->getPointeeType());
uint32_t num_pointee_children =
- CompilerType(this, pointee_type.getAsOpaquePtr())
- .GetNumChildren(omit_empty_base_classes, exe_ctx);
+ GetType(pointee_type).GetNumChildren(omit_empty_base_classes, exe_ctx);
if (num_pointee_children == 0) {
// We have a pointer to a pointee type that claims it has no children. We
// will want to look at
@@ -5665,8 +5036,7 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
clang::QualType pointee_type = reference_type->getPointeeType();
uint32_t num_pointee_children =
- CompilerType(this, pointee_type.getAsOpaquePtr())
- .GetNumChildren(omit_empty_base_classes, exe_ctx);
+ GetType(pointee_type).GetNumChildren(omit_empty_base_classes, exe_ctx);
// If this type points to a simple type, then it has 1 child
if (num_pointee_children == 0)
num_children = 1;
@@ -5674,36 +5044,6 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
num_children = num_pointee_children;
} break;
- case clang::Type::Typedef:
- num_children = CompilerType(this, llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr())
- .GetNumChildren(omit_empty_base_classes, exe_ctx);
- break;
-
- case clang::Type::Auto:
- num_children = CompilerType(this, llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr())
- .GetNumChildren(omit_empty_base_classes, exe_ctx);
- break;
-
- case clang::Type::Elaborated:
- num_children =
- CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr())
- .GetNumChildren(omit_empty_base_classes, exe_ctx);
- break;
-
- case clang::Type::Paren:
- num_children =
- CompilerType(
- this,
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr())
- .GetNumChildren(omit_empty_base_classes, exe_ctx);
- break;
default:
break;
}
@@ -5797,8 +5137,7 @@ void ClangASTContext::ForEachEnumerator(
if (enum_type) {
const clang::EnumDecl *enum_decl = enum_type->getDecl();
if (enum_decl) {
- CompilerType integer_type(this,
- enum_decl->getIntegerType().getAsOpaquePtr());
+ CompilerType integer_type = GetType(enum_decl->getIntegerType());
clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
for (enum_pos = enum_decl->enumerator_begin(),
@@ -5819,7 +5158,7 @@ uint32_t ClangASTContext::GetNumFields(lldb::opaque_compiler_type_t type) {
return 0;
uint32_t count = 0;
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
case clang::Type::Record:
@@ -5841,36 +5180,6 @@ uint32_t ClangASTContext::GetNumFields(lldb::opaque_compiler_type_t type) {
}
break;
- case clang::Type::Typedef:
- count = CompilerType(this, llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr())
- .GetNumFields();
- break;
-
- case clang::Type::Auto:
- count = CompilerType(this, llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr())
- .GetNumFields();
- break;
-
- case clang::Type::Elaborated:
- count = CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr())
- .GetNumFields();
- break;
-
- case clang::Type::Paren:
- count =
- CompilerType(
- this,
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr())
- .GetNumFields();
- break;
-
case clang::Type::ObjCObjectPointer: {
const clang::ObjCObjectPointerType *objc_class_type =
qual_type->getAs<clang::ObjCObjectPointerType>();
@@ -5969,7 +5278,7 @@ CompilerType ClangASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type,
if (!type)
return CompilerType();
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
case clang::Type::Record:
@@ -5991,7 +5300,7 @@ CompilerType ClangASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type,
// alignment (field_type_info.second) from the AST context.
if (bit_offset_ptr) {
const clang::ASTRecordLayout &record_layout =
- getASTContext()->getASTRecordLayout(record_decl);
+ getASTContext().getASTRecordLayout(record_decl);
*bit_offset_ptr = record_layout.getFieldOffset(field_idx);
}
@@ -6005,7 +5314,7 @@ CompilerType ClangASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type,
clang::Expr::EvalResult result;
if (bitfield_bit_size_expr &&
bitfield_bit_size_expr->EvaluateAsInt(result,
- *getASTContext())) {
+ getASTContext())) {
llvm::APSInt bitfield_apsint = result.Val.getInt();
*bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue();
}
@@ -6014,7 +5323,7 @@ CompilerType ClangASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type,
if (is_bitfield_ptr)
*is_bitfield_ptr = is_bitfield;
- return CompilerType(this, field->getType().getAsOpaquePtr());
+ return GetType(field->getType());
}
}
}
@@ -6032,7 +5341,7 @@ CompilerType ClangASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type,
objc_interface_type->getDecl();
if (class_interface_decl) {
return CompilerType(
- this, GetObjCFieldAtIndex(getASTContext(), class_interface_decl,
+ this, GetObjCFieldAtIndex(&getASTContext(), class_interface_decl,
idx, name, bit_offset_ptr,
bitfield_bit_size_ptr, is_bitfield_ptr));
}
@@ -6050,42 +5359,13 @@ CompilerType ClangASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type,
clang::ObjCInterfaceDecl *class_interface_decl =
objc_class_type->getInterface();
return CompilerType(
- this, GetObjCFieldAtIndex(getASTContext(), class_interface_decl,
+ this, GetObjCFieldAtIndex(&getASTContext(), class_interface_decl,
idx, name, bit_offset_ptr,
bitfield_bit_size_ptr, is_bitfield_ptr));
}
}
break;
- case clang::Type::Typedef:
- return CompilerType(this, llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr())
- .GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr,
- is_bitfield_ptr);
-
- case clang::Type::Auto:
- return CompilerType(this, llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr())
- .GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr,
- is_bitfield_ptr);
-
- case clang::Type::Elaborated:
- return CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr())
- .GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr,
- is_bitfield_ptr);
-
- case clang::Type::Paren:
- return CompilerType(this, llvm::cast<clang::ParenType>(qual_type)
- ->desugar()
- .getAsOpaquePtr())
- .GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr,
- is_bitfield_ptr);
-
default:
break;
}
@@ -6095,7 +5375,7 @@ CompilerType ClangASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type,
uint32_t
ClangASTContext::GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) {
uint32_t count = 0;
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
case clang::Type::Record:
@@ -6138,29 +5418,6 @@ ClangASTContext::GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) {
}
break;
- case clang::Type::Typedef:
- count = GetNumDirectBaseClasses(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr());
- break;
-
- case clang::Type::Auto:
- count = GetNumDirectBaseClasses(llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr());
- break;
-
- case clang::Type::Elaborated:
- count = GetNumDirectBaseClasses(llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr());
- break;
-
- case clang::Type::Paren:
- return GetNumDirectBaseClasses(
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr());
-
default:
break;
}
@@ -6170,7 +5427,7 @@ ClangASTContext::GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) {
uint32_t
ClangASTContext::GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) {
uint32_t count = 0;
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
case clang::Type::Record:
@@ -6182,31 +5439,6 @@ ClangASTContext::GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) {
}
break;
- case clang::Type::Typedef:
- count = GetNumVirtualBaseClasses(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr());
- break;
-
- case clang::Type::Auto:
- count = GetNumVirtualBaseClasses(llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr());
- break;
-
- case clang::Type::Elaborated:
- count =
- GetNumVirtualBaseClasses(llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr());
- break;
-
- case clang::Type::Paren:
- count = GetNumVirtualBaseClasses(
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr());
- break;
-
default:
break;
}
@@ -6215,7 +5447,7 @@ ClangASTContext::GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) {
CompilerType ClangASTContext::GetDirectBaseClassAtIndex(
lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) {
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
case clang::Type::Record:
@@ -6232,7 +5464,7 @@ CompilerType ClangASTContext::GetDirectBaseClassAtIndex(
if (curr_idx == idx) {
if (bit_offset_ptr) {
const clang::ASTRecordLayout &record_layout =
- getASTContext()->getASTRecordLayout(cxx_record_decl);
+ getASTContext().getASTRecordLayout(cxx_record_decl);
const clang::CXXRecordDecl *base_class_decl =
llvm::cast<clang::CXXRecordDecl>(
base_class->getType()
@@ -6249,7 +5481,7 @@ CompilerType ClangASTContext::GetDirectBaseClassAtIndex(
.getQuantity() *
8;
}
- return CompilerType(this, base_class->getType().getAsOpaquePtr());
+ return GetType(base_class->getType());
}
}
}
@@ -6273,9 +5505,8 @@ CompilerType ClangASTContext::GetDirectBaseClassAtIndex(
if (superclass_interface_decl) {
if (bit_offset_ptr)
*bit_offset_ptr = 0;
- return CompilerType(this,
- getASTContext()->getObjCInterfaceType(
- superclass_interface_decl).getAsOpaquePtr());
+ return GetType(getASTContext().getObjCInterfaceType(
+ superclass_interface_decl));
}
}
}
@@ -6295,41 +5526,14 @@ CompilerType ClangASTContext::GetDirectBaseClassAtIndex(
if (superclass_interface_decl) {
if (bit_offset_ptr)
*bit_offset_ptr = 0;
- return CompilerType(
- this, getASTContext()
- ->getObjCInterfaceType(superclass_interface_decl)
- .getAsOpaquePtr());
+ return GetType(getASTContext().getObjCInterfaceType(
+ superclass_interface_decl));
}
}
}
}
break;
- case clang::Type::Typedef:
- return GetDirectBaseClassAtIndex(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr(),
- idx, bit_offset_ptr);
-
- case clang::Type::Auto:
- return GetDirectBaseClassAtIndex(llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr(),
- idx, bit_offset_ptr);
-
- case clang::Type::Elaborated:
- return GetDirectBaseClassAtIndex(
- llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr(),
- idx, bit_offset_ptr);
-
- case clang::Type::Paren:
- return GetDirectBaseClassAtIndex(
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(),
- idx, bit_offset_ptr);
-
default:
break;
}
@@ -6338,7 +5542,7 @@ CompilerType ClangASTContext::GetDirectBaseClassAtIndex(
CompilerType ClangASTContext::GetVirtualBaseClassAtIndex(
lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) {
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
case clang::Type::Record:
@@ -6355,7 +5559,7 @@ CompilerType ClangASTContext::GetVirtualBaseClassAtIndex(
if (curr_idx == idx) {
if (bit_offset_ptr) {
const clang::ASTRecordLayout &record_layout =
- getASTContext()->getASTRecordLayout(cxx_record_decl);
+ getASTContext().getASTRecordLayout(cxx_record_decl);
const clang::CXXRecordDecl *base_class_decl =
llvm::cast<clang::CXXRecordDecl>(
base_class->getType()
@@ -6366,38 +5570,13 @@ CompilerType ClangASTContext::GetVirtualBaseClassAtIndex(
.getQuantity() *
8;
}
- return CompilerType(this, base_class->getType().getAsOpaquePtr());
+ return GetType(base_class->getType());
}
}
}
}
break;
- case clang::Type::Typedef:
- return GetVirtualBaseClassAtIndex(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr(),
- idx, bit_offset_ptr);
-
- case clang::Type::Auto:
- return GetVirtualBaseClassAtIndex(llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr(),
- idx, bit_offset_ptr);
-
- case clang::Type::Elaborated:
- return GetVirtualBaseClassAtIndex(
- llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr(),
- idx, bit_offset_ptr);
-
- case clang::Type::Paren:
- return GetVirtualBaseClassAtIndex(
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(),
- idx, bit_offset_ptr);
-
default:
break;
}
@@ -6413,7 +5592,7 @@ uint32_t ClangASTContext::GetNumPointeeChildren(clang::QualType type) {
if (type.isNull())
return 0;
- clang::QualType qual_type(type.getCanonicalType());
+ clang::QualType qual_type = RemoveWrappingTypes(type.getCanonicalType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
case clang::Type::Builtin:
@@ -6514,29 +5693,6 @@ uint32_t ClangASTContext::GetNumPointeeChildren(clang::QualType type) {
return 0; // When we function pointers, they have no children...
case clang::Type::UnresolvedUsing:
return 0;
- case clang::Type::Paren:
- return GetNumPointeeChildren(
- llvm::cast<clang::ParenType>(qual_type)->desugar());
- case clang::Type::Typedef:
- return GetNumPointeeChildren(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType());
- case clang::Type::Auto:
- return GetNumPointeeChildren(
- llvm::cast<clang::AutoType>(qual_type)->getDeducedType());
- case clang::Type::Elaborated:
- return GetNumPointeeChildren(
- llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType());
- case clang::Type::TypeOfExpr:
- return GetNumPointeeChildren(llvm::cast<clang::TypeOfExprType>(qual_type)
- ->getUnderlyingExpr()
- ->getType());
- case clang::Type::TypeOf:
- return GetNumPointeeChildren(
- llvm::cast<clang::TypeOfType>(qual_type)->getUnderlyingType());
- case clang::Type::Decltype:
- return GetNumPointeeChildren(
- llvm::cast<clang::DecltypeType>(qual_type)->getUnderlyingType());
case clang::Type::Record:
return 0;
case clang::Type::Enum:
@@ -6580,7 +5736,8 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
return exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
};
- clang::QualType parent_qual_type(GetCanonicalQualType(type));
+ clang::QualType parent_qual_type(
+ RemoveWrappingTypes(GetCanonicalQualType(type)));
const clang::Type::TypeClass parent_type_class =
parent_qual_type->getTypeClass();
child_bitfield_bit_size = 0;
@@ -6599,10 +5756,9 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
case clang::BuiltinType::ObjCClass:
child_name = "isa";
child_byte_size =
- getASTContext()->getTypeSize(getASTContext()->ObjCBuiltinClassTy) /
+ getASTContext().getTypeSize(getASTContext().ObjCBuiltinClassTy) /
CHAR_BIT;
- return CompilerType(
- this, getASTContext()->ObjCBuiltinClassTy.getAsOpaquePtr());
+ return GetType(getASTContext().ObjCBuiltinClassTy);
default:
break;
@@ -6617,7 +5773,7 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
const clang::RecordDecl *record_decl = record_type->getDecl();
assert(record_decl);
const clang::ASTRecordLayout &record_layout =
- getASTContext()->getASTRecordLayout(record_decl);
+ getASTContext().getASTRecordLayout(record_decl);
uint32_t child_idx = 0;
const clang::CXXRecordDecl *cxx_record_decl =
@@ -6648,7 +5804,7 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
bool handled = false;
if (valobj) {
clang::VTableContextBase *vtable_ctx =
- getASTContext()->getVTableContext();
+ getASTContext().getVTableContext();
if (vtable_ctx)
handled = GetVBaseBitOffset(*vtable_ctx, *valobj,
record_layout, cxx_record_decl,
@@ -6665,8 +5821,7 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
// Base classes should be a multiple of 8 bits in size
child_byte_offset = bit_offset / 8;
- CompilerType base_class_clang_type(
- this, base_class->getType().getAsOpaquePtr());
+ CompilerType base_class_clang_type = GetType(base_class->getType());
child_name = base_class_clang_type.GetTypeName().AsCString("");
Optional<uint64_t> size =
base_class_clang_type.GetBitSize(get_exe_scope());
@@ -6698,8 +5853,7 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
// Figure out the type byte size (field_type_info.first) and
// alignment (field_type_info.second) from the AST context.
- CompilerType field_clang_type(this,
- field->getType().getAsOpaquePtr());
+ CompilerType field_clang_type = GetType(field->getType());
assert(field_idx < record_layout.getFieldCount());
Optional<uint64_t> size =
field_clang_type.GetByteSize(get_exe_scope());
@@ -6711,8 +5865,7 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
// Figure out the field offset within the current struct/union/class
// type
bit_offset = record_layout.getFieldOffset(field_idx);
- if (ClangASTContext::FieldIsBitfield(getASTContext(), *field,
- child_bitfield_bit_size)) {
+ if (FieldIsBitfield(*field, child_bitfield_bit_size)) {
child_bitfield_bit_offset = bit_offset % child_bit_size;
const uint32_t child_bit_offset =
bit_offset - child_bitfield_bit_offset;
@@ -6741,33 +5894,32 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
if (class_interface_decl) {
const clang::ASTRecordLayout &interface_layout =
- getASTContext()->getASTObjCInterfaceLayout(class_interface_decl);
+ getASTContext().getASTObjCInterfaceLayout(class_interface_decl);
clang::ObjCInterfaceDecl *superclass_interface_decl =
class_interface_decl->getSuperClass();
if (superclass_interface_decl) {
if (omit_empty_base_classes) {
- CompilerType base_class_clang_type(
- this, getASTContext()
- ->getObjCInterfaceType(superclass_interface_decl)
- .getAsOpaquePtr());
+ CompilerType base_class_clang_type =
+ GetType(getASTContext().getObjCInterfaceType(
+ superclass_interface_decl));
if (base_class_clang_type.GetNumChildren(omit_empty_base_classes,
exe_ctx) > 0) {
if (idx == 0) {
clang::QualType ivar_qual_type(
- getASTContext()->getObjCInterfaceType(
+ getASTContext().getObjCInterfaceType(
superclass_interface_decl));
child_name.assign(
superclass_interface_decl->getNameAsString());
clang::TypeInfo ivar_type_info =
- getASTContext()->getTypeInfo(ivar_qual_type.getTypePtr());
+ getASTContext().getTypeInfo(ivar_qual_type.getTypePtr());
child_byte_size = ivar_type_info.Width / 8;
child_byte_offset = 0;
child_is_base_class = true;
- return CompilerType(this, ivar_qual_type.getAsOpaquePtr());
+ return GetType(ivar_qual_type);
}
++child_idx;
@@ -6792,7 +5944,7 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
child_name.assign(ivar_decl->getNameAsString());
clang::TypeInfo ivar_type_info =
- getASTContext()->getTypeInfo(ivar_qual_type.getTypePtr());
+ getASTContext().getTypeInfo(ivar_qual_type.getTypePtr());
child_byte_size = ivar_type_info.Width / 8;
@@ -6811,8 +5963,7 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
ObjCLanguageRuntime *objc_runtime =
ObjCLanguageRuntime::Get(*process);
if (objc_runtime != nullptr) {
- CompilerType parent_ast_type(
- this, parent_qual_type.getAsOpaquePtr());
+ CompilerType parent_ast_type = GetType(parent_qual_type);
child_byte_offset = objc_runtime->GetByteOffsetForIvar(
parent_ast_type, ivar_decl->getNameAsString().c_str());
}
@@ -6835,15 +5986,14 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
// offset from, we still need to get the bit offset for
// bitfields from the layout.
- if (ClangASTContext::FieldIsBitfield(getASTContext(), ivar_decl,
- child_bitfield_bit_size)) {
+ if (FieldIsBitfield(ivar_decl, child_bitfield_bit_size)) {
if (bit_offset == INT32_MAX)
bit_offset = interface_layout.getFieldOffset(
child_idx - superclass_idx);
child_bitfield_bit_offset = bit_offset % 8;
}
- return CompilerType(this, ivar_qual_type.getAsOpaquePtr());
+ return GetType(ivar_qual_type);
}
++child_idx;
}
@@ -6894,8 +6044,7 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
const clang::VectorType *array =
llvm::cast<clang::VectorType>(parent_qual_type.getTypePtr());
if (array) {
- CompilerType element_type(this,
- array->getElementType().getAsOpaquePtr());
+ CompilerType element_type = GetType(array->getElementType());
if (element_type.GetCompleteType()) {
char element_name[64];
::snprintf(element_name, sizeof(element_name), "[%" PRIu64 "]",
@@ -6917,8 +6066,7 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
if (ignore_array_bounds || idx_is_valid) {
const clang::ArrayType *array = GetQualType(type)->getAsArrayTypeUnsafe();
if (array) {
- CompilerType element_type(this,
- array->getElementType().getAsOpaquePtr());
+ CompilerType element_type = GetType(array->getElementType());
if (element_type.GetCompleteType()) {
child_name = llvm::formatv("[{0}]", idx);
if (Optional<uint64_t> size =
@@ -6976,8 +6124,8 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
if (idx_is_valid) {
const clang::ReferenceType *reference_type =
llvm::cast<clang::ReferenceType>(parent_qual_type.getTypePtr());
- CompilerType pointee_clang_type(
- this, reference_type->getPointeeType().getAsOpaquePtr());
+ CompilerType pointee_clang_type =
+ GetType(reference_type->getPointeeType());
if (transparent_pointers && pointee_clang_type.IsAggregateType()) {
child_is_deref_of_parent = false;
bool tmp_child_is_deref_of_parent = false;
@@ -7008,55 +6156,6 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
}
break;
- case clang::Type::Typedef: {
- CompilerType typedefed_clang_type(
- this, llvm::cast<clang::TypedefType>(parent_qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr());
- return typedefed_clang_type.GetChildCompilerTypeAtIndex(
- exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
- ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
- child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
- child_is_deref_of_parent, valobj, language_flags);
- } break;
-
- case clang::Type::Auto: {
- CompilerType elaborated_clang_type(
- this, llvm::cast<clang::AutoType>(parent_qual_type)
- ->getDeducedType()
- .getAsOpaquePtr());
- return elaborated_clang_type.GetChildCompilerTypeAtIndex(
- exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
- ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
- child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
- child_is_deref_of_parent, valobj, language_flags);
- }
-
- case clang::Type::Elaborated: {
- CompilerType elaborated_clang_type(
- this, llvm::cast<clang::ElaboratedType>(parent_qual_type)
- ->getNamedType()
- .getAsOpaquePtr());
- return elaborated_clang_type.GetChildCompilerTypeAtIndex(
- exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
- ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
- child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
- child_is_deref_of_parent, valobj, language_flags);
- }
-
- case clang::Type::Paren: {
- CompilerType paren_clang_type(this,
- llvm::cast<clang::ParenType>(parent_qual_type)
- ->desugar()
- .getAsOpaquePtr());
- return paren_clang_type.GetChildCompilerTypeAtIndex(
- exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
- ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
- child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
- child_is_deref_of_parent, valobj, language_flags);
- }
-
default:
break;
}
@@ -7155,7 +6254,7 @@ size_t ClangASTContext::GetIndexOfChildMemberWithName(
lldb::opaque_compiler_type_t type, const char *name,
bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) {
if (type && name && name[0]) {
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
case clang::Type::Record:
@@ -7178,7 +6277,7 @@ size_t ClangASTContext::GetIndexOfChildMemberWithName(
field != field_end; ++field, ++child_idx) {
llvm::StringRef field_name = field->getName();
if (field_name.empty()) {
- CompilerType field_type(this, field->getType().getAsOpaquePtr());
+ CompilerType field_type = GetType(field->getType());
child_indexes.push_back(child_idx);
if (field_type.GetIndexOfChildMemberWithName(
name, omit_empty_base_classes, child_indexes))
@@ -7202,7 +6301,7 @@ size_t ClangASTContext::GetIndexOfChildMemberWithName(
// const Decl *root_cdecl = cxx_record_decl->getCanonicalDecl();
// Didn't find things easily, lets let clang do its thang...
clang::IdentifierInfo &ident_ref =
- getASTContext()->Idents.get(name_sref);
+ getASTContext().Idents.get(name_sref);
clang::DeclarationName decl_name(&ident_ref);
clang::CXXBasePaths paths;
@@ -7289,10 +6388,9 @@ size_t ClangASTContext::GetIndexOfChildMemberWithName(
// superclass...
child_indexes.push_back(0);
- CompilerType superclass_clang_type(
- this, getASTContext()
- ->getObjCInterfaceType(superclass_interface_decl)
- .getAsOpaquePtr());
+ CompilerType superclass_clang_type =
+ GetType(getASTContext().getObjCInterfaceType(
+ superclass_interface_decl));
if (superclass_clang_type.GetIndexOfChildMemberWithName(
name, omit_empty_base_classes, child_indexes)) {
// We did find an ivar in a superclass so just return the
@@ -7310,10 +6408,9 @@ size_t ClangASTContext::GetIndexOfChildMemberWithName(
break;
case clang::Type::ObjCObjectPointer: {
- CompilerType objc_object_clang_type(
- this, llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())
- ->getPointeeType()
- .getAsOpaquePtr());
+ CompilerType objc_object_clang_type = GetType(
+ llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())
+ ->getPointeeType());
return objc_object_clang_type.GetIndexOfChildMemberWithName(
name, omit_empty_base_classes, child_indexes);
} break;
@@ -7363,7 +6460,7 @@ size_t ClangASTContext::GetIndexOfChildMemberWithName(
const clang::ReferenceType *reference_type =
llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
clang::QualType pointee_type(reference_type->getPointeeType());
- CompilerType pointee_clang_type(this, pointee_type.getAsOpaquePtr());
+ CompilerType pointee_clang_type = GetType(pointee_type);
if (pointee_clang_type.IsAggregateType()) {
return pointee_clang_type.GetIndexOfChildMemberWithName(
@@ -7380,35 +6477,6 @@ size_t ClangASTContext::GetIndexOfChildMemberWithName(
}
} break;
- case clang::Type::Typedef:
- return CompilerType(this, llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr())
- .GetIndexOfChildMemberWithName(name, omit_empty_base_classes,
- child_indexes);
-
- case clang::Type::Auto:
- return CompilerType(this, llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr())
- .GetIndexOfChildMemberWithName(name, omit_empty_base_classes,
- child_indexes);
-
- case clang::Type::Elaborated:
- return CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr())
- .GetIndexOfChildMemberWithName(name, omit_empty_base_classes,
- child_indexes);
-
- case clang::Type::Paren:
- return CompilerType(this, llvm::cast<clang::ParenType>(qual_type)
- ->desugar()
- .getAsOpaquePtr())
- .GetIndexOfChildMemberWithName(name, omit_empty_base_classes,
- child_indexes);
-
default:
break;
}
@@ -7425,7 +6493,7 @@ ClangASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
const char *name,
bool omit_empty_base_classes) {
if (type && name && name[0]) {
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
@@ -7458,8 +6526,7 @@ ClangASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
!ClangASTContext::RecordHasFields(base_class_decl))
continue;
- CompilerType base_class_clang_type(
- this, base_class->getType().getAsOpaquePtr());
+ CompilerType base_class_clang_type = GetType(base_class->getType());
std::string base_class_type_name(
base_class_clang_type.GetTypeName().AsCString(""));
if (base_class_type_name == name)
@@ -7522,10 +6589,9 @@ ClangASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
break;
case clang::Type::ObjCObjectPointer: {
- CompilerType pointee_clang_type(
- this, llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())
- ->getPointeeType()
- .getAsOpaquePtr());
+ CompilerType pointee_clang_type = GetType(
+ llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())
+ ->getPointeeType());
return pointee_clang_type.GetIndexOfChildWithName(
name, omit_empty_base_classes);
} break;
@@ -7574,8 +6640,7 @@ ClangASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
case clang::Type::RValueReference: {
const clang::ReferenceType *reference_type =
llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
- CompilerType pointee_type(
- this, reference_type->getPointeeType().getAsOpaquePtr());
+ CompilerType pointee_type = GetType(reference_type->getPointeeType());
if (pointee_type.IsAggregateType()) {
return pointee_type.GetIndexOfChildWithName(name,
@@ -7586,8 +6651,7 @@ ClangASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
case clang::Type::Pointer: {
const clang::PointerType *pointer_type =
llvm::cast<clang::PointerType>(qual_type.getTypePtr());
- CompilerType pointee_type(
- this, pointer_type->getPointeeType().getAsOpaquePtr());
+ CompilerType pointee_type = GetType(pointer_type->getPointeeType());
if (pointee_type.IsAggregateType()) {
return pointee_type.GetIndexOfChildWithName(name,
@@ -7612,31 +6676,6 @@ ClangASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
}
} break;
- case clang::Type::Auto:
- return CompilerType(this, llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr())
- .GetIndexOfChildWithName(name, omit_empty_base_classes);
-
- case clang::Type::Elaborated:
- return CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr())
- .GetIndexOfChildWithName(name, omit_empty_base_classes);
-
- case clang::Type::Paren:
- return CompilerType(this, llvm::cast<clang::ParenType>(qual_type)
- ->desugar()
- .getAsOpaquePtr())
- .GetIndexOfChildWithName(name, omit_empty_base_classes);
-
- case clang::Type::Typedef:
- return CompilerType(this, llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr())
- .GetIndexOfChildWithName(name, omit_empty_base_classes);
-
default:
break;
}
@@ -7649,7 +6688,7 @@ ClangASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) {
if (!type)
return 0;
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
case clang::Type::Record:
@@ -7666,31 +6705,6 @@ ClangASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) {
}
break;
- case clang::Type::Typedef:
- return CompilerType(this, llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr())
- .GetNumTemplateArguments();
-
- case clang::Type::Auto:
- return CompilerType(this, llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr())
- .GetNumTemplateArguments();
-
- case clang::Type::Elaborated:
- return CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr())
- .GetNumTemplateArguments();
-
- case clang::Type::Paren:
- return CompilerType(this, llvm::cast<clang::ParenType>(qual_type)
- ->desugar()
- .getAsOpaquePtr())
- .GetNumTemplateArguments();
-
default:
break;
}
@@ -7704,7 +6718,7 @@ ClangASTContext::GetAsTemplateSpecialization(
if (!type)
return nullptr;
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
case clang::Type::Record: {
@@ -7718,27 +6732,6 @@ ClangASTContext::GetAsTemplateSpecialization(
cxx_record_decl);
}
- case clang::Type::Typedef:
- return GetAsTemplateSpecialization(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr());
-
- case clang::Type::Auto:
- return GetAsTemplateSpecialization(llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr());
-
- case clang::Type::Elaborated:
- return GetAsTemplateSpecialization(
- llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr());
-
- case clang::Type::Paren:
- return GetAsTemplateSpecialization(
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr());
-
default:
return nullptr;
}
@@ -7796,7 +6789,7 @@ ClangASTContext::GetTypeTemplateArgument(lldb::opaque_compiler_type_t type,
if (template_arg.getKind() != clang::TemplateArgument::Type)
return CompilerType();
- return CompilerType(this, template_arg.getAsType().getAsOpaquePtr());
+ return GetType(template_arg.getAsType());
}
Optional<CompilerType::IntegralTemplateArgument>
@@ -7813,8 +6806,7 @@ ClangASTContext::GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type,
return llvm::None;
return {
- {template_arg.getAsIntegral(),
- CompilerType(this, template_arg.getIntegralType().getAsOpaquePtr())}};
+ {template_arg.getAsIntegral(), GetType(template_arg.getIntegralType())}};
}
CompilerType ClangASTContext::GetTypeForFormatters(void *type) {
@@ -7877,26 +6869,26 @@ clang::FieldDecl *ClangASTContext::AddFieldToRecordType(
llvm::dyn_cast_or_null<ClangASTContext>(type.GetTypeSystem());
if (!ast)
return nullptr;
- clang::ASTContext *clang_ast = ast->getASTContext();
+ clang::ASTContext &clang_ast = ast->getASTContext();
clang::IdentifierInfo *ident = nullptr;
if (!name.empty())
- ident = &clang_ast->Idents.get(name);
+ ident = &clang_ast.Idents.get(name);
clang::FieldDecl *field = nullptr;
clang::Expr *bit_width = nullptr;
if (bitfield_bit_size != 0) {
- llvm::APInt bitfield_bit_size_apint(
- clang_ast->getTypeSize(clang_ast->IntTy), bitfield_bit_size);
- bit_width = new (*clang_ast)
- clang::IntegerLiteral(*clang_ast, bitfield_bit_size_apint,
- clang_ast->IntTy, clang::SourceLocation());
+ llvm::APInt bitfield_bit_size_apint(clang_ast.getTypeSize(clang_ast.IntTy),
+ bitfield_bit_size);
+ bit_width = new (clang_ast)
+ clang::IntegerLiteral(clang_ast, bitfield_bit_size_apint,
+ clang_ast.IntTy, clang::SourceLocation());
}
clang::RecordDecl *record_decl = ast->GetAsRecordDecl(type);
if (record_decl) {
field = clang::FieldDecl::Create(
- *clang_ast, record_decl, clang::SourceLocation(),
+ clang_ast, record_decl, clang::SourceLocation(),
clang::SourceLocation(),
ident, // Identifier
ClangUtil::GetQualType(field_clang_type), // Field type
@@ -7939,7 +6931,7 @@ clang::FieldDecl *ClangASTContext::AddFieldToRecordType(
field_clang_type.GetCompleteType();
field = clang::ObjCIvarDecl::Create(
- *clang_ast, class_interface_decl, clang::SourceLocation(),
+ clang_ast, class_interface_decl, clang::SourceLocation(),
clang::SourceLocation(),
ident, // Identifier
ClangUtil::GetQualType(field_clang_type), // Field type
@@ -8001,12 +6993,12 @@ void ClangASTContext::BuildIndirectFields(const CompilerType &type) {
if (clang::FieldDecl *nested_field_decl =
llvm::dyn_cast<clang::FieldDecl>(*di)) {
clang::NamedDecl **chain =
- new (*ast->getASTContext()) clang::NamedDecl *[2];
+ new (ast->getASTContext()) clang::NamedDecl *[2];
chain[0] = *field_pos;
chain[1] = nested_field_decl;
clang::IndirectFieldDecl *indirect_field =
clang::IndirectFieldDecl::Create(
- *ast->getASTContext(), record_decl, clang::SourceLocation(),
+ ast->getASTContext(), record_decl, clang::SourceLocation(),
nested_field_decl->getIdentifier(),
nested_field_decl->getType(), {chain, 2});
@@ -8020,7 +7012,7 @@ void ClangASTContext::BuildIndirectFields(const CompilerType &type) {
llvm::dyn_cast<clang::IndirectFieldDecl>(*di)) {
size_t nested_chain_size =
nested_indirect_field_decl->getChainingSize();
- clang::NamedDecl **chain = new (*ast->getASTContext())
+ clang::NamedDecl **chain = new (ast->getASTContext())
clang::NamedDecl *[nested_chain_size + 1];
chain[0] = *field_pos;
@@ -8035,7 +7027,7 @@ void ClangASTContext::BuildIndirectFields(const CompilerType &type) {
clang::IndirectFieldDecl *indirect_field =
clang::IndirectFieldDecl::Create(
- *ast->getASTContext(), record_decl, clang::SourceLocation(),
+ ast->getASTContext(), record_decl, clang::SourceLocation(),
nested_indirect_field_decl->getIdentifier(),
nested_indirect_field_decl->getType(),
{chain, nested_chain_size + 1});
@@ -8076,7 +7068,7 @@ void ClangASTContext::SetIsPacked(const CompilerType &type) {
return;
record_decl->addAttr(
- clang::PackedAttr::CreateImplicit(*ast->getASTContext()));
+ clang::PackedAttr::CreateImplicit(ast->getASTContext()));
}
}
}
@@ -8098,10 +7090,10 @@ clang::VarDecl *ClangASTContext::AddVariableToRecordType(
clang::VarDecl *var_decl = nullptr;
clang::IdentifierInfo *ident = nullptr;
if (!name.empty())
- ident = &ast->getASTContext()->Idents.get(name);
+ ident = &ast->getASTContext().Idents.get(name);
var_decl = clang::VarDecl::Create(
- *ast->getASTContext(), // ASTContext &
+ ast->getASTContext(), // ASTContext &
record_decl, // DeclContext *
clang::SourceLocation(), // clang::SourceLocation StartLoc
clang::SourceLocation(), // clang::SourceLocation IdLoc
@@ -8124,12 +7116,11 @@ clang::VarDecl *ClangASTContext::AddVariableToRecordType(
}
clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType(
- lldb::opaque_compiler_type_t type, const char *name, const char *mangled_name,
- const CompilerType &method_clang_type, lldb::AccessType access,
- bool is_virtual, bool is_static, bool is_inline, bool is_explicit,
- bool is_attr_used, bool is_artificial) {
- if (!type || !method_clang_type.IsValid() || name == nullptr ||
- name[0] == '\0')
+ lldb::opaque_compiler_type_t type, llvm::StringRef name,
+ const char *mangled_name, const CompilerType &method_clang_type,
+ lldb::AccessType access, bool is_virtual, bool is_static, bool is_inline,
+ bool is_explicit, bool is_attr_used, bool is_artificial) {
+ if (!type || !method_clang_type.IsValid() || name.empty())
return nullptr;
clang::QualType record_qual_type(GetCanonicalQualType(type));
@@ -8144,7 +7135,7 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType(
clang::CXXMethodDecl *cxx_method_decl = nullptr;
- clang::DeclarationName decl_name(&getASTContext()->Idents.get(name));
+ clang::DeclarationName decl_name(&getASTContext().Idents.get(name));
const clang::FunctionType *function_type =
llvm::dyn_cast<clang::FunctionType>(method_qual_type.getTypePtr());
@@ -8170,22 +7161,22 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType(
nullptr /*expr*/, is_explicit
? clang::ExplicitSpecKind::ResolvedTrue
: clang::ExplicitSpecKind::ResolvedFalse);
- if (name[0] == '~') {
+ if (name.startswith("~")) {
cxx_dtor_decl = clang::CXXDestructorDecl::Create(
- *getASTContext(), cxx_record_decl, clang::SourceLocation(),
+ getASTContext(), cxx_record_decl, clang::SourceLocation(),
clang::DeclarationNameInfo(
- getASTContext()->DeclarationNames.getCXXDestructorName(
- getASTContext()->getCanonicalType(record_qual_type)),
+ getASTContext().DeclarationNames.getCXXDestructorName(
+ getASTContext().getCanonicalType(record_qual_type)),
clang::SourceLocation()),
method_qual_type, nullptr, is_inline, is_artificial,
- ConstexprSpecKind::CSK_unspecified);
+ ConstexprSpecKind::CSK_unspecified);
cxx_method_decl = cxx_dtor_decl;
} else if (decl_name == cxx_record_decl->getDeclName()) {
cxx_ctor_decl = clang::CXXConstructorDecl::Create(
- *getASTContext(), cxx_record_decl, clang::SourceLocation(),
+ getASTContext(), cxx_record_decl, clang::SourceLocation(),
clang::DeclarationNameInfo(
- getASTContext()->DeclarationNames.getCXXConstructorName(
- getASTContext()->getCanonicalType(record_qual_type)),
+ getASTContext().DeclarationNames.getCXXConstructorName(
+ getASTContext().getCanonicalType(record_qual_type)),
clang::SourceLocation()),
method_qual_type,
nullptr, // TypeSourceInfo *
@@ -8206,9 +7197,9 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType(
is_method, op_kind, num_params))
return nullptr;
cxx_method_decl = clang::CXXMethodDecl::Create(
- *getASTContext(), cxx_record_decl, clang::SourceLocation(),
+ getASTContext(), cxx_record_decl, clang::SourceLocation(),
clang::DeclarationNameInfo(
- getASTContext()->DeclarationNames.getCXXOperatorName(op_kind),
+ getASTContext().DeclarationNames.getCXXOperatorName(op_kind),
clang::SourceLocation()),
method_qual_type,
nullptr, // TypeSourceInfo *
@@ -8216,22 +7207,21 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType(
} else if (num_params == 0) {
// Conversion operators don't take params...
cxx_method_decl = clang::CXXConversionDecl::Create(
- *getASTContext(), cxx_record_decl, clang::SourceLocation(),
+ getASTContext(), cxx_record_decl, clang::SourceLocation(),
clang::DeclarationNameInfo(
- getASTContext()->DeclarationNames.getCXXConversionFunctionName(
- getASTContext()->getCanonicalType(
+ getASTContext().DeclarationNames.getCXXConversionFunctionName(
+ getASTContext().getCanonicalType(
function_type->getReturnType())),
clang::SourceLocation()),
method_qual_type,
nullptr, // TypeSourceInfo *
- is_inline, explicit_spec, CSK_unspecified,
- clang::SourceLocation());
+ is_inline, explicit_spec, CSK_unspecified, clang::SourceLocation());
}
}
if (cxx_method_decl == nullptr) {
cxx_method_decl = clang::CXXMethodDecl::Create(
- *getASTContext(), cxx_record_decl, clang::SourceLocation(),
+ getASTContext(), cxx_record_decl, clang::SourceLocation(),
clang::DeclarationNameInfo(decl_name, clang::SourceLocation()),
method_qual_type,
nullptr, // TypeSourceInfo *
@@ -8246,11 +7236,11 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType(
cxx_method_decl->setVirtualAsWritten(is_virtual);
if (is_attr_used)
- cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(*getASTContext()));
+ cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(getASTContext()));
if (mangled_name != nullptr) {
cxx_method_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(
- *getASTContext(), mangled_name, /*literal=*/false));
+ getASTContext(), mangled_name, /*literal=*/false));
}
// Populate the method decl with parameter decls
@@ -8259,7 +7249,7 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType(
for (unsigned param_index = 0; param_index < num_params; ++param_index) {
params.push_back(clang::ParmVarDecl::Create(
- *getASTContext(), cxx_method_decl, clang::SourceLocation(),
+ getASTContext(), cxx_method_decl, clang::SourceLocation(),
clang::SourceLocation(),
nullptr, // anonymous
method_function_prototype->getParamType(param_index), nullptr,
@@ -8326,7 +7316,7 @@ ClangASTContext::CreateBaseClassSpecifier(lldb::opaque_compiler_type_t type,
return std::make_unique<clang::CXXBaseSpecifier>(
clang::SourceRange(), is_virtual, base_of_class,
ClangASTContext::ConvertAccessTypeToAccessSpecifier(access),
- getASTContext()->getTrivialTypeSourceInfo(GetQualType(type)),
+ getASTContext().getTrivialTypeSourceInfo(GetQualType(type)),
clang::SourceLocation());
}
@@ -8355,7 +7345,7 @@ bool ClangASTContext::SetObjCSuperClass(
llvm::dyn_cast_or_null<ClangASTContext>(type.GetTypeSystem());
if (!ast)
return false;
- clang::ASTContext *clang_ast = ast->getASTContext();
+ clang::ASTContext &clang_ast = ast->getASTContext();
if (type && superclass_clang_type.IsValid() &&
superclass_clang_type.GetTypeSystem() == type.GetTypeSystem()) {
@@ -8364,8 +7354,8 @@ bool ClangASTContext::SetObjCSuperClass(
clang::ObjCInterfaceDecl *super_interface_decl =
GetAsObjCInterfaceDecl(superclass_clang_type);
if (class_interface_decl && super_interface_decl) {
- class_interface_decl->setSuperClass(clang_ast->getTrivialTypeSourceInfo(
- clang_ast->getObjCInterfaceType(super_interface_decl)));
+ class_interface_decl->setSuperClass(clang_ast.getTrivialTypeSourceInfo(
+ clang_ast.getObjCInterfaceType(super_interface_decl)));
return true;
}
}
@@ -8383,188 +7373,182 @@ bool ClangASTContext::AddObjCClassProperty(
ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
if (!ast)
return false;
- clang::ASTContext *clang_ast = ast->getASTContext();
+ clang::ASTContext &clang_ast = ast->getASTContext();
clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl(type);
+ if (!class_interface_decl)
+ return false;
- if (class_interface_decl) {
- CompilerType property_clang_type_to_access;
-
- if (property_clang_type.IsValid())
- property_clang_type_to_access = property_clang_type;
- else if (ivar_decl)
- property_clang_type_to_access =
- CompilerType(ast, ivar_decl->getType().getAsOpaquePtr());
-
- if (class_interface_decl && property_clang_type_to_access.IsValid()) {
- clang::TypeSourceInfo *prop_type_source;
- if (ivar_decl)
- prop_type_source =
- clang_ast->getTrivialTypeSourceInfo(ivar_decl->getType());
- else
- prop_type_source = clang_ast->getTrivialTypeSourceInfo(
- ClangUtil::GetQualType(property_clang_type));
-
- clang::ObjCPropertyDecl *property_decl = clang::ObjCPropertyDecl::Create(
- *clang_ast, class_interface_decl,
- clang::SourceLocation(), // Source Location
- &clang_ast->Idents.get(property_name),
- clang::SourceLocation(), // Source Location for AT
- clang::SourceLocation(), // Source location for (
- ivar_decl ? ivar_decl->getType()
- : ClangUtil::GetQualType(property_clang_type),
- prop_type_source);
-
- if (property_decl) {
- if (metadata)
- ClangASTContext::SetMetadata(clang_ast, property_decl, *metadata);
-
- class_interface_decl->addDecl(property_decl);
-
- clang::Selector setter_sel, getter_sel;
-
- if (property_setter_name != nullptr) {
- std::string property_setter_no_colon(
- property_setter_name, strlen(property_setter_name) - 1);
- clang::IdentifierInfo *setter_ident =
- &clang_ast->Idents.get(property_setter_no_colon);
- setter_sel = clang_ast->Selectors.getSelector(1, &setter_ident);
- } else if (!(property_attributes & DW_APPLE_PROPERTY_readonly)) {
- std::string setter_sel_string("set");
- setter_sel_string.push_back(::toupper(property_name[0]));
- setter_sel_string.append(&property_name[1]);
- clang::IdentifierInfo *setter_ident =
- &clang_ast->Idents.get(setter_sel_string);
- setter_sel = clang_ast->Selectors.getSelector(1, &setter_ident);
- }
- property_decl->setSetterName(setter_sel);
- property_decl->setPropertyAttributes(
- clang::ObjCPropertyDecl::OBJC_PR_setter);
-
- if (property_getter_name != nullptr) {
- clang::IdentifierInfo *getter_ident =
- &clang_ast->Idents.get(property_getter_name);
- getter_sel = clang_ast->Selectors.getSelector(0, &getter_ident);
- } else {
- clang::IdentifierInfo *getter_ident =
- &clang_ast->Idents.get(property_name);
- getter_sel = clang_ast->Selectors.getSelector(0, &getter_ident);
- }
- property_decl->setGetterName(getter_sel);
- property_decl->setPropertyAttributes(
- clang::ObjCPropertyDecl::OBJC_PR_getter);
-
- if (ivar_decl)
- property_decl->setPropertyIvarDecl(ivar_decl);
-
- if (property_attributes & DW_APPLE_PROPERTY_readonly)
- property_decl->setPropertyAttributes(
- clang::ObjCPropertyDecl::OBJC_PR_readonly);
- if (property_attributes & DW_APPLE_PROPERTY_readwrite)
- property_decl->setPropertyAttributes(
- clang::ObjCPropertyDecl::OBJC_PR_readwrite);
- if (property_attributes & DW_APPLE_PROPERTY_assign)
- property_decl->setPropertyAttributes(
- clang::ObjCPropertyDecl::OBJC_PR_assign);
- if (property_attributes & DW_APPLE_PROPERTY_retain)
- property_decl->setPropertyAttributes(
- clang::ObjCPropertyDecl::OBJC_PR_retain);
- if (property_attributes & DW_APPLE_PROPERTY_copy)
- property_decl->setPropertyAttributes(
- clang::ObjCPropertyDecl::OBJC_PR_copy);
- if (property_attributes & DW_APPLE_PROPERTY_nonatomic)
- property_decl->setPropertyAttributes(
- clang::ObjCPropertyDecl::OBJC_PR_nonatomic);
- if (property_attributes & clang::ObjCPropertyDecl::OBJC_PR_nullability)
- property_decl->setPropertyAttributes(
- clang::ObjCPropertyDecl::OBJC_PR_nullability);
- if (property_attributes &
- clang::ObjCPropertyDecl::OBJC_PR_null_resettable)
- property_decl->setPropertyAttributes(
- clang::ObjCPropertyDecl::OBJC_PR_null_resettable);
- if (property_attributes & clang::ObjCPropertyDecl::OBJC_PR_class)
- property_decl->setPropertyAttributes(
- clang::ObjCPropertyDecl::OBJC_PR_class);
-
- const bool isInstance =
- (property_attributes & clang::ObjCPropertyDecl::OBJC_PR_class) == 0;
-
- if (!getter_sel.isNull() &&
- !(isInstance
- ? class_interface_decl->lookupInstanceMethod(getter_sel)
- : class_interface_decl->lookupClassMethod(getter_sel))) {
- const bool isVariadic = false;
- const bool isSynthesized = false;
- const bool isImplicitlyDeclared = true;
- const bool isDefined = false;
- const clang::ObjCMethodDecl::ImplementationControl impControl =
- clang::ObjCMethodDecl::None;
- const bool HasRelatedResultType = false;
-
- clang::ObjCMethodDecl *getter = clang::ObjCMethodDecl::Create(
- *clang_ast, clang::SourceLocation(), clang::SourceLocation(),
- getter_sel, ClangUtil::GetQualType(property_clang_type_to_access),
- nullptr, class_interface_decl, isInstance, isVariadic,
- isSynthesized, isImplicitlyDeclared, isDefined, impControl,
- HasRelatedResultType);
-
- if (getter && metadata)
- ClangASTContext::SetMetadata(clang_ast, getter, *metadata);
-
- if (getter) {
- getter->setMethodParams(*clang_ast,
- llvm::ArrayRef<clang::ParmVarDecl *>(),
- llvm::ArrayRef<clang::SourceLocation>());
-
- class_interface_decl->addDecl(getter);
- }
- }
+ CompilerType property_clang_type_to_access;
- if (!setter_sel.isNull() &&
- !(isInstance
- ? class_interface_decl->lookupInstanceMethod(setter_sel)
- : class_interface_decl->lookupClassMethod(setter_sel))) {
- clang::QualType result_type = clang_ast->VoidTy;
- const bool isVariadic = false;
- const bool isSynthesized = false;
- const bool isImplicitlyDeclared = true;
- const bool isDefined = false;
- const clang::ObjCMethodDecl::ImplementationControl impControl =
- clang::ObjCMethodDecl::None;
- const bool HasRelatedResultType = false;
-
- clang::ObjCMethodDecl *setter = clang::ObjCMethodDecl::Create(
- *clang_ast, clang::SourceLocation(), clang::SourceLocation(),
- setter_sel, result_type, nullptr, class_interface_decl,
- isInstance, isVariadic, isSynthesized, isImplicitlyDeclared,
- isDefined, impControl, HasRelatedResultType);
-
- if (setter && metadata)
- ClangASTContext::SetMetadata(clang_ast, setter, *metadata);
-
- llvm::SmallVector<clang::ParmVarDecl *, 1> params;
-
- params.push_back(clang::ParmVarDecl::Create(
- *clang_ast, setter, clang::SourceLocation(),
- clang::SourceLocation(),
- nullptr, // anonymous
- ClangUtil::GetQualType(property_clang_type_to_access), nullptr,
- clang::SC_Auto, nullptr));
-
- if (setter) {
- setter->setMethodParams(
- *clang_ast, llvm::ArrayRef<clang::ParmVarDecl *>(params),
- llvm::ArrayRef<clang::SourceLocation>());
-
- class_interface_decl->addDecl(setter);
- }
- }
+ if (property_clang_type.IsValid())
+ property_clang_type_to_access = property_clang_type;
+ else if (ivar_decl)
+ property_clang_type_to_access = ast->GetType(ivar_decl->getType());
- return true;
- }
+ if (!class_interface_decl || !property_clang_type_to_access.IsValid())
+ return false;
+
+ clang::TypeSourceInfo *prop_type_source;
+ if (ivar_decl)
+ prop_type_source = clang_ast.getTrivialTypeSourceInfo(ivar_decl->getType());
+ else
+ prop_type_source = clang_ast.getTrivialTypeSourceInfo(
+ ClangUtil::GetQualType(property_clang_type));
+
+ clang::ObjCPropertyDecl *property_decl = clang::ObjCPropertyDecl::Create(
+ clang_ast, class_interface_decl,
+ clang::SourceLocation(), // Source Location
+ &clang_ast.Idents.get(property_name),
+ clang::SourceLocation(), // Source Location for AT
+ clang::SourceLocation(), // Source location for (
+ ivar_decl ? ivar_decl->getType()
+ : ClangUtil::GetQualType(property_clang_type),
+ prop_type_source);
+
+ if (!property_decl)
+ return false;
+
+ if (metadata)
+ ast->SetMetadata(property_decl, *metadata);
+
+ class_interface_decl->addDecl(property_decl);
+
+ clang::Selector setter_sel, getter_sel;
+
+ if (property_setter_name) {
+ std::string property_setter_no_colon(property_setter_name,
+ strlen(property_setter_name) - 1);
+ clang::IdentifierInfo *setter_ident =
+ &clang_ast.Idents.get(property_setter_no_colon);
+ setter_sel = clang_ast.Selectors.getSelector(1, &setter_ident);
+ } else if (!(property_attributes & DW_APPLE_PROPERTY_readonly)) {
+ std::string setter_sel_string("set");
+ setter_sel_string.push_back(::toupper(property_name[0]));
+ setter_sel_string.append(&property_name[1]);
+ clang::IdentifierInfo *setter_ident =
+ &clang_ast.Idents.get(setter_sel_string);
+ setter_sel = clang_ast.Selectors.getSelector(1, &setter_ident);
+ }
+ property_decl->setSetterName(setter_sel);
+ property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter);
+
+ if (property_getter_name != nullptr) {
+ clang::IdentifierInfo *getter_ident =
+ &clang_ast.Idents.get(property_getter_name);
+ getter_sel = clang_ast.Selectors.getSelector(0, &getter_ident);
+ } else {
+ clang::IdentifierInfo *getter_ident = &clang_ast.Idents.get(property_name);
+ getter_sel = clang_ast.Selectors.getSelector(0, &getter_ident);
+ }
+ property_decl->setGetterName(getter_sel);
+ property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter);
+
+ if (ivar_decl)
+ property_decl->setPropertyIvarDecl(ivar_decl);
+
+ if (property_attributes & DW_APPLE_PROPERTY_readonly)
+ property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
+ if (property_attributes & DW_APPLE_PROPERTY_readwrite)
+ property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
+ if (property_attributes & DW_APPLE_PROPERTY_assign)
+ property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
+ if (property_attributes & DW_APPLE_PROPERTY_retain)
+ property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
+ if (property_attributes & DW_APPLE_PROPERTY_copy)
+ property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
+ if (property_attributes & DW_APPLE_PROPERTY_nonatomic)
+ property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
+ if (property_attributes & ObjCPropertyDecl::OBJC_PR_nullability)
+ property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nullability);
+ if (property_attributes & ObjCPropertyDecl::OBJC_PR_null_resettable)
+ property_decl->setPropertyAttributes(
+ ObjCPropertyDecl::OBJC_PR_null_resettable);
+ if (property_attributes & ObjCPropertyDecl::OBJC_PR_class)
+ property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_class);
+
+ const bool isInstance =
+ (property_attributes & ObjCPropertyDecl::OBJC_PR_class) == 0;
+
+ clang::ObjCMethodDecl *getter = nullptr;
+ if (!getter_sel.isNull())
+ getter = isInstance ? class_interface_decl->lookupInstanceMethod(getter_sel)
+ : class_interface_decl->lookupClassMethod(getter_sel);
+ if (!getter_sel.isNull() && !getter) {
+ const bool isVariadic = false;
+ const bool isPropertyAccessor = false;
+ const bool isSynthesizedAccessorStub = false;
+ const bool isImplicitlyDeclared = true;
+ const bool isDefined = false;
+ const clang::ObjCMethodDecl::ImplementationControl impControl =
+ clang::ObjCMethodDecl::None;
+ const bool HasRelatedResultType = false;
+
+ getter = clang::ObjCMethodDecl::Create(
+ clang_ast, clang::SourceLocation(), clang::SourceLocation(), getter_sel,
+ ClangUtil::GetQualType(property_clang_type_to_access), nullptr,
+ class_interface_decl, isInstance, isVariadic, isPropertyAccessor,
+ isSynthesizedAccessorStub, isImplicitlyDeclared, isDefined, impControl,
+ HasRelatedResultType);
+
+ if (getter) {
+ if (metadata)
+ ast->SetMetadata(getter, *metadata);
+
+ getter->setMethodParams(clang_ast, llvm::ArrayRef<clang::ParmVarDecl *>(),
+ llvm::ArrayRef<clang::SourceLocation>());
+ class_interface_decl->addDecl(getter);
+ }
+ }
+ if (getter) {
+ getter->setPropertyAccessor(true);
+ property_decl->setGetterMethodDecl(getter);
+ }
+
+ clang::ObjCMethodDecl *setter = nullptr;
+ setter = isInstance ? class_interface_decl->lookupInstanceMethod(setter_sel)
+ : class_interface_decl->lookupClassMethod(setter_sel);
+ if (!setter_sel.isNull() && !setter) {
+ clang::QualType result_type = clang_ast.VoidTy;
+ const bool isVariadic = false;
+ const bool isPropertyAccessor = true;
+ const bool isSynthesizedAccessorStub = false;
+ const bool isImplicitlyDeclared = true;
+ const bool isDefined = false;
+ const clang::ObjCMethodDecl::ImplementationControl impControl =
+ clang::ObjCMethodDecl::None;
+ const bool HasRelatedResultType = false;
+
+ setter = clang::ObjCMethodDecl::Create(
+ clang_ast, clang::SourceLocation(), clang::SourceLocation(), setter_sel,
+ result_type, nullptr, class_interface_decl, isInstance, isVariadic,
+ isPropertyAccessor, isSynthesizedAccessorStub, isImplicitlyDeclared,
+ isDefined, impControl, HasRelatedResultType);
+
+ if (setter) {
+ if (metadata)
+ ast->SetMetadata(setter, *metadata);
+
+ llvm::SmallVector<clang::ParmVarDecl *, 1> params;
+ params.push_back(clang::ParmVarDecl::Create(
+ clang_ast, setter, clang::SourceLocation(), clang::SourceLocation(),
+ nullptr, // anonymous
+ ClangUtil::GetQualType(property_clang_type_to_access), nullptr,
+ clang::SC_Auto, nullptr));
+
+ setter->setMethodParams(clang_ast,
+ llvm::ArrayRef<clang::ParmVarDecl *>(params),
+ llvm::ArrayRef<clang::SourceLocation>());
+
+ class_interface_decl->addDecl(setter);
}
}
- return false;
+ if (setter) {
+ setter->setPropertyAccessor(true);
+ property_decl->setSetterMethodDecl(setter);
+ }
+
+ return true;
}
bool ClangASTContext::IsObjCClassTypeAndHasIVars(const CompilerType &type,
@@ -8581,7 +7565,7 @@ clang::ObjCMethodDecl *ClangASTContext::AddMethodToObjCObjectType(
// (lldb::opaque_compiler_type_t type, "-[NString
// stringWithCString:]")
const CompilerType &method_clang_type, lldb::AccessType access,
- bool is_artificial, bool is_variadic) {
+ bool is_artificial, bool is_variadic, bool is_objc_direct_call) {
if (!type || !method_clang_type.IsValid())
return nullptr;
@@ -8593,7 +7577,7 @@ clang::ObjCMethodDecl *ClangASTContext::AddMethodToObjCObjectType(
llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
if (lldb_ast == nullptr)
return nullptr;
- clang::ASTContext *ast = lldb_ast->getASTContext();
+ clang::ASTContext &ast = lldb_ast->getASTContext();
const char *selector_start = ::strchr(name, ' ');
if (selector_start == nullptr)
@@ -8613,7 +7597,7 @@ clang::ObjCMethodDecl *ClangASTContext::AddMethodToObjCObjectType(
bool has_arg = (start[len] == ':');
if (has_arg)
++num_selectors_with_args;
- selector_idents.push_back(&ast->Idents.get(llvm::StringRef(start, len)));
+ selector_idents.push_back(&ast.Idents.get(llvm::StringRef(start, len)));
if (has_arg)
len += 1;
}
@@ -8621,7 +7605,7 @@ clang::ObjCMethodDecl *ClangASTContext::AddMethodToObjCObjectType(
if (selector_idents.size() == 0)
return nullptr;
- clang::Selector method_selector = ast->Selectors.getSelector(
+ clang::Selector method_selector = ast.Selectors.getSelector(
num_selectors_with_args ? selector_idents.size() : 0,
selector_idents.data());
@@ -8639,10 +7623,16 @@ clang::ObjCMethodDecl *ClangASTContext::AddMethodToObjCObjectType(
if (!method_function_prototype)
return nullptr;
- bool is_synthesized = false;
- bool is_defined = false;
- clang::ObjCMethodDecl::ImplementationControl imp_control =
+ const bool isInstance = (name[0] == '-');
+ const bool isVariadic = is_variadic;
+ const bool isPropertyAccessor = false;
+ const bool isSynthesizedAccessorStub = false;
+ /// Force this to true because we don't have source locations.
+ const bool isImplicitlyDeclared = true;
+ const bool isDefined = false;
+ const clang::ObjCMethodDecl::ImplementationControl impControl =
clang::ObjCMethodDecl::None;
+ const bool HasRelatedResultType = false;
const unsigned num_args = method_function_prototype->getNumParams();
@@ -8651,17 +7641,14 @@ clang::ObjCMethodDecl *ClangASTContext::AddMethodToObjCObjectType(
// deal with it.
clang::ObjCMethodDecl *objc_method_decl = clang::ObjCMethodDecl::Create(
- *ast,
+ ast,
clang::SourceLocation(), // beginLoc,
clang::SourceLocation(), // endLoc,
method_selector, method_function_prototype->getReturnType(),
nullptr, // TypeSourceInfo *ResultTInfo,
- ClangASTContext::GetASTContext(ast)->GetDeclContextForType(
- ClangUtil::GetQualType(type)),
- name[0] == '-', is_variadic, is_synthesized,
- true, // is_implicitly_declared; we force this to true because we don't
- // have source locations
- is_defined, imp_control, false /*has_related_result_type*/);
+ lldb_ast->GetDeclContextForType(ClangUtil::GetQualType(type)), isInstance,
+ isVariadic, isPropertyAccessor, isSynthesizedAccessorStub,
+ isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType);
if (objc_method_decl == nullptr)
return nullptr;
@@ -8671,7 +7658,7 @@ clang::ObjCMethodDecl *ClangASTContext::AddMethodToObjCObjectType(
for (unsigned param_index = 0; param_index < num_args; ++param_index) {
params.push_back(clang::ParmVarDecl::Create(
- *ast, objc_method_decl, clang::SourceLocation(),
+ ast, objc_method_decl, clang::SourceLocation(),
clang::SourceLocation(),
nullptr, // anonymous
method_function_prototype->getParamType(param_index), nullptr,
@@ -8679,10 +7666,22 @@ clang::ObjCMethodDecl *ClangASTContext::AddMethodToObjCObjectType(
}
objc_method_decl->setMethodParams(
- *ast, llvm::ArrayRef<clang::ParmVarDecl *>(params),
+ ast, llvm::ArrayRef<clang::ParmVarDecl *>(params),
llvm::ArrayRef<clang::SourceLocation>());
}
+ if (is_objc_direct_call) {
+ // Add a the objc_direct attribute to the declaration we generate that
+ // we generate a direct method call for this ObjCMethodDecl.
+ objc_method_decl->addAttr(
+ clang::ObjCDirectAttr::CreateImplicit(ast, SourceLocation()));
+ // Usually Sema is creating implicit parameters (e.g., self) when it
+ // parses the method. We don't have a parsing Sema when we build our own
+ // AST here so we manually need to create these implicit parameters to
+ // make the direct call code generation happy.
+ objc_method_decl->createImplicitParams(ast, class_interface_decl);
+ }
+
class_interface_decl->addDecl(objc_method_decl);
#ifdef LLDB_CONFIGURATION_DEBUG
@@ -8697,7 +7696,7 @@ bool ClangASTContext::SetHasExternalStorage(lldb::opaque_compiler_type_t type,
if (!type)
return false;
- clang::QualType qual_type(GetCanonicalQualType(type));
+ clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class) {
@@ -8737,30 +7736,6 @@ bool ClangASTContext::SetHasExternalStorage(lldb::opaque_compiler_type_t type,
}
} break;
- case clang::Type::Typedef:
- return SetHasExternalStorage(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr(),
- has_extern);
-
- case clang::Type::Auto:
- return SetHasExternalStorage(llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr(),
- has_extern);
-
- case clang::Type::Elaborated:
- return SetHasExternalStorage(llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr(),
- has_extern);
-
- case clang::Type::Paren:
- return SetHasExternalStorage(
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(),
- has_extern);
-
default:
break;
}
@@ -8797,70 +7772,65 @@ bool ClangASTContext::StartTagDeclarationDefinition(const CompilerType &type) {
bool ClangASTContext::CompleteTagDeclarationDefinition(
const CompilerType &type) {
clang::QualType qual_type(ClangUtil::GetQualType(type));
- if (!qual_type.isNull()) {
- // Make sure we use the same methodology as
- // ClangASTContext::StartTagDeclarationDefinition() as to how we start/end
- // the definition. Previously we were calling
- const clang::TagType *tag_type = qual_type->getAs<clang::TagType>();
- if (tag_type) {
- clang::TagDecl *tag_decl = tag_type->getDecl();
- if (tag_decl) {
- clang::CXXRecordDecl *cxx_record_decl =
- llvm::dyn_cast_or_null<clang::CXXRecordDecl>(tag_decl);
+ if (qual_type.isNull())
+ return false;
- if (cxx_record_decl) {
- if (!cxx_record_decl->isCompleteDefinition())
- cxx_record_decl->completeDefinition();
- cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true);
- cxx_record_decl->setHasExternalLexicalStorage(false);
- cxx_record_decl->setHasExternalVisibleStorage(false);
- return true;
- }
- }
+ // Make sure we use the same methodology as
+ // ClangASTContext::StartTagDeclarationDefinition() as to how we start/end
+ // the definition.
+ const clang::TagType *tag_type = qual_type->getAs<clang::TagType>();
+ if (tag_type) {
+ clang::TagDecl *tag_decl = tag_type->getDecl();
+
+ if (auto *cxx_record_decl = llvm::dyn_cast<CXXRecordDecl>(tag_decl)) {
+ if (!cxx_record_decl->isCompleteDefinition())
+ cxx_record_decl->completeDefinition();
+ cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true);
+ cxx_record_decl->setHasExternalLexicalStorage(false);
+ cxx_record_decl->setHasExternalVisibleStorage(false);
+ return true;
}
+ }
- const clang::EnumType *enutype = qual_type->getAs<clang::EnumType>();
+ const clang::EnumType *enutype = qual_type->getAs<clang::EnumType>();
- if (enutype) {
- clang::EnumDecl *enum_decl = enutype->getDecl();
+ if (!enutype)
+ return false;
+ clang::EnumDecl *enum_decl = enutype->getDecl();
- if (enum_decl) {
- if (!enum_decl->isCompleteDefinition()) {
- ClangASTContext *lldb_ast =
- llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
- if (lldb_ast == nullptr)
- return false;
- clang::ASTContext *ast = lldb_ast->getASTContext();
-
- /// TODO This really needs to be fixed.
-
- QualType integer_type(enum_decl->getIntegerType());
- if (!integer_type.isNull()) {
- unsigned NumPositiveBits = 1;
- unsigned NumNegativeBits = 0;
-
- clang::QualType promotion_qual_type;
- // If the enum integer type is less than an integer in bit width,
- // then we must promote it to an integer size.
- if (ast->getTypeSize(enum_decl->getIntegerType()) <
- ast->getTypeSize(ast->IntTy)) {
- if (enum_decl->getIntegerType()->isSignedIntegerType())
- promotion_qual_type = ast->IntTy;
- else
- promotion_qual_type = ast->UnsignedIntTy;
- } else
- promotion_qual_type = enum_decl->getIntegerType();
+ if (enum_decl->isCompleteDefinition())
+ return true;
- enum_decl->completeDefinition(enum_decl->getIntegerType(),
- promotion_qual_type, NumPositiveBits,
- NumNegativeBits);
- }
- }
- return true;
- }
- }
+ ClangASTContext *lldb_ast =
+ llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
+ if (lldb_ast == nullptr)
+ return false;
+ clang::ASTContext &ast = lldb_ast->getASTContext();
+
+ /// TODO This really needs to be fixed.
+
+ QualType integer_type(enum_decl->getIntegerType());
+ if (!integer_type.isNull()) {
+ unsigned NumPositiveBits = 1;
+ unsigned NumNegativeBits = 0;
+
+ clang::QualType promotion_qual_type;
+ // If the enum integer type is less than an integer in bit width,
+ // then we must promote it to an integer size.
+ if (ast.getTypeSize(enum_decl->getIntegerType()) <
+ ast.getTypeSize(ast.IntTy)) {
+ if (enum_decl->getIntegerType()->isSignedIntegerType())
+ promotion_qual_type = ast.IntTy;
+ else
+ promotion_qual_type = ast.UnsignedIntTy;
+ } else
+ promotion_qual_type = enum_decl->getIntegerType();
+
+ enum_decl->completeDefinition(enum_decl->getIntegerType(),
+ promotion_qual_type, NumPositiveBits,
+ NumNegativeBits);
}
- return false;
+ return true;
}
clang::EnumConstantDecl *ClangASTContext::AddEnumerationValueToEnumerationType(
@@ -8892,8 +7862,8 @@ clang::EnumConstantDecl *ClangASTContext::AddEnumerationValueToEnumerationType(
return nullptr;
clang::EnumConstantDecl *enumerator_decl = clang::EnumConstantDecl::Create(
- *getASTContext(), enutype->getDecl(), clang::SourceLocation(),
- name ? &getASTContext()->Idents.get(name) : nullptr, // Identifier
+ getASTContext(), enutype->getDecl(), clang::SourceLocation(),
+ name ? &getASTContext().Idents.get(name) : nullptr, // Identifier
clang::QualType(enutype, 0), nullptr, value);
if (!enumerator_decl)
@@ -8932,7 +7902,7 @@ ClangASTContext::GetEnumerationIntegerType(lldb::opaque_compiler_type_t type) {
if (enutype) {
clang::EnumDecl *enum_decl = enutype->getDecl();
if (enum_decl)
- return CompilerType(this, enum_decl->getIntegerType().getAsOpaquePtr());
+ return GetType(enum_decl->getIntegerType());
}
}
return CompilerType();
@@ -8947,11 +7917,9 @@ ClangASTContext::CreateMemberPointerType(const CompilerType &type,
llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
if (!ast)
return CompilerType();
- return CompilerType(ast, ast->getASTContext()
- ->getMemberPointerType(
- ClangUtil::GetQualType(pointee_type),
- ClangUtil::GetQualType(type).getTypePtr())
- .getAsOpaquePtr());
+ return ast->GetType(ast->getASTContext().getMemberPointerType(
+ ClangUtil::GetQualType(pointee_type),
+ ClangUtil::GetQualType(type).getTypePtr()));
}
return CompilerType();
}
@@ -8989,27 +7957,34 @@ void ClangASTContext::DumpFromSymbolFile(Stream &s,
TypeSP type = type_list.GetTypeAtIndex(i);
if (!symbol_name.empty())
- if (symbol_name.compare(type->GetName().GetStringRef()) != 0)
+ if (symbol_name != type->GetName().GetStringRef())
continue;
s << type->GetName().AsCString() << "\n";
- if (clang::TagDecl *tag_decl =
- GetAsTagDecl(type->GetFullCompilerType()))
+ CompilerType full_type = type->GetFullCompilerType();
+ if (clang::TagDecl *tag_decl = GetAsTagDecl(full_type)) {
tag_decl->dump(s.AsRawOstream());
- else if (clang::TypedefNameDecl *typedef_decl =
- GetAsTypedefDecl(type->GetFullCompilerType()))
+ continue;
+ }
+ if (clang::TypedefNameDecl *typedef_decl = GetAsTypedefDecl(full_type)) {
typedef_decl->dump(s.AsRawOstream());
- else {
- GetCanonicalQualType(type->GetFullCompilerType().GetOpaqueQualType())
- .dump(s.AsRawOstream());
+ continue;
+ }
+ if (auto *objc_obj = llvm::dyn_cast<clang::ObjCObjectType>(
+ ClangUtil::GetQualType(full_type).getTypePtr())) {
+ if (clang::ObjCInterfaceDecl *interface_decl = objc_obj->getInterface()) {
+ interface_decl->dump(s.AsRawOstream());
+ continue;
+ }
}
+ GetCanonicalQualType(full_type.GetOpaqueQualType()).dump(s.AsRawOstream());
}
}
void ClangASTContext::DumpValue(
lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s,
- lldb::Format format, const DataExtractor &data,
+ lldb::Format format, const lldb_private::DataExtractor &data,
lldb::offset_t data_byte_offset, size_t data_byte_size,
uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types,
bool show_summary, bool verbose, uint32_t depth) {
@@ -9027,7 +8002,7 @@ void ClangASTContext::DumpValue(
uint32_t field_bit_offset = 0;
uint32_t field_byte_offset = 0;
const clang::ASTRecordLayout &record_layout =
- getASTContext()->getASTRecordLayout(record_decl);
+ getASTContext().getASTRecordLayout(record_decl);
uint32_t child_idx = 0;
const clang::CXXRecordDecl *cxx_record_decl =
@@ -9071,11 +8046,10 @@ void ClangASTContext::DumpValue(
base_class_type_name);
clang::TypeInfo base_class_type_info =
- getASTContext()->getTypeInfo(base_class_qual_type);
+ getASTContext().getTypeInfo(base_class_qual_type);
// Dump the value of the member
- CompilerType base_clang_type(this,
- base_class_qual_type.getAsOpaquePtr());
+ CompilerType base_clang_type = GetType(base_class_qual_type);
base_clang_type.DumpValue(
exe_ctx,
s, // Stream to dump to
@@ -9118,7 +8092,7 @@ void ClangASTContext::DumpValue(
// Figure out the type byte size (field_type_info.first) and alignment
// (field_type_info.second) from the AST context.
clang::TypeInfo field_type_info =
- getASTContext()->getTypeInfo(field_type);
+ getASTContext().getTypeInfo(field_type);
assert(field_idx < record_layout.getFieldCount());
// Figure out the field offset within the current struct/union/class
// type
@@ -9126,8 +8100,7 @@ void ClangASTContext::DumpValue(
field_byte_offset = field_bit_offset / 8;
uint32_t field_bitfield_bit_size = 0;
uint32_t field_bitfield_bit_offset = 0;
- if (ClangASTContext::FieldIsBitfield(getASTContext(), *field,
- field_bitfield_bit_size))
+ if (FieldIsBitfield(*field, field_bitfield_bit_size))
field_bitfield_bit_offset = field_bit_offset % 8;
if (show_types) {
@@ -9142,7 +8115,7 @@ void ClangASTContext::DumpValue(
s->Printf("%s = ", field->getNameAsString().c_str());
// Dump the value of the member
- CompilerType field_clang_type(this, field_type.getAsOpaquePtr());
+ CompilerType field_clang_type = GetType(field_type);
field_clang_type.DumpValue(
exe_ctx,
s, // Stream to dump to
@@ -9207,7 +8180,7 @@ void ClangASTContext::DumpValue(
const uint64_t element_count = array->getSize().getLimitedValue();
clang::TypeInfo field_type_info =
- getASTContext()->getTypeInfo(element_qual_type);
+ getASTContext().getTypeInfo(element_qual_type);
uint32_t element_idx = 0;
uint32_t element_offset = 0;
@@ -9222,7 +8195,7 @@ void ClangASTContext::DumpValue(
s->PutChar('"');
return;
} else {
- CompilerType element_clang_type(this, element_qual_type.getAsOpaquePtr());
+ CompilerType element_clang_type = GetType(element_qual_type);
lldb::Format element_format = element_clang_type.GetFormat();
for (element_idx = 0; element_idx < element_count; ++element_idx) {
@@ -9273,10 +8246,10 @@ void ClangASTContext::DumpValue(
->getDecl()
->getUnderlyingType();
- CompilerType typedef_clang_type(this, typedef_qual_type.getAsOpaquePtr());
+ CompilerType typedef_clang_type = GetType(typedef_qual_type);
lldb::Format typedef_format = typedef_clang_type.GetFormat();
clang::TypeInfo typedef_type_info =
- getASTContext()->getTypeInfo(typedef_qual_type);
+ getASTContext().getTypeInfo(typedef_qual_type);
uint64_t typedef_byte_size = typedef_type_info.Width / 8;
return typedef_clang_type.DumpValue(
@@ -9298,11 +8271,10 @@ void ClangASTContext::DumpValue(
case clang::Type::Auto: {
clang::QualType elaborated_qual_type =
llvm::cast<clang::AutoType>(qual_type)->getDeducedType();
- CompilerType elaborated_clang_type(this,
- elaborated_qual_type.getAsOpaquePtr());
+ CompilerType elaborated_clang_type = GetType(elaborated_qual_type);
lldb::Format elaborated_format = elaborated_clang_type.GetFormat();
clang::TypeInfo elaborated_type_info =
- getASTContext()->getTypeInfo(elaborated_qual_type);
+ getASTContext().getTypeInfo(elaborated_qual_type);
uint64_t elaborated_byte_size = elaborated_type_info.Width / 8;
return elaborated_clang_type.DumpValue(
@@ -9324,11 +8296,10 @@ void ClangASTContext::DumpValue(
case clang::Type::Elaborated: {
clang::QualType elaborated_qual_type =
llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType();
- CompilerType elaborated_clang_type(this,
- elaborated_qual_type.getAsOpaquePtr());
+ CompilerType elaborated_clang_type = GetType(elaborated_qual_type);
lldb::Format elaborated_format = elaborated_clang_type.GetFormat();
clang::TypeInfo elaborated_type_info =
- getASTContext()->getTypeInfo(elaborated_qual_type);
+ getASTContext().getTypeInfo(elaborated_qual_type);
uint64_t elaborated_byte_size = elaborated_type_info.Width / 8;
return elaborated_clang_type.DumpValue(
@@ -9350,11 +8321,11 @@ void ClangASTContext::DumpValue(
case clang::Type::Paren: {
clang::QualType desugar_qual_type =
llvm::cast<clang::ParenType>(qual_type)->desugar();
- CompilerType desugar_clang_type(this, desugar_qual_type.getAsOpaquePtr());
+ CompilerType desugar_clang_type = GetType(desugar_qual_type);
lldb::Format desugar_format = desugar_clang_type.GetFormat();
clang::TypeInfo desugar_type_info =
- getASTContext()->getTypeInfo(desugar_qual_type);
+ getASTContext().getTypeInfo(desugar_qual_type);
uint64_t desugar_byte_size = desugar_type_info.Width / 8;
return desugar_clang_type.DumpValue(
@@ -9467,8 +8438,8 @@ static bool DumpEnumValue(const clang::QualType &qual_type, Stream *s,
bool ClangASTContext::DumpTypeValue(
lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format,
- const DataExtractor &data, lldb::offset_t byte_offset, size_t byte_size,
- uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
+ const lldb_private::DataExtractor &data, lldb::offset_t byte_offset,
+ size_t byte_size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
ExecutionContextScope *exe_scope) {
if (!type)
return false;
@@ -9491,11 +8462,11 @@ bool ClangASTContext::DumpTypeValue(
llvm::cast<clang::TypedefType>(qual_type)
->getDecl()
->getUnderlyingType();
- CompilerType typedef_clang_type(this, typedef_qual_type.getAsOpaquePtr());
+ CompilerType typedef_clang_type = GetType(typedef_qual_type);
if (format == eFormatDefault)
format = typedef_clang_type.GetFormat();
clang::TypeInfo typedef_type_info =
- getASTContext()->getTypeInfo(typedef_qual_type);
+ getASTContext().getTypeInfo(typedef_qual_type);
uint64_t typedef_byte_size = typedef_type_info.Width / 8;
return typedef_clang_type.DumpTypeValue(
@@ -9636,8 +8607,10 @@ void ClangASTContext::DumpSummary(lldb::opaque_compiler_type_t type,
void ClangASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) {
StreamFile s(stdout, false);
DumpTypeDescription(type, &s);
- ClangASTMetadata *metadata =
- ClangASTContext::GetMetadata(getASTContext(), type);
+
+ CompilerType ct(this, type);
+ const clang::Type *clang_type = ClangUtil::GetQualType(ct).getTypePtr();
+ ClangASTMetadata *metadata = GetMetadata(clang_type);
if (metadata) {
metadata->Dump(&s);
}
@@ -9646,7 +8619,8 @@ void ClangASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) {
void ClangASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type,
Stream *s) {
if (type) {
- clang::QualType qual_type(GetQualType(type));
+ clang::QualType qual_type =
+ RemoveWrappingTypes(GetQualType(type), {clang::Type::Typedef});
llvm::SmallVector<char, 1024> buf;
llvm::raw_svector_ostream llvm_ostrm(buf);
@@ -9664,7 +8638,7 @@ void ClangASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type,
clang::ObjCInterfaceDecl *class_interface_decl =
objc_class_type->getInterface();
if (class_interface_decl) {
- clang::PrintingPolicy policy = getASTContext()->getPrintingPolicy();
+ clang::PrintingPolicy policy = getASTContext().getPrintingPolicy();
class_interface_decl->print(llvm_ostrm, policy, s->GetIndentLevel());
}
}
@@ -9684,27 +8658,6 @@ void ClangASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type,
}
} break;
- case clang::Type::Auto:
- CompilerType(this, llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr())
- .DumpTypeDescription(s);
- return;
-
- case clang::Type::Elaborated:
- CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr())
- .DumpTypeDescription(s);
- return;
-
- case clang::Type::Paren:
- CompilerType(
- this,
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr())
- .DumpTypeDescription(s);
- return;
-
case clang::Type::Record: {
GetCompleteType(type);
@@ -9715,10 +8668,10 @@ void ClangASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type,
llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
if (cxx_record_decl)
- cxx_record_decl->print(llvm_ostrm, getASTContext()->getPrintingPolicy(),
+ cxx_record_decl->print(llvm_ostrm, getASTContext().getPrintingPolicy(),
s->GetIndentLevel());
else
- record_decl->print(llvm_ostrm, getASTContext()->getPrintingPolicy(),
+ record_decl->print(llvm_ostrm, getASTContext().getPrintingPolicy(),
s->GetIndentLevel());
} break;
@@ -9830,9 +8783,8 @@ clang::ClassTemplateDecl *ClangASTContext::ParseClassTemplateDecl(
return nullptr;
}
-void ClangASTContext::CompleteTagDecl(void *baton, clang::TagDecl *decl) {
- ClangASTContext *ast = (ClangASTContext *)baton;
- SymbolFile *sym_file = ast->GetSymbolFile();
+void ClangASTContext::CompleteTagDecl(clang::TagDecl *decl) {
+ SymbolFile *sym_file = GetSymbolFile();
if (sym_file) {
CompilerType clang_type = GetTypeForDecl(decl);
if (clang_type)
@@ -9841,9 +8793,8 @@ void ClangASTContext::CompleteTagDecl(void *baton, clang::TagDecl *decl) {
}
void ClangASTContext::CompleteObjCInterfaceDecl(
- void *baton, clang::ObjCInterfaceDecl *decl) {
- ClangASTContext *ast = (ClangASTContext *)baton;
- SymbolFile *sym_file = ast->GetSymbolFile();
+ clang::ObjCInterfaceDecl *decl) {
+ SymbolFile *sym_file = GetSymbolFile();
if (sym_file) {
CompilerType clang_type = GetTypeForDecl(decl);
if (clang_type)
@@ -9864,19 +8815,18 @@ PDBASTParser *ClangASTContext::GetPDBParser() {
}
bool ClangASTContext::LayoutRecordType(
- void *baton, const clang::RecordDecl *record_decl, uint64_t &bit_size,
+ const clang::RecordDecl *record_decl, uint64_t &bit_size,
uint64_t &alignment,
llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
&base_offsets,
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
&vbase_offsets) {
- ClangASTContext *ast = (ClangASTContext *)baton;
lldb_private::ClangASTImporter *importer = nullptr;
- if (ast->m_dwarf_ast_parser_up)
- importer = &ast->m_dwarf_ast_parser_up->GetClangASTImporter();
- if (!importer && ast->m_pdb_ast_parser_up)
- importer = &ast->m_pdb_ast_parser_up->GetClangASTImporter();
+ if (m_dwarf_ast_parser_up)
+ importer = &m_dwarf_ast_parser_up->GetClangASTImporter();
+ if (!importer && m_pdb_ast_parser_up)
+ importer = &m_pdb_ast_parser_up->GetClangASTImporter();
if (!importer)
return false;
@@ -9924,19 +8874,17 @@ ConstString ClangASTContext::DeclGetMangledName(void *opaque_decl) {
CompilerDeclContext ClangASTContext::DeclGetDeclContext(void *opaque_decl) {
if (opaque_decl)
- return CompilerDeclContext(this,
- ((clang::Decl *)opaque_decl)->getDeclContext());
- else
- return CompilerDeclContext();
+ return CreateDeclContext(((clang::Decl *)opaque_decl)->getDeclContext());
+ return CompilerDeclContext();
}
CompilerType ClangASTContext::DeclGetFunctionReturnType(void *opaque_decl) {
if (clang::FunctionDecl *func_decl =
llvm::dyn_cast<clang::FunctionDecl>((clang::Decl *)opaque_decl))
- return CompilerType(this, func_decl->getReturnType().getAsOpaquePtr());
+ return GetType(func_decl->getReturnType());
if (clang::ObjCMethodDecl *objc_method =
llvm::dyn_cast<clang::ObjCMethodDecl>((clang::Decl *)opaque_decl))
- return CompilerType(this, objc_method->getReturnType().getAsOpaquePtr());
+ return GetType(objc_method->getReturnType());
else
return CompilerType();
}
@@ -9959,15 +8907,13 @@ CompilerType ClangASTContext::DeclGetFunctionArgumentType(void *opaque_decl,
if (idx < func_decl->param_size()) {
ParmVarDecl *var_decl = func_decl->getParamDecl(idx);
if (var_decl)
- return CompilerType(this, var_decl->getOriginalType().getAsOpaquePtr());
+ return GetType(var_decl->getOriginalType());
}
} else if (clang::ObjCMethodDecl *objc_method =
llvm::dyn_cast<clang::ObjCMethodDecl>(
(clang::Decl *)opaque_decl)) {
if (idx < objc_method->param_size())
- return CompilerType(
- this,
- objc_method->parameters()[idx]->getOriginalType().getAsOpaquePtr());
+ return GetType(objc_method->parameters()[idx]->getOriginalType());
}
return CompilerType();
}
@@ -9993,7 +8939,7 @@ std::vector<CompilerDecl> ClangASTContext::DeclContextFindDeclByName(
if (!searched.insert(it->second).second)
continue;
symbol_file->ParseDeclsForContext(
- CompilerDeclContext(this, it->second));
+ CreateDeclContext(it->second));
for (clang::Decl *child : it->second->decls()) {
if (clang::UsingDirectiveDecl *ud =
@@ -10108,7 +9054,7 @@ uint32_t ClangASTContext::CountDeclLevels(clang::DeclContext *frame_decl_ctx,
searched.insert(it->second);
symbol_file->ParseDeclsForContext(
- CompilerDeclContext(this, it->second));
+ CreateDeclContext(it->second));
for (clang::Decl *child : it->second->decls()) {
if (clang::UsingDirectiveDecl *ud =
@@ -10135,7 +9081,7 @@ uint32_t ClangASTContext::CountDeclLevels(clang::DeclContext *frame_decl_ctx,
continue;
// Check types, if one was provided.
if (child_type) {
- CompilerType clang_type = ClangASTContext::GetTypeForDecl(nd);
+ CompilerType clang_type = GetTypeForDecl(nd);
if (!AreTypesSame(clang_type, *child_type,
/*ignore_qualifiers=*/true))
continue;
@@ -10153,13 +9099,6 @@ uint32_t ClangASTContext::CountDeclLevels(clang::DeclContext *frame_decl_ctx,
return LLDB_INVALID_DECL_LEVEL;
}
-bool ClangASTContext::DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) {
- if (opaque_decl_ctx)
- return ((clang::DeclContext *)opaque_decl_ctx)->isRecord();
- else
- return false;
-}
-
ConstString ClangASTContext::DeclContextGetName(void *opaque_decl_ctx) {
if (opaque_decl_ctx) {
clang::NamedDecl *named_decl =
@@ -10207,8 +9146,7 @@ bool ClangASTContext::DeclContextIsClassMethod(
return true;
} else if (clang::FunctionDecl *function_decl =
llvm::dyn_cast<clang::FunctionDecl>(decl_ctx)) {
- ClangASTMetadata *metadata =
- GetMetadata(&decl_ctx->getParentASTContext(), function_decl);
+ ClangASTMetadata *metadata = GetMetadata(function_decl);
if (metadata && metadata->HasObjectPtr()) {
if (is_instance_method_ptr)
*is_instance_method_ptr = true;
@@ -10240,16 +9178,20 @@ bool ClangASTContext::DeclContextIsContainedInLookup(
return false;
}
+static bool IsClangDeclContext(const CompilerDeclContext &dc) {
+ return dc.IsValid() && isa<ClangASTContext>(dc.GetTypeSystem());
+}
+
clang::DeclContext *
ClangASTContext::DeclContextGetAsDeclContext(const CompilerDeclContext &dc) {
- if (dc.IsClang())
+ if (IsClangDeclContext(dc))
return (clang::DeclContext *)dc.GetOpaqueDeclContext();
return nullptr;
}
ObjCMethodDecl *
ClangASTContext::DeclContextGetAsObjCMethodDecl(const CompilerDeclContext &dc) {
- if (dc.IsClang())
+ if (IsClangDeclContext(dc))
return llvm::dyn_cast<clang::ObjCMethodDecl>(
(clang::DeclContext *)dc.GetOpaqueDeclContext());
return nullptr;
@@ -10257,7 +9199,7 @@ ClangASTContext::DeclContextGetAsObjCMethodDecl(const CompilerDeclContext &dc) {
CXXMethodDecl *
ClangASTContext::DeclContextGetAsCXXMethodDecl(const CompilerDeclContext &dc) {
- if (dc.IsClang())
+ if (IsClangDeclContext(dc))
return llvm::dyn_cast<clang::CXXMethodDecl>(
(clang::DeclContext *)dc.GetOpaqueDeclContext());
return nullptr;
@@ -10265,7 +9207,7 @@ ClangASTContext::DeclContextGetAsCXXMethodDecl(const CompilerDeclContext &dc) {
clang::FunctionDecl *
ClangASTContext::DeclContextGetAsFunctionDecl(const CompilerDeclContext &dc) {
- if (dc.IsClang())
+ if (IsClangDeclContext(dc))
return llvm::dyn_cast<clang::FunctionDecl>(
(clang::DeclContext *)dc.GetOpaqueDeclContext());
return nullptr;
@@ -10273,7 +9215,7 @@ ClangASTContext::DeclContextGetAsFunctionDecl(const CompilerDeclContext &dc) {
clang::NamespaceDecl *
ClangASTContext::DeclContextGetAsNamespaceDecl(const CompilerDeclContext &dc) {
- if (dc.IsClang())
+ if (IsClangDeclContext(dc))
return llvm::dyn_cast<clang::NamespaceDecl>(
(clang::DeclContext *)dc.GetOpaqueDeclContext());
return nullptr;
@@ -10281,11 +9223,9 @@ ClangASTContext::DeclContextGetAsNamespaceDecl(const CompilerDeclContext &dc) {
ClangASTMetadata *
ClangASTContext::DeclContextGetMetaData(const CompilerDeclContext &dc,
- const void *object) {
- clang::ASTContext *ast = DeclContextGetClangASTContext(dc);
- if (ast)
- return ClangASTContext::GetMetadata(ast, object);
- return nullptr;
+ const Decl *object) {
+ ClangASTContext *ast = llvm::cast<ClangASTContext>(dc.GetTypeSystem());
+ return ast->GetMetadata(object);
}
clang::ASTContext *
@@ -10293,14 +9233,26 @@ ClangASTContext::DeclContextGetClangASTContext(const CompilerDeclContext &dc) {
ClangASTContext *ast =
llvm::dyn_cast_or_null<ClangASTContext>(dc.GetTypeSystem());
if (ast)
- return ast->getASTContext();
+ return &ast->getASTContext();
return nullptr;
}
-ClangASTContextForExpressions::ClangASTContextForExpressions(Target &target,
- ArchSpec arch)
- : ClangASTContext(arch), m_target_wp(target.shared_from_this()),
- m_persistent_variables(new ClangPersistentVariables) {}
+ClangASTContextForExpressions::ClangASTContextForExpressions(
+ Target &target, llvm::Triple triple)
+ : ClangASTContext(triple), m_target_wp(target.shared_from_this()),
+ m_persistent_variables(new ClangPersistentVariables) {
+ m_scratch_ast_source_up.reset(new ClangASTSource(
+ target.shared_from_this(), target.GetClangASTImporter()));
+ m_scratch_ast_source_up->InstallASTContext(*this);
+ llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source(
+ m_scratch_ast_source_up->CreateProxy());
+ SetExternalSource(proxy_ast_source);
+}
+
+void ClangASTContextForExpressions::Finalize() {
+ ClangASTContext::Finalize();
+ m_scratch_ast_source_up.reset();
+}
UserExpression *ClangASTContextForExpressions::GetUserExpression(
llvm::StringRef expr, llvm::StringRef prefix, lldb::LanguageType language,
@@ -10344,9 +9296,3 @@ PersistentExpressionState *
ClangASTContextForExpressions::GetPersistentExpressionState() {
return m_persistent_variables.get();
}
-
-clang::ExternalASTMerger &
-ClangASTContextForExpressions::GetMergerUnchecked() {
- lldbassert(m_scratch_ast_source_up != nullptr);
- return m_scratch_ast_source_up->GetMergerUnchecked();
-}
diff --git a/lldb/source/Symbol/ClangASTImporter.cpp b/lldb/source/Symbol/ClangASTImporter.cpp
index 92d51f79a007..8cb404231a8d 100644
--- a/lldb/source/Symbol/ClangASTImporter.cpp
+++ b/lldb/source/Symbol/ClangASTImporter.cpp
@@ -9,7 +9,7 @@
#include "lldb/Symbol/ClangASTImporter.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/ClangASTMetadata.h"
#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
@@ -25,90 +25,46 @@
using namespace lldb_private;
using namespace clang;
-ClangASTMetrics::Counters ClangASTMetrics::global_counters = {0, 0, 0, 0, 0, 0};
-ClangASTMetrics::Counters ClangASTMetrics::local_counters = {0, 0, 0, 0, 0, 0};
-
-void ClangASTMetrics::DumpCounters(Log *log,
- ClangASTMetrics::Counters &counters) {
- LLDB_LOGF(log, " Number of visible Decl queries by name : %" PRIu64,
- counters.m_visible_query_count);
- LLDB_LOGF(log, " Number of lexical Decl queries : %" PRIu64,
- counters.m_lexical_query_count);
- LLDB_LOGF(log, " Number of imports initiated by LLDB : %" PRIu64,
- counters.m_lldb_import_count);
- LLDB_LOGF(log, " Number of imports conducted by Clang : %" PRIu64,
- counters.m_clang_import_count);
- LLDB_LOGF(log, " Number of Decls completed : %" PRIu64,
- counters.m_decls_completed_count);
- LLDB_LOGF(log, " Number of records laid out : %" PRIu64,
- counters.m_record_layout_count);
-}
-
-void ClangASTMetrics::DumpCounters(Log *log) {
- if (!log)
- return;
+CompilerType ClangASTImporter::CopyType(ClangASTContext &dst_ast,
+ const CompilerType &src_type) {
+ clang::ASTContext &dst_clang_ast = dst_ast.getASTContext();
- LLDB_LOGF(log, "== ClangASTMetrics output ==");
- LLDB_LOGF(log, "-- Global metrics --");
- DumpCounters(log, global_counters);
- LLDB_LOGF(log, "-- Local metrics --");
- DumpCounters(log, local_counters);
-}
+ ClangASTContext *src_ast =
+ llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem());
+ if (!src_ast)
+ return CompilerType();
-clang::QualType ClangASTImporter::CopyType(clang::ASTContext *dst_ast,
- clang::ASTContext *src_ast,
- clang::QualType type) {
- ImporterDelegateSP delegate_sp(GetDelegate(dst_ast, src_ast));
+ clang::ASTContext &src_clang_ast = src_ast->getASTContext();
- ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, dst_ast);
+ clang::QualType src_qual_type = ClangUtil::GetQualType(src_type);
+ ImporterDelegateSP delegate_sp(GetDelegate(&dst_clang_ast, &src_clang_ast));
if (!delegate_sp)
- return QualType();
+ return CompilerType();
- llvm::Expected<QualType> ret_or_error = delegate_sp->Import(type);
+ ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, &dst_clang_ast);
+
+ llvm::Expected<QualType> ret_or_error = delegate_sp->Import(src_qual_type);
if (!ret_or_error) {
Log *log =
lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
LLDB_LOG_ERROR(log, ret_or_error.takeError(),
"Couldn't import type: {0}");
- return QualType();
+ return CompilerType();
}
- return *ret_or_error;
-}
-lldb::opaque_compiler_type_t
-ClangASTImporter::CopyType(clang::ASTContext *dst_ast,
- clang::ASTContext *src_ast,
- lldb::opaque_compiler_type_t type) {
- return CopyType(dst_ast, src_ast, QualType::getFromOpaquePtr(type))
- .getAsOpaquePtr();
-}
+ lldb::opaque_compiler_type_t dst_clang_type = ret_or_error->getAsOpaquePtr();
-CompilerType ClangASTImporter::CopyType(ClangASTContext &dst_ast,
- const CompilerType &src_type) {
- clang::ASTContext *dst_clang_ast = dst_ast.getASTContext();
- if (dst_clang_ast) {
- ClangASTContext *src_ast =
- llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem());
- if (src_ast) {
- clang::ASTContext *src_clang_ast = src_ast->getASTContext();
- if (src_clang_ast) {
- lldb::opaque_compiler_type_t dst_clang_type = CopyType(
- dst_clang_ast, src_clang_ast, src_type.GetOpaqueQualType());
-
- if (dst_clang_type)
- return CompilerType(&dst_ast, dst_clang_type);
- }
- }
- }
+ if (dst_clang_type)
+ return CompilerType(&dst_ast, dst_clang_type);
return CompilerType();
}
clang::Decl *ClangASTImporter::CopyDecl(clang::ASTContext *dst_ast,
- clang::ASTContext *src_ast,
clang::Decl *decl) {
ImporterDelegateSP delegate_sp;
+ clang::ASTContext *src_ast = &decl->getASTContext();
delegate_sp = GetDelegate(dst_ast, src_ast);
ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, dst_ast);
@@ -151,7 +107,7 @@ private:
clang::DeclContext *lexical_decl_context;
};
- std::map<clang::Decl *, Backup> m_backups;
+ llvm::DenseMap<clang::Decl *, Backup> m_backups;
void OverrideOne(clang::Decl *decl) {
if (m_backups.find(decl) != m_backups.end()) {
@@ -258,10 +214,8 @@ namespace {
/// imported while completing the original Decls).
class CompleteTagDeclsScope : public ClangASTImporter::NewDeclListener {
ClangASTImporter::ImporterDelegateSP m_delegate;
- // FIXME: Investigate how many decls we usually have in these sets and
- // see if we can use SmallPtrSet instead here.
- std::set<NamedDecl *> m_decls_to_complete;
- std::set<NamedDecl *> m_decls_already_completed;
+ llvm::SmallVector<NamedDecl *, 32> m_decls_to_complete;
+ llvm::SmallPtrSet<NamedDecl *, 32> m_decls_already_completed;
clang::ASTContext *m_dst_ctx;
clang::ASTContext *m_src_ctx;
ClangASTImporter &importer;
@@ -285,10 +239,8 @@ public:
// Complete all decls we collected until now.
while (!m_decls_to_complete.empty()) {
- NamedDecl *decl = *m_decls_to_complete.begin();
-
+ NamedDecl *decl = m_decls_to_complete.pop_back_val();
m_decls_already_completed.insert(decl);
- m_decls_to_complete.erase(decl);
// We should only complete decls coming from the source context.
assert(to_context_md->m_origins[decl].ctx == m_src_ctx);
@@ -333,46 +285,39 @@ public:
// Check if we already completed this type.
if (m_decls_already_completed.count(to_named_decl) != 0)
return;
- m_decls_to_complete.insert(to_named_decl);
+ m_decls_to_complete.push_back(to_named_decl);
}
};
} // namespace
-lldb::opaque_compiler_type_t
-ClangASTImporter::DeportType(clang::ASTContext *dst_ctx,
- clang::ASTContext *src_ctx,
- lldb::opaque_compiler_type_t type) {
+CompilerType ClangASTImporter::DeportType(ClangASTContext &dst,
+ const CompilerType &src_type) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- LLDB_LOGF(log,
- " [ClangASTImporter] DeportType called on (%sType*)0x%llx "
- "from (ASTContext*)%p to (ASTContext*)%p",
- QualType::getFromOpaquePtr(type)->getTypeClassName(),
- (unsigned long long)type, static_cast<void *>(src_ctx),
- static_cast<void *>(dst_ctx));
+ ClangASTContext *src_ctxt =
+ llvm::cast<ClangASTContext>(src_type.GetTypeSystem());
+
+ LLDB_LOG(log,
+ " [ClangASTImporter] DeportType called on ({0}Type*){1:x} "
+ "from (ASTContext*){2:x} to (ASTContext*){3:x}",
+ src_type.GetTypeName(), src_type.GetOpaqueQualType(),
+ &src_ctxt->getASTContext(), &dst.getASTContext());
DeclContextOverride decl_context_override;
- if (auto *t = QualType::getFromOpaquePtr(type)->getAs<TagType>())
+ if (auto *t = ClangUtil::GetQualType(src_type)->getAs<TagType>())
decl_context_override.OverrideAllDeclsFromContainingFunction(t->getDecl());
- lldb::opaque_compiler_type_t result;
- {
- CompleteTagDeclsScope complete_scope(*this, dst_ctx, src_ctx);
- result = CopyType(dst_ctx, src_ctx, type);
- }
-
- if (!result)
- return nullptr;
-
- return result;
+ CompleteTagDeclsScope complete_scope(*this, &dst.getASTContext(),
+ &src_ctxt->getASTContext());
+ return CopyType(dst, src_type);
}
clang::Decl *ClangASTImporter::DeportDecl(clang::ASTContext *dst_ctx,
- clang::ASTContext *src_ctx,
clang::Decl *decl) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+ clang::ASTContext *src_ctx = &decl->getASTContext();
LLDB_LOGF(log,
" [ClangASTImporter] DeportDecl called on (%sDecl*)%p from "
"(ASTContext*)%p to (ASTContext*)%p",
@@ -386,7 +331,7 @@ clang::Decl *ClangASTImporter::DeportDecl(clang::ASTContext *dst_ctx,
clang::Decl *result;
{
CompleteTagDeclsScope complete_scope(*this, dst_ctx, src_ctx);
- result = CopyDecl(dst_ctx, src_ctx, decl);
+ result = CopyDecl(dst_ctx, decl);
}
if (!result)
@@ -417,7 +362,7 @@ bool ClangASTImporter::CanImport(const CompilerType &type) {
const clang::CXXRecordDecl *cxx_record_decl =
qual_type->getAsCXXRecordDecl();
if (cxx_record_decl) {
- if (ResolveDeclOrigin(cxx_record_decl, nullptr, nullptr))
+ if (GetDeclOrigin(cxx_record_decl).Valid())
return true;
}
} break;
@@ -426,7 +371,7 @@ bool ClangASTImporter::CanImport(const CompilerType &type) {
clang::EnumDecl *enum_decl =
llvm::cast<clang::EnumType>(qual_type)->getDecl();
if (enum_decl) {
- if (ResolveDeclOrigin(enum_decl, nullptr, nullptr))
+ if (GetDeclOrigin(enum_decl).Valid())
return true;
}
} break;
@@ -441,7 +386,7 @@ bool ClangASTImporter::CanImport(const CompilerType &type) {
// We currently can't complete objective C types through the newly added
// ASTContext because it only supports TagDecl objects right now...
if (class_interface_decl) {
- if (ResolveDeclOrigin(class_interface_decl, nullptr, nullptr))
+ if (GetDeclOrigin(class_interface_decl).Valid())
return true;
}
}
@@ -493,7 +438,7 @@ bool ClangASTImporter::Import(const CompilerType &type) {
const clang::CXXRecordDecl *cxx_record_decl =
qual_type->getAsCXXRecordDecl();
if (cxx_record_decl) {
- if (ResolveDeclOrigin(cxx_record_decl, nullptr, nullptr))
+ if (GetDeclOrigin(cxx_record_decl).Valid())
return CompleteAndFetchChildren(qual_type);
}
} break;
@@ -502,7 +447,7 @@ bool ClangASTImporter::Import(const CompilerType &type) {
clang::EnumDecl *enum_decl =
llvm::cast<clang::EnumType>(qual_type)->getDecl();
if (enum_decl) {
- if (ResolveDeclOrigin(enum_decl, nullptr, nullptr))
+ if (GetDeclOrigin(enum_decl).Valid())
return CompleteAndFetchChildren(qual_type);
}
} break;
@@ -517,7 +462,7 @@ bool ClangASTImporter::Import(const CompilerType &type) {
// We currently can't complete objective C types through the newly added
// ASTContext because it only supports TagDecl objects right now...
if (class_interface_decl) {
- if (ResolveDeclOrigin(class_interface_decl, nullptr, nullptr))
+ if (GetDeclOrigin(class_interface_decl).Valid())
return CompleteAndFetchChildren(qual_type);
}
}
@@ -596,7 +541,7 @@ bool ClangASTImporter::LayoutRecordType(
return success;
}
-void ClangASTImporter::InsertRecordDecl(clang::RecordDecl *decl,
+void ClangASTImporter::SetRecordLayout(clang::RecordDecl *decl,
const LayoutInfo &layout) {
m_record_decl_to_layout_map.insert(std::make_pair(decl, layout));
}
@@ -628,8 +573,6 @@ void ClangASTImporter::CompleteDecl(clang::Decl *decl) {
}
bool ClangASTImporter::CompleteTagDecl(clang::TagDecl *decl) {
- ClangASTMetrics::RegisterDeclCompletion();
-
DeclOrigin decl_origin = GetDeclOrigin(decl);
if (!decl_origin.Valid())
@@ -651,8 +594,6 @@ bool ClangASTImporter::CompleteTagDecl(clang::TagDecl *decl) {
bool ClangASTImporter::CompleteTagDeclWithOrigin(clang::TagDecl *decl,
clang::TagDecl *origin_decl) {
- ClangASTMetrics::RegisterDeclCompletion();
-
clang::ASTContext *origin_ast_ctx = &origin_decl->getASTContext();
if (!ClangASTContext::GetCompleteDecl(origin_ast_ctx, origin_decl))
@@ -675,8 +616,6 @@ bool ClangASTImporter::CompleteTagDeclWithOrigin(clang::TagDecl *decl,
bool ClangASTImporter::CompleteObjCInterfaceDecl(
clang::ObjCInterfaceDecl *interface_decl) {
- ClangASTMetrics::RegisterDeclCompletion();
-
DeclOrigin decl_origin = GetDeclOrigin(interface_decl);
if (!decl_origin.Valid())
@@ -729,9 +668,8 @@ bool ClangASTImporter::CompleteAndFetchChildren(clang::QualType type) {
}
}
- if (RecordDecl *record_decl = dyn_cast<RecordDecl>(origin_tag_decl)) {
+ if (RecordDecl *record_decl = dyn_cast<RecordDecl>(origin_tag_decl))
record_decl->setHasLoadedFieldsFromExternalStorage(true);
- }
return true;
}
@@ -761,9 +699,8 @@ bool ClangASTImporter::CompleteAndFetchChildren(clang::QualType type) {
}
return true;
- } else {
- return false;
}
+ return false;
}
return true;
@@ -785,15 +722,12 @@ bool ClangASTImporter::RequireCompleteType(clang::QualType type) {
if (ObjCInterfaceDecl *objc_interface_decl =
objc_object_type->getInterface())
return CompleteObjCInterfaceDecl(objc_interface_decl);
- else
- return false;
+ return false;
}
- if (const ArrayType *array_type = type->getAsArrayTypeUnsafe()) {
+ if (const ArrayType *array_type = type->getAsArrayTypeUnsafe())
return RequireCompleteType(array_type->getElementType());
- }
- if (const AtomicType *atomic_type = type->getAs<AtomicType>()) {
+ if (const AtomicType *atomic_type = type->getAs<AtomicType>())
return RequireCompleteType(atomic_type->getPointeeType());
- }
return true;
}
@@ -801,10 +735,12 @@ bool ClangASTImporter::RequireCompleteType(clang::QualType type) {
ClangASTMetadata *ClangASTImporter::GetDeclMetadata(const clang::Decl *decl) {
DeclOrigin decl_origin = GetDeclOrigin(decl);
- if (decl_origin.Valid())
- return ClangASTContext::GetMetadata(decl_origin.ctx, decl_origin.decl);
- else
- return ClangASTContext::GetMetadata(&decl->getASTContext(), decl);
+ if (decl_origin.Valid()) {
+ ClangASTContext *ast = ClangASTContext::GetASTContext(decl_origin.ctx);
+ return ast->GetMetadata(decl_origin.decl);
+ }
+ ClangASTContext *ast = ClangASTContext::GetASTContext(&decl->getASTContext());
+ return ast->GetMetadata(decl);
}
ClangASTImporter::DeclOrigin
@@ -817,8 +753,7 @@ ClangASTImporter::GetDeclOrigin(const clang::Decl *decl) {
if (iter != origins.end())
return iter->second;
- else
- return DeclOrigin();
+ return DeclOrigin();
}
void ClangASTImporter::SetDeclOrigin(const clang::Decl *decl,
@@ -832,9 +767,9 @@ void ClangASTImporter::SetDeclOrigin(const clang::Decl *decl,
if (iter != origins.end()) {
iter->second.decl = original_decl;
iter->second.ctx = &original_decl->getASTContext();
- } else {
- origins[decl] = DeclOrigin(&original_decl->getASTContext(), original_decl);
+ return;
}
+ origins[decl] = DeclOrigin(&original_decl->getASTContext(), original_decl);
}
void ClangASTImporter::RegisterNamespaceMap(const clang::NamespaceDecl *decl,
@@ -854,8 +789,7 @@ ClangASTImporter::GetNamespaceMap(const clang::NamespaceDecl *decl) {
if (iter != namespace_maps.end())
return iter->second;
- else
- return NamespaceMapSP();
+ return NamespaceMapSP();
}
void ClangASTImporter::BuildNamespaceMap(const clang::NamespaceDecl *decl) {
@@ -936,6 +870,39 @@ ClangASTImporter::ASTImporterDelegate::ImportImpl(Decl *From) {
}
}
+ // Check which ASTContext this declaration originally came from.
+ DeclOrigin origin = m_master.GetDeclOrigin(From);
+ // If it originally came from the target ASTContext then we can just
+ // pretend that the original is the one we imported. This can happen for
+ // example when inspecting a persistent declaration from the scratch
+ // ASTContext (which will provide the declaration when parsing the
+ // expression and then we later try to copy the declaration back to the
+ // scratch ASTContext to store the result).
+ // Without this check we would ask the ASTImporter to import a declaration
+ // into the same ASTContext where it came from (which doesn't make a lot of
+ // sense).
+ if (origin.Valid() && origin.ctx == &getToContext()) {
+ RegisterImportedDecl(From, origin.decl);
+ return origin.decl;
+ }
+
+ // This declaration came originally from another ASTContext. Instead of
+ // copying our potentially incomplete 'From' Decl we instead go to the
+ // original ASTContext and copy the original to the target. This is not
+ // only faster than first completing our current decl and then copying it
+ // to the target, but it also prevents that indirectly copying the same
+ // declaration to the same target requires the ASTImporter to merge all
+ // the different decls that appear to come from different ASTContexts (even
+ // though all these different source ASTContexts just got a copy from
+ // one source AST).
+ if (origin.Valid()) {
+ auto R = m_master.CopyDecl(&getToContext(), origin.decl);
+ if (R) {
+ RegisterImportedDecl(From, R);
+ return R;
+ }
+ }
+
return ASTImporter::ImportImpl(From);
}
@@ -1037,8 +1004,6 @@ void ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo(
void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from,
clang::Decl *to) {
- ClangASTMetrics::RegisterClangImport();
-
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
// Some decls shouldn't be tracked here because they were not created by
@@ -1196,16 +1161,5 @@ void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from,
clang::Decl *
ClangASTImporter::ASTImporterDelegate::GetOriginalDecl(clang::Decl *To) {
- ASTContextMetadataSP to_context_md =
- m_master.GetContextMetadata(&To->getASTContext());
-
- if (!to_context_md)
- return nullptr;
-
- OriginMap::iterator iter = to_context_md->m_origins.find(To);
-
- if (iter == to_context_md->m_origins.end())
- return nullptr;
-
- return const_cast<clang::Decl *>(iter->second.decl);
+ return m_master.GetDeclOrigin(To).decl;
}
diff --git a/lldb/source/Symbol/ClangASTMetadata.cpp b/lldb/source/Symbol/ClangASTMetadata.cpp
new file mode 100644
index 000000000000..31b012f553fa
--- /dev/null
+++ b/lldb/source/Symbol/ClangASTMetadata.cpp
@@ -0,0 +1,35 @@
+//===-- ClangASTMetadata.cpp ------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/ClangASTMetadata.h"
+#include "lldb/Utility/Stream.h"
+
+using namespace lldb_private;
+
+void ClangASTMetadata::Dump(Stream *s) {
+ lldb::user_id_t uid = GetUserID();
+
+ if (uid != LLDB_INVALID_UID) {
+ s->Printf("uid=0x%" PRIx64, uid);
+ }
+
+ uint64_t isa_ptr = GetISAPtr();
+ if (isa_ptr != 0) {
+ s->Printf("isa_ptr=0x%" PRIx64, isa_ptr);
+ }
+
+ const char *obj_ptr_name = GetObjectPtrName();
+ if (obj_ptr_name) {
+ s->Printf("obj_ptr_name=\"%s\" ", obj_ptr_name);
+ }
+
+ if (m_is_dynamic_cxx) {
+ s->Printf("is_dynamic_cxx=%i ", m_is_dynamic_cxx);
+ }
+ s->EOL();
+}
diff --git a/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp b/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp
index c35fc585bfa5..008c2acd9b48 100644
--- a/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp
+++ b/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp
@@ -7,69 +7,19 @@
//===----------------------------------------------------------------------===//
#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h"
+#include "lldb/Symbol/ClangASTContext.h"
-
-// Clang headers like to use NDEBUG inside of them to enable/disable debug
-// related features using "#ifndef NDEBUG" preprocessor blocks to do one thing
-// or another. This is bad because it means that if clang was built in release
-// mode, it assumes that you are building in release mode which is not always
-// the case. You can end up with functions that are defined as empty in header
-// files when NDEBUG is not defined, and this can cause link errors with the
-// clang .a files that you have since you might be missing functions in the .a
-// file. So we have to define NDEBUG when including clang headers to avoid any
-// mismatches. This is covered by rdar://problem/8691220
-
-#if !defined(NDEBUG) && !defined(LLVM_NDEBUG_OFF)
-#define LLDB_DEFINED_NDEBUG_FOR_CLANG
-#define NDEBUG
-// Need to include assert.h so it is as clang would expect it to be (disabled)
-#include <assert.h>
-#endif
-
-#include "clang/AST/DeclBase.h"
-#include "clang/AST/DeclarationName.h"
-
-#ifdef LLDB_DEFINED_NDEBUG_FOR_CLANG
-#undef NDEBUG
-#undef LLDB_DEFINED_NDEBUG_FOR_CLANG
-// Need to re-include assert.h so it is as _we_ would expect it to be (enabled)
-#include <assert.h>
-#endif
-
-#include "lldb/Utility/Log.h"
#include "clang/AST/Decl.h"
-using namespace clang;
using namespace lldb_private;
-bool ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(
- const clang::DeclContext *decl_ctx,
- clang::DeclarationName clang_decl_name) {
- if (m_callback_find_by_name) {
- llvm::SmallVector<clang::NamedDecl *, 3> results;
-
- m_callback_find_by_name(m_callback_baton, decl_ctx, clang_decl_name,
- &results);
-
- SetExternalVisibleDeclsForName(decl_ctx, clang_decl_name, results);
-
- return (results.size() != 0);
- }
-
- std::string decl_name(clang_decl_name.getAsString());
- SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
- return false;
-}
-
-void ClangExternalASTSourceCallbacks::CompleteType(TagDecl *tag_decl) {
- if (m_callback_tag_decl)
- m_callback_tag_decl(m_callback_baton, tag_decl);
+void ClangExternalASTSourceCallbacks::CompleteType(clang::TagDecl *tag_decl) {
+ m_ast.CompleteTagDecl(tag_decl);
}
void ClangExternalASTSourceCallbacks::CompleteType(
- ObjCInterfaceDecl *objc_decl) {
- if (m_callback_objc_decl)
- m_callback_objc_decl(m_callback_baton, objc_decl);
+ clang::ObjCInterfaceDecl *objc_decl) {
+ m_ast.CompleteObjCInterfaceDecl(objc_decl);
}
bool ClangExternalASTSourceCallbacks::layoutRecordType(
@@ -78,19 +28,15 @@ bool ClangExternalASTSourceCallbacks::layoutRecordType(
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets,
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
&VirtualBaseOffsets) {
- if (m_callback_layout_record_type)
- return m_callback_layout_record_type(m_callback_baton, Record, Size,
- Alignment, FieldOffsets, BaseOffsets,
- VirtualBaseOffsets);
-
- return false;
+ return m_ast.LayoutRecordType(Record, Size, Alignment, FieldOffsets,
+ BaseOffsets, VirtualBaseOffsets);
}
void ClangExternalASTSourceCallbacks::FindExternalLexicalDecls(
const clang::DeclContext *decl_ctx,
llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
llvm::SmallVectorImpl<clang::Decl *> &decls) {
- if (m_callback_tag_decl && decl_ctx) {
+ if (decl_ctx) {
clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(
const_cast<clang::DeclContext *>(decl_ctx));
if (tag_decl)
diff --git a/lldb/source/Symbol/ClangExternalASTSourceCommon.cpp b/lldb/source/Symbol/ClangExternalASTSourceCommon.cpp
deleted file mode 100644
index 3dcf9051d0a4..000000000000
--- a/lldb/source/Symbol/ClangExternalASTSourceCommon.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-//===-- ClangExternalASTSourceCommon.cpp ------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
-#include "lldb/Utility/Stream.h"
-
-#include <mutex>
-
-using namespace lldb_private;
-
-uint64_t g_TotalSizeOfMetadata = 0;
-
-typedef llvm::DenseMap<clang::ExternalASTSource *,
- ClangExternalASTSourceCommon *>
- ASTSourceMap;
-
-static ASTSourceMap &GetSourceMap(std::unique_lock<std::mutex> &guard) {
- // Intentionally leaked to avoid problems with global destructors.
- static ASTSourceMap *s_source_map = new ASTSourceMap;
- static std::mutex s_mutex;
- std::unique_lock<std::mutex> locked_guard(s_mutex);
- guard.swap(locked_guard);
- return *s_source_map;
-}
-
-ClangExternalASTSourceCommon *
-ClangExternalASTSourceCommon::Lookup(clang::ExternalASTSource *source) {
- std::unique_lock<std::mutex> guard;
- ASTSourceMap &source_map = GetSourceMap(guard);
-
- ASTSourceMap::iterator iter = source_map.find(source);
-
- if (iter != source_map.end()) {
- return iter->second;
- } else {
- return nullptr;
- }
-}
-
-ClangExternalASTSourceCommon::ClangExternalASTSourceCommon()
- : clang::ExternalASTSource() {
- g_TotalSizeOfMetadata += m_metadata.size();
- std::unique_lock<std::mutex> guard;
- GetSourceMap(guard)[this] = this;
-}
-
-ClangExternalASTSourceCommon::~ClangExternalASTSourceCommon() {
- std::unique_lock<std::mutex> guard;
- GetSourceMap(guard).erase(this);
- g_TotalSizeOfMetadata -= m_metadata.size();
-}
-
-ClangASTMetadata *
-ClangExternalASTSourceCommon::GetMetadata(const void *object) {
- if (HasMetadata(object))
- return &m_metadata[object];
- else
- return nullptr;
-}
-
-void ClangExternalASTSourceCommon::SetMetadata(const void *object,
- ClangASTMetadata &metadata) {
- uint64_t orig_size = m_metadata.size();
- m_metadata[object] = metadata;
- uint64_t new_size = m_metadata.size();
- g_TotalSizeOfMetadata += (new_size - orig_size);
-}
-
-bool ClangExternalASTSourceCommon::HasMetadata(const void *object) {
- return m_metadata.find(object) != m_metadata.end();
-}
-
-void ClangASTMetadata::Dump(Stream *s) {
- lldb::user_id_t uid = GetUserID();
-
- if (uid != LLDB_INVALID_UID) {
- s->Printf("uid=0x%" PRIx64, uid);
- }
-
- uint64_t isa_ptr = GetISAPtr();
- if (isa_ptr != 0) {
- s->Printf("isa_ptr=0x%" PRIx64, isa_ptr);
- }
-
- const char *obj_ptr_name = GetObjectPtrName();
- if (obj_ptr_name) {
- s->Printf("obj_ptr_name=\"%s\" ", obj_ptr_name);
- }
-
- if (m_is_dynamic_cxx) {
- s->Printf("is_dynamic_cxx=%i ", m_is_dynamic_cxx);
- }
- s->EOL();
-}
diff --git a/lldb/source/Symbol/ClangUtil.cpp b/lldb/source/Symbol/ClangUtil.cpp
index 86be895fadcb..52ea4f5111d6 100644
--- a/lldb/source/Symbol/ClangUtil.cpp
+++ b/lldb/source/Symbol/ClangUtil.cpp
@@ -15,6 +15,10 @@ using namespace clang;
using namespace lldb_private;
bool ClangUtil::IsClangType(const CompilerType &ct) {
+ // Invalid types are never Clang types.
+ if (!ct)
+ return false;
+
if (llvm::dyn_cast_or_null<ClangASTContext>(ct.GetTypeSystem()) == nullptr)
return false;
@@ -55,3 +59,24 @@ clang::TagDecl *ClangUtil::GetAsTagDecl(const CompilerType &type) {
return qual_type->getAsTagDecl();
}
+
+std::string ClangUtil::DumpDecl(const clang::Decl *d) {
+ if (!d)
+ return "nullptr";
+
+ std::string result;
+ llvm::raw_string_ostream stream(result);
+ bool deserialize = false;
+ d->dump(stream, deserialize);
+
+ stream.flush();
+ return result;
+}
+
+std::string ClangUtil::ToString(const clang::Type *t) {
+ return clang::QualType(t, 0).getAsString();
+}
+
+std::string ClangUtil::ToString(const CompilerType &c) {
+ return ClangUtil::GetQualType(c).getAsString();
+}
diff --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp
index 41086d2df3df..b05036e27fcf 100644
--- a/lldb/source/Symbol/CompileUnit.cpp
+++ b/lldb/source/Symbol/CompileUnit.cpp
@@ -12,6 +12,7 @@
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Language.h"
+#include "lldb/Utility/Timer.h"
using namespace lldb;
using namespace lldb_private;
@@ -20,30 +21,21 @@ CompileUnit::CompileUnit(const lldb::ModuleSP &module_sp, void *user_data,
const char *pathname, const lldb::user_id_t cu_sym_id,
lldb::LanguageType language,
lldb_private::LazyBool is_optimized)
- : ModuleChild(module_sp), FileSpec(pathname), UserID(cu_sym_id),
- m_user_data(user_data), m_language(language), m_flags(0),
- m_support_files(), m_line_table_up(), m_variables(),
- m_is_optimized(is_optimized) {
- if (language != eLanguageTypeUnknown)
- m_flags.Set(flagsParsedLanguage);
- assert(module_sp);
-}
+ : CompileUnit(module_sp, user_data, FileSpec(pathname), cu_sym_id, language,
+ is_optimized) {}
CompileUnit::CompileUnit(const lldb::ModuleSP &module_sp, void *user_data,
const FileSpec &fspec, const lldb::user_id_t cu_sym_id,
lldb::LanguageType language,
lldb_private::LazyBool is_optimized)
- : ModuleChild(module_sp), FileSpec(fspec), UserID(cu_sym_id),
- m_user_data(user_data), m_language(language), m_flags(0),
- m_support_files(), m_line_table_up(), m_variables(),
+ : ModuleChild(module_sp), UserID(cu_sym_id), m_user_data(user_data),
+ m_language(language), m_flags(0), m_file_spec(fspec),
m_is_optimized(is_optimized) {
if (language != eLanguageTypeUnknown)
m_flags.Set(flagsParsedLanguage);
assert(module_sp);
}
-CompileUnit::~CompileUnit() {}
-
void CompileUnit::CalculateSymbolContext(SymbolContext *sc) {
sc->comp_unit = this;
GetModule()->CalculateSymbolContext(sc);
@@ -62,7 +54,7 @@ void CompileUnit::GetDescription(Stream *s,
lldb::DescriptionLevel level) const {
const char *language = Language::GetNameForLanguageType(m_language);
*s << "id = " << (const UserID &)*this << ", file = \""
- << (const FileSpec &)*this << "\", language = \"" << language << '"';
+ << this->GetPrimaryFile() << "\", language = \"" << language << '"';
}
void CompileUnit::ForeachFunction(
@@ -81,6 +73,31 @@ void CompileUnit::ForeachFunction(
return;
}
+lldb::FunctionSP CompileUnit::FindFunction(
+ llvm::function_ref<bool(const FunctionSP &)> matching_lambda) {
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "CompileUnit::FindFunction");
+
+ lldb::ModuleSP module = CalculateSymbolContextModule();
+
+ if (!module)
+ return {};
+
+ SymbolFile *symbol_file = module->GetSymbolFile();
+
+ if (!symbol_file)
+ return {};
+
+ // m_functions_by_uid is filled in lazily but we need all the entries.
+ symbol_file->ParseFunctions(*this);
+
+ for (auto &p : m_functions_by_uid) {
+ if (matching_lambda(p.second))
+ return p.second;
+ }
+ return {};
+}
+
// Dump the current contents of this object. No functions that cause on demand
// parsing of functions, globals, statics are called, so this is a good
// function to call to get an idea of the current contents of the CompileUnit
@@ -91,8 +108,7 @@ void CompileUnit::Dump(Stream *s, bool show_context) const {
s->Printf("%p: ", static_cast<const void *>(this));
s->Indent();
*s << "CompileUnit" << static_cast<const UserID &>(*this) << ", language = \""
- << language << "\", file = '" << static_cast<const FileSpec &>(*this)
- << "'\n";
+ << language << "\", file = '" << GetPrimaryFile() << "'\n";
// m_types.Dump(s);
@@ -191,53 +207,50 @@ VariableListSP CompileUnit::GetVariableList(bool can_create) {
return m_variables;
}
+std::vector<uint32_t> FindFileIndexes(const FileSpecList &files, const FileSpec &file) {
+ std::vector<uint32_t> result;
+ uint32_t idx = -1;
+ while ((idx = files.FindFileIndex(idx + 1, file, /*full=*/true)) !=
+ UINT32_MAX)
+ result.push_back(idx);
+ return result;
+}
+
uint32_t CompileUnit::FindLineEntry(uint32_t start_idx, uint32_t line,
const FileSpec *file_spec_ptr, bool exact,
LineEntry *line_entry_ptr) {
- uint32_t file_idx = 0;
+ if (!file_spec_ptr)
+ file_spec_ptr = &GetPrimaryFile();
+ std::vector<uint32_t> file_indexes = FindFileIndexes(GetSupportFiles(), *file_spec_ptr);
+ if (file_indexes.empty())
+ return UINT32_MAX;
- if (file_spec_ptr) {
- file_idx = GetSupportFiles().FindFileIndex(1, *file_spec_ptr, true);
- if (file_idx == UINT32_MAX)
- return UINT32_MAX;
- } else {
- // All the line table entries actually point to the version of the Compile
- // Unit that is in the support files (the one at 0 was artificially added.)
- // So prefer the one further on in the support files if it exists...
- const FileSpecList &support_files = GetSupportFiles();
- const bool full = true;
- file_idx = support_files.FindFileIndex(
- 1, support_files.GetFileSpecAtIndex(0), full);
- if (file_idx == UINT32_MAX)
- file_idx = 0;
- }
LineTable *line_table = GetLineTable();
if (line_table)
- return line_table->FindLineEntryIndexByFileIndex(start_idx, file_idx, line,
- exact, line_entry_ptr);
+ return line_table->FindLineEntryIndexByFileIndex(
+ start_idx, file_indexes, line, exact, line_entry_ptr);
return UINT32_MAX;
}
-uint32_t CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,
- uint32_t line, bool check_inlines,
- bool exact,
- SymbolContextItem resolve_scope,
- SymbolContextList &sc_list) {
+void CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,
+ uint32_t line, bool check_inlines,
+ bool exact,
+ SymbolContextItem resolve_scope,
+ SymbolContextList &sc_list) {
// First find all of the file indexes that match our "file_spec". If
// "file_spec" has an empty directory, then only compare the basenames when
// finding file indexes
std::vector<uint32_t> file_indexes;
- const bool full_match = (bool)file_spec.GetDirectory();
bool file_spec_matches_cu_file_spec =
- FileSpec::Equal(file_spec, *this, full_match);
+ FileSpec::Match(file_spec, this->GetPrimaryFile());
// If we are not looking for inlined functions and our file spec doesn't
// match then we are done...
if (!file_spec_matches_cu_file_spec && !check_inlines)
- return 0;
+ return;
uint32_t file_idx =
- GetSupportFiles().FindFileIndex(1, file_spec, true);
+ GetSupportFiles().FindFileIndex(0, file_spec, true);
while (file_idx != UINT32_MAX) {
file_indexes.push_back(file_idx);
file_idx = GetSupportFiles().FindFileIndex(file_idx + 1, file_spec, true);
@@ -245,84 +258,67 @@ uint32_t CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,
const size_t num_file_indexes = file_indexes.size();
if (num_file_indexes == 0)
- return 0;
-
- const uint32_t prev_size = sc_list.GetSize();
+ return;
SymbolContext sc(GetModule());
sc.comp_unit = this;
- if (line != 0) {
- LineTable *line_table = sc.comp_unit->GetLineTable();
-
- if (line_table != nullptr) {
- uint32_t found_line;
- uint32_t line_idx;
-
- if (num_file_indexes == 1) {
- // We only have a single support file that matches, so use the line
- // table function that searches for a line entries that match a single
- // support file index
- LineEntry line_entry;
- line_idx = line_table->FindLineEntryIndexByFileIndex(
- 0, file_indexes.front(), line, exact, &line_entry);
-
- // If "exact == true", then "found_line" will be the same as "line". If
- // "exact == false", the "found_line" will be the closest line entry
- // with a line number greater than "line" and we will use this for our
- // subsequent line exact matches below.
- found_line = line_entry.line;
-
- while (line_idx != UINT32_MAX) {
- // If they only asked for the line entry, then we're done, we can
- // just copy that over. But if they wanted more than just the line
- // number, fill it in.
- if (resolve_scope == eSymbolContextLineEntry) {
- sc.line_entry = line_entry;
- } else {
- line_entry.range.GetBaseAddress().CalculateSymbolContext(
- &sc, resolve_scope);
- }
-
- sc_list.Append(sc);
- line_idx = line_table->FindLineEntryIndexByFileIndex(
- line_idx + 1, file_indexes.front(), found_line, true,
- &line_entry);
- }
- } else {
- // We found multiple support files that match "file_spec" so use the
- // line table function that searches for a line entries that match a
- // multiple support file indexes.
- LineEntry line_entry;
- line_idx = line_table->FindLineEntryIndexByFileIndex(
- 0, file_indexes, line, exact, &line_entry);
-
- // If "exact == true", then "found_line" will be the same as "line". If
- // "exact == false", the "found_line" will be the closest line entry
- // with a line number greater than "line" and we will use this for our
- // subsequent line exact matches below.
- found_line = line_entry.line;
-
- while (line_idx != UINT32_MAX) {
- if (resolve_scope == eSymbolContextLineEntry) {
- sc.line_entry = line_entry;
- } else {
- line_entry.range.GetBaseAddress().CalculateSymbolContext(
- &sc, resolve_scope);
- }
-
- sc_list.Append(sc);
- line_idx = line_table->FindLineEntryIndexByFileIndex(
- line_idx + 1, file_indexes, found_line, true, &line_entry);
- }
- }
+ if (line == 0) {
+ if (file_spec_matches_cu_file_spec && !check_inlines) {
+ // only append the context if we aren't looking for inline call sites by
+ // file and line and if the file spec matches that of the compile unit
+ sc_list.Append(sc);
}
- } else if (file_spec_matches_cu_file_spec && !check_inlines) {
- // only append the context if we aren't looking for inline call sites by
- // file and line and if the file spec matches that of the compile unit
+ return;
+ }
+
+ LineTable *line_table = sc.comp_unit->GetLineTable();
+
+ if (line_table == nullptr)
+ return;
+
+ uint32_t line_idx;
+ LineEntry line_entry;
+
+ if (num_file_indexes == 1) {
+ // We only have a single support file that matches, so use the line
+ // table function that searches for a line entries that match a single
+ // support file index
+ line_idx = line_table->FindLineEntryIndexByFileIndex(
+ 0, file_indexes.front(), line, exact, &line_entry);
+ } else {
+ // We found multiple support files that match "file_spec" so use the
+ // line table function that searches for a line entries that match a
+ // multiple support file indexes.
+ line_idx = line_table->FindLineEntryIndexByFileIndex(0, file_indexes, line,
+ exact, &line_entry);
+ }
+
+ // If "exact == true", then "found_line" will be the same as "line". If
+ // "exact == false", the "found_line" will be the closest line entry
+ // with a line number greater than "line" and we will use this for our
+ // subsequent line exact matches below.
+ uint32_t found_line = line_entry.line;
+
+ while (line_idx != UINT32_MAX) {
+ // If they only asked for the line entry, then we're done, we can
+ // just copy that over. But if they wanted more than just the line
+ // number, fill it in.
+ if (resolve_scope == eSymbolContextLineEntry) {
+ sc.line_entry = line_entry;
+ } else {
+ line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc,
+ resolve_scope);
+ }
+
sc_list.Append(sc);
+ if (num_file_indexes == 1)
+ line_idx = line_table->FindLineEntryIndexByFileIndex(
+ line_idx + 1, file_indexes.front(), found_line, true, &line_entry);
+ else
+ line_idx = line_table->FindLineEntryIndexByFileIndex(
+ line_idx + 1, file_indexes, found_line, true, &line_entry);
}
- return sc_list.GetSize() - prev_size;
}
bool CompileUnit::GetIsOptimized() {
@@ -353,9 +349,12 @@ const std::vector<SourceModule> &CompileUnit::GetImportedModules() {
return m_imported_modules;
}
-void CompileUnit::ForEachExternalModule(llvm::function_ref<void(ModuleSP)> f) {
+bool CompileUnit::ForEachExternalModule(
+ llvm::DenseSet<SymbolFile *> &visited_symbol_files,
+ llvm::function_ref<bool(Module &)> lambda) {
if (SymbolFile *symfile = GetModule()->GetSymbolFile())
- symfile->ForEachExternalModule(*this, f);
+ return symfile->ForEachExternalModule(*this, visited_symbol_files, lambda);
+ return false;
}
const FileSpecList &CompileUnit::GetSupportFiles() {
diff --git a/lldb/source/Symbol/CompilerDecl.cpp b/lldb/source/Symbol/CompilerDecl.cpp
index 2c64113a2bbe..48d9169c1a7a 100644
--- a/lldb/source/Symbol/CompilerDecl.cpp
+++ b/lldb/source/Symbol/CompilerDecl.cpp
@@ -12,10 +12,6 @@
using namespace lldb_private;
-bool CompilerDecl::IsClang() const {
- return IsValid() && m_type_system->getKind() == TypeSystem::eKindClang;
-}
-
ConstString CompilerDecl::GetName() const {
return m_type_system->DeclGetName(m_opaque_decl);
}
diff --git a/lldb/source/Symbol/CompilerDeclContext.cpp b/lldb/source/Symbol/CompilerDeclContext.cpp
index a6f046c4eb22..581e0872a6a7 100644
--- a/lldb/source/Symbol/CompilerDeclContext.cpp
+++ b/lldb/source/Symbol/CompilerDeclContext.cpp
@@ -19,33 +19,19 @@ CompilerDeclContext::FindDeclByName(ConstString name,
if (IsValid())
return m_type_system->DeclContextFindDeclByName(m_opaque_decl_ctx, name,
ignore_using_decls);
- else
- return std::vector<CompilerDecl>();
-}
-
-bool CompilerDeclContext::IsClang() const {
- return IsValid() && m_type_system->getKind() == TypeSystem::eKindClang;
+ return std::vector<CompilerDecl>();
}
ConstString CompilerDeclContext::GetName() const {
if (IsValid())
return m_type_system->DeclContextGetName(m_opaque_decl_ctx);
- else
- return ConstString();
+ return ConstString();
}
ConstString CompilerDeclContext::GetScopeQualifiedName() const {
if (IsValid())
return m_type_system->DeclContextGetScopeQualifiedName(m_opaque_decl_ctx);
- else
- return ConstString();
-}
-
-bool CompilerDeclContext::IsStructUnionOrClass() const {
- if (IsValid())
- return m_type_system->DeclContextIsStructUnionOrClass(m_opaque_decl_ctx);
- else
- return false;
+ return ConstString();
}
bool CompilerDeclContext::IsClassMethod(lldb::LanguageType *language_ptr,
@@ -55,8 +41,7 @@ bool CompilerDeclContext::IsClassMethod(lldb::LanguageType *language_ptr,
return m_type_system->DeclContextIsClassMethod(
m_opaque_decl_ctx, language_ptr, is_instance_method_ptr,
language_object_name_ptr);
- else
- return false;
+ return false;
}
bool CompilerDeclContext::IsContainedInLookup(CompilerDeclContext other) const {
diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp
index 571a8570a43b..09930f7a800e 100644
--- a/lldb/source/Symbol/CompilerType.cpp
+++ b/lldb/source/Symbol/CompilerType.cpp
@@ -26,12 +26,6 @@
using namespace lldb;
using namespace lldb_private;
-CompilerType::CompilerType(TypeSystem *type_system,
- lldb::opaque_compiler_type_t type)
- : m_type(type), m_type_system(type_system) {}
-
-CompilerType::~CompilerType() {}
-
// Tests
bool CompilerType::IsAggregateType() const {
@@ -427,6 +421,12 @@ CompilerType CompilerType::GetRValueReferenceType() const {
return CompilerType();
}
+CompilerType CompilerType::GetAtomicType() const {
+ if (IsValid())
+ return m_type_system->GetAtomicType(m_type);
+ return CompilerType();
+}
+
CompilerType CompilerType::AddConstModifier() const {
if (IsValid())
return m_type_system->AddConstModifier(m_type);
@@ -874,173 +874,6 @@ bool CompilerType::GetValueAsScalar(const lldb_private::DataExtractor &data,
return false;
}
-bool CompilerType::SetValueFromScalar(const Scalar &value, Stream &strm) {
- if (!IsValid())
- return false;
-
- // Aggregate types don't have scalar values
- if (!IsAggregateType()) {
- strm.GetFlags().Set(Stream::eBinary);
- uint64_t count = 0;
- lldb::Encoding encoding = GetEncoding(count);
-
- if (encoding == lldb::eEncodingInvalid || count != 1)
- return false;
-
- llvm::Optional<uint64_t> bit_width = GetBitSize(nullptr);
- if (!bit_width)
- return false;
-
- // This function doesn't currently handle non-byte aligned assignments
- if ((*bit_width % 8) != 0)
- return false;
-
- const uint64_t byte_size = (*bit_width + 7) / 8;
- switch (encoding) {
- case lldb::eEncodingInvalid:
- break;
- case lldb::eEncodingVector:
- break;
- case lldb::eEncodingUint:
- switch (byte_size) {
- case 1:
- strm.PutHex8(value.UInt());
- return true;
- case 2:
- strm.PutHex16(value.UInt());
- return true;
- case 4:
- strm.PutHex32(value.UInt());
- return true;
- case 8:
- strm.PutHex64(value.ULongLong());
- return true;
- default:
- break;
- }
- break;
-
- case lldb::eEncodingSint:
- switch (byte_size) {
- case 1:
- strm.PutHex8(value.SInt());
- return true;
- case 2:
- strm.PutHex16(value.SInt());
- return true;
- case 4:
- strm.PutHex32(value.SInt());
- return true;
- case 8:
- strm.PutHex64(value.SLongLong());
- return true;
- default:
- break;
- }
- break;
-
- case lldb::eEncodingIEEE754:
- if (byte_size <= sizeof(long double)) {
- if (byte_size == sizeof(float)) {
- strm.PutFloat(value.Float());
- return true;
- } else if (byte_size == sizeof(double)) {
- strm.PutDouble(value.Double());
- return true;
- } else if (byte_size == sizeof(long double)) {
- strm.PutDouble(value.LongDouble());
- return true;
- }
- }
- break;
- }
- }
- return false;
-}
-
-bool CompilerType::ReadFromMemory(lldb_private::ExecutionContext *exe_ctx,
- lldb::addr_t addr, AddressType address_type,
- lldb_private::DataExtractor &data) {
- if (!IsValid())
- return false;
-
- // Can't convert a file address to anything valid without more context (which
- // Module it came from)
- if (address_type == eAddressTypeFile)
- return false;
-
- if (!GetCompleteType())
- return false;
-
- auto byte_size =
- GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr);
- if (!byte_size)
- return false;
-
- if (data.GetByteSize() < *byte_size) {
- lldb::DataBufferSP data_sp(new DataBufferHeap(*byte_size, '\0'));
- data.SetData(data_sp);
- }
-
- uint8_t *dst = const_cast<uint8_t *>(data.PeekData(0, *byte_size));
- if (dst != nullptr) {
- if (address_type == eAddressTypeHost) {
- if (addr == 0)
- return false;
- // The address is an address in this process, so just copy it
- memcpy(dst, reinterpret_cast<uint8_t *>(addr), *byte_size);
- return true;
- } else {
- Process *process = nullptr;
- if (exe_ctx)
- process = exe_ctx->GetProcessPtr();
- if (process) {
- Status error;
- return process->ReadMemory(addr, dst, *byte_size, error) == *byte_size;
- }
- }
- }
- return false;
-}
-
-bool CompilerType::WriteToMemory(lldb_private::ExecutionContext *exe_ctx,
- lldb::addr_t addr, AddressType address_type,
- StreamString &new_value) {
- if (!IsValid())
- return false;
-
- // Can't convert a file address to anything valid without more context (which
- // Module it came from)
- if (address_type == eAddressTypeFile)
- return false;
-
- if (!GetCompleteType())
- return false;
-
- auto byte_size =
- GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr);
- if (!byte_size)
- return false;
-
- if (*byte_size > 0) {
- if (address_type == eAddressTypeHost) {
- // The address is an address in this process, so just copy it
- memcpy((void *)addr, new_value.GetData(), *byte_size);
- return true;
- } else {
- Process *process = nullptr;
- if (exe_ctx)
- process = exe_ctx->GetProcessPtr();
- if (process) {
- Status error;
- return process->WriteMemory(addr, new_value.GetData(), *byte_size,
- error) == *byte_size;
- }
- }
- }
- return false;
-}
-
bool lldb_private::operator==(const lldb_private::CompilerType &lhs,
const lldb_private::CompilerType &rhs) {
return lhs.GetTypeSystem() == rhs.GetTypeSystem() &&
diff --git a/lldb/source/Symbol/Declaration.cpp b/lldb/source/Symbol/Declaration.cpp
index d78ba967d280..4d0975d34256 100644
--- a/lldb/source/Symbol/Declaration.cpp
+++ b/lldb/source/Symbol/Declaration.cpp
@@ -90,12 +90,9 @@ bool Declaration::FileAndLineEqual(const Declaration &declaration) const {
bool lldb_private::operator==(const Declaration &lhs, const Declaration &rhs) {
#ifdef LLDB_ENABLE_DECLARATION_COLUMNS
- if (lhs.GetColumn() == rhs.GetColumn())
- if (lhs.GetLine() == rhs.GetLine())
- return lhs.GetFile() == rhs.GetFile();
+ if (lhs.GetColumn() != rhs.GetColumn())
+ return false;
#else
- if (lhs.GetLine() == rhs.GetLine())
- return FileSpec::Equal(lhs.GetFile(), rhs.GetFile(), true);
+ return lhs.GetLine() == rhs.GetLine() && lhs.GetFile() == rhs.GetFile();
#endif
- return false;
}
diff --git a/lldb/source/Symbol/FuncUnwinders.cpp b/lldb/source/Symbol/FuncUnwinders.cpp
index f609bf7821e1..7a6f3cefea66 100644
--- a/lldb/source/Symbol/FuncUnwinders.cpp
+++ b/lldb/source/Symbol/FuncUnwinders.cpp
@@ -41,7 +41,9 @@ FuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, AddressRange range)
m_unwind_plan_arch_default_sp(),
m_unwind_plan_arch_default_at_func_entry_sp(),
m_tried_unwind_plan_assembly(false), m_tried_unwind_plan_eh_frame(false),
+ m_tried_unwind_plan_object_file(false),
m_tried_unwind_plan_debug_frame(false),
+ m_tried_unwind_plan_object_file_augmented(false),
m_tried_unwind_plan_eh_frame_augmented(false),
m_tried_unwind_plan_debug_frame_augmented(false),
m_tried_unwind_plan_compact_unwind(false),
diff --git a/lldb/source/Symbol/Function.cpp b/lldb/source/Symbol/Function.cpp
index a4c2d3b4b44a..e92585ccfed7 100644
--- a/lldb/source/Symbol/Function.cpp
+++ b/lldb/source/Symbol/Function.cpp
@@ -17,6 +17,7 @@
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Target/Language.h"
+#include "lldb/Target/Target.h"
#include "lldb/Utility/Log.h"
#include "llvm/Support/Casting.h"
@@ -75,16 +76,6 @@ InlineFunctionInfo::InlineFunctionInfo(ConstString name,
InlineFunctionInfo::~InlineFunctionInfo() {}
-int InlineFunctionInfo::Compare(const InlineFunctionInfo &a,
- const InlineFunctionInfo &b) {
-
- int result = FunctionInfo::Compare(a, b);
- if (result)
- return result;
- // only compare the mangled names if both have them
- return Mangled::Compare(a.m_mangled, a.m_mangled);
-}
-
void InlineFunctionInfo::Dump(Stream *s, bool show_fullpaths) const {
FunctionInfo::Dump(s, show_fullpaths);
if (m_mangled)
@@ -127,23 +118,21 @@ size_t InlineFunctionInfo::MemorySize() const {
return FunctionInfo::MemorySize() + m_mangled.MemorySize();
}
-//
-CallEdge::CallEdge(const char *symbol_name, lldb::addr_t return_pc,
- CallSiteParameterArray parameters)
- : return_pc(return_pc), parameters(std::move(parameters)), resolved(false) {
- lazy_callee.symbol_name = symbol_name;
-}
+/// @name Call site related structures
+/// @{
-llvm::ArrayRef<CallSiteParameter> CallEdge::GetCallSiteParameters() const {
- return parameters;
+lldb::addr_t CallEdge::GetReturnPCAddress(Function &caller,
+ Target &target) const {
+ const Address &base = caller.GetAddressRange().GetBaseAddress();
+ return base.GetLoadAddress(&target) + return_pc;
}
-void CallEdge::ParseSymbolFileAndResolve(ModuleList &images) {
+void DirectCallEdge::ParseSymbolFileAndResolve(ModuleList &images) {
if (resolved)
return;
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
- LLDB_LOG(log, "CallEdge: Lazily parsing the call graph for {0}",
+ LLDB_LOG(log, "DirectCallEdge: Lazily parsing the call graph for {0}",
lazy_callee.symbol_name);
auto resolve_lazy_callee = [&]() -> Function * {
@@ -152,18 +141,19 @@ void CallEdge::ParseSymbolFileAndResolve(ModuleList &images) {
images.FindFunctionSymbols(callee_name, eFunctionNameTypeAuto, sc_list);
size_t num_matches = sc_list.GetSize();
if (num_matches == 0 || !sc_list[0].symbol) {
- LLDB_LOG(log, "CallEdge: Found no symbols for {0}, cannot resolve it",
+ LLDB_LOG(log,
+ "DirectCallEdge: Found no symbols for {0}, cannot resolve it",
callee_name);
return nullptr;
}
Address callee_addr = sc_list[0].symbol->GetAddress();
if (!callee_addr.IsValid()) {
- LLDB_LOG(log, "CallEdge: Invalid symbol address");
+ LLDB_LOG(log, "DirectCallEdge: Invalid symbol address");
return nullptr;
}
Function *f = callee_addr.CalculateSymbolContextFunction();
if (!f) {
- LLDB_LOG(log, "CallEdge: Could not find complete function");
+ LLDB_LOG(log, "DirectCallEdge: Could not find complete function");
return nullptr;
}
return f;
@@ -172,18 +162,50 @@ void CallEdge::ParseSymbolFileAndResolve(ModuleList &images) {
resolved = true;
}
-Function *CallEdge::GetCallee(ModuleList &images) {
+Function *DirectCallEdge::GetCallee(ModuleList &images, ExecutionContext &) {
ParseSymbolFileAndResolve(images);
assert(resolved && "Did not resolve lazy callee");
return lazy_callee.def;
}
-lldb::addr_t CallEdge::GetReturnPCAddress(Function &caller,
- Target &target) const {
- const Address &base = caller.GetAddressRange().GetBaseAddress();
- return base.GetLoadAddress(&target) + return_pc;
+Function *IndirectCallEdge::GetCallee(ModuleList &images,
+ ExecutionContext &exe_ctx) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+ Status error;
+ Value callee_addr_val;
+ if (!call_target.Evaluate(&exe_ctx, exe_ctx.GetRegisterContext(),
+ /*loclist_base_addr=*/LLDB_INVALID_ADDRESS,
+ /*initial_value_ptr=*/nullptr,
+ /*object_address_ptr=*/nullptr, callee_addr_val,
+ &error)) {
+ LLDB_LOGF(log, "IndirectCallEdge: Could not evaluate expression: %s",
+ error.AsCString());
+ return nullptr;
+ }
+
+ addr_t raw_addr = callee_addr_val.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+ if (raw_addr == LLDB_INVALID_ADDRESS) {
+ LLDB_LOG(log, "IndirectCallEdge: Could not extract address from scalar");
+ return nullptr;
+ }
+
+ Address callee_addr;
+ if (!exe_ctx.GetTargetPtr()->ResolveLoadAddress(raw_addr, callee_addr)) {
+ LLDB_LOG(log, "IndirectCallEdge: Could not resolve callee's load address");
+ return nullptr;
+ }
+
+ Function *f = callee_addr.CalculateSymbolContextFunction();
+ if (!f) {
+ LLDB_LOG(log, "IndirectCallEdge: Could not find complete function");
+ return nullptr;
+ }
+
+ return f;
}
+/// @}
+
//
Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid,
lldb::user_id_t type_uid, const Mangled &mangled, Type *type,
@@ -246,7 +268,7 @@ void Function::GetEndLineSourceInfo(FileSpec &source_file, uint32_t &line_no) {
}
}
-llvm::MutableArrayRef<CallEdge> Function::GetCallEdges() {
+llvm::ArrayRef<std::unique_ptr<CallEdge>> Function::GetCallEdges() {
if (m_call_edges_resolved)
return m_call_edges;
@@ -267,19 +289,20 @@ llvm::MutableArrayRef<CallEdge> Function::GetCallEdges() {
// Sort the call edges to speed up return_pc lookups.
llvm::sort(m_call_edges.begin(), m_call_edges.end(),
- [](const CallEdge &LHS, const CallEdge &RHS) {
- return LHS.GetUnresolvedReturnPCAddress() <
- RHS.GetUnresolvedReturnPCAddress();
+ [](const std::unique_ptr<CallEdge> &LHS,
+ const std::unique_ptr<CallEdge> &RHS) {
+ return LHS->GetUnresolvedReturnPCAddress() <
+ RHS->GetUnresolvedReturnPCAddress();
});
return m_call_edges;
}
-llvm::MutableArrayRef<CallEdge> Function::GetTailCallingEdges() {
+llvm::ArrayRef<std::unique_ptr<CallEdge>> Function::GetTailCallingEdges() {
// Call edges are sorted by return PC, and tail calling edges have invalid
// return PCs. Find them at the end of the list.
- return GetCallEdges().drop_until([](const CallEdge &edge) {
- return edge.GetUnresolvedReturnPCAddress() == LLDB_INVALID_ADDRESS;
+ return GetCallEdges().drop_until([](const std::unique_ptr<CallEdge> &edge) {
+ return edge->GetUnresolvedReturnPCAddress() == LLDB_INVALID_ADDRESS;
});
}
@@ -288,13 +311,13 @@ CallEdge *Function::GetCallEdgeForReturnAddress(addr_t return_pc,
auto edges = GetCallEdges();
auto edge_it =
std::lower_bound(edges.begin(), edges.end(), return_pc,
- [&](const CallEdge &edge, addr_t pc) {
- return edge.GetReturnPCAddress(*this, target) < pc;
+ [&](const std::unique_ptr<CallEdge> &edge, addr_t pc) {
+ return edge->GetReturnPCAddress(*this, target) < pc;
});
if (edge_it == edges.end() ||
- edge_it->GetReturnPCAddress(*this, target) != return_pc)
+ edge_it->get()->GetReturnPCAddress(*this, target) != return_pc)
return nullptr;
- return &const_cast<CallEdge &>(*edge_it);
+ return &const_cast<CallEdge &>(*edge_it->get());
}
Block &Function::GetBlock(bool can_create) {
@@ -307,7 +330,8 @@ Block &Function::GetBlock(bool can_create) {
"error: unable to find module "
"shared pointer for function '%s' "
"in %s\n",
- GetName().GetCString(), m_comp_unit->GetPath().c_str());
+ GetName().GetCString(),
+ m_comp_unit->GetPrimaryFile().GetPath().c_str());
}
m_block.SetBlockInfoHasBeenParsed(true, true);
}
diff --git a/lldb/source/Symbol/LineEntry.cpp b/lldb/source/Symbol/LineEntry.cpp
index 959a3274ec92..bb3828fef784 100644
--- a/lldb/source/Symbol/LineEntry.cpp
+++ b/lldb/source/Symbol/LineEntry.cpp
@@ -51,7 +51,7 @@ bool LineEntry::IsValid() const {
bool LineEntry::DumpStopContext(Stream *s, bool show_fullpaths) const {
if (file) {
if (show_fullpaths)
- file.Dump(s);
+ file.Dump(s->AsRawOstream());
else
file.GetFilename().Dump(s);
diff --git a/lldb/source/Symbol/LineTable.cpp b/lldb/source/Symbol/LineTable.cpp
index 1433dc156d91..fecc90c409f2 100644
--- a/lldb/source/Symbol/LineTable.cpp
+++ b/lldb/source/Symbol/LineTable.cpp
@@ -34,11 +34,9 @@ void LineTable::InsertLineEntry(lldb::addr_t file_addr, uint32_t line,
is_start_of_basic_block, is_prologue_end, is_epilogue_begin,
is_terminal_entry);
- entry_collection::iterator begin_pos = m_entries.begin();
- entry_collection::iterator end_pos = m_entries.end();
LineTable::Entry::LessThanBinaryPredicate less_than_bp(this);
entry_collection::iterator pos =
- upper_bound(begin_pos, end_pos, entry, less_than_bp);
+ llvm::upper_bound(m_entries, entry, less_than_bp);
// Stream s(stdout);
// s << "\n\nBefore:\n";
@@ -289,8 +287,6 @@ uint32_t LineTable::FindLineEntryIndexByFileIndex(
uint32_t line, bool exact, LineEntry *line_entry_ptr) {
const size_t count = m_entries.size();
- std::vector<uint32_t>::const_iterator begin_pos = file_indexes.begin();
- std::vector<uint32_t>::const_iterator end_pos = file_indexes.end();
size_t best_match = UINT32_MAX;
for (size_t idx = start_idx; idx < count; ++idx) {
@@ -299,7 +295,7 @@ uint32_t LineTable::FindLineEntryIndexByFileIndex(
if (m_entries[idx].is_terminal_entry)
continue;
- if (find(begin_pos, end_pos, m_entries[idx].file_idx) == end_pos)
+ if (llvm::find(file_indexes, m_entries[idx].file_idx) == file_indexes.end())
continue;
// Exact match always wins. Otherwise try to find the closest line > the
diff --git a/lldb/source/Symbol/LocateSymbolFile.cpp b/lldb/source/Symbol/LocateSymbolFile.cpp
index 0d0e5300668f..d2b39d6acd70 100644
--- a/lldb/source/Symbol/LocateSymbolFile.cpp
+++ b/lldb/source/Symbol/LocateSymbolFile.cpp
@@ -230,19 +230,19 @@ static FileSpec LocateExecutableSymbolFileDsym(const ModuleSpec &module_spec) {
ModuleSpec Symbols::LocateExecutableObjectFile(const ModuleSpec &module_spec) {
ModuleSpec result;
- const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
+ const FileSpec &exec_fspec = module_spec.GetFileSpec();
const ArchSpec *arch = module_spec.GetArchitecturePtr();
const UUID *uuid = module_spec.GetUUIDPtr();
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(
func_cat, "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)",
- exec_fspec ? exec_fspec->GetFilename().AsCString("<NULL>") : "<NULL>",
+ exec_fspec ? exec_fspec.GetFilename().AsCString("<NULL>") : "<NULL>",
arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid);
ModuleSpecList module_specs;
ModuleSpec matched_module_spec;
if (exec_fspec &&
- ObjectFile::GetModuleSpecifications(*exec_fspec, 0, 0, module_specs) &&
+ ObjectFile::GetModuleSpecifications(exec_fspec, 0, 0, module_specs) &&
module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) {
result.GetFileSpec() = exec_fspec;
} else {
diff --git a/lldb/source/Symbol/LocateSymbolFileMacOSX.cpp b/lldb/source/Symbol/LocateSymbolFileMacOSX.cpp
index 74718a8c5e30..5ee632ec2077 100644
--- a/lldb/source/Symbol/LocateSymbolFileMacOSX.cpp
+++ b/lldb/source/Symbol/LocateSymbolFileMacOSX.cpp
@@ -595,7 +595,7 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
}
Status error = Host::RunShellCommand(
command.GetData(),
- NULL, // current working directory
+ FileSpec(), // current working directory
&exit_status, // Exit status
&signo, // Signal int *
&command_output, // Command output
diff --git a/lldb/source/Symbol/ObjectFile.cpp b/lldb/source/Symbol/ObjectFile.cpp
index 38bc7722d0d0..8a72b5fe6f67 100644
--- a/lldb/source/Symbol/ObjectFile.cpp
+++ b/lldb/source/Symbol/ObjectFile.cpp
@@ -352,7 +352,9 @@ AddressClass ObjectFile::GetAddressClass(addr_t file_addr) {
case eSectionTypeDWARFDebugLine:
case eSectionTypeDWARFDebugLineStr:
case eSectionTypeDWARFDebugLoc:
+ case eSectionTypeDWARFDebugLocDwo:
case eSectionTypeDWARFDebugLocLists:
+ case eSectionTypeDWARFDebugLocListsDwo:
case eSectionTypeDWARFDebugMacInfo:
case eSectionTypeDWARFDebugMacro:
case eSectionTypeDWARFDebugNames:
@@ -360,6 +362,7 @@ AddressClass ObjectFile::GetAddressClass(addr_t file_addr) {
case eSectionTypeDWARFDebugPubTypes:
case eSectionTypeDWARFDebugRanges:
case eSectionTypeDWARFDebugRngLists:
+ case eSectionTypeDWARFDebugRngListsDwo:
case eSectionTypeDWARFDebugStr:
case eSectionTypeDWARFDebugStrDwo:
case eSectionTypeDWARFDebugStrOffsets:
diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp
index 3f2414335813..3ace153d32ab 100644
--- a/lldb/source/Symbol/Symbol.cpp
+++ b/lldb/source/Symbol/Symbol.cpp
@@ -210,7 +210,8 @@ void Symbol::GetDescription(Stream *s, lldb::DescriptionLevel level,
s->Printf(", mangled=\"%s\"", m_mangled.GetMangledName().AsCString());
}
-void Symbol::Dump(Stream *s, Target *target, uint32_t index) const {
+void Symbol::Dump(Stream *s, Target *target, uint32_t index,
+ Mangled::NamePreference name_preference) const {
s->Printf("[%5u] %6u %c%c%c %-15s ", index, GetID(), m_is_debug ? 'D' : ' ',
m_is_synthetic ? 'S' : ' ', m_is_external ? 'X' : ' ',
GetTypeAsString());
@@ -218,7 +219,7 @@ void Symbol::Dump(Stream *s, Target *target, uint32_t index) const {
// Make sure the size of the symbol is up to date before dumping
GetByteSize();
- ConstString name = m_mangled.GetName(GetLanguage());
+ ConstString name = m_mangled.GetName(GetLanguage(), name_preference);
if (ValueIsAddress()) {
if (!m_addr_range.GetBaseAddress().Dump(s, nullptr,
Address::DumpStyleFileAddress))
diff --git a/lldb/source/Symbol/SymbolContext.cpp b/lldb/source/Symbol/SymbolContext.cpp
index 31e0c89eed94..9eb805976f95 100644
--- a/lldb/source/Symbol/SymbolContext.cpp
+++ b/lldb/source/Symbol/SymbolContext.cpp
@@ -55,20 +55,6 @@ SymbolContext::SymbolContext(SymbolContextScope *sc_scope)
SymbolContext::~SymbolContext() {}
-const SymbolContext &SymbolContext::operator=(const SymbolContext &rhs) {
- if (this != &rhs) {
- target_sp = rhs.target_sp;
- module_sp = rhs.module_sp;
- comp_unit = rhs.comp_unit;
- function = rhs.function;
- block = rhs.block;
- line_entry = rhs.line_entry;
- symbol = rhs.symbol;
- variable = rhs.variable;
- }
- return *this;
-}
-
void SymbolContext::Clear(bool clear_target) {
if (clear_target)
target_sp.reset();
@@ -198,7 +184,7 @@ void SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level,
Target *target) const {
if (module_sp) {
s->Indent(" Module: file = \"");
- module_sp->GetFileSpec().Dump(s);
+ module_sp->GetFileSpec().Dump(s->AsRawOstream());
*s << '"';
if (module_sp->GetArchitecture().IsValid())
s->Printf(", arch = \"%s\"",
@@ -324,19 +310,19 @@ void SymbolContext::Dump(Stream *s, Target *target) const {
s->Indent();
*s << "Module = " << module_sp.get() << ' ';
if (module_sp)
- module_sp->GetFileSpec().Dump(s);
+ module_sp->GetFileSpec().Dump(s->AsRawOstream());
s->EOL();
s->Indent();
*s << "CompileUnit = " << comp_unit;
if (comp_unit != nullptr)
- *s << " {0x" << comp_unit->GetID() << "} "
- << *(static_cast<FileSpec *>(comp_unit));
+ s->Format(" {{{0:x-16}} {1}", comp_unit->GetID(),
+ comp_unit->GetPrimaryFile());
s->EOL();
s->Indent();
*s << "Function = " << function;
if (function != nullptr) {
- *s << " {0x" << function->GetID() << "} " << function->GetType()->GetName()
- << ", address-range = ";
+ s->Format(" {{{0:x-16}} {1}, address-range = ", function->GetID(),
+ function->GetType()->GetName());
function->GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress,
Address::DumpStyleModuleWithFileAddress);
s->EOL();
@@ -351,10 +337,7 @@ void SymbolContext::Dump(Stream *s, Target *target) const {
s->Indent();
*s << "Block = " << block;
if (block != nullptr)
- *s << " {0x" << block->GetID() << '}';
- // Dump the block and pass it a negative depth to we print all the parent
- // blocks if (block != NULL)
- // block->Dump(s, function->GetFileAddress(), INT_MIN);
+ s->Format(" {{{0:x-16}}", block->GetID());
s->EOL();
s->Indent();
*s << "LineEntry = ";
@@ -368,7 +351,8 @@ void SymbolContext::Dump(Stream *s, Target *target) const {
s->EOL();
*s << "Variable = " << variable;
if (variable != nullptr) {
- *s << " {0x" << variable->GetID() << "} " << variable->GetType()->GetName();
+ s->Format(" {{{0:x-16}} {1}", variable->GetID(),
+ variable->GetType()->GetName());
s->EOL();
}
s->IndentLess();
@@ -1042,8 +1026,7 @@ bool SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc) {
return false;
} else {
FileSpec module_file_spec(m_module_spec);
- if (!FileSpec::Equal(module_file_spec, sc.module_sp->GetFileSpec(),
- false))
+ if (!FileSpec::Match(module_file_spec, sc.module_sp->GetFileSpec()))
return false;
}
}
@@ -1062,8 +1045,8 @@ bool SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc) {
sc.block->GetInlinedFunctionInfo();
if (inline_info != nullptr) {
was_inlined = true;
- if (!FileSpec::Equal(inline_info->GetDeclaration().GetFile(),
- *(m_file_spec_up.get()), false))
+ if (!FileSpec::Match(*m_file_spec_up,
+ inline_info->GetDeclaration().GetFile()))
return false;
}
}
@@ -1071,7 +1054,7 @@ bool SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc) {
// Next check the comp unit, but only if the SymbolContext was not
// inlined.
if (!was_inlined && sc.comp_unit != nullptr) {
- if (!FileSpec::Equal(*(sc.comp_unit), *(m_file_spec_up.get()), false))
+ if (!FileSpec::Match(*m_file_spec_up, sc.comp_unit->GetPrimaryFile()))
return false;
}
}
diff --git a/lldb/source/Symbol/SymbolFile.cpp b/lldb/source/Symbol/SymbolFile.cpp
index c4f3a9c1a8c8..90f7d1011716 100644
--- a/lldb/source/Symbol/SymbolFile.cpp
+++ b/lldb/source/Symbol/SymbolFile.cpp
@@ -24,6 +24,8 @@
using namespace lldb_private;
using namespace lldb;
+char SymbolFile::ID;
+
void SymbolFile::PreloadSymbols() {
// No-op for most implementations.
}
@@ -134,7 +136,9 @@ void SymbolFile::FindTypes(
TypeMap &types) {}
void SymbolFile::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
- LanguageSet languages, TypeMap &types) {}
+ LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files,
+ TypeMap &types) {}
void SymbolFile::AssertModuleLock() {
// The code below is too expensive to leave enabled in release builds. It's
diff --git a/lldb/source/Symbol/Symtab.cpp b/lldb/source/Symbol/Symtab.cpp
index c4e6c2ccfb09..f5bd22ee5ee2 100644
--- a/lldb/source/Symbol/Symtab.cpp
+++ b/lldb/source/Symbol/Symtab.cpp
@@ -13,7 +13,6 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/RichManglingContext.h"
-#include "lldb/Core/STLUtils.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
@@ -29,7 +28,7 @@ using namespace lldb;
using namespace lldb_private;
Symtab::Symtab(ObjectFile *objfile)
- : m_objfile(objfile), m_symbols(), m_file_addr_to_index(),
+ : m_objfile(objfile), m_symbols(), m_file_addr_to_index(*this),
m_name_to_index(), m_mutex(), m_file_addr_to_index_computed(false),
m_name_indexes_computed(false) {}
@@ -70,7 +69,8 @@ void Symtab::SectionFileAddressesChanged() {
m_file_addr_to_index_computed = false;
}
-void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order) {
+void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order,
+ Mangled::NamePreference name_preference) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
// s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
@@ -97,7 +97,7 @@ void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order) {
const_iterator end = m_symbols.end();
for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) {
s->Indent();
- pos->Dump(s, target, std::distance(begin, pos));
+ pos->Dump(s, target, std::distance(begin, pos), name_preference);
}
} break;
@@ -106,10 +106,8 @@ void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order) {
// sorted by name. So we must make the ordered symbol list up ourselves.
s->PutCString(" (sorted by name):\n");
DumpSymbolHeader(s);
- typedef std::multimap<const char *, const Symbol *,
- CStringCompareFunctionObject>
- CStringToSymbol;
- CStringToSymbol name_map;
+
+ std::multimap<llvm::StringRef, const Symbol *> name_map;
for (const_iterator pos = m_symbols.begin(), end = m_symbols.end();
pos != end; ++pos) {
const char *name = pos->GetName().AsCString();
@@ -117,11 +115,10 @@ void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order) {
name_map.insert(std::make_pair(name, &(*pos)));
}
- for (CStringToSymbol::const_iterator pos = name_map.begin(),
- end = name_map.end();
- pos != end; ++pos) {
+ for (const auto &name_to_symbol : name_map) {
+ const Symbol *symbol = name_to_symbol.second;
s->Indent();
- pos->second->Dump(s, target, pos->second - &m_symbols[0]);
+ symbol->Dump(s, target, symbol - &m_symbols[0], name_preference);
}
} break;
@@ -134,7 +131,7 @@ void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order) {
for (size_t i = 0; i < num_entries; ++i) {
s->Indent();
const uint32_t symbol_idx = m_file_addr_to_index.GetEntryRef(i).data;
- m_symbols[symbol_idx].Dump(s, target, symbol_idx);
+ m_symbols[symbol_idx].Dump(s, target, symbol_idx, name_preference);
}
break;
}
@@ -143,8 +140,8 @@ void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order) {
}
}
-void Symtab::Dump(Stream *s, Target *target,
- std::vector<uint32_t> &indexes) const {
+void Symtab::Dump(Stream *s, Target *target, std::vector<uint32_t> &indexes,
+ Mangled::NamePreference name_preference) const {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
const size_t num_symbols = GetNumSymbols();
@@ -162,7 +159,7 @@ void Symtab::Dump(Stream *s, Target *target,
size_t idx = *pos;
if (idx < num_symbols) {
s->Indent();
- m_symbols[idx].Dump(s, target, idx);
+ m_symbols[idx].Dump(s, target, idx, name_preference);
}
}
}
@@ -893,14 +890,8 @@ void Symtab::InitAddressIndexes() {
for (size_t i = 0; i < num_entries; i++) {
FileRangeToIndexMap::Entry *entry =
m_file_addr_to_index.GetMutableEntryAtIndex(i);
- if (entry->GetByteSize() > 0)
- continue;
- addr_t curr_base_addr = entry->GetRangeBase();
- // Symbols with non-zero size will show after zero-sized symbols on the
- // same address. So do not set size of a non-last zero-sized symbol.
- if (i == num_entries - 1 ||
- m_file_addr_to_index.GetMutableEntryAtIndex(i + 1)
- ->GetRangeBase() != curr_base_addr) {
+ if (entry->GetByteSize() == 0) {
+ addr_t curr_base_addr = entry->GetRangeBase();
const RangeVector<addr_t, addr_t>::Entry *containing_section =
section_ranges.FindEntryThatContains(curr_base_addr);
diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp
index 5666590c2246..f194356a0a07 100644
--- a/lldb/source/Symbol/Type.cpp
+++ b/lldb/source/Symbol/Type.cpp
@@ -139,16 +139,19 @@ Type *SymbolFileType::GetType() {
return m_type_sp.get();
}
-Type::Type(lldb::user_id_t uid, SymbolFile *symbol_file,
- ConstString name, llvm::Optional<uint64_t> byte_size,
- SymbolContextScope *context, user_id_t encoding_uid,
- EncodingDataType encoding_uid_type, const Declaration &decl,
- const CompilerType &compiler_type,
+Type::Type(lldb::user_id_t uid, SymbolFile *symbol_file, ConstString name,
+ llvm::Optional<uint64_t> byte_size, SymbolContextScope *context,
+ user_id_t encoding_uid, EncodingDataType encoding_uid_type,
+ const Declaration &decl, const CompilerType &compiler_type,
ResolveState compiler_type_resolve_state)
: std::enable_shared_from_this<Type>(), UserID(uid), m_name(name),
m_symbol_file(symbol_file), m_context(context), m_encoding_type(nullptr),
m_encoding_uid(encoding_uid), m_encoding_uid_type(encoding_uid_type),
- m_decl(decl), m_compiler_type(compiler_type) {
+ m_decl(decl), m_compiler_type(compiler_type),
+ m_compiler_type_resolve_state(
+ compiler_type ? compiler_type_resolve_state
+ : ResolveState::Unresolved),
+ m_is_complete_objc_class(false) {
if (byte_size) {
m_byte_size = *byte_size;
m_byte_size_has_value = true;
@@ -156,19 +159,15 @@ Type::Type(lldb::user_id_t uid, SymbolFile *symbol_file,
m_byte_size = 0;
m_byte_size_has_value = false;
}
- m_flags.compiler_type_resolve_state =
- (compiler_type ? compiler_type_resolve_state : eResolveStateUnresolved);
- m_flags.is_complete_objc_class = false;
}
Type::Type()
: std::enable_shared_from_this<Type>(), UserID(0), m_name("<INVALID TYPE>"),
m_symbol_file(nullptr), m_context(nullptr), m_encoding_type(nullptr),
m_encoding_uid(LLDB_INVALID_UID), m_encoding_uid_type(eEncodingInvalid),
- m_byte_size(0), m_byte_size_has_value(false), m_decl(),
- m_compiler_type() {
- m_flags.compiler_type_resolve_state = eResolveStateUnresolved;
- m_flags.is_complete_objc_class = false;
+ m_compiler_type_resolve_state(ResolveState::Unresolved) {
+ m_byte_size = 0;
+ m_byte_size_has_value = false;
}
void Type::GetDescription(Stream *s, lldb::DescriptionLevel level,
@@ -214,6 +213,9 @@ void Type::GetDescription(Stream *s, lldb::DescriptionLevel level,
case eEncodingIsVolatileUID:
s->PutCString(" (unresolved volatile type)");
break;
+ case eEncodingIsAtomicUID:
+ s->PutCString(" (unresolved atomic type)");
+ break;
case eEncodingIsTypedefUID:
s->PutCString(" (unresolved typedef)");
break;
@@ -256,7 +258,7 @@ void Type::Dump(Stream *s, bool show_context) {
*s << ", compiler_type = " << m_compiler_type.GetOpaqueQualType() << ' ';
GetForwardCompilerType().DumpTypeDescription(s);
} else if (m_encoding_uid != LLDB_INVALID_UID) {
- *s << ", type_data = " << (uint64_t)m_encoding_uid;
+ s->Format(", type_data = {0:x-16}", m_encoding_uid);
switch (m_encoding_uid_type) {
case eEncodingInvalid:
break;
@@ -272,6 +274,9 @@ void Type::Dump(Stream *s, bool show_context) {
case eEncodingIsVolatileUID:
s->PutCString(" (unresolved volatile type)");
break;
+ case eEncodingIsAtomicUID:
+ s->PutCString(" (unresolved atomic type)");
+ break;
case eEncodingIsTypedefUID:
s->PutCString(" (unresolved typedef)");
break;
@@ -308,7 +313,7 @@ void Type::DumpValue(ExecutionContext *exe_ctx, Stream *s,
const DataExtractor &data, uint32_t data_byte_offset,
bool show_types, bool show_summary, bool verbose,
lldb::Format format) {
- if (ResolveClangType(eResolveStateForward)) {
+ if (ResolveClangType(ResolveState::Forward)) {
if (show_types) {
s->PutChar('(');
if (verbose)
@@ -344,6 +349,7 @@ llvm::Optional<uint64_t> Type::GetByteSize() {
case eEncodingIsConstUID:
case eEncodingIsRestrictUID:
case eEncodingIsVolatileUID:
+ case eEncodingIsAtomicUID:
case eEncodingIsTypedefUID: {
Type *encoding_type = GetEncodingType();
if (encoding_type)
@@ -472,8 +478,8 @@ bool Type::ResolveClangType(ResolveState compiler_type_resolve_state) {
encoding_type->GetForwardCompilerType();
if (encoding_compiler_type.IsValid()) {
m_compiler_type = encoding_compiler_type;
- m_flags.compiler_type_resolve_state =
- encoding_type->m_flags.compiler_type_resolve_state;
+ m_compiler_type_resolve_state =
+ encoding_type->m_compiler_type_resolve_state;
}
} break;
@@ -492,6 +498,11 @@ bool Type::ResolveClangType(ResolveState compiler_type_resolve_state) {
encoding_type->GetForwardCompilerType().AddVolatileModifier();
break;
+ case eEncodingIsAtomicUID:
+ m_compiler_type =
+ encoding_type->GetForwardCompilerType().GetAtomicType();
+ break;
+
case eEncodingIsTypedefUID:
m_compiler_type = encoding_type->GetForwardCompilerType().CreateTypedef(
m_name.AsCString("__lldb_invalid_typedef_name"),
@@ -546,6 +557,10 @@ bool Type::ResolveClangType(ResolveState compiler_type_resolve_state) {
m_compiler_type = void_compiler_type.AddVolatileModifier();
break;
+ case eEncodingIsAtomicUID:
+ m_compiler_type = void_compiler_type.GetAtomicType();
+ break;
+
case eEncodingIsTypedefUID:
m_compiler_type = void_compiler_type.CreateTypedef(
m_name.AsCString("__lldb_invalid_typedef_name"),
@@ -574,16 +589,16 @@ bool Type::ResolveClangType(ResolveState compiler_type_resolve_state) {
// set to eResolveStateUnresolved so we need to update it to say that we
// now have a forward declaration since that is what we created above.
if (m_compiler_type.IsValid())
- m_flags.compiler_type_resolve_state = eResolveStateForward;
+ m_compiler_type_resolve_state = ResolveState::Forward;
}
// Check if we have a forward reference to a class/struct/union/enum?
- if (compiler_type_resolve_state == eResolveStateLayout ||
- compiler_type_resolve_state == eResolveStateFull) {
+ if (compiler_type_resolve_state == ResolveState::Layout ||
+ compiler_type_resolve_state == ResolveState::Full) {
// Check if we have a forward reference to a class/struct/union/enum?
if (m_compiler_type.IsValid() &&
- m_flags.compiler_type_resolve_state < compiler_type_resolve_state) {
- m_flags.compiler_type_resolve_state = eResolveStateFull;
+ m_compiler_type_resolve_state < compiler_type_resolve_state) {
+ m_compiler_type_resolve_state = ResolveState::Full;
if (!m_compiler_type.IsDefined()) {
// We have a forward declaration, we need to resolve it to a complete
// definition.
@@ -601,12 +616,12 @@ bool Type::ResolveClangType(ResolveState compiler_type_resolve_state) {
ResolveState encoding_compiler_type_resolve_state =
compiler_type_resolve_state;
- if (compiler_type_resolve_state == eResolveStateLayout) {
+ if (compiler_type_resolve_state == ResolveState::Layout) {
switch (m_encoding_uid_type) {
case eEncodingIsPointerUID:
case eEncodingIsLValueReferenceUID:
case eEncodingIsRValueReferenceUID:
- encoding_compiler_type_resolve_state = eResolveStateForward;
+ encoding_compiler_type_resolve_state = ResolveState::Forward;
break;
default:
break;
@@ -627,31 +642,20 @@ uint32_t Type::GetEncodingMask() {
}
CompilerType Type::GetFullCompilerType() {
- ResolveClangType(eResolveStateFull);
+ ResolveClangType(ResolveState::Full);
return m_compiler_type;
}
CompilerType Type::GetLayoutCompilerType() {
- ResolveClangType(eResolveStateLayout);
+ ResolveClangType(ResolveState::Layout);
return m_compiler_type;
}
CompilerType Type::GetForwardCompilerType() {
- ResolveClangType(eResolveStateForward);
+ ResolveClangType(ResolveState::Forward);
return m_compiler_type;
}
-int Type::Compare(const Type &a, const Type &b) {
- // Just compare the UID values for now...
- lldb::user_id_t a_uid = a.GetID();
- lldb::user_id_t b_uid = b.GetID();
- if (a_uid < b_uid)
- return -1;
- if (a_uid > b_uid)
- return 1;
- return 0;
-}
-
ConstString Type::GetQualifiedName() {
return GetForwardCompilerType().GetConstTypeName();
}
diff --git a/lldb/source/Symbol/TypeSystem.cpp b/lldb/source/Symbol/TypeSystem.cpp
index c63f24aea335..29a49a6fb1d4 100644
--- a/lldb/source/Symbol/TypeSystem.cpp
+++ b/lldb/source/Symbol/TypeSystem.cpp
@@ -43,8 +43,6 @@ size_t LanguageSet::Size() const { return bitvector.count(); }
bool LanguageSet::Empty() const { return bitvector.none(); }
bool LanguageSet::operator[](unsigned i) const { return bitvector[i]; }
-TypeSystem::TypeSystem(LLVMCastKind kind) : m_kind(kind), m_sym_file(nullptr) {}
-
TypeSystem::~TypeSystem() {}
static lldb::TypeSystemSP CreateInstanceHelper(lldb::LanguageType language,
@@ -91,6 +89,10 @@ TypeSystem::GetRValueReferenceType(lldb::opaque_compiler_type_t type) {
return CompilerType();
}
+CompilerType TypeSystem::GetAtomicType(lldb::opaque_compiler_type_t type) {
+ return CompilerType();
+}
+
CompilerType TypeSystem::AddConstModifier(lldb::opaque_compiler_type_t type) {
return CompilerType();
}
diff --git a/lldb/source/Symbol/Variable.cpp b/lldb/source/Symbol/Variable.cpp
index 3f3d7c198f15..a0496824a0a3 100644
--- a/lldb/source/Symbol/Variable.cpp
+++ b/lldb/source/Symbol/Variable.cpp
@@ -112,7 +112,7 @@ void Variable::Dump(Stream *s, bool show_context) const {
if (m_symfile_type_sp) {
Type *type = m_symfile_type_sp->GetType();
if (type) {
- *s << ", type = {" << type->GetID() << "} " << (void *)type << " (";
+ s->Format(", type = {{{0:x-16}} {1} (", type->GetID(), type);
type->DumpTypeName(s);
s->PutChar(')');
}
@@ -134,7 +134,7 @@ void Variable::Dump(Stream *s, bool show_context) const {
s->PutCString("thread local");
break;
default:
- *s << "??? (" << m_scope << ')';
+ s->AsRawOstream() << "??? (" << m_scope << ')';
}
}
@@ -492,13 +492,6 @@ static void PrivateAutoCompleteMembers(
llvm::StringRef partial_path,
const llvm::Twine
&prefix_path, // Anything that has been resolved already will be in here
- const CompilerType &compiler_type, CompletionRequest &request);
-
-static void PrivateAutoCompleteMembers(
- StackFrame *frame, const std::string &partial_member_name,
- llvm::StringRef partial_path,
- const llvm::Twine
- &prefix_path, // Anything that has been resolved already will be in here
const CompilerType &compiler_type, CompletionRequest &request) {
// We are in a type parsing child members
@@ -609,11 +602,8 @@ static void PrivateAutoComplete(
VariableList *variable_list = frame->GetVariableList(get_file_globals);
if (variable_list) {
- const size_t num_variables = variable_list->GetSize();
- for (size_t i = 0; i < num_variables; ++i) {
- Variable *variable = variable_list->GetVariableAtIndex(i).get();
- request.AddCompletion(variable->GetName().AsCString());
- }
+ for (const VariableSP &var_sp : *variable_list)
+ request.AddCompletion(var_sp->GetName().AsCString());
}
}
}
@@ -710,17 +700,15 @@ static void PrivateAutoComplete(
if (!variable_list)
break;
- const size_t num_variables = variable_list->GetSize();
- for (size_t i = 0; i < num_variables; ++i) {
- Variable *variable = variable_list->GetVariableAtIndex(i).get();
+ for (VariableSP var_sp : *variable_list) {
- if (!variable)
+ if (!var_sp)
continue;
- const char *variable_name = variable->GetName().AsCString();
- if (strstr(variable_name, token.c_str()) == variable_name) {
- if (strcmp(variable_name, token.c_str()) == 0) {
- Type *variable_type = variable->GetType();
+ llvm::StringRef variable_name = var_sp->GetName().GetStringRef();
+ if (variable_name.startswith(token)) {
+ if (variable_name == token) {
+ Type *variable_type = var_sp->GetType();
if (variable_type) {
CompilerType variable_compiler_type(
variable_type->GetForwardCompilerType());
diff --git a/lldb/source/Target/ABI.cpp b/lldb/source/Target/ABI.cpp
index 005261e0ddee..58396ba70586 100644
--- a/lldb/source/Target/ABI.cpp
+++ b/lldb/source/Target/ABI.cpp
@@ -63,24 +63,6 @@ bool ABI::GetRegisterInfoByName(ConstString name, RegisterInfo &info) {
return false;
}
-bool ABI::GetRegisterInfoByKind(RegisterKind reg_kind, uint32_t reg_num,
- RegisterInfo &info) {
- if (reg_kind < eRegisterKindEHFrame || reg_kind >= kNumRegisterKinds)
- return false;
-
- uint32_t count = 0;
- const RegisterInfo *register_info_array = GetRegisterInfoArray(count);
- if (register_info_array) {
- for (uint32_t i = 0; i < count; ++i) {
- if (register_info_array[i].kinds[reg_kind] == reg_num) {
- info = register_info_array[i];
- return true;
- }
- }
- }
- return false;
-}
-
ValueObjectSP ABI::GetReturnValueObject(Thread &thread, CompilerType &ast_type,
bool persistent) const {
if (!ast_type.IsValid())
@@ -105,7 +87,7 @@ ValueObjectSP ABI::GetReturnValueObject(Thread &thread, CompilerType &ast_type,
ast_type.GetMinimumLanguage());
if (!persistent_expression_state)
- return ValueObjectSP();
+ return {};
auto prefix = persistent_expression_state->GetPersistentVariablePrefix();
ConstString persistent_variable_name =
@@ -229,3 +211,20 @@ std::unique_ptr<llvm::MCRegisterInfo> ABI::MakeMCRegisterInfo(const ArchSpec &ar
assert(info_up);
return info_up;
}
+
+void ABI::AugmentRegisterInfo(RegisterInfo &info) {
+ if (info.kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM &&
+ info.kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
+ return;
+
+ RegisterInfo abi_info;
+ if (!GetRegisterInfoByName(ConstString(info.name), abi_info))
+ return;
+
+ if (info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM)
+ info.kinds[eRegisterKindEHFrame] = abi_info.kinds[eRegisterKindEHFrame];
+ if (info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM)
+ info.kinds[eRegisterKindDWARF] = abi_info.kinds[eRegisterKindDWARF];
+ if (info.kinds[eRegisterKindGeneric] == LLDB_INVALID_REGNUM)
+ info.kinds[eRegisterKindGeneric] = abi_info.kinds[eRegisterKindGeneric];
+}
diff --git a/lldb/source/Target/Language.cpp b/lldb/source/Target/Language.cpp
index 43d0be0f737c..10a9ddd56c44 100644
--- a/lldb/source/Target/Language.cpp
+++ b/lldb/source/Target/Language.cpp
@@ -134,11 +134,6 @@ Language::GetHardcodedSynthetics() {
return {};
}
-HardcodedFormatters::HardcodedValidatorFinder
-Language::GetHardcodedValidators() {
- return {};
-}
-
std::vector<ConstString>
Language::GetPossibleFormattersMatches(ValueObject &valobj,
lldb::DynamicValueType use_dynamic) {
diff --git a/lldb/source/Target/LanguageRuntime.cpp b/lldb/source/Target/LanguageRuntime.cpp
index 999ac99e93c3..32dd805a00b1 100644
--- a/lldb/source/Target/LanguageRuntime.cpp
+++ b/lldb/source/Target/LanguageRuntime.cpp
@@ -155,8 +155,10 @@ public:
protected:
BreakpointResolverSP CopyForBreakpoint(Breakpoint &breakpoint) override {
- return BreakpointResolverSP(
+ BreakpointResolverSP ret_sp(
new ExceptionBreakpointResolver(m_language, m_catch_bp, m_throw_bp));
+ ret_sp->SetBreakpoint(&breakpoint);
+ return ret_sp;
}
bool SetActualResolver() {
diff --git a/lldb/source/Target/MemoryRegionInfo.cpp b/lldb/source/Target/MemoryRegionInfo.cpp
new file mode 100644
index 000000000000..2c31563786aa
--- /dev/null
+++ b/lldb/source/Target/MemoryRegionInfo.cpp
@@ -0,0 +1,40 @@
+//===-- MemoryRegionInfo.cpp ------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/MemoryRegionInfo.h"
+
+using namespace lldb_private;
+
+llvm::raw_ostream &lldb_private::operator<<(llvm::raw_ostream &OS,
+ const MemoryRegionInfo &Info) {
+ return OS << llvm::formatv("MemoryRegionInfo([{0}, {1}), {2:r}{3:w}{4:x}, "
+ "{5}, `{6}`, {7}, {8})",
+ Info.GetRange().GetRangeBase(),
+ Info.GetRange().GetRangeEnd(), Info.GetReadable(),
+ Info.GetWritable(), Info.GetExecutable(),
+ Info.GetMapped(), Info.GetName(), Info.GetFlash(),
+ Info.GetBlocksize());
+}
+
+void llvm::format_provider<MemoryRegionInfo::OptionalBool>::format(
+ const MemoryRegionInfo::OptionalBool &B, raw_ostream &OS,
+ StringRef Options) {
+ assert(Options.size() <= 1);
+ bool Empty = Options.empty();
+ switch (B) {
+ case lldb_private::MemoryRegionInfo::eNo:
+ OS << (Empty ? "no" : "-");
+ return;
+ case lldb_private::MemoryRegionInfo::eYes:
+ OS << (Empty ? "yes" : Options);
+ return;
+ case lldb_private::MemoryRegionInfo::eDontKnow:
+ OS << (Empty ? "don't know" : "?");
+ return;
+ }
+}
diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp
index c9849a9e5f09..aaf48f35f921 100644
--- a/lldb/source/Target/Platform.cpp
+++ b/lldb/source/Target/Platform.cpp
@@ -406,7 +406,7 @@ void Platform::GetStatus(Stream &strm) {
if (arch.IsValid()) {
if (!arch.GetTriple().str().empty()) {
strm.Printf(" Triple: ");
- arch.DumpTriple(strm);
+ arch.DumpTriple(strm.AsRawOstream());
strm.EOL();
}
}
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index ed0b951fbce1..6711dc37eca6 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -137,19 +137,12 @@ ProcessProperties::ProcessProperties(lldb_private::Process *process)
Process::GetGlobalProperties().get());
m_collection_sp->SetValueChangedCallback(
ePropertyPythonOSPluginPath,
- ProcessProperties::OptionValueChangedCallback, this);
+ [this] { m_process->LoadOperatingSystemPlugin(true); });
}
}
ProcessProperties::~ProcessProperties() = default;
-void ProcessProperties::OptionValueChangedCallback(void *baton,
- OptionValue *option_value) {
- ProcessProperties *properties = (ProcessProperties *)baton;
- if (properties->m_process)
- properties->m_process->LoadOperatingSystemPlugin(true);
-}
-
bool ProcessProperties::GetDisableMemoryCache() const {
const uint32_t idx = ePropertyDisableMemCache;
return m_collection_sp->GetPropertyAtIndexAsBoolean(
@@ -1486,8 +1479,7 @@ const lldb::ABISP &Process::GetABI() {
return m_abi_sp;
}
-std::vector<LanguageRuntime *>
-Process::GetLanguageRuntimes(bool retry_if_null) {
+std::vector<LanguageRuntime *> Process::GetLanguageRuntimes() {
std::vector<LanguageRuntime *> language_runtimes;
if (m_finalizing)
@@ -1500,15 +1492,14 @@ Process::GetLanguageRuntimes(bool retry_if_null) {
// yet or the proper condition for loading wasn't yet met (e.g. libc++.so
// hadn't been loaded).
for (const lldb::LanguageType lang_type : Language::GetSupportedLanguages()) {
- if (LanguageRuntime *runtime = GetLanguageRuntime(lang_type, retry_if_null))
+ if (LanguageRuntime *runtime = GetLanguageRuntime(lang_type))
language_runtimes.emplace_back(runtime);
}
return language_runtimes;
}
-LanguageRuntime *Process::GetLanguageRuntime(lldb::LanguageType language,
- bool retry_if_null) {
+LanguageRuntime *Process::GetLanguageRuntime(lldb::LanguageType language) {
if (m_finalizing)
return nullptr;
@@ -1517,7 +1508,7 @@ LanguageRuntime *Process::GetLanguageRuntime(lldb::LanguageType language,
std::lock_guard<std::recursive_mutex> guard(m_language_runtimes_mutex);
LanguageRuntimeCollection::iterator pos;
pos = m_language_runtimes.find(language);
- if (pos == m_language_runtimes.end() || (retry_if_null && !pos->second)) {
+ if (pos == m_language_runtimes.end() || !pos->second) {
lldb::LanguageRuntimeSP runtime_sp(
LanguageRuntime::FindPlugin(this, language));
@@ -5802,7 +5793,8 @@ Process::AdvanceAddressToNextBranchInstruction(Address default_stop_addr,
uint32_t branch_index =
insn_list->GetIndexOfNextBranchInstruction(insn_offset, target,
- false /* ignore_calls*/);
+ false /* ignore_calls*/,
+ nullptr);
if (branch_index == UINT32_MAX) {
return retval;
}
diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp
index 5e5a596e471d..5c6ea7a03933 100644
--- a/lldb/source/Target/StackFrame.cpp
+++ b/lldb/source/Target/StackFrame.cpp
@@ -573,8 +573,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
if (!var_sp && (options & eExpressionPathOptionsInspectAnonymousUnions)) {
// Check if any anonymous unions are there which contain a variable with
// the name we need
- for (size_t i = 0; i < variable_list->GetSize(); i++) {
- VariableSP variable_sp = variable_list->GetVariableAtIndex(i);
+ for (const VariableSP &variable_sp : *variable_list) {
if (!variable_sp)
continue;
if (!variable_sp->GetName().IsEmpty())
@@ -1529,11 +1528,9 @@ lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg,
: Instruction::Operand::BuildDereference(
Instruction::Operand::BuildRegister(reg));
- for (size_t vi = 0, ve = variables.GetSize(); vi != ve; ++vi) {
- VariableSP var_sp = variables.GetVariableAtIndex(vi);
- if (var_sp->LocationExpression().MatchesOperand(frame, op)) {
+ for (VariableSP var_sp : variables) {
+ if (var_sp->LocationExpression().MatchesOperand(frame, op))
return frame.GetValueObjectForFrameVariable(var_sp, eNoDynamicValues);
- }
}
const uint32_t current_inst =
diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp
index 6d0c46259c20..87b49849bc99 100644
--- a/lldb/source/Target/StackFrameList.cpp
+++ b/lldb/source/Target/StackFrameList.cpp
@@ -243,7 +243,8 @@ void StackFrameList::GetOnlyConcreteFramesUpTo(uint32_t end_idx,
/// \p return_pc) to \p end. On success this path is stored into \p path, and
/// on failure \p path is unchanged.
static void FindInterveningFrames(Function &begin, Function &end,
- Target &target, addr_t return_pc,
+ ExecutionContext &exe_ctx, Target &target,
+ addr_t return_pc,
std::vector<Function *> &path,
ModuleList &images, Log *log) {
LLDB_LOG(log, "Finding frames between {0} and {1}, retn-pc={2:x}",
@@ -251,9 +252,9 @@ static void FindInterveningFrames(Function &begin, Function &end,
// Find a non-tail calling edge with the correct return PC.
if (log)
- for (const CallEdge &edge : begin.GetCallEdges())
+ for (const auto &edge : begin.GetCallEdges())
LLDB_LOG(log, "FindInterveningFrames: found call with retn-PC = {0:x}",
- edge.GetReturnPCAddress(begin, target));
+ edge->GetReturnPCAddress(begin, target));
CallEdge *first_edge = begin.GetCallEdgeForReturnAddress(return_pc, target);
if (!first_edge) {
LLDB_LOG(log, "No call edge outgoing from {0} with retn-PC == {1:x}",
@@ -262,7 +263,7 @@ static void FindInterveningFrames(Function &begin, Function &end,
}
// The first callee may not be resolved, or there may be nothing to fill in.
- Function *first_callee = first_edge->GetCallee(images);
+ Function *first_callee = first_edge->GetCallee(images, exe_ctx);
if (!first_callee) {
LLDB_LOG(log, "Could not resolve callee");
return;
@@ -283,8 +284,10 @@ static void FindInterveningFrames(Function &begin, Function &end,
bool ambiguous = false;
Function *end;
ModuleList &images;
+ ExecutionContext &context;
- DFS(Function *end, ModuleList &images) : end(end), images(images) {}
+ DFS(Function *end, ModuleList &images, ExecutionContext &context)
+ : end(end), images(images), context(context) {}
void search(Function &first_callee, std::vector<Function *> &path) {
dfs(first_callee);
@@ -313,8 +316,8 @@ static void FindInterveningFrames(Function &begin, Function &end,
// Search the calls made from this callee.
active_path.push_back(&callee);
- for (CallEdge &edge : callee.GetTailCallingEdges()) {
- Function *next_callee = edge.GetCallee(images);
+ for (const auto &edge : callee.GetTailCallingEdges()) {
+ Function *next_callee = edge->GetCallee(images, context);
if (!next_callee)
continue;
@@ -326,7 +329,7 @@ static void FindInterveningFrames(Function &begin, Function &end,
}
};
- DFS(&end, images).search(*first_callee, path);
+ DFS(&end, images, exe_ctx).search(*first_callee, path);
}
/// Given that \p next_frame will be appended to the frame list, synthesize
@@ -379,8 +382,10 @@ void StackFrameList::SynthesizeTailCallFrames(StackFrame &next_frame) {
addr_t return_pc = next_reg_ctx_sp->GetPC();
Target &target = *target_sp.get();
ModuleList &images = next_frame.CalculateTarget()->GetImages();
- FindInterveningFrames(*next_func, *prev_func, target, return_pc, path, images,
- log);
+ ExecutionContext exe_ctx(target_sp, /*get_process=*/true);
+ exe_ctx.SetFramePtr(&next_frame);
+ FindInterveningFrames(*next_func, *prev_func, exe_ctx, target, return_pc,
+ path, images, log);
// Push synthetic tail call frames.
for (Function *callee : llvm::reverse(path)) {
diff --git a/lldb/source/Target/StackFrameRecognizer.cpp b/lldb/source/Target/StackFrameRecognizer.cpp
index 567d694bf093..75a6cd215126 100644
--- a/lldb/source/Target/StackFrameRecognizer.cpp
+++ b/lldb/source/Target/StackFrameRecognizer.cpp
@@ -39,7 +39,7 @@ ScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame) {
ValueObjectListSP args =
m_interpreter->GetRecognizedArguments(m_python_object_sp, frame);
auto args_synthesized = ValueObjectListSP(new ValueObjectList());
- for (const auto o : args->GetObjects()) {
+ for (const auto &o : args->GetObjects()) {
args_synthesized->Append(ValueObjectRecognizerSynthesizedValue::Create(
*o, eValueTypeVariableArgument));
}
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 4b9a1b77ad16..83e6f3062666 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -404,8 +404,8 @@ Target::CreateAddressInModuleBreakpoint(lldb::addr_t file_addr, bool internal,
bool request_hardware) {
SearchFilterSP filter_sp(
new SearchFilterForUnconstrainedSearches(shared_from_this()));
- BreakpointResolverSP resolver_sp(
- new BreakpointResolverAddress(nullptr, file_addr, file_spec));
+ BreakpointResolverSP resolver_sp(new BreakpointResolverAddress(
+ nullptr, file_addr, file_spec ? *file_spec : FileSpec()));
return CreateBreakpoint(filter_sp, resolver_sp, internal, request_hardware,
false);
}
@@ -728,11 +728,17 @@ void Target::ConfigureBreakpointName(
}
void Target::ApplyNameToBreakpoints(BreakpointName &bp_name) {
- BreakpointList bkpts_with_name(false);
- m_breakpoint_list.FindBreakpointsByName(bp_name.GetName().AsCString(),
- bkpts_with_name);
+ llvm::Expected<std::vector<BreakpointSP>> expected_vector =
+ m_breakpoint_list.FindBreakpointsByName(bp_name.GetName().AsCString());
+
+ if (!expected_vector) {
+ LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS),
+ "invalid breakpoint name: {}",
+ llvm::toString(expected_vector.takeError()));
+ return;
+ }
- for (auto bp_sp : bkpts_with_name.Breakpoints())
+ for (auto bp_sp : *expected_vector)
bp_name.ConfigureBreakpoint(bp_sp);
}
@@ -1425,8 +1431,7 @@ void Target::SetExecutableModule(ModuleSP &executable_sp,
ModuleList added_modules;
executable_objfile->GetDependentModules(dependent_files);
for (uint32_t i = 0; i < dependent_files.GetSize(); i++) {
- FileSpec dependent_file_spec(
- dependent_files.GetFileSpecPointerAtIndex(i));
+ FileSpec dependent_file_spec(dependent_files.GetFileSpecAtIndex(i));
FileSpec platform_dependent_file_spec;
if (m_platform_sp)
m_platform_sp->GetFileWithUUID(dependent_file_spec, nullptr,
@@ -2253,20 +2258,6 @@ Target::GetUtilityFunctionForLanguage(const char *text,
return utility_fn;
}
-ClangASTContext *Target::GetScratchClangASTContext(bool create_on_demand) {
- if (!m_valid)
- return nullptr;
-
- auto type_system_or_err =
- GetScratchTypeSystemForLanguage(eLanguageTypeC, create_on_demand);
- if (auto err = type_system_or_err.takeError()) {
- LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TARGET),
- std::move(err), "Couldn't get scratch ClangASTContext");
- return nullptr;
- }
- return llvm::dyn_cast<ClangASTContext>(&type_system_or_err.get());
-}
-
ClangASTImporterSP Target::GetClangASTImporter() {
if (m_valid) {
if (!m_ast_importer_sp) {
@@ -3177,7 +3168,7 @@ void Target::StopHook::SetThreadSpecifier(ThreadSpec *specifier) {
void Target::StopHook::GetDescription(Stream *s,
lldb::DescriptionLevel level) const {
- int indent_level = s->GetIndentLevel();
+ unsigned indent_level = s->GetIndentLevel();
s->SetIndentLevel(indent_level + 2);
@@ -3470,29 +3461,24 @@ TargetProperties::TargetProperties(Target *target)
// Set callbacks to update launch_info whenever "settins set" updated any
// of these properties
m_collection_sp->SetValueChangedCallback(
- ePropertyArg0, TargetProperties::Arg0ValueChangedCallback, this);
- m_collection_sp->SetValueChangedCallback(
- ePropertyRunArgs, TargetProperties::RunArgsValueChangedCallback, this);
+ ePropertyArg0, [this] { Arg0ValueChangedCallback(); });
m_collection_sp->SetValueChangedCallback(
- ePropertyEnvVars, TargetProperties::EnvVarsValueChangedCallback, this);
+ ePropertyRunArgs, [this] { RunArgsValueChangedCallback(); });
m_collection_sp->SetValueChangedCallback(
- ePropertyInputPath, TargetProperties::InputPathValueChangedCallback,
- this);
+ ePropertyEnvVars, [this] { EnvVarsValueChangedCallback(); });
m_collection_sp->SetValueChangedCallback(
- ePropertyOutputPath, TargetProperties::OutputPathValueChangedCallback,
- this);
+ ePropertyInputPath, [this] { InputPathValueChangedCallback(); });
m_collection_sp->SetValueChangedCallback(
- ePropertyErrorPath, TargetProperties::ErrorPathValueChangedCallback,
- this);
+ ePropertyOutputPath, [this] { OutputPathValueChangedCallback(); });
m_collection_sp->SetValueChangedCallback(
- ePropertyDetachOnError,
- TargetProperties::DetachOnErrorValueChangedCallback, this);
+ ePropertyErrorPath, [this] { ErrorPathValueChangedCallback(); });
+ m_collection_sp->SetValueChangedCallback(ePropertyDetachOnError, [this] {
+ DetachOnErrorValueChangedCallback();
+ });
m_collection_sp->SetValueChangedCallback(
- ePropertyDisableASLR, TargetProperties::DisableASLRValueChangedCallback,
- this);
+ ePropertyDisableASLR, [this] { DisableASLRValueChangedCallback(); });
m_collection_sp->SetValueChangedCallback(
- ePropertyDisableSTDIO,
- TargetProperties::DisableSTDIOValueChangedCallback, this);
+ ePropertyDisableSTDIO, [this] { DisableSTDIOValueChangedCallback(); });
m_experimental_properties_up.reset(new TargetExperimentalProperties());
m_collection_sp->AppendProperty(
@@ -3502,16 +3488,16 @@ TargetProperties::TargetProperties(Target *target)
true, m_experimental_properties_up->GetValueProperties());
// Update m_launch_info once it was created
- Arg0ValueChangedCallback(this, nullptr);
- RunArgsValueChangedCallback(this, nullptr);
- // EnvVarsValueChangedCallback(this, nullptr); // FIXME: cause segfault in
+ Arg0ValueChangedCallback();
+ RunArgsValueChangedCallback();
+ // EnvVarsValueChangedCallback(); // FIXME: cause segfault in
// Target::GetPlatform()
- InputPathValueChangedCallback(this, nullptr);
- OutputPathValueChangedCallback(this, nullptr);
- ErrorPathValueChangedCallback(this, nullptr);
- DetachOnErrorValueChangedCallback(this, nullptr);
- DisableASLRValueChangedCallback(this, nullptr);
- DisableSTDIOValueChangedCallback(this, nullptr);
+ InputPathValueChangedCallback();
+ OutputPathValueChangedCallback();
+ ErrorPathValueChangedCallback();
+ DetachOnErrorValueChangedCallback();
+ DisableASLRValueChangedCallback();
+ DisableSTDIOValueChangedCallback();
} else {
m_collection_sp =
std::make_shared<TargetOptionValueProperties>(ConstString("target"));
@@ -3554,18 +3540,6 @@ void TargetProperties::SetInjectLocalVariables(ExecutionContext *exe_ctx,
true);
}
-bool TargetProperties::GetUseModernTypeLookup() const {
- const Property *exp_property = m_collection_sp->GetPropertyAtIndex(
- nullptr, false, ePropertyExperimental);
- OptionValueProperties *exp_values =
- exp_property->GetValue()->GetAsProperties();
- if (exp_values)
- return exp_values->GetPropertyAtIndexAsBoolean(
- nullptr, ePropertyUseModernTypeLookup, true);
- else
- return true;
-}
-
ArchSpec TargetProperties::GetDefaultArchitecture() const {
OptionValueArch *value = m_collection_sp->GetPropertyAtIndexAsOptionValueArch(
nullptr, ePropertyDefaultArch);
@@ -3996,81 +3970,54 @@ void TargetProperties::SetRequireHardwareBreakpoints(bool b) {
m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
}
-void TargetProperties::Arg0ValueChangedCallback(void *target_property_ptr,
- OptionValue *) {
- TargetProperties *this_ =
- reinterpret_cast<TargetProperties *>(target_property_ptr);
- this_->m_launch_info.SetArg0(this_->GetArg0());
+void TargetProperties::Arg0ValueChangedCallback() {
+ m_launch_info.SetArg0(GetArg0());
}
-void TargetProperties::RunArgsValueChangedCallback(void *target_property_ptr,
- OptionValue *) {
- TargetProperties *this_ =
- reinterpret_cast<TargetProperties *>(target_property_ptr);
+void TargetProperties::RunArgsValueChangedCallback() {
Args args;
- if (this_->GetRunArguments(args))
- this_->m_launch_info.GetArguments() = args;
+ if (GetRunArguments(args))
+ m_launch_info.GetArguments() = args;
}
-void TargetProperties::EnvVarsValueChangedCallback(void *target_property_ptr,
- OptionValue *) {
- TargetProperties *this_ =
- reinterpret_cast<TargetProperties *>(target_property_ptr);
- this_->m_launch_info.GetEnvironment() = this_->GetEnvironment();
+void TargetProperties::EnvVarsValueChangedCallback() {
+ m_launch_info.GetEnvironment() = GetEnvironment();
}
-void TargetProperties::InputPathValueChangedCallback(void *target_property_ptr,
- OptionValue *) {
- TargetProperties *this_ =
- reinterpret_cast<TargetProperties *>(target_property_ptr);
- this_->m_launch_info.AppendOpenFileAction(
- STDIN_FILENO, this_->GetStandardInputPath(), true, false);
+void TargetProperties::InputPathValueChangedCallback() {
+ m_launch_info.AppendOpenFileAction(STDIN_FILENO, GetStandardInputPath(), true,
+ false);
}
-void TargetProperties::OutputPathValueChangedCallback(void *target_property_ptr,
- OptionValue *) {
- TargetProperties *this_ =
- reinterpret_cast<TargetProperties *>(target_property_ptr);
- this_->m_launch_info.AppendOpenFileAction(
- STDOUT_FILENO, this_->GetStandardOutputPath(), false, true);
+void TargetProperties::OutputPathValueChangedCallback() {
+ m_launch_info.AppendOpenFileAction(STDOUT_FILENO, GetStandardOutputPath(),
+ false, true);
}
-void TargetProperties::ErrorPathValueChangedCallback(void *target_property_ptr,
- OptionValue *) {
- TargetProperties *this_ =
- reinterpret_cast<TargetProperties *>(target_property_ptr);
- this_->m_launch_info.AppendOpenFileAction(
- STDERR_FILENO, this_->GetStandardErrorPath(), false, true);
+void TargetProperties::ErrorPathValueChangedCallback() {
+ m_launch_info.AppendOpenFileAction(STDERR_FILENO, GetStandardErrorPath(),
+ false, true);
}
-void TargetProperties::DetachOnErrorValueChangedCallback(
- void *target_property_ptr, OptionValue *) {
- TargetProperties *this_ =
- reinterpret_cast<TargetProperties *>(target_property_ptr);
- if (this_->GetDetachOnError())
- this_->m_launch_info.GetFlags().Set(lldb::eLaunchFlagDetachOnError);
+void TargetProperties::DetachOnErrorValueChangedCallback() {
+ if (GetDetachOnError())
+ m_launch_info.GetFlags().Set(lldb::eLaunchFlagDetachOnError);
else
- this_->m_launch_info.GetFlags().Clear(lldb::eLaunchFlagDetachOnError);
+ m_launch_info.GetFlags().Clear(lldb::eLaunchFlagDetachOnError);
}
-void TargetProperties::DisableASLRValueChangedCallback(
- void *target_property_ptr, OptionValue *) {
- TargetProperties *this_ =
- reinterpret_cast<TargetProperties *>(target_property_ptr);
- if (this_->GetDisableASLR())
- this_->m_launch_info.GetFlags().Set(lldb::eLaunchFlagDisableASLR);
+void TargetProperties::DisableASLRValueChangedCallback() {
+ if (GetDisableASLR())
+ m_launch_info.GetFlags().Set(lldb::eLaunchFlagDisableASLR);
else
- this_->m_launch_info.GetFlags().Clear(lldb::eLaunchFlagDisableASLR);
+ m_launch_info.GetFlags().Clear(lldb::eLaunchFlagDisableASLR);
}
-void TargetProperties::DisableSTDIOValueChangedCallback(
- void *target_property_ptr, OptionValue *) {
- TargetProperties *this_ =
- reinterpret_cast<TargetProperties *>(target_property_ptr);
- if (this_->GetDisableSTDIO())
- this_->m_launch_info.GetFlags().Set(lldb::eLaunchFlagDisableSTDIO);
+void TargetProperties::DisableSTDIOValueChangedCallback() {
+ if (GetDisableSTDIO())
+ m_launch_info.GetFlags().Set(lldb::eLaunchFlagDisableSTDIO);
else
- this_->m_launch_info.GetFlags().Clear(lldb::eLaunchFlagDisableSTDIO);
+ m_launch_info.GetFlags().Clear(lldb::eLaunchFlagDisableSTDIO);
}
// Target::TargetEventData
@@ -4094,7 +4041,7 @@ void Target::TargetEventData::Dump(Stream *s) const {
if (i != 0)
*s << ", ";
m_module_list.GetModuleAtIndex(i)->GetDescription(
- s, lldb::eDescriptionLevelBrief);
+ s->AsRawOstream(), lldb::eDescriptionLevelBrief);
}
}
diff --git a/lldb/source/Target/TargetList.cpp b/lldb/source/Target/TargetList.cpp
index 7c7a36e97bbf..1b4db0c2aba5 100644
--- a/lldb/source/Target/TargetList.cpp
+++ b/lldb/source/Target/TargetList.cpp
@@ -144,9 +144,9 @@ Status TargetList::CreateTargetInternal(
StreamString platform_arch_strm;
StreamString module_arch_strm;
- platform_arch.DumpTriple(platform_arch_strm);
+ platform_arch.DumpTriple(platform_arch_strm.AsRawOstream());
matching_module_spec.GetArchitecture().DumpTriple(
- module_arch_strm);
+ module_arch_strm.AsRawOstream());
error.SetErrorStringWithFormat(
"the specified architecture '%s' is not compatible with '%s' "
"in '%s'",
@@ -457,15 +457,12 @@ TargetSP TargetList::FindTargetWithExecutableAndArchitecture(
const FileSpec &exe_file_spec, const ArchSpec *exe_arch_ptr) const {
std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
TargetSP target_sp;
- bool full_match = (bool)exe_file_spec.GetDirectory();
-
collection::const_iterator pos, end = m_target_list.end();
for (pos = m_target_list.begin(); pos != end; ++pos) {
Module *exe_module = (*pos)->GetExecutableModulePointer();
if (exe_module) {
- if (FileSpec::Equal(exe_file_spec, exe_module->GetFileSpec(),
- full_match)) {
+ if (FileSpec::Match(exe_file_spec, exe_module->GetFileSpec())) {
if (exe_arch_ptr) {
if (!exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture()))
continue;
diff --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td
index 9079c3cf4276..ff8062aaa2cb 100644
--- a/lldb/source/Target/TargetProperties.td
+++ b/lldb/source/Target/TargetProperties.td
@@ -4,9 +4,6 @@ let Definition = "experimental" in {
def InjectLocalVars : Property<"inject-local-vars", "Boolean">,
Global, DefaultTrue,
Desc<"If true, inject local variables explicitly into the expression text. This will fix symbol resolution when there are name collisions between ivars and local variables. But it can make expressions run much more slowly.">;
- def UseModernTypeLookup : Property<"use-modern-type-lookup", "Boolean">,
- Global, DefaultFalse,
- Desc<"If true, use Clang's modern type lookup infrastructure.">;
}
let Definition = "target" in {
diff --git a/lldb/source/Target/ThreadPlanRunToAddress.cpp b/lldb/source/Target/ThreadPlanRunToAddress.cpp
index 160743a9f3f8..32ea2e675270 100644
--- a/lldb/source/Target/ThreadPlanRunToAddress.cpp
+++ b/lldb/source/Target/ThreadPlanRunToAddress.cpp
@@ -97,7 +97,7 @@ void ThreadPlanRunToAddress::GetDescription(Stream *s,
s->Printf("run to addresses: ");
for (size_t i = 0; i < num_addresses; i++) {
- s->Address(m_addresses[i], sizeof(addr_t));
+ DumpAddress(s->AsRawOstream(), m_addresses[i], sizeof(addr_t));
s->Printf(" ");
}
} else {
@@ -116,7 +116,7 @@ void ThreadPlanRunToAddress::GetDescription(Stream *s,
s->Indent();
}
- s->Address(m_addresses[i], sizeof(addr_t));
+ DumpAddress(s->AsRawOstream(), m_addresses[i], sizeof(addr_t));
s->Printf(" using breakpoint: %d - ", m_break_ids[i]);
Breakpoint *breakpoint =
m_thread.CalculateTarget()->GetBreakpointByID(m_break_ids[i]).get();
@@ -143,7 +143,7 @@ bool ThreadPlanRunToAddress::ValidatePlan(Stream *error) {
all_bps_good = false;
if (error) {
error->Printf("Could not set breakpoint for address: ");
- error->Address(m_addresses[i], sizeof(addr_t));
+ DumpAddress(error->AsRawOstream(), m_addresses[i], sizeof(addr_t));
error->Printf("\n");
}
}
diff --git a/lldb/source/Target/ThreadPlanStepInRange.cpp b/lldb/source/Target/ThreadPlanStepInRange.cpp
index 71045cc7a990..ab1f6a21a862 100644
--- a/lldb/source/Target/ThreadPlanStepInRange.cpp
+++ b/lldb/source/Target/ThreadPlanStepInRange.cpp
@@ -145,8 +145,8 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) {
if (log) {
StreamString s;
- s.Address(
- m_thread.GetRegisterContext()->GetPC(),
+ DumpAddress(
+ s.AsRawOstream(), m_thread.GetRegisterContext()->GetPC(),
m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
LLDB_LOGF(log, "ThreadPlanStepInRange reached %s.", s.GetData());
}
@@ -339,7 +339,7 @@ bool ThreadPlanStepInRange::FrameMatchesAvoidCriteria() {
if (frame_library) {
for (size_t i = 0; i < num_libraries; i++) {
const FileSpec &file_spec(libraries_to_avoid.GetFileSpecAtIndex(i));
- if (FileSpec::Equal(file_spec, frame_library, false)) {
+ if (FileSpec::Match(file_spec, frame_library)) {
libraries_say_avoid = true;
break;
}
@@ -392,7 +392,7 @@ bool ThreadPlanStepInRange::DefaultShouldStopHereCallback(
should_stop_here = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback(
current_plan, flags, operation, status, baton);
if (!should_stop_here)
- return should_stop_here;
+ return false;
if (should_stop_here && current_plan->GetKind() == eKindStepInRange &&
operation == eFrameCompareYounger) {
diff --git a/lldb/source/Target/ThreadPlanStepInstruction.cpp b/lldb/source/Target/ThreadPlanStepInstruction.cpp
index 0c75cb811156..afcc9d608b27 100644
--- a/lldb/source/Target/ThreadPlanStepInstruction.cpp
+++ b/lldb/source/Target/ThreadPlanStepInstruction.cpp
@@ -65,7 +65,7 @@ void ThreadPlanStepInstruction::GetDescription(Stream *s,
PrintFailureIfAny();
} else {
s->Printf("Stepping one instruction past ");
- s->Address(m_instruction_addr, sizeof(addr_t));
+ DumpAddress(s->AsRawOstream(), m_instruction_addr, sizeof(addr_t));
if (!m_start_has_symbol)
s->Printf(" which has no symbol");
@@ -182,14 +182,16 @@ bool ThreadPlanStepInstruction::ShouldStop(Event *event_ptr) {
s.PutCString("Stepped in to: ");
addr_t stop_addr =
m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
- s.Address(stop_addr, m_thread.CalculateTarget()
- ->GetArchitecture()
- .GetAddressByteSize());
+ DumpAddress(s.AsRawOstream(), stop_addr,
+ m_thread.CalculateTarget()
+ ->GetArchitecture()
+ .GetAddressByteSize());
s.PutCString(" stepping out to: ");
addr_t return_addr = return_frame->GetRegisterContext()->GetPC();
- s.Address(return_addr, m_thread.CalculateTarget()
- ->GetArchitecture()
- .GetAddressByteSize());
+ DumpAddress(s.AsRawOstream(), return_addr,
+ m_thread.CalculateTarget()
+ ->GetArchitecture()
+ .GetAddressByteSize());
LLDB_LOGF(log, "%s.", s.GetData());
}
diff --git a/lldb/source/Target/ThreadPlanStepOut.cpp b/lldb/source/Target/ThreadPlanStepOut.cpp
index d7dae446b229..f15a343aaa38 100644
--- a/lldb/source/Target/ThreadPlanStepOut.cpp
+++ b/lldb/source/Target/ThreadPlanStepOut.cpp
@@ -126,6 +126,25 @@ ThreadPlanStepOut::ThreadPlanStepOut(
if (m_return_addr == LLDB_INVALID_ADDRESS)
return;
+ // Perform some additional validation on the return address.
+ uint32_t permissions = 0;
+ if (!m_thread.GetProcess()->GetLoadAddressPermissions(m_return_addr,
+ permissions)) {
+ m_constructor_errors.Printf("Return address (0x%" PRIx64
+ ") permissions not found.",
+ m_return_addr);
+ LLDB_LOGF(log, "ThreadPlanStepOut(%p): %s", static_cast<void *>(this),
+ m_constructor_errors.GetData());
+ return;
+ } else if (!(permissions & ePermissionsExecutable)) {
+ m_constructor_errors.Printf("Return address (0x%" PRIx64
+ ") did not point to executable memory.",
+ m_return_addr);
+ LLDB_LOGF(log, "ThreadPlanStepOut(%p): %s", static_cast<void *>(this),
+ m_constructor_errors.GetData());
+ return;
+ }
+
Breakpoint *return_bp = m_thread.CalculateTarget()
->CreateBreakpoint(m_return_addr, true, false)
.get();
@@ -238,8 +257,13 @@ bool ThreadPlanStepOut::ValidatePlan(Stream *error) {
}
if (m_return_bp_id == LLDB_INVALID_BREAK_ID) {
- if (error)
+ if (error) {
error->PutCString("Could not create return address breakpoint.");
+ if (m_constructor_errors.GetSize() > 0) {
+ error->PutCString(" ");
+ error->PutCString(m_constructor_errors.GetString());
+ }
+ }
return false;
}
diff --git a/lldb/source/Target/ThreadPlanStepOverRange.cpp b/lldb/source/Target/ThreadPlanStepOverRange.cpp
index 2de678597c8a..3dc1967e6d4e 100644
--- a/lldb/source/Target/ThreadPlanStepOverRange.cpp
+++ b/lldb/source/Target/ThreadPlanStepOverRange.cpp
@@ -128,8 +128,8 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
if (log) {
StreamString s;
- s.Address(
- m_thread.GetRegisterContext()->GetPC(),
+ DumpAddress(
+ s.AsRawOstream(), m_thread.GetRegisterContext()->GetPC(),
m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
LLDB_LOGF(log, "ThreadPlanStepOverRange reached %s.", s.GetData());
}
diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp
index 27513a34eadb..d1c56165da50 100644
--- a/lldb/source/Target/ThreadPlanStepRange.cpp
+++ b/lldb/source/Target/ThreadPlanStepRange.cpp
@@ -238,8 +238,19 @@ lldb::FrameComparison ThreadPlanStepRange::CompareCurrentFrameToStartFrame() {
}
bool ThreadPlanStepRange::StopOthers() {
- return (m_stop_others == lldb::eOnlyThisThread ||
- m_stop_others == lldb::eOnlyDuringStepping);
+ switch (m_stop_others) {
+ case lldb::eOnlyThisThread:
+ return true;
+ case lldb::eOnlyDuringStepping:
+ // If there is a call in the range of the next branch breakpoint,
+ // then we should always run all threads, since a call can execute
+ // arbitrary code which might for instance take a lock that's held
+ // by another thread.
+ return !m_found_calls;
+ case lldb::eAllThreads:
+ return false;
+ }
+ llvm_unreachable("Unhandled run mode!");
}
InstructionList *ThreadPlanStepRange::GetInstructionsForAddress(
@@ -292,6 +303,7 @@ void ThreadPlanStepRange::ClearNextBranchBreakpoint() {
GetTarget().RemoveBreakpointByID(m_next_branch_bp_sp->GetID());
m_next_branch_bp_sp.reset();
m_could_not_resolve_hw_bp = false;
+ m_found_calls = false;
}
}
@@ -305,6 +317,9 @@ bool ThreadPlanStepRange::SetNextBranchBreakpoint() {
if (!m_use_fast_step)
return false;
+ // clear the m_found_calls, we'll rediscover it for this range.
+ m_found_calls = false;
+
lldb::addr_t cur_addr = GetThread().GetRegisterContext()->GetPC();
// Find the current address in our address ranges, and fetch the disassembly
// if we haven't already:
@@ -319,7 +334,8 @@ bool ThreadPlanStepRange::SetNextBranchBreakpoint() {
const bool ignore_calls = GetKind() == eKindStepOverRange;
uint32_t branch_index =
instructions->GetIndexOfNextBranchInstruction(pc_index, target,
- ignore_calls);
+ ignore_calls,
+ &m_found_calls);
Address run_to_address;
diff --git a/lldb/source/Target/ThreadPlanStepThrough.cpp b/lldb/source/Target/ThreadPlanStepThrough.cpp
index 92b7fce1bc90..8c7b180fce2d 100644
--- a/lldb/source/Target/ThreadPlanStepThrough.cpp
+++ b/lldb/source/Target/ThreadPlanStepThrough.cpp
@@ -119,11 +119,11 @@ void ThreadPlanStepThrough::GetDescription(Stream *s,
s->Printf("Step through");
else {
s->PutCString("Stepping through trampoline code from: ");
- s->Address(m_start_address, sizeof(addr_t));
+ DumpAddress(s->AsRawOstream(), m_start_address, sizeof(addr_t));
if (m_backstop_bkpt_id != LLDB_INVALID_BREAK_ID) {
s->Printf(" with backstop breakpoint ID: %d at address: ",
m_backstop_bkpt_id);
- s->Address(m_backstop_addr, sizeof(addr_t));
+ DumpAddress(s->AsRawOstream(), m_backstop_addr, sizeof(addr_t));
} else
s->PutCString(" unable to set a backstop breakpoint.");
}
diff --git a/lldb/source/Target/ThreadPlanTracer.cpp b/lldb/source/Target/ThreadPlanTracer.cpp
index 5782fe8e6443..b50c1636b7ff 100644
--- a/lldb/source/Target/ThreadPlanTracer.cpp
+++ b/lldb/source/Target/ThreadPlanTracer.cpp
@@ -115,10 +115,6 @@ TypeFromUser ThreadPlanAssemblyTracer::GetIntPointerType() {
ThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer() = default;
void ThreadPlanAssemblyTracer::TracingStarted() {
- RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
-
- if (m_register_values.empty())
- m_register_values.resize(reg_ctx->GetRegisterCount());
}
void ThreadPlanAssemblyTracer::TracingEnded() { m_register_values.clear(); }
@@ -208,6 +204,11 @@ void ThreadPlanAssemblyTracer::Log() {
}
}
+ if (m_register_values.empty()) {
+ RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
+ m_register_values.resize(reg_ctx->GetRegisterCount());
+ }
+
RegisterValue reg_value;
for (uint32_t reg_num = 0, num_registers = reg_ctx->GetRegisterCount();
reg_num < num_registers; ++reg_num) {
diff --git a/lldb/source/Utility/ArchSpec.cpp b/lldb/source/Utility/ArchSpec.cpp
index 40cc4a092b0d..3dae25ceacd6 100644
--- a/lldb/source/Utility/ArchSpec.cpp
+++ b/lldb/source/Utility/ArchSpec.cpp
@@ -9,17 +9,13 @@
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/NameMatches.h"
-#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StringList.h"
#include "lldb/lldb-defines.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/BinaryFormat/MachO.h"
#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Host.h"
using namespace lldb;
using namespace lldb_private;
@@ -61,6 +57,8 @@ static const CoreDefinition g_core_definitions[] = {
"armv6m"},
{eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_armv7,
"armv7"},
+ {eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_armv7l,
+ "armv7l"},
{eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_armv7f,
"armv7f"},
{eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_armv7s,
@@ -101,6 +99,8 @@ static const CoreDefinition g_core_definitions[] = {
ArchSpec::eCore_arm_arm64, "arm64"},
{eByteOrderLittle, 8, 4, 4, llvm::Triple::aarch64,
ArchSpec::eCore_arm_armv8, "armv8"},
+ {eByteOrderLittle, 4, 2, 4, llvm::Triple::arm,
+ ArchSpec::eCore_arm_armv8l, "armv8l"},
{eByteOrderLittle, 4, 4, 4, llvm::Triple::aarch64_32,
ArchSpec::eCore_arm_arm64_32, "arm64_32"},
{eByteOrderLittle, 8, 4, 4, llvm::Triple::aarch64,
@@ -444,7 +444,7 @@ static const ArchDefinitionEntry g_elf_arch_entries[] = {
{ArchSpec::eCore_hexagon_generic, llvm::ELF::EM_HEXAGON,
LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, // HEXAGON
{ArchSpec::eCore_arc, llvm::ELF::EM_ARC_COMPACT2, LLDB_INVALID_CPUTYPE,
- 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARC
+ 0xFFFFFFFFu, 0xFFFFFFFFu}, // ARC
};
static const ArchDefinition g_elf_arch_def = {
@@ -564,20 +564,6 @@ ArchSpec::ArchSpec(ArchitectureType arch_type, uint32_t cpu, uint32_t subtype) {
ArchSpec::~ArchSpec() = default;
-//===----------------------------------------------------------------------===//
-// Assignment and initialization.
-
-const ArchSpec &ArchSpec::operator=(const ArchSpec &rhs) {
- if (this != &rhs) {
- m_triple = rhs.m_triple;
- m_core = rhs.m_core;
- m_byte_order = rhs.m_byte_order;
- m_distribution_id = rhs.m_distribution_id;
- m_flags = rhs.m_flags;
- }
- return *this;
-}
-
void ArchSpec::Clear() {
m_triple = llvm::Triple();
m_core = kCore_invalid;
@@ -878,7 +864,7 @@ void ArchSpec::MergeFrom(const ArchSpec &other) {
IsCompatibleMatch(other) && GetCore() == ArchSpec::eCore_arm_generic &&
other.GetCore() != ArchSpec::eCore_arm_generic) {
m_core = other.GetCore();
- CoreUpdated(true);
+ CoreUpdated(false);
}
if (GetFlags() == 0) {
SetFlags(other.GetFlags());
@@ -1202,6 +1188,8 @@ static bool cores_match(const ArchSpec::Core core1, const ArchSpec::Core core2,
case ArchSpec::eCore_arm_armv7f:
case ArchSpec::eCore_arm_armv7k:
case ArchSpec::eCore_arm_armv7s:
+ case ArchSpec::eCore_arm_armv7l:
+ case ArchSpec::eCore_arm_armv8l:
if (!enforce_exact_match) {
if (core2 == ArchSpec::eCore_arm_generic)
return true;
@@ -1451,21 +1439,24 @@ bool ArchSpec::IsAlwaysThumbInstructions() const {
GetCore() == ArchSpec::Core::eCore_thumbv6m) {
return true;
}
+ // Windows on ARM is always thumb.
+ if (GetTriple().isOSWindows())
+ return true;
}
return false;
}
-void ArchSpec::DumpTriple(Stream &s) const {
+void ArchSpec::DumpTriple(llvm::raw_ostream &s) const {
const llvm::Triple &triple = GetTriple();
llvm::StringRef arch_str = triple.getArchName();
llvm::StringRef vendor_str = triple.getVendorName();
llvm::StringRef os_str = triple.getOSName();
llvm::StringRef environ_str = triple.getEnvironmentName();
- s.Printf("%s-%s-%s", arch_str.empty() ? "*" : arch_str.str().c_str(),
- vendor_str.empty() ? "*" : vendor_str.str().c_str(),
- os_str.empty() ? "*" : os_str.str().c_str());
+ s << llvm::formatv("{0}-{1}-{2}", arch_str.empty() ? "*" : arch_str,
+ vendor_str.empty() ? "*" : vendor_str,
+ os_str.empty() ? "*" : os_str);
if (!environ_str.empty())
- s.Printf("-%s", environ_str.str().c_str());
+ s << "-" << environ_str;
}
diff --git a/lldb/source/Utility/Baton.cpp b/lldb/source/Utility/Baton.cpp
index 84e295e24686..7bba10dcec96 100644
--- a/lldb/source/Utility/Baton.cpp
+++ b/lldb/source/Utility/Baton.cpp
@@ -8,5 +8,6 @@
#include "lldb/Utility/Baton.h"
-void lldb_private::UntypedBaton::GetDescription(
- Stream *s, lldb::DescriptionLevel level) const {}
+void lldb_private::UntypedBaton::GetDescription(llvm::raw_ostream &s,
+ lldb::DescriptionLevel level,
+ unsigned indentation) const {}
diff --git a/lldb/source/Utility/Broadcaster.cpp b/lldb/source/Utility/Broadcaster.cpp
index 148fdf7ba5b1..ee0c39f8fd42 100644
--- a/lldb/source/Utility/Broadcaster.cpp
+++ b/lldb/source/Utility/Broadcaster.cpp
@@ -17,7 +17,6 @@
#include <algorithm>
#include <memory>
-#include <type_traits>
#include <utility>
#include <assert.h>
@@ -318,9 +317,6 @@ bool BroadcastEventSpec::operator<(const BroadcastEventSpec &rhs) const {
return GetBroadcasterClass() < rhs.GetBroadcasterClass();
}
-BroadcastEventSpec &BroadcastEventSpec::
-operator=(const BroadcastEventSpec &rhs) = default;
-
BroadcasterManager::BroadcasterManager() : m_manager_mutex() {}
lldb::BroadcasterManagerSP BroadcasterManager::MakeBroadcasterManager() {
diff --git a/lldb/source/Utility/ConstString.cpp b/lldb/source/Utility/ConstString.cpp
index 2516ecf6a989..e90bb929bb81 100644
--- a/lldb/source/Utility/ConstString.cpp
+++ b/lldb/source/Utility/ConstString.cpp
@@ -18,7 +18,6 @@
#include "llvm/Support/RWMutex.h"
#include "llvm/Support/Threading.h"
-#include <algorithm>
#include <array>
#include <utility>
diff --git a/lldb/source/Utility/DataBufferLLVM.cpp b/lldb/source/Utility/DataBufferLLVM.cpp
index 4227e9b39960..c20e1b06f52e 100644
--- a/lldb/source/Utility/DataBufferLLVM.cpp
+++ b/lldb/source/Utility/DataBufferLLVM.cpp
@@ -8,12 +8,9 @@
#include "lldb/Utility/DataBufferLLVM.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include <assert.h>
-#include <type_traits>
using namespace lldb_private;
diff --git a/lldb/source/Utility/DataEncoder.cpp b/lldb/source/Utility/DataEncoder.cpp
index 13c505e34e82..8a1036e26dce 100644
--- a/lldb/source/Utility/DataEncoder.cpp
+++ b/lldb/source/Utility/DataEncoder.cpp
@@ -13,9 +13,7 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MathExtras.h"
-#include <cassert>
#include <cstddef>
#include <string.h>
@@ -61,42 +59,6 @@ void DataEncoder::Clear() {
m_data_sp.reset();
}
-// If this object contains shared data, this function returns the offset into
-// that shared data. Else zero is returned.
-size_t DataEncoder::GetSharedDataOffset() const {
- if (m_start != nullptr) {
- const DataBuffer *data = m_data_sp.get();
- if (data != nullptr) {
- const uint8_t *data_bytes = data->GetBytes();
- if (data_bytes != nullptr) {
- assert(m_start >= data_bytes);
- return m_start - data_bytes;
- }
- }
- }
- return 0;
-}
-
-// Set the data with which this object will extract from to data starting at
-// BYTES and set the length of the data to LENGTH bytes long. The data is
-// externally owned must be around at least as long as this object points to
-// the data. No copy of the data is made, this object just refers to this data
-// and can extract from it. If this object refers to any shared data upon
-// entry, the reference to that data will be released. Is SWAP is set to true,
-// any data extracted will be endian swapped.
-uint32_t DataEncoder::SetData(void *bytes, uint32_t length, ByteOrder endian) {
- m_byte_order = endian;
- m_data_sp.reset();
- if (bytes == nullptr || length == 0) {
- m_start = nullptr;
- m_end = nullptr;
- } else {
- m_start = static_cast<uint8_t *>(bytes);
- m_end = m_start + length;
- }
- return GetByteSize();
-}
-
// Assign the data for this object to be a subrange of the shared data in
// "data_sp" starting "data_offset" bytes into "data_sp" and ending
// "data_length" bytes later. If "data_offset" is not a valid offset into
@@ -187,16 +149,8 @@ uint32_t DataEncoder::PutU64(uint32_t offset, uint64_t value) {
return UINT32_MAX;
}
-// Extract a single integer value from the data and update the offset pointed
-// to by "offset_ptr". The size of the extracted integer is specified by the
-// "byte_size" argument. "byte_size" should have a value >= 1 and <= 8 since
-// the return value is only 64 bits wide. Any "byte_size" values less than 1 or
-// greater than 8 will result in nothing being extracted, and zero being
-// returned.
-//
-// RETURNS the integer value that was extracted, or zero on failure.
-uint32_t DataEncoder::PutMaxU64(uint32_t offset, uint32_t byte_size,
- uint64_t value) {
+uint32_t DataEncoder::PutUnsigned(uint32_t offset, uint32_t byte_size,
+ uint64_t value) {
switch (byte_size) {
case 1:
return PutU8(offset, value);
@@ -225,7 +179,7 @@ uint32_t DataEncoder::PutData(uint32_t offset, const void *src,
}
uint32_t DataEncoder::PutAddress(uint32_t offset, lldb::addr_t addr) {
- return PutMaxU64(offset, GetAddressByteSize(), addr);
+ return PutUnsigned(offset, m_addr_size, addr);
}
uint32_t DataEncoder::PutCString(uint32_t offset, const char *cstr) {
diff --git a/lldb/source/Utility/DataExtractor.cpp b/lldb/source/Utility/DataExtractor.cpp
index f642a8fc7639..fed2a1326b86 100644
--- a/lldb/source/Utility/DataExtractor.cpp
+++ b/lldb/source/Utility/DataExtractor.cpp
@@ -129,9 +129,8 @@ DataExtractor::DataExtractor()
DataExtractor::DataExtractor(const void *data, offset_t length,
ByteOrder endian, uint32_t addr_size,
uint32_t target_byte_size /*=1*/)
- : m_start(const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(data))),
- m_end(const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(data)) +
- length),
+ : m_start(const_cast<uint8_t *>(static_cast<const uint8_t *>(data))),
+ m_end(const_cast<uint8_t *>(static_cast<const uint8_t *>(data)) + length),
m_byte_order(endian), m_addr_size(addr_size), m_data_sp(),
m_target_byte_size(target_byte_size) {
assert(addr_size == 4 || addr_size == 8);
@@ -232,7 +231,7 @@ lldb::offset_t DataExtractor::SetData(const void *bytes, offset_t length,
m_start = nullptr;
m_end = nullptr;
} else {
- m_start = const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(bytes));
+ m_start = const_cast<uint8_t *>(static_cast<const uint8_t *>(bytes));
m_end = m_start + length;
}
return GetByteSize();
@@ -577,18 +576,28 @@ int64_t DataExtractor::GetMaxS64(offset_t *offset_ptr, size_t byte_size) const {
uint64_t DataExtractor::GetMaxU64Bitfield(offset_t *offset_ptr, size_t size,
uint32_t bitfield_bit_size,
uint32_t bitfield_bit_offset) const {
+ assert(bitfield_bit_size <= 64);
uint64_t uval64 = GetMaxU64(offset_ptr, size);
- if (bitfield_bit_size > 0) {
- int32_t lsbcount = bitfield_bit_offset;
- if (m_byte_order == eByteOrderBig)
- lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size;
- if (lsbcount > 0)
- uval64 >>= lsbcount;
- uint64_t bitfield_mask = ((1ul << bitfield_bit_size) - 1);
- if (!bitfield_mask && bitfield_bit_offset == 0 && bitfield_bit_size == 64)
- return uval64;
- uval64 &= bitfield_mask;
- }
+
+ if (bitfield_bit_size == 0)
+ return uval64;
+
+ int32_t lsbcount = bitfield_bit_offset;
+ if (m_byte_order == eByteOrderBig)
+ lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size;
+
+ if (lsbcount > 0)
+ uval64 >>= lsbcount;
+
+ uint64_t bitfield_mask =
+ (bitfield_bit_size == 64
+ ? std::numeric_limits<uint64_t>::max()
+ : ((static_cast<uint64_t>(1) << bitfield_bit_size) - 1));
+ if (!bitfield_mask && bitfield_bit_offset == 0 && bitfield_bit_size == 64)
+ return uval64;
+
+ uval64 &= bitfield_mask;
+
return uval64;
}
@@ -975,8 +984,7 @@ uint32_t DataExtractor::Skip_LEB128(offset_t *offset_ptr) const {
lldb::offset_t DataExtractor::PutToLog(Log *log, offset_t start_offset,
offset_t length, uint64_t base_addr,
uint32_t num_per_line,
- DataExtractor::Type type,
- const char *format) const {
+ DataExtractor::Type type) const {
if (log == nullptr)
return start_offset;
@@ -1000,29 +1008,29 @@ lldb::offset_t DataExtractor::PutToLog(Log *log, offset_t start_offset,
switch (type) {
case TypeUInt8:
- sstr.Printf(format ? format : " %2.2x", GetU8(&offset));
+ sstr.Printf(" %2.2x", GetU8(&offset));
break;
case TypeChar: {
char ch = GetU8(&offset);
- sstr.Printf(format ? format : " %c", isprint(ch) ? ch : ' ');
+ sstr.Printf(" %c", isprint(ch) ? ch : ' ');
} break;
case TypeUInt16:
- sstr.Printf(format ? format : " %4.4x", GetU16(&offset));
+ sstr.Printf(" %4.4x", GetU16(&offset));
break;
case TypeUInt32:
- sstr.Printf(format ? format : " %8.8x", GetU32(&offset));
+ sstr.Printf(" %8.8x", GetU32(&offset));
break;
case TypeUInt64:
- sstr.Printf(format ? format : " %16.16" PRIx64, GetU64(&offset));
+ sstr.Printf(" %16.16" PRIx64, GetU64(&offset));
break;
case TypePointer:
- sstr.Printf(format ? format : " 0x%" PRIx64, GetAddress(&offset));
+ sstr.Printf(" 0x%" PRIx64, GetAddress(&offset));
break;
case TypeULEB128:
- sstr.Printf(format ? format : " 0x%" PRIx64, GetULEB128(&offset));
+ sstr.Printf(" 0x%" PRIx64, GetULEB128(&offset));
break;
case TypeSLEB128:
- sstr.Printf(format ? format : " %" PRId64, GetSLEB128(&offset));
+ sstr.Printf(" %" PRId64, GetSLEB128(&offset));
break;
}
}
diff --git a/lldb/source/Utility/Environment.cpp b/lldb/source/Utility/Environment.cpp
index 140533600712..8cafd3024618 100644
--- a/lldb/source/Utility/Environment.cpp
+++ b/lldb/source/Utility/Environment.cpp
@@ -13,7 +13,7 @@ using namespace lldb_private;
char *Environment::Envp::make_entry(llvm::StringRef Key,
llvm::StringRef Value) {
const size_t size = Key.size() + 1 /*=*/ + Value.size() + 1 /*\0*/;
- char *Result = reinterpret_cast<char *>(
+ char *Result = static_cast<char *>(
Allocator.Allocate(sizeof(char) * size, alignof(char)));
char *Next = Result;
@@ -26,7 +26,7 @@ char *Environment::Envp::make_entry(llvm::StringRef Key,
}
Environment::Envp::Envp(const Environment &Env) {
- Data = reinterpret_cast<char **>(
+ Data = static_cast<char **>(
Allocator.Allocate(sizeof(char *) * (Env.size() + 1), alignof(char *)));
char **Next = Data;
for (const auto &KV : Env)
diff --git a/lldb/source/Utility/FileSpec.cpp b/lldb/source/Utility/FileSpec.cpp
index f22ab4d84e40..5c216d947f75 100644
--- a/lldb/source/Utility/FileSpec.cpp
+++ b/lldb/source/Utility/FileSpec.cpp
@@ -75,15 +75,6 @@ FileSpec::FileSpec(llvm::StringRef path, Style style) : m_style(style) {
FileSpec::FileSpec(llvm::StringRef path, const llvm::Triple &triple)
: FileSpec{path, triple.isOSWindows() ? Style::windows : Style::posix} {}
-// Copy constructor
-FileSpec::FileSpec(const FileSpec *rhs) : m_directory(), m_filename() {
- if (rhs)
- *this = *rhs;
-}
-
-// Virtual destructor in case anyone inherits from this class.
-FileSpec::~FileSpec() {}
-
namespace {
/// Safely get a character at the specified index.
///
@@ -174,16 +165,6 @@ bool needsNormalization(const llvm::StringRef &path) {
}
-// Assignment operator.
-const FileSpec &FileSpec::operator=(const FileSpec &rhs) {
- if (this != &rhs) {
- m_directory = rhs.m_directory;
- m_filename = rhs.m_filename;
- m_is_resolved = rhs.m_is_resolved;
- m_style = rhs.m_style;
- }
- return *this;
-}
void FileSpec::SetFile(llvm::StringRef pathname) { SetFile(pathname, m_style); }
@@ -271,7 +252,7 @@ bool FileSpec::operator<(const FileSpec &rhs) const {
// Dump a FileSpec object to a stream
Stream &lldb_private::operator<<(Stream &s, const FileSpec &f) {
- f.Dump(&s);
+ f.Dump(s.AsRawOstream());
return s;
}
@@ -312,20 +293,18 @@ int FileSpec::Compare(const FileSpec &a, const FileSpec &b, bool full) {
}
bool FileSpec::Equal(const FileSpec &a, const FileSpec &b, bool full) {
- // case sensitivity of equality test
- const bool case_sensitive = a.IsCaseSensitive() || b.IsCaseSensitive();
-
- const bool filenames_equal = ConstString::Equals(a.m_filename,
- b.m_filename,
- case_sensitive);
-
- if (!filenames_equal)
- return false;
+ if (full || (a.GetDirectory() && b.GetDirectory()))
+ return a == b;
- if (!full && (a.GetDirectory().IsEmpty() || b.GetDirectory().IsEmpty()))
- return filenames_equal;
+ return a.FileEquals(b);
+}
- return a == b;
+bool FileSpec::Match(const FileSpec &pattern, const FileSpec &file) {
+ if (pattern.GetDirectory())
+ return pattern == file;
+ if (pattern.GetFilename())
+ return pattern.FileEquals(file);
+ return true;
}
llvm::Optional<FileSpec::Style> FileSpec::GuessPathStyle(llvm::StringRef absolute_path) {
@@ -342,14 +321,12 @@ llvm::Optional<FileSpec::Style> FileSpec::GuessPathStyle(llvm::StringRef absolut
// Dump the object to the supplied stream. If the object contains a valid
// directory name, it will be displayed followed by a directory delimiter, and
// the filename.
-void FileSpec::Dump(Stream *s) const {
- if (s) {
- std::string path{GetPath(true)};
- s->PutCString(path);
- char path_separator = GetPreferredPathSeparator(m_style);
- if (!m_filename && !path.empty() && path.back() != path_separator)
- s->PutChar(path_separator);
- }
+void FileSpec::Dump(llvm::raw_ostream &s) const {
+ std::string path{GetPath(true)};
+ s << path;
+ char path_separator = GetPreferredPathSeparator(m_style);
+ if (!m_filename && !path.empty() && path.back() != path_separator)
+ s << path_separator;
}
FileSpec::Style FileSpec::GetPathStyle() const { return m_style; }
diff --git a/lldb/source/Utility/GDBRemote.cpp b/lldb/source/Utility/GDBRemote.cpp
index 85c4bc69a8d1..f267d00fc97e 100644
--- a/lldb/source/Utility/GDBRemote.cpp
+++ b/lldb/source/Utility/GDBRemote.cpp
@@ -14,6 +14,7 @@
#include <stdio.h>
using namespace lldb;
+using namespace lldb_private::repro;
using namespace lldb_private;
using namespace llvm;
@@ -45,12 +46,6 @@ int StreamGDBRemote::PutEscapedBytes(const void *s, size_t src_len) {
return bytes_written;
}
-void GDBRemotePacket::Serialize(raw_ostream &strm) const {
- yaml::Output yout(strm);
- yout << const_cast<GDBRemotePacket &>(*this);
- strm.flush();
-}
-
llvm::StringRef GDBRemotePacket::GetTypeStr() const {
switch (type) {
case GDBRemotePacket::ePacketTypeSend:
@@ -98,8 +93,68 @@ void yaml::MappingTraits<GDBRemotePacket>::mapping(IO &io,
StringRef
yaml::MappingTraits<GDBRemotePacket>::validate(IO &io,
GDBRemotePacket &Packet) {
- if (Packet.bytes_transmitted != Packet.packet.data.size())
- return "BinaryData size doesn't match bytes transmitted";
-
return {};
}
+
+void GDBRemoteProvider::Keep() {
+ std::vector<std::string> files;
+ for (auto &recorder : m_packet_recorders) {
+ files.push_back(recorder->GetFilename().GetPath());
+ }
+
+ FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file);
+ std::error_code ec;
+ llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text);
+ if (ec)
+ return;
+ yaml::Output yout(os);
+ yout << files;
+}
+
+void GDBRemoteProvider::Discard() { m_packet_recorders.clear(); }
+
+llvm::Expected<std::unique_ptr<PacketRecorder>>
+PacketRecorder::Create(const FileSpec &filename) {
+ std::error_code ec;
+ auto recorder = std::make_unique<PacketRecorder>(std::move(filename), ec);
+ if (ec)
+ return llvm::errorCodeToError(ec);
+ return std::move(recorder);
+}
+
+PacketRecorder *GDBRemoteProvider::GetNewPacketRecorder() {
+ std::size_t i = m_packet_recorders.size() + 1;
+ std::string filename = (llvm::Twine(Info::name) + llvm::Twine("-") +
+ llvm::Twine(i) + llvm::Twine(".yaml"))
+ .str();
+ auto recorder_or_error =
+ PacketRecorder::Create(GetRoot().CopyByAppendingPathComponent(filename));
+ if (!recorder_or_error) {
+ llvm::consumeError(recorder_or_error.takeError());
+ return nullptr;
+ }
+
+ m_packet_recorders.push_back(std::move(*recorder_or_error));
+ return m_packet_recorders.back().get();
+}
+
+void PacketRecorder::Record(const GDBRemotePacket &packet) {
+ if (!m_record)
+ return;
+ yaml::Output yout(m_os);
+ yout << const_cast<GDBRemotePacket &>(packet);
+ m_os.flush();
+}
+
+llvm::raw_ostream *GDBRemoteProvider::GetHistoryStream() {
+ FileSpec history_file = GetRoot().CopyByAppendingPathComponent(Info::file);
+
+ std::error_code EC;
+ m_stream_up = std::make_unique<raw_fd_ostream>(history_file.GetPath(), EC,
+ sys::fs::OpenFlags::OF_Text);
+ return m_stream_up.get();
+}
+
+char GDBRemoteProvider::ID = 0;
+const char *GDBRemoteProvider::Info::file = "gdb-remote.yaml";
+const char *GDBRemoteProvider::Info::name = "gdb-remote";
diff --git a/lldb/source/Utility/LLDBAssert.cpp b/lldb/source/Utility/LLDBAssert.cpp
index 75530d806310..361d6d04a28f 100644
--- a/lldb/source/Utility/LLDBAssert.cpp
+++ b/lldb/source/Utility/LLDBAssert.cpp
@@ -21,10 +21,10 @@ void lldb_private::lldb_assert(bool expression, const char *expr_text,
if (LLVM_LIKELY(expression))
return;
- // In a Debug configuration lldb_assert() behaves like assert(0).
- llvm_unreachable("lldb_assert failed");
+ // If asserts are enabled abort here.
+ assert(false && "lldb_assert failed");
- // In a Release configuration it will print a warning and encourage the user
+ // In a release configuration it will print a warning and encourage the user
// to file a bug report, similar to LLVM’s crash handler, and then return
// execution.
errs() << format("Assertion failed: (%s), function %s, file %s, line %u\n",
diff --git a/lldb/source/Utility/PPC64LE_ehframe_Registers.h b/lldb/source/Utility/PPC64LE_ehframe_Registers.h
deleted file mode 100644
index 77cb3e5924e7..000000000000
--- a/lldb/source/Utility/PPC64LE_ehframe_Registers.h
+++ /dev/null
@@ -1,193 +0,0 @@
-//===-- PPC64LE_ehframe_Registers.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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef utility_PPC64LE_ehframe_Registers_h_
-#define utility_PPC64LE_ehframe_Registers_h_
-
-// The register numbers used in the eh_frame unwind information.
-// Should be the same as DWARF register numbers.
-
-namespace ppc64le_ehframe {
-
-enum {
- r0 = 0,
- r1,
- r2,
- r3,
- r4,
- r5,
- r6,
- r7,
- r8,
- r9,
- r10,
- r11,
- r12,
- r13,
- r14,
- r15,
- r16,
- r17,
- r18,
- r19,
- r20,
- r21,
- r22,
- r23,
- r24,
- r25,
- r26,
- r27,
- r28,
- r29,
- r30,
- r31,
- f0,
- f1,
- f2,
- f3,
- f4,
- f5,
- f6,
- f7,
- f8,
- f9,
- f10,
- f11,
- f12,
- f13,
- f14,
- f15,
- f16,
- f17,
- f18,
- f19,
- f20,
- f21,
- f22,
- f23,
- f24,
- f25,
- f26,
- f27,
- f28,
- f29,
- f30,
- f31,
- lr = 65,
- ctr,
- cr = 68,
- xer = 76,
- vr0,
- vr1,
- vr2,
- vr3,
- vr4,
- vr5,
- vr6,
- vr7,
- vr8,
- vr9,
- vr10,
- vr11,
- vr12,
- vr13,
- vr14,
- vr15,
- vr16,
- vr17,
- vr18,
- vr19,
- vr20,
- vr21,
- vr22,
- vr23,
- vr24,
- vr25,
- vr26,
- vr27,
- vr28,
- vr29,
- vr30,
- vr31,
- vscr = 110,
- vrsave = 117,
- pc,
- softe,
- trap,
- origr3,
- fpscr,
- msr,
- vs0,
- vs1,
- vs2,
- vs3,
- vs4,
- vs5,
- vs6,
- vs7,
- vs8,
- vs9,
- vs10,
- vs11,
- vs12,
- vs13,
- vs14,
- vs15,
- vs16,
- vs17,
- vs18,
- vs19,
- vs20,
- vs21,
- vs22,
- vs23,
- vs24,
- vs25,
- vs26,
- vs27,
- vs28,
- vs29,
- vs30,
- vs31,
- vs32,
- vs33,
- vs34,
- vs35,
- vs36,
- vs37,
- vs38,
- vs39,
- vs40,
- vs41,
- vs42,
- vs43,
- vs44,
- vs45,
- vs46,
- vs47,
- vs48,
- vs49,
- vs50,
- vs51,
- vs52,
- vs53,
- vs54,
- vs55,
- vs56,
- vs57,
- vs58,
- vs59,
- vs60,
- vs61,
- vs62,
- vs63,
-};
-}
-
-#endif // utility_PPC64LE_ehframe_Registers_h_
diff --git a/lldb/source/Utility/ProcessInfo.cpp b/lldb/source/Utility/ProcessInfo.cpp
index 5743d223be4f..b159e2641973 100644
--- a/lldb/source/Utility/ProcessInfo.cpp
+++ b/lldb/source/Utility/ProcessInfo.cpp
@@ -49,7 +49,7 @@ llvm::StringRef ProcessInfo::GetNameAsStringRef() const {
void ProcessInfo::Dump(Stream &s, Platform *platform) const {
s << "Executable: " << GetName() << "\n";
s << "Triple: ";
- m_arch.DumpTriple(s);
+ m_arch.DumpTriple(s.AsRawOstream());
s << "\n";
s << "Arguments:\n";
@@ -119,7 +119,7 @@ void ProcessInstanceInfo::Dump(Stream &s, UserIDResolver &resolver) const {
if (m_executable) {
s.Printf(" name = %s\n", m_executable.GetFilename().GetCString());
s.PutCString(" file = ");
- m_executable.Dump(&s);
+ m_executable.Dump(s.AsRawOstream());
s.EOL();
}
const uint32_t argc = m_arguments.GetArgumentCount();
@@ -137,7 +137,7 @@ void ProcessInstanceInfo::Dump(Stream &s, UserIDResolver &resolver) const {
if (m_arch.IsValid()) {
s.Printf(" arch = ");
- m_arch.DumpTriple(s);
+ m_arch.DumpTriple(s.AsRawOstream());
s.EOL();
}
@@ -189,7 +189,7 @@ void ProcessInstanceInfo::DumpAsTableRow(Stream &s, UserIDResolver &resolver,
StreamString arch_strm;
if (m_arch.IsValid())
- m_arch.DumpTriple(arch_strm);
+ m_arch.DumpTriple(arch_strm.AsRawOstream());
auto print = [&](bool (ProcessInstanceInfo::*isValid)() const,
uint32_t (ProcessInstanceInfo::*getID)() const,
diff --git a/lldb/source/Utility/RegisterValue.cpp b/lldb/source/Utility/RegisterValue.cpp
index a01c35a2818e..36790f5d8efa 100644
--- a/lldb/source/Utility/RegisterValue.cpp
+++ b/lldb/source/Utility/RegisterValue.cpp
@@ -8,7 +8,6 @@
#include "lldb/Utility/RegisterValue.h"
-#include "lldb/Utility/Args.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
@@ -330,6 +329,35 @@ static bool ParseVectorEncoding(const RegisterInfo *reg_info,
return true;
}
+static bool UInt64ValueIsValidForByteSize(uint64_t uval64,
+ size_t total_byte_size) {
+ if (total_byte_size > 8)
+ return false;
+
+ if (total_byte_size == 8)
+ return true;
+
+ const uint64_t max =
+ (static_cast<uint64_t>(1) << static_cast<uint64_t>(total_byte_size * 8)) -
+ 1;
+ return uval64 <= max;
+}
+
+static bool SInt64ValueIsValidForByteSize(int64_t sval64,
+ size_t total_byte_size) {
+ if (total_byte_size > 8)
+ return false;
+
+ if (total_byte_size == 8)
+ return true;
+
+ const int64_t max = (static_cast<int64_t>(1)
+ << static_cast<uint64_t>(total_byte_size * 8 - 1)) -
+ 1;
+ const int64_t min = ~(max);
+ return min <= sval64 && sval64 <= max;
+}
+
Status RegisterValue::SetValueFromString(const RegisterInfo *reg_info,
llvm::StringRef value_str) {
Status error;
@@ -368,7 +396,7 @@ Status RegisterValue::SetValueFromString(const RegisterInfo *reg_info,
break;
}
- if (!Args::UInt64ValueIsValidForByteSize(uval64, byte_size)) {
+ if (!UInt64ValueIsValidForByteSize(uval64, byte_size)) {
error.SetErrorStringWithFormat(
"value 0x%" PRIx64
" is too large to fit in a %u byte unsigned integer value",
@@ -397,7 +425,7 @@ Status RegisterValue::SetValueFromString(const RegisterInfo *reg_info,
break;
}
- if (!Args::SInt64ValueIsValidForByteSize(ival64, byte_size)) {
+ if (!SInt64ValueIsValidForByteSize(ival64, byte_size)) {
error.SetErrorStringWithFormat(
"value 0x%" PRIx64
" is too large to fit in a %u byte signed integer value",
diff --git a/lldb/source/Utility/Reproducer.cpp b/lldb/source/Utility/Reproducer.cpp
index 4777d7576a32..b11e1a577ed2 100644
--- a/lldb/source/Utility/Reproducer.cpp
+++ b/lldb/source/Utility/Reproducer.cpp
@@ -25,6 +25,16 @@ llvm::Error Reproducer::Initialize(ReproducerMode mode,
lldbassert(!InstanceImpl() && "Already initialized.");
InstanceImpl().emplace();
+ // The environment can override the capture mode.
+ if (mode != ReproducerMode::Replay) {
+ std::string env =
+ llvm::StringRef(getenv("LLDB_CAPTURE_REPRODUCER")).lower();
+ if (env == "0" || env == "off")
+ mode = ReproducerMode::Off;
+ else if (env == "1" || env == "on")
+ mode = ReproducerMode::Capture;
+ }
+
switch (mode) {
case ReproducerMode::Capture: {
if (!root) {
@@ -143,12 +153,14 @@ static FileSpec MakeAbsolute(FileSpec file_spec) {
return FileSpec(path, file_spec.GetPathStyle());
}
-Generator::Generator(FileSpec root)
- : m_root(MakeAbsolute(std::move(root))), m_done(false) {
+Generator::Generator(FileSpec root) : m_root(MakeAbsolute(std::move(root))) {
GetOrCreate<repro::WorkingDirectoryProvider>();
}
-Generator::~Generator() {}
+Generator::~Generator() {
+ if (!m_done)
+ Discard();
+}
ProviderBase *Generator::Register(std::unique_ptr<ProviderBase> provider) {
std::lock_guard<std::mutex> lock(m_providers_mutex);
@@ -243,7 +255,7 @@ DataRecorder::Create(const FileSpec &filename) {
DataRecorder *CommandProvider::GetNewDataRecorder() {
std::size_t i = m_data_recorders.size() + 1;
std::string filename = (llvm::Twine(Info::name) + llvm::Twine("-") +
- llvm::Twine(i) + llvm::Twine(".txt"))
+ llvm::Twine(i) + llvm::Twine(".yaml"))
.str();
auto recorder_or_error =
DataRecorder::Create(GetRoot().CopyByAppendingPathComponent(filename));
@@ -292,53 +304,9 @@ void WorkingDirectoryProvider::Keep() {
os << m_cwd << "\n";
}
-llvm::raw_ostream *ProcessGDBRemoteProvider::GetHistoryStream() {
- FileSpec history_file = GetRoot().CopyByAppendingPathComponent(Info::file);
-
- std::error_code EC;
- m_stream_up = std::make_unique<raw_fd_ostream>(history_file.GetPath(), EC,
- sys::fs::OpenFlags::OF_Text);
- return m_stream_up.get();
-}
-
-std::unique_ptr<CommandLoader> CommandLoader::Create(Loader *loader) {
- if (!loader)
- return {};
-
- FileSpec file = loader->GetFile<repro::CommandProvider::Info>();
- if (!file)
- return {};
-
- auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath());
- if (auto err = error_or_file.getError())
- return {};
-
- std::vector<std::string> files;
- llvm::yaml::Input yin((*error_or_file)->getBuffer());
- yin >> files;
-
- if (auto err = yin.error())
- return {};
-
- for (auto &file : files) {
- FileSpec absolute_path =
- loader->GetRoot().CopyByAppendingPathComponent(file);
- file = absolute_path.GetPath();
- }
-
- return std::make_unique<CommandLoader>(std::move(files));
-}
-
-llvm::Optional<std::string> CommandLoader::GetNextFile() {
- if (m_index >= m_files.size())
- return {};
- return m_files[m_index++];
-}
-
void ProviderBase::anchor() {}
char CommandProvider::ID = 0;
char FileProvider::ID = 0;
-char ProcessGDBRemoteProvider::ID = 0;
char ProviderBase::ID = 0;
char VersionProvider::ID = 0;
char WorkingDirectoryProvider::ID = 0;
@@ -346,8 +314,6 @@ const char *CommandProvider::Info::file = "command-interpreter.yaml";
const char *CommandProvider::Info::name = "command-interpreter";
const char *FileProvider::Info::file = "files.yaml";
const char *FileProvider::Info::name = "files";
-const char *ProcessGDBRemoteProvider::Info::file = "gdb-remote.yaml";
-const char *ProcessGDBRemoteProvider::Info::name = "gdb-remote";
const char *VersionProvider::Info::file = "version.txt";
const char *VersionProvider::Info::name = "version";
const char *WorkingDirectoryProvider::Info::file = "cwd.txt";
diff --git a/lldb/source/Utility/Scalar.cpp b/lldb/source/Utility/Scalar.cpp
index e9aec17b6650..a9293e87220b 100644
--- a/lldb/source/Utility/Scalar.cpp
+++ b/lldb/source/Utility/Scalar.cpp
@@ -74,7 +74,7 @@ Scalar::Scalar() : m_type(e_void), m_float(static_cast<float>(0)) {}
bool Scalar::GetData(DataExtractor &data, size_t limit_byte_size) const {
size_t byte_size = GetByteSize();
if (byte_size > 0) {
- const uint8_t *bytes = reinterpret_cast<const uint8_t *>(GetBytes());
+ const uint8_t *bytes = static_cast<const uint8_t *>(GetBytes());
if (limit_byte_size < byte_size) {
if (endian::InlHostByteOrder() == eByteOrderLittle) {
@@ -132,7 +132,7 @@ const void *Scalar::GetBytes() const {
swapped_words[1] = apint_words[0];
apint_words = swapped_words;
}
- return reinterpret_cast<const void *>(apint_words);
+ return static_cast<const void *>(apint_words);
case e_sint256:
case e_uint256:
apint_words = m_integer.getRawData();
@@ -143,7 +143,7 @@ const void *Scalar::GetBytes() const {
swapped_words[3] = apint_words[0];
apint_words = swapped_words;
}
- return reinterpret_cast<const void *>(apint_words);
+ return static_cast<const void *>(apint_words);
case e_sint512:
case e_uint512:
apint_words = m_integer.getRawData();
@@ -158,13 +158,13 @@ const void *Scalar::GetBytes() const {
swapped_words[7] = apint_words[0];
apint_words = swapped_words;
}
- return reinterpret_cast<const void *>(apint_words);
+ return static_cast<const void *>(apint_words);
case e_float:
flt_val = m_float.convertToFloat();
- return reinterpret_cast<const void *>(&flt_val);
+ return static_cast<const void *>(&flt_val);
case e_double:
dbl_val = m_float.convertToDouble();
- return reinterpret_cast<const void *>(&dbl_val);
+ return static_cast<const void *>(&dbl_val);
case e_long_double:
llvm::APInt ldbl_val = m_float.bitcastToAPInt();
apint_words = ldbl_val.getRawData();
@@ -176,7 +176,7 @@ const void *Scalar::GetBytes() const {
swapped_words[1] = apint_words[0];
apint_words = swapped_words;
}
- return reinterpret_cast<const void *>(apint_words);
+ return static_cast<const void *>(apint_words);
}
return nullptr;
}
@@ -305,15 +305,6 @@ const char *Scalar::GetTypeAsCString() const {
return "<invalid Scalar type>";
}
-Scalar &Scalar::operator=(const Scalar &rhs) {
- if (this != &rhs) {
- m_type = rhs.m_type;
- m_integer = llvm::APInt(rhs.m_integer);
- m_float = rhs.m_float;
- }
- return *this;
-}
-
Scalar &Scalar::operator=(const int v) {
m_type = e_sint;
m_integer = llvm::APInt(sizeof(int) * 8, v, true);
diff --git a/lldb/source/Utility/Status.cpp b/lldb/source/Utility/Status.cpp
index 3d64fb810abf..b74db72773dd 100644
--- a/lldb/source/Utility/Status.cpp
+++ b/lldb/source/Utility/Status.cpp
@@ -93,16 +93,6 @@ llvm::Error Status::ToError() const {
llvm::inconvertibleErrorCode());
}
-// Assignment operator
-const Status &Status::operator=(const Status &rhs) {
- if (this != &rhs) {
- m_code = rhs.m_code;
- m_type = rhs.m_type;
- m_string = rhs.m_string;
- }
- return *this;
-}
-
Status::~Status() = default;
#ifdef _WIN32
@@ -110,14 +100,23 @@ static std::string RetrieveWin32ErrorString(uint32_t error_code) {
char *buffer = nullptr;
std::string message;
// Retrieve win32 system error.
+ // First, attempt to load a en-US message
if (::FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_MAX_WIDTH_MASK,
- NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ NULL, error_code, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
(LPSTR)&buffer, 0, NULL)) {
message.assign(buffer);
::LocalFree(buffer);
}
+ // If the previous didn't work, use the default OS language
+ else if (::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_MAX_WIDTH_MASK,
+ NULL, error_code, 0, (LPSTR)&buffer, 0, NULL)) {
+ message.assign(buffer);
+ ::LocalFree(buffer);
+ }
return message;
}
#endif
diff --git a/lldb/source/Utility/Stream.cpp b/lldb/source/Utility/Stream.cpp
index c48a12acd906..b336cb6b5185 100644
--- a/lldb/source/Utility/Stream.cpp
+++ b/lldb/source/Utility/Stream.cpp
@@ -11,6 +11,7 @@
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/VASPrintf.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/LEB128.h"
#include <string>
@@ -76,28 +77,27 @@ void Stream::QuotedCString(const char *cstr, const char *format) {
// Put an address "addr" out to the stream with optional prefix and suffix
// strings.
-void Stream::Address(uint64_t addr, uint32_t addr_size, const char *prefix,
- const char *suffix) {
+void lldb_private::DumpAddress(llvm::raw_ostream &s, uint64_t addr,
+ uint32_t addr_size, const char *prefix,
+ const char *suffix) {
if (prefix == nullptr)
prefix = "";
if (suffix == nullptr)
suffix = "";
- // int addr_width = m_addr_size << 1;
- // Printf ("%s0x%0*" PRIx64 "%s", prefix, addr_width, addr, suffix);
- Printf("%s0x%0*" PRIx64 "%s", prefix, addr_size * 2, addr, suffix);
+ s << prefix << llvm::format_hex(addr, 2 + 2 * addr_size) << suffix;
}
// Put an address range out to the stream with optional prefix and suffix
// strings.
-void Stream::AddressRange(uint64_t lo_addr, uint64_t hi_addr,
- uint32_t addr_size, const char *prefix,
- const char *suffix) {
+void lldb_private::DumpAddressRange(llvm::raw_ostream &s, uint64_t lo_addr,
+ uint64_t hi_addr, uint32_t addr_size,
+ const char *prefix, const char *suffix) {
if (prefix && prefix[0])
- PutCString(prefix);
- Address(lo_addr, addr_size, "[");
- Address(hi_addr, addr_size, "-", ")");
+ s << prefix;
+ DumpAddress(s, lo_addr, addr_size, "[");
+ DumpAddress(s, hi_addr, addr_size, "-", ")");
if (suffix && suffix[0])
- PutCString(suffix);
+ s << suffix;
}
size_t Stream::PutChar(char ch) { return Write(&ch, 1); }
@@ -160,65 +160,19 @@ Stream &Stream::operator<<(const void *p) {
return *this;
}
-// Stream a uint8_t "uval" out to this stream.
-Stream &Stream::operator<<(uint8_t uval) {
- PutHex8(uval);
- return *this;
-}
-
-// Stream a uint16_t "uval" out to this stream.
-Stream &Stream::operator<<(uint16_t uval) {
- PutHex16(uval, m_byte_order);
- return *this;
-}
-
-// Stream a uint32_t "uval" out to this stream.
-Stream &Stream::operator<<(uint32_t uval) {
- PutHex32(uval, m_byte_order);
- return *this;
-}
-
-// Stream a uint64_t "uval" out to this stream.
-Stream &Stream::operator<<(uint64_t uval) {
- PutHex64(uval, m_byte_order);
- return *this;
-}
-
-// Stream a int8_t "sval" out to this stream.
-Stream &Stream::operator<<(int8_t sval) {
- Printf("%i", static_cast<int>(sval));
- return *this;
-}
-
-// Stream a int16_t "sval" out to this stream.
-Stream &Stream::operator<<(int16_t sval) {
- Printf("%i", static_cast<int>(sval));
- return *this;
-}
-
-// Stream a int32_t "sval" out to this stream.
-Stream &Stream::operator<<(int32_t sval) {
- Printf("%i", static_cast<int>(sval));
- return *this;
-}
-
-// Stream a int64_t "sval" out to this stream.
-Stream &Stream::operator<<(int64_t sval) {
- Printf("%" PRIi64, sval);
- return *this;
-}
-
// Get the current indentation level
-int Stream::GetIndentLevel() const { return m_indent_level; }
+unsigned Stream::GetIndentLevel() const { return m_indent_level; }
// Set the current indentation level
-void Stream::SetIndentLevel(int indent_level) { m_indent_level = indent_level; }
+void Stream::SetIndentLevel(unsigned indent_level) {
+ m_indent_level = indent_level;
+}
// Increment the current indentation level
-void Stream::IndentMore(int amount) { m_indent_level += amount; }
+void Stream::IndentMore(unsigned amount) { m_indent_level += amount; }
// Decrement the current indentation level
-void Stream::IndentLess(int amount) {
+void Stream::IndentLess(unsigned amount) {
if (m_indent_level >= amount)
m_indent_level -= amount;
else
diff --git a/lldb/source/Utility/StreamString.cpp b/lldb/source/Utility/StreamString.cpp
index bf9814d6c305..6b5b7d337fcc 100644
--- a/lldb/source/Utility/StreamString.cpp
+++ b/lldb/source/Utility/StreamString.cpp
@@ -24,7 +24,7 @@ void StreamString::Flush() {
}
size_t StreamString::WriteImpl(const void *s, size_t length) {
- m_packet.append(reinterpret_cast<const char *>(s), length);
+ m_packet.append(static_cast<const char *>(s), length);
return length;
}
diff --git a/lldb/source/Utility/StructuredData.cpp b/lldb/source/Utility/StructuredData.cpp
index 783a08082174..d5d7a7ec99a0 100644
--- a/lldb/source/Utility/StructuredData.cpp
+++ b/lldb/source/Utility/StructuredData.cpp
@@ -7,16 +7,12 @@
//===----------------------------------------------------------------------===//
#include "lldb/Utility/StructuredData.h"
-#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Status.h"
-#include "lldb/Utility/StreamString.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cerrno>
#include <cstdlib>
#include <inttypes.h>
-#include <limits>
using namespace lldb_private;
using namespace llvm;
@@ -82,7 +78,7 @@ static StructuredData::ObjectSP ParseJSONObject(json::Object *object) {
if (StructuredData::ObjectSP value_sp = ParseJSONValue(value))
dict_up->AddItem(key, value_sp);
}
- return dict_up;
+ return std::move(dict_up);
}
static StructuredData::ObjectSP ParseJSONArray(json::Array *array) {
@@ -91,7 +87,7 @@ static StructuredData::ObjectSP ParseJSONArray(json::Array *array) {
if (StructuredData::ObjectSP value_sp = ParseJSONValue(value))
array_up->AddItem(value_sp);
}
- return array_up;
+ return std::move(array_up);
}
StructuredData::ObjectSP
diff --git a/lldb/source/Utility/VMRange.cpp b/lldb/source/Utility/VMRange.cpp
index f3f4ae7efc3c..c8c3334138d3 100644
--- a/lldb/source/Utility/VMRange.cpp
+++ b/lldb/source/Utility/VMRange.cpp
@@ -35,9 +35,10 @@ bool VMRange::ContainsRange(const VMRange::collection &coll,
}) != coll.end();
}
-void VMRange::Dump(Stream *s, lldb::addr_t offset, uint32_t addr_width) const {
- s->AddressRange(offset + GetBaseAddress(), offset + GetEndAddress(),
- addr_width);
+void VMRange::Dump(llvm::raw_ostream &s, lldb::addr_t offset,
+ uint32_t addr_width) const {
+ DumpAddressRange(s, offset + GetBaseAddress(), offset + GetEndAddress(),
+ addr_width);
}
bool lldb_private::operator==(const VMRange &lhs, const VMRange &rhs) {
diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp
index 6ab2bd93659f..73874389aa1b 100644
--- a/lldb/tools/driver/Driver.cpp
+++ b/lldb/tools/driver/Driver.cpp
@@ -22,7 +22,6 @@
#include "llvm/Support/Format.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/WithColor.h"
@@ -733,8 +732,30 @@ void sigcont_handler(int signo) {
signal(signo, sigcont_handler);
}
+void reproducer_handler(void *argv0) {
+ if (SBReproducer::Generate()) {
+ auto exe = static_cast<const char *>(argv0);
+ llvm::outs() << "********************\n";
+ llvm::outs() << "Crash reproducer for ";
+ llvm::outs() << lldb::SBDebugger::GetVersionString() << '\n';
+ llvm::outs() << '\n';
+ llvm::outs() << "Reproducer written to '" << SBReproducer::GetPath()
+ << "'\n";
+ llvm::outs() << '\n';
+ llvm::outs() << "Before attaching the reproducer to a bug report:\n";
+ llvm::outs() << " - Look at the directory to ensure you're willing to "
+ "share its content.\n";
+ llvm::outs()
+ << " - Make sure the reproducer works by replaying the reproducer.\n";
+ llvm::outs() << '\n';
+ llvm::outs() << "Replay the reproducer with the following command:\n";
+ llvm::outs() << exe << " -replay " << SBReproducer::GetPath() << "\n";
+ llvm::outs() << "********************\n";
+ }
+}
+
static void printHelp(LLDBOptTable &table, llvm::StringRef tool_name) {
- std::string usage_str = tool_name.str() + "options";
+ std::string usage_str = tool_name.str() + " [options]";
table.PrintHelp(llvm::outs(), usage_str.c_str(), "LLDB", false);
std::string examples = R"___(
@@ -770,14 +791,15 @@ EXAMPLES:
lldb -K /source/before/crash -k /source/after/crash
Note: In REPL mode no file is loaded, so commands specified to run after
- loading the file (via -o or -s) will be ignored.
- )___";
- llvm::outs() << examples;
+ loading the file (via -o or -s) will be ignored.)___";
+ llvm::outs() << examples << '\n';
}
llvm::Optional<int> InitializeReproducer(opt::InputArgList &input_args) {
if (auto *replay_path = input_args.getLastArg(OPT_replay)) {
- if (const char *error = SBReproducer::Replay(replay_path->getValue())) {
+ const bool skip_version_check = input_args.hasArg(OPT_skip_version_check);
+ if (const char *error =
+ SBReproducer::Replay(replay_path->getValue(), skip_version_check)) {
WithColor::error() << "reproducer replay failed: " << error << '\n';
return 1;
}
@@ -807,14 +829,10 @@ llvm::Optional<int> InitializeReproducer(opt::InputArgList &input_args) {
return llvm::None;
}
-int main(int argc, char const *argv[])
-{
- llvm::InitLLVM IL(argc, argv);
-
- // Print stack trace on crash.
- llvm::StringRef ToolName = llvm::sys::path::filename(argv[0]);
- llvm::sys::PrintStackTraceOnErrorSignal(ToolName);
- llvm::PrettyStackTraceProgram X(argc, argv);
+int main(int argc, char const *argv[]) {
+ // Setup LLVM signal handlers and make sure we call llvm_shutdown() on
+ // destruction.
+ llvm::InitLLVM IL(argc, argv, /*InstallPipeSignalExitHandler=*/false);
// Parse arguments.
LLDBOptTable T;
@@ -824,7 +842,7 @@ int main(int argc, char const *argv[])
opt::InputArgList input_args = T.ParseArgs(arg_arr, MAI, MAC);
if (input_args.hasArg(OPT_help)) {
- printHelp(T, ToolName);
+ printHelp(T, llvm::sys::path::filename(argv[0]));
return 0;
}
@@ -837,6 +855,9 @@ int main(int argc, char const *argv[])
return *exit_code;
}
+ // Register the reproducer signal handler.
+ llvm::sys::AddSignalHandler(reproducer_handler, const_cast<char *>(argv[0]));
+
SBError error = SBDebugger::InitializeWithErrorHandling();
if (error.Fail()) {
WithColor::error() << "initialization failed: " << error.GetCString()
@@ -853,16 +874,6 @@ int main(int argc, char const *argv[])
signal(SIGCONT, sigcont_handler);
#endif
- // Occasionally, during test teardown, LLDB writes to a closed pipe.
- // Sometimes the communication is inherently unreliable, so LLDB tries to
- // avoid being killed due to SIGPIPE. However, LLVM's default SIGPIPE behavior
- // is to exit with IO_ERR. Opt LLDB out of that.
- //
- // We don't disable LLVM's signal handling entirely because we still want
- // pretty stack traces, and file cleanup (for when, say, the clang embedded
- // in LLDB leaves behind temporary objects).
- llvm::sys::SetPipeSignalFunction(nullptr);
-
int exit_code = 0;
// Create a scope for driver so that the driver object will destroy itself
// before SBDebugger::Terminate() is called.
diff --git a/lldb/tools/driver/Options.td b/lldb/tools/driver/Options.td
index 4ea98ee48fa2..c237f568f64c 100644
--- a/lldb/tools/driver/Options.td
+++ b/lldb/tools/driver/Options.td
@@ -5,6 +5,8 @@ class S<string name>: Separate<["--", "-"], name>;
class R<list<string> prefixes, string name>
: Option<prefixes, name, KIND_REMAINING_ARGS>;
+// Please keep this in sync with the man page in docs/man/lldb.rst
+
// Attaching options.
def grp_attach : OptionGroup<"attaching">, HelpText<"ATTACHING">;
@@ -117,7 +119,7 @@ def: Flag<["-"], "Q">,
def one_line_on_crash: Separate<["--", "-"], "one-line-on-crash">,
MetaVarName<"<command>">,
- HelpText<"When in batch mode, tells the debugger to source this file of lldb commands if the target crashes.">,
+ HelpText<"When in batch mode, tells the debugger to run this one-line lldb command if the target crashes.">,
Group<grp_command>;
def: Separate<["-"], "k">,
Alias<one_line_on_crash>,
@@ -230,5 +232,7 @@ def capture_path: Separate<["--", "-"], "capture-path">,
def replay: Separate<["--", "-"], "replay">,
MetaVarName<"<filename>">,
HelpText<"Tells the debugger to replay a reproducer from <filename>.">;
+def skip_version_check: F<"reproducer-skip-version-check">,
+ HelpText<"Skip the reproducer version check.">;
def REM : R<["--"], "">;
diff --git a/lldb/tools/lldb-server/lldb-gdbserver.cpp b/lldb/tools/lldb-server/lldb-gdbserver.cpp
index 204c67bc470f..5f06503d6424 100644
--- a/lldb/tools/lldb-server/lldb-gdbserver.cpp
+++ b/lldb/tools/lldb-server/lldb-gdbserver.cpp
@@ -22,6 +22,7 @@
#include "LLDBServerUtilities.h"
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h"
#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
+#include "lldb/Host/Config.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostGetOpt.h"
@@ -237,7 +238,7 @@ void ConnectToRemote(MainLoop &mainloop,
snprintf(connection_url, sizeof(connection_url), "fd://%d", connection_fd);
// Create the connection.
-#if !defined LLDB_DISABLE_POSIX && !defined _WIN32
+#if LLDB_ENABLE_POSIX && !defined _WIN32
::fcntl(connection_fd, F_SETFD, FD_CLOEXEC);
#endif
connection_up.reset(new ConnectionFileDescriptor);
@@ -521,7 +522,7 @@ int main_gdbserver(int argc, char *argv[]) {
printf("%s-%s\n", LLGS_PROGRAM_NAME, LLGS_VERSION_STR);
ConnectToRemote(mainloop, gdb_server, reverse_connect, host_and_port,
- progname, subcommand, named_pipe_path.c_str(),
+ progname, subcommand, named_pipe_path.c_str(),
unnamed_pipe, connection_fd);
if (!gdb_server.IsConnected()) {
diff --git a/lldb/tools/lldb-server/lldb-server.cpp b/lldb/tools/lldb-server/lldb-server.cpp
index ab32eefb518e..749a381ebca0 100644
--- a/lldb/tools/lldb-server/lldb-server.cpp
+++ b/lldb/tools/lldb-server/lldb-server.cpp
@@ -49,7 +49,7 @@ static void terminate_debugger() { g_debugger_lifetime->Terminate(); }
// main
int main(int argc, char *argv[]) {
- llvm::InitLLVM IL(argc, argv);
+ llvm::InitLLVM IL(argc, argv, /*InstallPipeSignalExitHandler=*/false);
llvm::StringRef ToolName = argv[0];
llvm::sys::PrintStackTraceOnErrorSignal(ToolName);
llvm::PrettyStackTraceProgram X(argc, argv);
diff --git a/lldb/utils/TableGen/LLDBPropertyDefEmitter.cpp b/lldb/utils/TableGen/LLDBPropertyDefEmitter.cpp
index f49c05c9a585..f36deeebf906 100644
--- a/lldb/utils/TableGen/LLDBPropertyDefEmitter.cpp
+++ b/lldb/utils/TableGen/LLDBPropertyDefEmitter.cpp
@@ -57,6 +57,21 @@ static void emitProperty(Record *Property, raw_ostream &OS) {
assert(!(hasDefaultUnsignedValue && hasDefaultEnumValue) &&
"Property cannot have both a unsigned and enum default value.");
+ // Guarantee that every boolean property has a boolean default value.
+ assert(!(Property->getValueAsString("Type") == "Boolean" &&
+ !Property->getValue("HasDefaultBooleanValue")) &&
+ "Boolean property must have a boolean default value.");
+
+ // Guarantee that every string property has a string default value.
+ assert(!(Property->getValueAsString("Type") == "String" &&
+ !hasDefaultStringValue) &&
+ "String property must have a string default value.");
+
+ // Guarantee that every enum property has an enum default value.
+ assert(
+ !(Property->getValueAsString("Type") == "Enum" && !hasDefaultEnumValue) &&
+ "Enum property must have a enum default value.");
+
// Emit the default uint value.
if (hasDefaultUnsignedValue) {
OS << std::to_string(Property->getValueAsInt("DefaultUnsignedValue"));