aboutsummaryrefslogtreecommitdiff
path: root/lldb/source
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
commit344a3780b2e33f6ca763666c380202b18aab72a3 (patch)
treef0b203ee6eb71d7fdd792373e3c81eb18d6934dd /lldb/source
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/API/SBBlock.cpp4
-rw-r--r--lldb/source/API/SBBreakpoint.cpp20
-rw-r--r--lldb/source/API/SBBreakpointLocation.cpp8
-rw-r--r--lldb/source/API/SBBreakpointName.cpp15
-rw-r--r--lldb/source/API/SBBroadcaster.cpp2
-rw-r--r--lldb/source/API/SBCommandInterpreter.cpp42
-rw-r--r--lldb/source/API/SBCommandInterpreterRunOptions.cpp18
-rw-r--r--lldb/source/API/SBCommandReturnObject.cpp7
-rw-r--r--lldb/source/API/SBCommunication.cpp2
-rw-r--r--lldb/source/API/SBCompileUnit.cpp5
-rw-r--r--lldb/source/API/SBDebugger.cpp47
-rw-r--r--lldb/source/API/SBDeclaration.cpp4
-rw-r--r--lldb/source/API/SBError.cpp2
-rw-r--r--lldb/source/API/SBEvent.cpp4
-rw-r--r--lldb/source/API/SBFileSpec.cpp4
-rw-r--r--lldb/source/API/SBFileSpecList.cpp2
-rw-r--r--lldb/source/API/SBFunction.cpp8
-rw-r--r--lldb/source/API/SBLanguageRuntime.cpp3
-rw-r--r--lldb/source/API/SBLaunchInfo.cpp59
-rw-r--r--lldb/source/API/SBLineEntry.cpp2
-rw-r--r--lldb/source/API/SBListener.cpp2
-rw-r--r--lldb/source/API/SBMemoryRegionInfo.cpp36
-rw-r--r--lldb/source/API/SBPlatform.cpp15
-rw-r--r--lldb/source/API/SBProcess.cpp77
-rw-r--r--lldb/source/API/SBProcessInfo.cpp16
-rw-r--r--lldb/source/API/SBQueue.cpp13
-rw-r--r--lldb/source/API/SBReproducer.cpp1
-rw-r--r--lldb/source/API/SBStream.cpp2
-rw-r--r--lldb/source/API/SBStructuredData.cpp36
-rw-r--r--lldb/source/API/SBSymbol.cpp8
-rw-r--r--lldb/source/API/SBTarget.cpp57
-rw-r--r--lldb/source/API/SBThread.cpp25
-rw-r--r--lldb/source/API/SBTrace.cpp153
-rw-r--r--lldb/source/API/SBTraceOptions.cpp159
-rw-r--r--lldb/source/API/SBTypeCategory.cpp16
-rw-r--r--lldb/source/API/SBValue.cpp2
-rw-r--r--lldb/source/API/SBVariablesOptions.cpp9
-rw-r--r--lldb/source/API/SystemInitializerFull.cpp23
-rw-r--r--lldb/source/Breakpoint/Breakpoint.cpp120
-rw-r--r--lldb/source/Breakpoint/BreakpointID.cpp2
-rw-r--r--lldb/source/Breakpoint/BreakpointIDList.cpp6
-rw-r--r--lldb/source/Breakpoint/BreakpointList.cpp2
-rw-r--r--lldb/source/Breakpoint/BreakpointLocation.cpp101
-rw-r--r--lldb/source/Breakpoint/BreakpointLocationCollection.cpp4
-rw-r--r--lldb/source/Breakpoint/BreakpointName.cpp4
-rw-r--r--lldb/source/Breakpoint/BreakpointOptions.cpp6
-rw-r--r--lldb/source/Breakpoint/BreakpointResolver.cpp36
-rw-r--r--lldb/source/Breakpoint/BreakpointResolverFileLine.cpp88
-rw-r--r--lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp9
-rw-r--r--lldb/source/Breakpoint/BreakpointResolverName.cpp16
-rw-r--r--lldb/source/Breakpoint/BreakpointSite.cpp4
-rw-r--r--lldb/source/Breakpoint/BreakpointSiteList.cpp2
-rw-r--r--lldb/source/Breakpoint/Stoppoint.cpp4
-rw-r--r--lldb/source/Breakpoint/StoppointCallbackContext.cpp3
-rw-r--r--lldb/source/Breakpoint/WatchpointList.cpp5
-rw-r--r--lldb/source/Breakpoint/WatchpointOptions.cpp2
-rw-r--r--lldb/source/Commands/CommandCompletions.cpp6
-rw-r--r--lldb/source/Commands/CommandObjectApropos.cpp2
-rw-r--r--lldb/source/Commands/CommandObjectBreakpoint.cpp219
-rw-r--r--lldb/source/Commands/CommandObjectBreakpointCommand.cpp85
-rw-r--r--lldb/source/Commands/CommandObjectCommands.cpp69
-rw-r--r--lldb/source/Commands/CommandObjectDisassemble.cpp13
-rw-r--r--lldb/source/Commands/CommandObjectDisassemble.h20
-rw-r--r--lldb/source/Commands/CommandObjectExpression.cpp19
-rw-r--r--lldb/source/Commands/CommandObjectFrame.cpp24
-rw-r--r--lldb/source/Commands/CommandObjectGUI.cpp4
-rw-r--r--lldb/source/Commands/CommandObjectHelp.cpp3
-rw-r--r--lldb/source/Commands/CommandObjectHelp.h2
-rw-r--r--lldb/source/Commands/CommandObjectLanguage.cpp2
-rw-r--r--lldb/source/Commands/CommandObjectLog.cpp6
-rw-r--r--lldb/source/Commands/CommandObjectMemory.cpp95
-rw-r--r--lldb/source/Commands/CommandObjectMemoryTag.cpp128
-rw-r--r--lldb/source/Commands/CommandObjectMemoryTag.h25
-rw-r--r--lldb/source/Commands/CommandObjectMultiword.cpp6
-rw-r--r--lldb/source/Commands/CommandObjectPlatform.cpp77
-rw-r--r--lldb/source/Commands/CommandObjectPlugin.cpp2
-rw-r--r--lldb/source/Commands/CommandObjectProcess.cpp221
-rw-r--r--lldb/source/Commands/CommandObjectQuit.cpp8
-rw-r--r--lldb/source/Commands/CommandObjectRegexCommand.cpp8
-rw-r--r--lldb/source/Commands/CommandObjectRegister.cpp7
-rw-r--r--lldb/source/Commands/CommandObjectReproducer.cpp12
-rw-r--r--lldb/source/Commands/CommandObjectScript.cpp4
-rw-r--r--lldb/source/Commands/CommandObjectSettings.cpp33
-rw-r--r--lldb/source/Commands/CommandObjectSource.cpp13
-rw-r--r--lldb/source/Commands/CommandObjectStats.cpp2
-rw-r--r--lldb/source/Commands/CommandObjectTarget.cpp129
-rw-r--r--lldb/source/Commands/CommandObjectThread.cpp345
-rw-r--r--lldb/source/Commands/CommandObjectThreadUtil.cpp45
-rw-r--r--lldb/source/Commands/CommandObjectThreadUtil.h20
-rw-r--r--lldb/source/Commands/CommandObjectTrace.cpp44
-rw-r--r--lldb/source/Commands/CommandObjectTrace.h28
-rw-r--r--lldb/source/Commands/CommandObjectType.cpp72
-rw-r--r--lldb/source/Commands/CommandObjectVersion.cpp3
-rw-r--r--lldb/source/Commands/CommandObjectWatchpoint.cpp71
-rw-r--r--lldb/source/Commands/CommandObjectWatchpointCommand.cpp29
-rw-r--r--lldb/source/Commands/CommandOptionsProcessLaunch.cpp4
-rw-r--r--lldb/source/Commands/CommandOptionsProcessLaunch.h8
-rw-r--r--lldb/source/Commands/Options.td34
-rw-r--r--lldb/source/Core/Address.cpp14
-rw-r--r--lldb/source/Core/AddressRange.cpp31
-rw-r--r--lldb/source/Core/AddressResolver.cpp4
-rw-r--r--lldb/source/Core/AddressResolverFileLine.cpp33
-rw-r--r--lldb/source/Core/AddressResolverName.cpp198
-rw-r--r--lldb/source/Core/Communication.cpp6
-rw-r--r--lldb/source/Core/CoreProperties.td6
-rw-r--r--lldb/source/Core/Debugger.cpp127
-rw-r--r--lldb/source/Core/Declaration.cpp (renamed from lldb/source/Symbol/Declaration.cpp)29
-rw-r--r--lldb/source/Core/Disassembler.cpp16
-rw-r--r--lldb/source/Core/DumpDataExtractor.cpp60
-rw-r--r--lldb/source/Core/DynamicLoader.cpp2
-rw-r--r--lldb/source/Core/EmulateInstruction.cpp4
-rw-r--r--lldb/source/Core/FileLineResolver.cpp2
-rw-r--r--lldb/source/Core/FileSpecList.cpp2
-rw-r--r--lldb/source/Core/FormatEntity.cpp410
-rw-r--r--lldb/source/Core/IOHandler.cpp70
-rw-r--r--lldb/source/Core/IOHandlerCursesGUI.cpp2115
-rw-r--r--lldb/source/Core/Mangled.cpp88
-rw-r--r--lldb/source/Core/Module.cpp50
-rw-r--r--lldb/source/Core/ModuleChild.cpp2
-rw-r--r--lldb/source/Core/ModuleList.cpp3
-rw-r--r--lldb/source/Core/Opcode.cpp2
-rw-r--r--lldb/source/Core/PluginManager.cpp124
-rw-r--r--lldb/source/Core/Progress.cpp60
-rw-r--r--lldb/source/Core/RichManglingContext.cpp11
-rw-r--r--lldb/source/Core/SearchFilter.cpp4
-rw-r--r--lldb/source/Core/Section.cpp2
-rw-r--r--lldb/source/Core/SourceLocationSpec.cpp81
-rw-r--r--lldb/source/Core/SourceManager.cpp24
-rw-r--r--lldb/source/Core/StreamFile.cpp4
-rw-r--r--lldb/source/Core/Value.cpp153
-rw-r--r--lldb/source/Core/ValueObject.cpp366
-rw-r--r--lldb/source/Core/ValueObjectCast.cpp2
-rw-r--r--lldb/source/Core/ValueObjectChild.cpp28
-rw-r--r--lldb/source/Core/ValueObjectConstResult.cpp16
-rw-r--r--lldb/source/Core/ValueObjectConstResultCast.cpp2
-rw-r--r--lldb/source/Core/ValueObjectConstResultChild.cpp2
-rw-r--r--lldb/source/Core/ValueObjectConstResultImpl.cpp2
-rw-r--r--lldb/source/Core/ValueObjectDynamicValue.cpp2
-rw-r--r--lldb/source/Core/ValueObjectMemory.cpp35
-rw-r--r--lldb/source/Core/ValueObjectRegister.cpp10
-rw-r--r--lldb/source/Core/ValueObjectSyntheticFilter.cpp2
-rw-r--r--lldb/source/Core/ValueObjectUpdater.cpp56
-rw-r--r--lldb/source/Core/ValueObjectVariable.cpp47
-rw-r--r--lldb/source/DataFormatters/StringPrinter.cpp2
-rw-r--r--lldb/source/DataFormatters/TypeFormat.cpp11
-rw-r--r--lldb/source/DataFormatters/TypeSummary.cpp3
-rw-r--r--lldb/source/DataFormatters/TypeSynthetic.cpp4
-rw-r--r--lldb/source/DataFormatters/VectorType.cpp2
-rw-r--r--lldb/source/Expression/DWARFExpression.cpp200
-rw-r--r--lldb/source/Expression/ExpressionVariable.cpp4
-rw-r--r--lldb/source/Expression/FunctionCaller.cpp20
-rw-r--r--lldb/source/Expression/IRExecutionUnit.cpp34
-rw-r--r--lldb/source/Expression/IRInterpreter.cpp4
-rw-r--r--lldb/source/Expression/IRMemoryMap.cpp2
-rw-r--r--lldb/source/Expression/LLVMUserExpression.cpp5
-rw-r--r--lldb/source/Expression/Materializer.cpp6
-rw-r--r--lldb/source/Expression/UserExpression.cpp35
-rw-r--r--lldb/source/Expression/UtilityFunction.cpp5
-rw-r--r--lldb/source/Host/common/Editline.cpp261
-rw-r--r--lldb/source/Host/common/File.cpp8
-rw-r--r--lldb/source/Host/common/FileAction.cpp3
-rw-r--r--lldb/source/Host/common/FileSystem.cpp26
-rw-r--r--lldb/source/Host/common/GetOptInc.cpp6
-rw-r--r--lldb/source/Host/common/Host.cpp16
-rw-r--r--lldb/source/Host/common/HostInfoBase.cpp23
-rw-r--r--lldb/source/Host/common/HostNativeThreadBase.cpp3
-rw-r--r--lldb/source/Host/common/HostProcess.cpp2
-rw-r--r--lldb/source/Host/common/MainLoop.cpp35
-rw-r--r--lldb/source/Host/common/NativeProcessProtocol.cpp83
-rw-r--r--lldb/source/Host/common/NativeRegisterContext.cpp6
-rw-r--r--lldb/source/Host/common/ProcessLaunchInfo.cpp13
-rw-r--r--lldb/source/Host/common/ProcessRunLock.cpp2
-rw-r--r--lldb/source/Host/common/PseudoTerminal.cpp11
-rw-r--r--lldb/source/Host/common/Socket.cpp4
-rw-r--r--lldb/source/Host/common/SocketAddress.cpp10
-rw-r--r--lldb/source/Host/common/StringConvert.cpp2
-rw-r--r--lldb/source/Host/common/Terminal.cpp15
-rw-r--r--lldb/source/Host/common/XML.cpp8
-rw-r--r--lldb/source/Host/freebsd/Host.cpp2
-rw-r--r--lldb/source/Host/freebsd/HostInfoFreeBSD.cpp4
-rw-r--r--lldb/source/Host/netbsd/HostInfoNetBSD.cpp8
-rw-r--r--lldb/source/Host/netbsd/HostNetBSD.cpp4
-rw-r--r--lldb/source/Host/openbsd/Host.cpp2
-rw-r--r--lldb/source/Host/openbsd/HostInfoOpenBSD.cpp4
-rw-r--r--lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp8
-rw-r--r--lldb/source/Host/posix/DomainSocket.cpp2
-rw-r--r--lldb/source/Host/posix/HostInfoPosix.cpp4
-rw-r--r--lldb/source/Host/posix/HostProcessPosix.cpp4
-rw-r--r--lldb/source/Host/posix/HostThreadPosix.cpp6
-rw-r--r--lldb/source/Host/posix/PipePosix.cpp11
-rw-r--r--lldb/source/Host/posix/ProcessLauncherPosixFork.cpp2
-rw-r--r--lldb/source/Initialization/SystemInitializer.cpp4
-rw-r--r--lldb/source/Initialization/SystemInitializerCommon.cpp11
-rw-r--r--lldb/source/Initialization/SystemLifetimeManager.cpp3
-rw-r--r--lldb/source/Interpreter/CommandAlias.cpp3
-rw-r--r--lldb/source/Interpreter/CommandHistory.cpp6
-rw-r--r--lldb/source/Interpreter/CommandInterpreter.cpp220
-rw-r--r--lldb/source/Interpreter/CommandObject.cpp26
-rw-r--r--lldb/source/Interpreter/CommandReturnObject.cpp50
-rw-r--r--lldb/source/Interpreter/InterpreterProperties.td7
-rw-r--r--lldb/source/Interpreter/OptionArgParser.cpp16
-rw-r--r--lldb/source/Interpreter/OptionGroupArchitecture.cpp4
-rw-r--r--lldb/source/Interpreter/OptionGroupBoolean.cpp2
-rw-r--r--lldb/source/Interpreter/OptionGroupFile.cpp7
-rw-r--r--lldb/source/Interpreter/OptionGroupFormat.cpp2
-rw-r--r--lldb/source/Interpreter/OptionGroupOutputFile.cpp5
-rw-r--r--lldb/source/Interpreter/OptionGroupPythonClassWithDict.cpp21
-rw-r--r--lldb/source/Interpreter/OptionGroupString.cpp2
-rw-r--r--lldb/source/Interpreter/OptionGroupUInt64.cpp2
-rw-r--r--lldb/source/Interpreter/OptionGroupUUID.cpp4
-rw-r--r--lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp4
-rw-r--r--lldb/source/Interpreter/OptionGroupVariable.cpp6
-rw-r--r--lldb/source/Interpreter/OptionGroupWatchpoint.cpp4
-rw-r--r--lldb/source/Interpreter/OptionValue.cpp9
-rw-r--r--lldb/source/Interpreter/OptionValueArch.cpp4
-rw-r--r--lldb/source/Interpreter/OptionValueArgs.cpp4
-rw-r--r--lldb/source/Interpreter/OptionValueArray.cpp23
-rw-r--r--lldb/source/Interpreter/OptionValueBoolean.cpp4
-rw-r--r--lldb/source/Interpreter/OptionValueChar.cpp4
-rw-r--r--lldb/source/Interpreter/OptionValueDictionary.cpp23
-rw-r--r--lldb/source/Interpreter/OptionValueEnumeration.cpp9
-rw-r--r--lldb/source/Interpreter/OptionValueFileColonLine.cpp15
-rw-r--r--lldb/source/Interpreter/OptionValueFileSpec.cpp16
-rw-r--r--lldb/source/Interpreter/OptionValueFileSpecList.cpp4
-rw-r--r--lldb/source/Interpreter/OptionValueFormat.cpp4
-rw-r--r--lldb/source/Interpreter/OptionValueFormatEntity.cpp8
-rw-r--r--lldb/source/Interpreter/OptionValueLanguage.cpp4
-rw-r--r--lldb/source/Interpreter/OptionValuePathMappings.cpp4
-rw-r--r--lldb/source/Interpreter/OptionValueProperties.cpp120
-rw-r--r--lldb/source/Interpreter/OptionValueRegex.cpp4
-rw-r--r--lldb/source/Interpreter/OptionValueSInt64.cpp4
-rw-r--r--lldb/source/Interpreter/OptionValueString.cpp4
-rw-r--r--lldb/source/Interpreter/OptionValueUInt64.cpp4
-rw-r--r--lldb/source/Interpreter/OptionValueUUID.cpp4
-rw-r--r--lldb/source/Interpreter/Options.cpp5
-rw-r--r--lldb/source/Interpreter/Property.cpp2
-rw-r--r--lldb/source/Interpreter/ScriptInterpreter.cpp50
-rw-r--r--lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp13
-rw-r--r--lldb/source/Plugins/ABI/AArch64/ABIAArch64.h7
-rw-r--r--lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp12
-rw-r--r--lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h2
-rw-r--r--lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp58
-rw-r--r--lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h5
-rw-r--r--lldb/source/Plugins/ABI/ARC/ABISysV_arc.cpp6
-rw-r--r--lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp1
-rw-r--r--lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp5
-rw-r--r--lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp1
-rw-r--r--lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp1
-rw-r--r--lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp3
-rw-r--r--lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp10
-rw-r--r--lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp3
-rw-r--r--lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.cpp4
-rw-r--r--lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp1
-rw-r--r--lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp7
-rw-r--r--lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp5
-rw-r--r--lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp5
-rw-r--r--lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.cpp45
-rw-r--r--lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.h40
-rw-r--r--lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp4
-rw-r--r--lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp3
-rw-r--r--lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h14
-rw-r--r--lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h12
-rw-r--r--lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp10
-rw-r--r--lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp4
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp4
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp4
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp6
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp77
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h99
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp36
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h2
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h2
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp27
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h29
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h2
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp18
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp11
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h1
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h36
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp2
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp72
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp16
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h7
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp13
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp41
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h9
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h2
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp3
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp41
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h101
-rw-r--r--lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp2
-rw-r--r--lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h8
-rw-r--r--lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp4
-rw-r--r--lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h2
-rw-r--r--lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp11
-rw-r--r--lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp6
-rw-r--r--lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp2
-rw-r--r--lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp14
-rw-r--r--lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp13
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp4
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp15
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h9
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h2
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp75
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/LibCxx.h6
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp2
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp8
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp7
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp14
-rw-r--r--lldb/source/Plugins/Language/ObjC/Cocoa.cpp106
-rw-r--r--lldb/source/Plugins/Language/ObjC/CoreMedia.cpp2
-rw-r--r--lldb/source/Plugins/Language/ObjC/NSDictionary.cpp7
-rw-r--r--lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp21
-rw-r--r--lldb/source/Plugins/Language/ObjC/NSSet.cpp20
-rw-r--r--lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp38
-rw-r--r--lldb/source/Plugins/Language/ObjC/ObjCLanguage.h13
-rw-r--r--lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp2
-rw-r--r--lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp9
-rw-r--r--lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp2
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp14
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h49
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp4
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp2
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp6
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h15
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp1049
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h133
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp25
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h17
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp2
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h2
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp42
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h18
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp7
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h18
-rw-r--r--lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp2
-rw-r--r--lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp29
-rw-r--r--lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h4
-rw-r--r--lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp8
-rw-r--r--lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h14
-rw-r--r--lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp109
-rw-r--r--lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h10
-rw-r--r--lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp2
-rw-r--r--lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp2
-rw-r--r--lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp2
-rw-r--r--lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp8
-rw-r--r--lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp50
-rw-r--r--lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h3
-rw-r--r--lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp2
-rw-r--r--lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp2
-rw-r--r--lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp27
-rw-r--r--lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h3
-rw-r--r--lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp14
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp616
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h111
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp (renamed from lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.cpp)155
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.h (renamed from lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.h)16
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.cpp (renamed from lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.cpp)2
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h (renamed from lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.h)0
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.cpp202
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.h68
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp282
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h86
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp186
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.h71
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.cpp289
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.h74
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp (renamed from lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.cpp)2
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.h (renamed from lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.h)6
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp (renamed from lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.cpp)29
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h (renamed from lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.h)5
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp44
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h66
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp1080
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h221
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp1424
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h279
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h63
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp260
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h80
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp267
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h82
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp262
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h82
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp274
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h84
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp613
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h81
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp111
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h5
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp6
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h4
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp24
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h3
-rw-r--r--lldb/source/Plugins/Process/POSIX/CrashReason.h2
-rw-r--r--lldb/source/Plugins/Process/POSIX/NativeProcessELF.h5
-rw-r--r--lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp8
-rw-r--r--lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h3
-rw-r--r--lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp2
-rw-r--r--lldb/source/Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h4
-rw-r--r--lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp200
-rw-r--r--lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h53
-rw-r--r--lldb/source/Plugins/Process/Utility/NativeProcessSoftwareSingleStep.cpp182
-rw-r--r--lldb/source/Plugins/Process/Utility/NativeProcessSoftwareSingleStep.h31
-rw-r--r--lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.cpp469
-rw-r--r--lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h82
-rw-r--r--lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.cpp (renamed from lldb/source/Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.cpp)38
-rw-r--r--lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h (renamed from lldb/source/Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.h)16
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp4
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp8
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp6
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp149
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h36
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp207
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h39
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp6
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp15
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h1
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp30
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp6
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp4
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp6
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp6
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp190
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h44
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h23
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h306
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h6
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterInfos_s390x.h2
-rw-r--r--lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp2
-rw-r--r--lldb/source/Plugins/Process/Utility/lldb-mips-linux-register-enums.h360
-rw-r--r--lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp77
-rw-r--r--lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp2
-rw-r--r--lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp80
-rw-r--r--lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h23
-rw-r--r--lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp2
-rw-r--r--lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp2
-rw-r--r--lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp2
-rw-r--r--lldb/source/Plugins/Process/elf-core/RegisterUtilities.h12
-rw-r--r--lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp19
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp84
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h38
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp4
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp983
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h162
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp5
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h6
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp4
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h2
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp24
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h7
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp64
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h11
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp1007
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h46
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp5
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp33
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h1
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp267
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h30
-rw-r--r--lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp11
-rw-r--r--lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp2
-rw-r--r--lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp2
-rw-r--r--lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp2
-rw-r--r--lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp313
-rw-r--r--lldb/source/Plugins/Process/scripted/ScriptedProcess.h119
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp29
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h4
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp101
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h29
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp2
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp2
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h6
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp2
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp48
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h56
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp228
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h3
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h22
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp306
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h66
-rw-r--r--lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp36
-rw-r--r--lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp21
-rw-r--r--lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h5
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h2
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp123
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h4
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp12
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h7
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp15
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h15
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h6
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp4
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h43
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h5
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp56
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h32
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp40
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h3
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp20
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h2
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp280
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h9
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h10
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h2
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp75
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h6
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp98
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h19
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp3
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h6
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp20
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h2
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp171
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h11
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp17
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h31
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp2
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h16
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp2
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp2
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp2
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp6
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h3
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp44
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp16
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h9
-rw-r--r--lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp2
-rw-r--r--lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp2
-rw-r--r--lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.cpp (renamed from lldb/source/Target/ThreadTrace.cpp)16
-rw-r--r--lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.h60
-rw-r--r--lldb/source/Plugins/Trace/common/TraceSessionFileParser.cpp (renamed from lldb/source/Target/TraceSessionFileParser.cpp)13
-rw-r--r--lldb/source/Plugins/Trace/common/TraceSessionFileParser.h179
-rw-r--r--lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp133
-rw-r--r--lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h69
-rw-r--r--lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp74
-rw-r--r--lldb/source/Plugins/Trace/intel-pt/DecodedThread.h72
-rw-r--r--lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp134
-rw-r--r--lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.h69
-rw-r--r--lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp100
-rw-r--r--lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h50
-rw-r--r--lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp321
-rw-r--r--lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h119
-rw-r--r--lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h27
-rw-r--r--lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td72
-rw-r--r--lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp50
-rw-r--r--lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h28
-rw-r--r--lldb/source/Plugins/Trace/intel-pt/forward-declarations.h20
-rw-r--r--lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp66
-rw-r--r--lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.h56
-rw-r--r--lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.cpp53
-rw-r--r--lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.h42
-rw-r--r--lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTFOptions.td9
-rw-r--r--lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp282
-rw-r--r--lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h15
-rw-r--r--lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp6
-rw-r--r--lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp21
-rw-r--r--lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h6
-rw-r--r--lldb/source/Symbol/ArmUnwindInfo.cpp2
-rw-r--r--lldb/source/Symbol/Block.cpp2
-rw-r--r--lldb/source/Symbol/CompactUnwindInfo.cpp2
-rw-r--r--lldb/source/Symbol/CompileUnit.cpp59
-rw-r--r--lldb/source/Symbol/CompilerType.cpp2
-rw-r--r--lldb/source/Symbol/FuncUnwinders.cpp2
-rw-r--r--lldb/source/Symbol/Function.cpp13
-rw-r--r--lldb/source/Symbol/LineEntry.cpp13
-rw-r--r--lldb/source/Symbol/LineTable.cpp101
-rw-r--r--lldb/source/Symbol/ObjectFile.cpp8
-rw-r--r--lldb/source/Symbol/Symbol.cpp61
-rw-r--r--lldb/source/Symbol/SymbolContext.cpp28
-rw-r--r--lldb/source/Symbol/SymbolFile.cpp8
-rw-r--r--lldb/source/Symbol/Symtab.cpp195
-rw-r--r--lldb/source/Symbol/Type.cpp11
-rw-r--r--lldb/source/Symbol/TypeList.cpp2
-rw-r--r--lldb/source/Symbol/TypeMap.cpp2
-rw-r--r--lldb/source/Symbol/TypeSystem.cpp7
-rw-r--r--lldb/source/Symbol/UnwindPlan.cpp19
-rw-r--r--lldb/source/Symbol/UnwindTable.cpp4
-rw-r--r--lldb/source/Symbol/Variable.cpp2
-rw-r--r--lldb/source/Symbol/VariableList.cpp2
-rw-r--r--lldb/source/Target/ABI.cpp12
-rw-r--r--lldb/source/Target/AssertFrameRecognizer.cpp36
-rw-r--r--lldb/source/Target/ExecutionContext.cpp3
-rw-r--r--lldb/source/Target/JITLoaderList.cpp2
-rw-r--r--lldb/source/Target/Language.cpp8
-rw-r--r--lldb/source/Target/LanguageRuntime.cpp19
-rw-r--r--lldb/source/Target/Memory.cpp6
-rw-r--r--lldb/source/Target/ModuleCache.cpp2
-rw-r--r--lldb/source/Target/PathMappingList.cpp98
-rw-r--r--lldb/source/Target/Process.cpp238
-rw-r--r--lldb/source/Target/ProcessTrace.cpp2
-rw-r--r--lldb/source/Target/QueueItem.cpp2
-rw-r--r--lldb/source/Target/RegisterContext.cpp18
-rw-r--r--lldb/source/Target/RegisterContextUnwind.cpp192
-rw-r--r--lldb/source/Target/RegisterNumber.cpp4
-rw-r--r--lldb/source/Target/RemoteAwarePlatform.cpp7
-rw-r--r--lldb/source/Target/StackFrame.cpp87
-rw-r--r--lldb/source/Target/StackFrameList.cpp125
-rw-r--r--lldb/source/Target/StopInfo.cpp88
-rw-r--r--lldb/source/Target/StructuredDataPlugin.cpp4
-rw-r--r--lldb/source/Target/Target.cpp253
-rw-r--r--lldb/source/Target/TargetList.cpp2
-rw-r--r--lldb/source/Target/TargetProperties.td13
-rw-r--r--lldb/source/Target/Thread.cpp100
-rw-r--r--lldb/source/Target/ThreadCollection.cpp2
-rw-r--r--lldb/source/Target/ThreadList.cpp2
-rw-r--r--lldb/source/Target/ThreadPlan.cpp19
-rw-r--r--lldb/source/Target/ThreadPlanBase.cpp30
-rw-r--r--lldb/source/Target/ThreadPlanCallFunction.cpp4
-rw-r--r--lldb/source/Target/ThreadPlanCallUserExpression.cpp2
-rw-r--r--lldb/source/Target/ThreadPlanStack.cpp46
-rw-r--r--lldb/source/Target/ThreadPlanStepInRange.cpp11
-rw-r--r--lldb/source/Target/ThreadPlanStepInstruction.cpp7
-rw-r--r--lldb/source/Target/ThreadPlanStepOut.cpp6
-rw-r--r--lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp12
-rw-r--r--lldb/source/Target/ThreadPlanStepRange.cpp3
-rw-r--r--lldb/source/Target/ThreadPlanStepThrough.cpp1
-rw-r--r--lldb/source/Target/ThreadPlanTracer.cpp8
-rw-r--r--lldb/source/Target/ThreadSpec.cpp4
-rw-r--r--lldb/source/Target/Trace.cpp283
-rw-r--r--lldb/source/Target/TraceCursor.cpp35
-rw-r--r--lldb/source/Target/TraceExporter.cpp32
-rw-r--r--lldb/source/Target/TraceInstructionDumper.cpp292
-rw-r--r--lldb/source/Target/UnwindLLDB.cpp2
-rw-r--r--lldb/source/Utility/ArchSpec.cpp46
-rw-r--r--lldb/source/Utility/Args.cpp5
-rw-r--r--lldb/source/Utility/Broadcaster.cpp4
-rw-r--r--lldb/source/Utility/ConstString.cpp10
-rw-r--r--lldb/source/Utility/DataBufferLLVM.cpp4
-rw-r--r--lldb/source/Utility/DataEncoder.cpp5
-rw-r--r--lldb/source/Utility/DataExtractor.cpp11
-rw-r--r--lldb/source/Utility/Event.cpp4
-rw-r--r--lldb/source/Utility/FileSpec.cpp18
-rw-r--r--lldb/source/Utility/GDBRemote.cpp10
-rw-r--r--lldb/source/Utility/LLDBAssert.cpp14
-rw-r--r--lldb/source/Utility/Log.cpp13
-rw-r--r--lldb/source/Utility/Logging.cpp2
-rw-r--r--lldb/source/Utility/ProcessInfo.cpp3
-rw-r--r--lldb/source/Utility/RegisterValue.cpp6
-rw-r--r--lldb/source/Utility/Reproducer.cpp21
-rw-r--r--lldb/source/Utility/ReproducerInstrumentation.cpp8
-rw-r--r--lldb/source/Utility/ReproducerProvider.cpp6
-rw-r--r--lldb/source/Utility/Scalar.cpp2
-rw-r--r--lldb/source/Utility/SelectHelper.cpp2
-rw-r--r--lldb/source/Utility/Status.cpp4
-rw-r--r--lldb/source/Utility/Stream.cpp10
-rw-r--r--lldb/source/Utility/StreamString.cpp2
-rw-r--r--lldb/source/Utility/StringExtractor.cpp10
-rw-r--r--lldb/source/Utility/StringExtractorGDBRemote.cpp84
-rw-r--r--lldb/source/Utility/StringLexer.cpp2
-rw-r--r--lldb/source/Utility/StringList.cpp6
-rw-r--r--lldb/source/Utility/StructuredData.cpp2
-rw-r--r--lldb/source/Utility/TildeExpressionResolver.cpp4
-rw-r--r--lldb/source/Utility/Timer.cpp13
-rw-r--r--lldb/source/Utility/TraceGDBRemotePackets.cpp130
-rw-r--r--lldb/source/Utility/TraceIntelPTGDBRemotePackets.cpp46
-rw-r--r--lldb/source/Utility/TraceOptions.cpp25
-rw-r--r--lldb/source/Utility/UUID.cpp6
-rw-r--r--lldb/source/Utility/UriParser.cpp2
-rw-r--r--lldb/source/Utility/UserID.cpp2
-rw-r--r--lldb/source/Utility/VASprintf.cpp6
-rw-r--r--lldb/source/Utility/VMRange.cpp4
-rw-r--r--lldb/source/lldb.cpp20
677 files changed, 17894 insertions, 15685 deletions
diff --git a/lldb/source/API/SBBlock.cpp b/lldb/source/API/SBBlock.cpp
index a5fee445d5c6..5c49053dd972 100644
--- a/lldb/source/API/SBBlock.cpp
+++ b/lldb/source/API/SBBlock.cpp
@@ -25,9 +25,7 @@
using namespace lldb;
using namespace lldb_private;
-SBBlock::SBBlock() : m_opaque_ptr(nullptr) {
- LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBBlock);
-}
+SBBlock::SBBlock() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBBlock); }
SBBlock::SBBlock(lldb_private::Block *lldb_object_ptr)
: m_opaque_ptr(lldb_object_ptr) {}
diff --git a/lldb/source/API/SBBreakpoint.cpp b/lldb/source/API/SBBreakpoint.cpp
index 96ae305ffce5..0f0a93519993 100644
--- a/lldb/source/API/SBBreakpoint.cpp
+++ b/lldb/source/API/SBBreakpoint.cpp
@@ -384,7 +384,7 @@ void SBBreakpoint::SetThreadIndex(uint32_t index) {
if (bkpt_sp) {
std::lock_guard<std::recursive_mutex> guard(
bkpt_sp->GetTarget().GetAPIMutex());
- bkpt_sp->GetOptions()->GetThreadSpec()->SetIndex(index);
+ bkpt_sp->GetOptions().GetThreadSpec()->SetIndex(index);
}
}
@@ -397,7 +397,7 @@ uint32_t SBBreakpoint::GetThreadIndex() const {
std::lock_guard<std::recursive_mutex> guard(
bkpt_sp->GetTarget().GetAPIMutex());
const ThreadSpec *thread_spec =
- bkpt_sp->GetOptions()->GetThreadSpecNoCreate();
+ bkpt_sp->GetOptions().GetThreadSpecNoCreate();
if (thread_spec != nullptr)
thread_idx = thread_spec->GetIndex();
}
@@ -414,7 +414,7 @@ void SBBreakpoint::SetThreadName(const char *thread_name) {
if (bkpt_sp) {
std::lock_guard<std::recursive_mutex> guard(
bkpt_sp->GetTarget().GetAPIMutex());
- bkpt_sp->GetOptions()->GetThreadSpec()->SetName(thread_name);
+ bkpt_sp->GetOptions().GetThreadSpec()->SetName(thread_name);
}
}
@@ -427,7 +427,7 @@ const char *SBBreakpoint::GetThreadName() const {
std::lock_guard<std::recursive_mutex> guard(
bkpt_sp->GetTarget().GetAPIMutex());
const ThreadSpec *thread_spec =
- bkpt_sp->GetOptions()->GetThreadSpecNoCreate();
+ bkpt_sp->GetOptions().GetThreadSpecNoCreate();
if (thread_spec != nullptr)
name = thread_spec->GetName();
}
@@ -443,7 +443,7 @@ void SBBreakpoint::SetQueueName(const char *queue_name) {
if (bkpt_sp) {
std::lock_guard<std::recursive_mutex> guard(
bkpt_sp->GetTarget().GetAPIMutex());
- bkpt_sp->GetOptions()->GetThreadSpec()->SetQueueName(queue_name);
+ bkpt_sp->GetOptions().GetThreadSpec()->SetQueueName(queue_name);
}
}
@@ -456,7 +456,7 @@ const char *SBBreakpoint::GetQueueName() const {
std::lock_guard<std::recursive_mutex> guard(
bkpt_sp->GetTarget().GetAPIMutex());
const ThreadSpec *thread_spec =
- bkpt_sp->GetOptions()->GetThreadSpecNoCreate();
+ bkpt_sp->GetOptions().GetThreadSpecNoCreate();
if (thread_spec)
name = thread_spec->GetQueueName();
}
@@ -506,7 +506,7 @@ void SBBreakpoint::SetCommandLineCommands(SBStringList &commands) {
std::unique_ptr<BreakpointOptions::CommandData> cmd_data_up(
new BreakpointOptions::CommandData(*commands, eScriptLanguageNone));
- bkpt_sp->GetOptions()->SetCommandDataCallback(cmd_data_up);
+ bkpt_sp->GetOptions().SetCommandDataCallback(cmd_data_up);
}
bool SBBreakpoint::GetCommandLineCommands(SBStringList &commands) {
@@ -518,7 +518,7 @@ bool SBBreakpoint::GetCommandLineCommands(SBStringList &commands) {
return false;
StringList command_list;
bool has_commands =
- bkpt_sp->GetOptions()->GetCommandLineCallbacks(command_list);
+ bkpt_sp->GetOptions().GetCommandLineCallbacks(command_list);
if (has_commands)
commands.AppendList(command_list);
return has_commands;
@@ -636,7 +636,7 @@ SBError SBBreakpoint::SetScriptCallbackFunction(
Status error;
std::lock_guard<std::recursive_mutex> guard(
bkpt_sp->GetTarget().GetAPIMutex());
- BreakpointOptions *bp_options = bkpt_sp->GetOptions();
+ BreakpointOptions &bp_options = bkpt_sp->GetOptions();
error = bkpt_sp->GetTarget()
.GetDebugger()
.GetScriptInterpreter()
@@ -661,7 +661,7 @@ SBError SBBreakpoint::SetScriptCallbackBody(const char *callback_body_text) {
if (bkpt_sp) {
std::lock_guard<std::recursive_mutex> guard(
bkpt_sp->GetTarget().GetAPIMutex());
- BreakpointOptions *bp_options = bkpt_sp->GetOptions();
+ BreakpointOptions &bp_options = bkpt_sp->GetOptions();
Status error =
bkpt_sp->GetTarget()
.GetDebugger()
diff --git a/lldb/source/API/SBBreakpointLocation.cpp b/lldb/source/API/SBBreakpointLocation.cpp
index d6bbb5faf041..175120429925 100644
--- a/lldb/source/API/SBBreakpointLocation.cpp
+++ b/lldb/source/API/SBBreakpointLocation.cpp
@@ -227,7 +227,7 @@ SBError SBBreakpointLocation::SetScriptCallbackFunction(
Status error;
std::lock_guard<std::recursive_mutex> guard(
loc_sp->GetTarget().GetAPIMutex());
- BreakpointOptions *bp_options = loc_sp->GetLocationOptions();
+ BreakpointOptions &bp_options = loc_sp->GetLocationOptions();
error = loc_sp->GetBreakpoint()
.GetTarget()
.GetDebugger()
@@ -254,7 +254,7 @@ SBBreakpointLocation::SetScriptCallbackBody(const char *callback_body_text) {
if (loc_sp) {
std::lock_guard<std::recursive_mutex> guard(
loc_sp->GetTarget().GetAPIMutex());
- BreakpointOptions *bp_options = loc_sp->GetLocationOptions();
+ BreakpointOptions &bp_options = loc_sp->GetLocationOptions();
Status error =
loc_sp->GetBreakpoint()
.GetTarget()
@@ -283,7 +283,7 @@ void SBBreakpointLocation::SetCommandLineCommands(SBStringList &commands) {
std::unique_ptr<BreakpointOptions::CommandData> cmd_data_up(
new BreakpointOptions::CommandData(*commands, eScriptLanguageNone));
- loc_sp->GetLocationOptions()->SetCommandDataCallback(cmd_data_up);
+ loc_sp->GetLocationOptions().SetCommandDataCallback(cmd_data_up);
}
bool SBBreakpointLocation::GetCommandLineCommands(SBStringList &commands) {
@@ -295,7 +295,7 @@ bool SBBreakpointLocation::GetCommandLineCommands(SBStringList &commands) {
return false;
StringList command_list;
bool has_commands =
- loc_sp->GetLocationOptions()->GetCommandLineCallbacks(command_list);
+ loc_sp->GetLocationOptions().GetCommandLineCallbacks(command_list);
if (has_commands)
commands.AppendList(command_list);
return has_commands;
diff --git a/lldb/source/API/SBBreakpointName.cpp b/lldb/source/API/SBBreakpointName.cpp
index 3995defcf97c..b5c700c78bbb 100644
--- a/lldb/source/API/SBBreakpointName.cpp
+++ b/lldb/source/API/SBBreakpointName.cpp
@@ -144,7 +144,7 @@ SBBreakpointName::SBBreakpointName(SBBreakpoint &sb_bkpt, const char *name) {
}
// Now copy over the breakpoint's options:
- target.ConfigureBreakpointName(*bp_name, *bkpt_sp->GetOptions(),
+ target.ConfigureBreakpointName(*bp_name, bkpt_sp->GetOptions(),
BreakpointName::Permissions());
}
@@ -594,12 +594,11 @@ SBError SBBreakpointName::SetScriptCallbackFunction(
BreakpointOptions &bp_options = bp_name->GetOptions();
Status error;
error = m_impl_up->GetTarget()
- ->GetDebugger()
- .GetScriptInterpreter()
- ->SetBreakpointCommandCallbackFunction(&bp_options,
- callback_function_name,
- extra_args.m_impl_up
- ->GetObjectSP());
+ ->GetDebugger()
+ .GetScriptInterpreter()
+ ->SetBreakpointCommandCallbackFunction(
+ bp_options, callback_function_name,
+ extra_args.m_impl_up->GetObjectSP());
sb_error.SetError(error);
UpdateName(*bp_name);
return LLDB_RECORD_RESULT(sb_error);
@@ -623,7 +622,7 @@ SBBreakpointName::SetScriptCallbackBody(const char *callback_body_text) {
m_impl_up->GetTarget()
->GetDebugger()
.GetScriptInterpreter()
- ->SetBreakpointCommandCallback(&bp_options, callback_body_text);
+ ->SetBreakpointCommandCallback(bp_options, callback_body_text);
sb_error.SetError(error);
if (!sb_error.Fail())
UpdateName(*bp_name);
diff --git a/lldb/source/API/SBBroadcaster.cpp b/lldb/source/API/SBBroadcaster.cpp
index d42d7ce2a536..2e6d837f102b 100644
--- a/lldb/source/API/SBBroadcaster.cpp
+++ b/lldb/source/API/SBBroadcaster.cpp
@@ -16,7 +16,7 @@
using namespace lldb;
using namespace lldb_private;
-SBBroadcaster::SBBroadcaster() : m_opaque_sp(), m_opaque_ptr(nullptr) {
+SBBroadcaster::SBBroadcaster() : m_opaque_sp() {
LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBBroadcaster);
}
diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp
index 31e7da8323b8..b4a69c3e972a 100644
--- a/lldb/source/API/SBCommandInterpreter.cpp
+++ b/lldb/source/API/SBCommandInterpreter.cpp
@@ -171,27 +171,22 @@ lldb::ReturnStatus SBCommandInterpreter::HandleCommand(
lldb::SBCommandReturnObject &, bool),
command_line, override_context, result, add_to_history);
-
- ExecutionContext ctx, *ctx_ptr;
- if (override_context.get()) {
- ctx = override_context.get()->Lock(true);
- ctx_ptr = &ctx;
- } else
- ctx_ptr = nullptr;
-
result.Clear();
if (command_line && IsValid()) {
result.ref().SetInteractive(false);
- m_opaque_ptr->HandleCommand(command_line,
- add_to_history ? eLazyBoolYes : eLazyBoolNo,
- result.ref(), ctx_ptr);
+ auto do_add_to_history = add_to_history ? eLazyBoolYes : eLazyBoolNo;
+ if (override_context.get())
+ m_opaque_ptr->HandleCommand(command_line, do_add_to_history,
+ override_context.get()->Lock(true),
+ result.ref());
+ else
+ m_opaque_ptr->HandleCommand(command_line, do_add_to_history,
+ result.ref());
} else {
result->AppendError(
"SBCommandInterpreter or the command line is not valid");
- result->SetStatus(eReturnStatusFailed);
}
-
return result.GetStatus();
}
@@ -207,7 +202,6 @@ void SBCommandInterpreter::HandleCommandsFromFile(
if (!IsValid()) {
result->AppendError("SBCommandInterpreter is not valid.");
- result->SetStatus(eReturnStatusFailed);
return;
}
@@ -215,19 +209,17 @@ void SBCommandInterpreter::HandleCommandsFromFile(
SBStream s;
file.GetDescription(s);
result->AppendErrorWithFormat("File is not valid: %s.", s.GetData());
- result->SetStatus(eReturnStatusFailed);
}
FileSpec tmp_spec = file.ref();
- ExecutionContext ctx, *ctx_ptr;
- if (override_context.get()) {
- ctx = override_context.get()->Lock(true);
- ctx_ptr = &ctx;
- } else
- ctx_ptr = nullptr;
+ if (override_context.get())
+ m_opaque_ptr->HandleCommandsFromFile(tmp_spec,
+ override_context.get()->Lock(true),
+ options.ref(),
+ result.ref());
- m_opaque_ptr->HandleCommandsFromFile(tmp_spec, ctx_ptr, options.ref(),
- result.ref());
+ else
+ m_opaque_ptr->HandleCommandsFromFile(tmp_spec, options.ref(), result.ref());
}
int SBCommandInterpreter::HandleCompletion(
@@ -444,7 +436,6 @@ void SBCommandInterpreter::ResolveCommand(const char *command_line,
} else {
result->AppendError(
"SBCommandInterpreter or the command line is not valid");
- result->SetStatus(eReturnStatusFailed);
}
}
@@ -474,7 +465,6 @@ void SBCommandInterpreter::SourceInitFileInHomeDirectory(
m_opaque_ptr->SourceInitFileHome(result.ref());
} else {
result->AppendError("SBCommandInterpreter is not valid");
- result->SetStatus(eReturnStatusFailed);
}
}
@@ -492,7 +482,6 @@ void SBCommandInterpreter::SourceInitFileInHomeDirectory(
m_opaque_ptr->SourceInitFileHome(result.ref(), is_repl);
} else {
result->AppendError("SBCommandInterpreter is not valid");
- result->SetStatus(eReturnStatusFailed);
}
}
@@ -511,7 +500,6 @@ void SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory(
m_opaque_ptr->SourceInitFileCwd(result.ref());
} else {
result->AppendError("SBCommandInterpreter is not valid");
- result->SetStatus(eReturnStatusFailed);
}
}
diff --git a/lldb/source/API/SBCommandInterpreterRunOptions.cpp b/lldb/source/API/SBCommandInterpreterRunOptions.cpp
index da800e8b7804..317ec6d37127 100644
--- a/lldb/source/API/SBCommandInterpreterRunOptions.cpp
+++ b/lldb/source/API/SBCommandInterpreterRunOptions.cpp
@@ -131,6 +131,20 @@ void SBCommandInterpreterRunOptions::SetPrintResults(bool print_results) {
m_opaque_up->SetPrintResults(print_results);
}
+bool SBCommandInterpreterRunOptions::GetPrintErrors() const {
+ LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreterRunOptions,
+ GetPrintErrors);
+
+ return m_opaque_up->GetPrintErrors();
+}
+
+void SBCommandInterpreterRunOptions::SetPrintErrors(bool print_errors) {
+ LLDB_RECORD_METHOD(void, SBCommandInterpreterRunOptions, SetPrintErrors,
+ (bool), print_errors);
+
+ m_opaque_up->SetPrintErrors(print_errors);
+}
+
bool SBCommandInterpreterRunOptions::GetAddToHistory() const {
LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreterRunOptions,
GetAddToHistory);
@@ -270,6 +284,10 @@ template <> void RegisterMethods<SBCommandInterpreterRunOptions>(Registry &R) {
LLDB_REGISTER_METHOD(void, SBCommandInterpreterRunOptions, SetPrintResults,
(bool));
LLDB_REGISTER_METHOD_CONST(bool, SBCommandInterpreterRunOptions,
+ GetPrintErrors, ());
+ LLDB_REGISTER_METHOD(void, SBCommandInterpreterRunOptions, SetPrintErrors,
+ (bool));
+ LLDB_REGISTER_METHOD_CONST(bool, SBCommandInterpreterRunOptions,
GetAddToHistory, ());
LLDB_REGISTER_METHOD(void, SBCommandInterpreterRunOptions, SetAddToHistory,
(bool));
diff --git a/lldb/source/API/SBCommandReturnObject.cpp b/lldb/source/API/SBCommandReturnObject.cpp
index fddf90b66481..00150d198fca 100644
--- a/lldb/source/API/SBCommandReturnObject.cpp
+++ b/lldb/source/API/SBCommandReturnObject.cpp
@@ -21,8 +21,7 @@ using namespace lldb_private;
class lldb_private::SBCommandReturnObjectImpl {
public:
- SBCommandReturnObjectImpl()
- : m_ptr(new CommandReturnObject(false)), m_owned(true) {}
+ SBCommandReturnObjectImpl() : m_ptr(new CommandReturnObject(false)) {}
SBCommandReturnObjectImpl(CommandReturnObject &ref)
: m_ptr(&ref), m_owned(false) {}
SBCommandReturnObjectImpl(const SBCommandReturnObjectImpl &rhs)
@@ -42,7 +41,7 @@ public:
private:
CommandReturnObject *m_ptr;
- bool m_owned;
+ bool m_owned = true;
};
SBCommandReturnObject::SBCommandReturnObject()
@@ -364,7 +363,7 @@ void SBCommandReturnObject::SetError(const char *error_cstr) {
error_cstr);
if (error_cstr)
- ref().SetError(error_cstr);
+ ref().AppendError(error_cstr);
}
namespace lldb_private {
diff --git a/lldb/source/API/SBCommunication.cpp b/lldb/source/API/SBCommunication.cpp
index d55ecd35b557..9a2ab89d5e4e 100644
--- a/lldb/source/API/SBCommunication.cpp
+++ b/lldb/source/API/SBCommunication.cpp
@@ -16,7 +16,7 @@
using namespace lldb;
using namespace lldb_private;
-SBCommunication::SBCommunication() : m_opaque(nullptr), m_opaque_owned(false) {
+SBCommunication::SBCommunication() {
LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBCommunication);
}
diff --git a/lldb/source/API/SBCompileUnit.cpp b/lldb/source/API/SBCompileUnit.cpp
index 765957d680c9..a44d3b897110 100644
--- a/lldb/source/API/SBCompileUnit.cpp
+++ b/lldb/source/API/SBCompileUnit.cpp
@@ -21,7 +21,7 @@
using namespace lldb;
using namespace lldb_private;
-SBCompileUnit::SBCompileUnit() : m_opaque_ptr(nullptr) {
+SBCompileUnit::SBCompileUnit() {
LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBCompileUnit);
}
@@ -108,9 +108,10 @@ uint32_t SBCompileUnit::FindLineEntryIndex(uint32_t start_idx, uint32_t line,
else
file_spec = m_opaque_ptr->GetPrimaryFile();
+ LineEntry line_entry;
index = m_opaque_ptr->FindLineEntry(
start_idx, line, inline_file_spec ? inline_file_spec->get() : nullptr,
- exact, nullptr);
+ exact, &line_entry);
}
return index;
diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp
index 6245b3a83565..a854c22bb214 100644
--- a/lldb/source/API/SBDebugger.cpp
+++ b/lldb/source/API/SBDebugger.cpp
@@ -38,6 +38,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Progress.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/DataFormatters/DataVisualization.h"
@@ -149,6 +150,41 @@ SBDebugger &SBDebugger::operator=(const SBDebugger &rhs) {
return LLDB_RECORD_RESULT(*this);
}
+const char *SBDebugger::GetBroadcasterClass() {
+ LLDB_RECORD_STATIC_METHOD_NO_ARGS(const char *, SBDebugger,
+ GetBroadcasterClass);
+
+ return Debugger::GetStaticBroadcasterClass().AsCString();
+}
+
+const char *SBDebugger::GetProgressFromEvent(const lldb::SBEvent &event,
+ uint64_t &progress_id,
+ uint64_t &completed,
+ uint64_t &total,
+ bool &is_debugger_specific) {
+ const Debugger::ProgressEventData *progress_data =
+ Debugger::ProgressEventData::GetEventDataFromEvent(event.get());
+ if (progress_data == nullptr)
+ return nullptr;
+ progress_id = progress_data->GetID();
+ completed = progress_data->GetCompleted();
+ total = progress_data->GetTotal();
+ is_debugger_specific = progress_data->IsDebuggerSpecific();
+ // We must record the static method _after_ the out parameters have been
+ // filled in.
+ LLDB_RECORD_STATIC_METHOD(
+ const char *, SBDebugger, GetProgressFromEvent,
+ (const lldb::SBEvent &, uint64_t &, uint64_t &, uint64_t &, bool &),
+ event, progress_id, completed, total, is_debugger_specific);
+ return LLDB_RECORD_RESULT(progress_data->GetMessage().c_str())
+}
+
+SBBroadcaster SBDebugger::GetBroadcaster() {
+ LLDB_RECORD_METHOD_NO_ARGS(lldb::SBBroadcaster, SBDebugger, GetBroadcaster);
+ SBBroadcaster broadcaster(&m_opaque_sp->GetBroadcaster(), false);
+ return LLDB_RECORD_RESULT(broadcaster);
+}
+
void SBDebugger::Initialize() {
LLDB_RECORD_STATIC_METHOD_NO_ARGS(void, SBDebugger, Initialize);
SBError ignored = SBDebugger::InitializeWithErrorHandling();
@@ -824,7 +860,7 @@ SBTarget SBDebugger::CreateTargetWithFileAndArch(const char *filename,
if (error.Success())
sb_target.SetSP(target_sp);
}
-
+
LLDB_LOGF(log,
"SBDebugger(%p)::CreateTargetWithFileAndArch (filename=\"%s\", "
"arch=%s) => SBTarget(%p)",
@@ -1298,7 +1334,6 @@ SBDebugger::GetInternalVariableValue(const char *var_name,
lldb::SBStringList, SBDebugger, GetInternalVariableValue,
(const char *, const char *), var_name, debugger_instance_name);
- SBStringList ret_value;
DebuggerSP debugger_sp(Debugger::FindDebuggerWithInstanceName(
ConstString(debugger_instance_name)));
Status error;
@@ -1351,7 +1386,7 @@ void SBDebugger::SetPrompt(const char *prompt) {
LLDB_RECORD_METHOD(void, SBDebugger, SetPrompt, (const char *), prompt);
if (m_opaque_sp)
- m_opaque_sp->SetPrompt(llvm::StringRef::withNullAsEmpty(prompt));
+ m_opaque_sp->SetPrompt(llvm::StringRef(prompt));
}
const char *SBDebugger::GetReproducerPath() const {
@@ -1711,6 +1746,12 @@ template <> void RegisterMethods<SBDebugger>(Registry &R) {
LLDB_REGISTER_METHOD(void, SBDebugger, Clear, ());
LLDB_REGISTER_STATIC_METHOD(lldb::SBDebugger, SBDebugger, Create, ());
LLDB_REGISTER_STATIC_METHOD(lldb::SBDebugger, SBDebugger, Create, (bool));
+ LLDB_REGISTER_STATIC_METHOD(
+ const char *, SBDebugger, GetProgressFromEvent,
+ (const lldb::SBEvent &, uint64_t &, uint64_t &, uint64_t &, bool &));
+ LLDB_REGISTER_STATIC_METHOD(const char *, SBDebugger, GetBroadcasterClass,
+ ());
+ LLDB_REGISTER_METHOD(SBBroadcaster, SBDebugger, GetBroadcaster, ());
LLDB_REGISTER_STATIC_METHOD(void, SBDebugger, Destroy, (lldb::SBDebugger &));
LLDB_REGISTER_STATIC_METHOD(void, SBDebugger, MemoryPressureDetected, ());
LLDB_REGISTER_METHOD_CONST(bool, SBDebugger, IsValid, ());
diff --git a/lldb/source/API/SBDeclaration.cpp b/lldb/source/API/SBDeclaration.cpp
index f1066d63c06a..1496096e46d1 100644
--- a/lldb/source/API/SBDeclaration.cpp
+++ b/lldb/source/API/SBDeclaration.cpp
@@ -10,11 +10,11 @@
#include "SBReproducerPrivate.h"
#include "Utils.h"
#include "lldb/API/SBStream.h"
+#include "lldb/Core/Declaration.h"
#include "lldb/Host/PosixApi.h"
-#include "lldb/Symbol/Declaration.h"
#include "lldb/Utility/Stream.h"
-#include <limits.h>
+#include <climits>
using namespace lldb;
using namespace lldb_private;
diff --git a/lldb/source/API/SBError.cpp b/lldb/source/API/SBError.cpp
index f979572778e0..89b5f26fd80c 100644
--- a/lldb/source/API/SBError.cpp
+++ b/lldb/source/API/SBError.cpp
@@ -12,7 +12,7 @@
#include "lldb/API/SBStream.h"
#include "lldb/Utility/Status.h"
-#include <stdarg.h>
+#include <cstdarg>
using namespace lldb;
using namespace lldb_private;
diff --git a/lldb/source/API/SBEvent.cpp b/lldb/source/API/SBEvent.cpp
index 2776ec49c092..a0b606e3812e 100644
--- a/lldb/source/API/SBEvent.cpp
+++ b/lldb/source/API/SBEvent.cpp
@@ -22,9 +22,7 @@
using namespace lldb;
using namespace lldb_private;
-SBEvent::SBEvent() : m_event_sp(), m_opaque_ptr(nullptr) {
- LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBEvent);
-}
+SBEvent::SBEvent() : m_event_sp() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBEvent); }
SBEvent::SBEvent(uint32_t event_type, const char *cstr, uint32_t cstr_len)
: m_event_sp(new Event(event_type, new EventDataBytes(cstr, cstr_len))),
diff --git a/lldb/source/API/SBFileSpec.cpp b/lldb/source/API/SBFileSpec.cpp
index 7bfb665df4fb..0a6b63bb460c 100644
--- a/lldb/source/API/SBFileSpec.cpp
+++ b/lldb/source/API/SBFileSpec.cpp
@@ -17,8 +17,8 @@
#include "llvm/ADT/SmallString.h"
-#include <inttypes.h>
-#include <limits.h>
+#include <cinttypes>
+#include <climits>
using namespace lldb;
using namespace lldb_private;
diff --git a/lldb/source/API/SBFileSpecList.cpp b/lldb/source/API/SBFileSpecList.cpp
index 7afa34363271..768ff0affd15 100644
--- a/lldb/source/API/SBFileSpecList.cpp
+++ b/lldb/source/API/SBFileSpecList.cpp
@@ -16,7 +16,7 @@
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Stream.h"
-#include <limits.h>
+#include <climits>
using namespace lldb;
using namespace lldb_private;
diff --git a/lldb/source/API/SBFunction.cpp b/lldb/source/API/SBFunction.cpp
index 9f3cf817fc8c..2d0cb239de75 100644
--- a/lldb/source/API/SBFunction.cpp
+++ b/lldb/source/API/SBFunction.cpp
@@ -22,9 +22,7 @@
using namespace lldb;
using namespace lldb_private;
-SBFunction::SBFunction() : m_opaque_ptr(nullptr) {
- LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBFunction);
-}
+SBFunction::SBFunction() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBFunction); }
SBFunction::SBFunction(lldb_private::Function *lldb_object_ptr)
: m_opaque_ptr(lldb_object_ptr) {}
@@ -132,10 +130,10 @@ SBInstructionList SBFunction::GetInstructions(SBTarget target,
m_opaque_ptr->GetAddressRange().GetBaseAddress().GetModule());
if (target_sp && module_sp) {
lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
- const bool prefer_file_cache = false;
+ const bool force_live_memory = true;
sb_instructions.SetDisassembler(Disassembler::DisassembleRange(
module_sp->GetArchitecture(), nullptr, flavor, *target_sp,
- m_opaque_ptr->GetAddressRange(), prefer_file_cache));
+ m_opaque_ptr->GetAddressRange(), force_live_memory));
}
}
return LLDB_RECORD_RESULT(sb_instructions);
diff --git a/lldb/source/API/SBLanguageRuntime.cpp b/lldb/source/API/SBLanguageRuntime.cpp
index 33c900d20c31..e65b58270517 100644
--- a/lldb/source/API/SBLanguageRuntime.cpp
+++ b/lldb/source/API/SBLanguageRuntime.cpp
@@ -18,8 +18,7 @@ SBLanguageRuntime::GetLanguageTypeFromString(const char *string) {
LLDB_RECORD_STATIC_METHOD(lldb::LanguageType, SBLanguageRuntime,
GetLanguageTypeFromString, (const char *), string);
- return Language::GetLanguageTypeFromString(
- llvm::StringRef::withNullAsEmpty(string));
+ return Language::GetLanguageTypeFromString(llvm::StringRef(string));
}
const char *
diff --git a/lldb/source/API/SBLaunchInfo.cpp b/lldb/source/API/SBLaunchInfo.cpp
index cda8134c9853..70cd1c6ecf74 100644
--- a/lldb/source/API/SBLaunchInfo.cpp
+++ b/lldb/source/API/SBLaunchInfo.cpp
@@ -10,8 +10,12 @@
#include "SBReproducerPrivate.h"
#include "lldb/API/SBEnvironment.h"
+#include "lldb/API/SBError.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBListener.h"
+#include "lldb/API/SBStream.h"
+#include "lldb/API/SBStructuredData.h"
+#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Host/ProcessLaunchInfo.h"
using namespace lldb;
@@ -343,6 +347,53 @@ bool SBLaunchInfo::GetDetachOnError() const {
return m_opaque_sp->GetDetachOnError();
}
+const char *SBLaunchInfo::GetScriptedProcessClassName() const {
+ LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBLaunchInfo,
+ GetScriptedProcessClassName);
+
+ // Constify this string so that it is saved in the string pool. Otherwise it
+ // would be freed when this function goes out of scope.
+ ConstString class_name(m_opaque_sp->GetScriptedProcessClassName().c_str());
+ return class_name.AsCString();
+}
+
+void SBLaunchInfo::SetScriptedProcessClassName(const char *class_name) {
+ LLDB_RECORD_METHOD(void, SBLaunchInfo, SetScriptedProcessClassName,
+ (const char *), class_name);
+
+ m_opaque_sp->SetScriptedProcessClassName(class_name);
+}
+
+lldb::SBStructuredData SBLaunchInfo::GetScriptedProcessDictionary() const {
+ LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBStructuredData, SBLaunchInfo,
+ GetScriptedProcessDictionary);
+
+ lldb_private::StructuredData::DictionarySP dict_sp =
+ m_opaque_sp->GetScriptedProcessDictionarySP();
+
+ SBStructuredData data;
+ data.m_impl_up->SetObjectSP(dict_sp);
+
+ return LLDB_RECORD_RESULT(data);
+}
+
+void SBLaunchInfo::SetScriptedProcessDictionary(lldb::SBStructuredData dict) {
+ LLDB_RECORD_METHOD(void, SBLaunchInfo, SetScriptedProcessDictionary,
+ (lldb::SBStructuredData), dict);
+
+ SBStream stream;
+ SBError error = dict.GetAsJSON(stream);
+
+ if (error.Fail())
+ return;
+
+ StructuredData::DictionarySP dict_sp;
+ llvm::json::OStream s(stream.ref().AsRawOstream());
+ dict_sp->Serialize(s);
+
+ m_opaque_sp->SetScriptedProcessDictionarySP(dict_sp);
+}
+
namespace lldb_private {
namespace repro {
@@ -403,6 +454,14 @@ void RegisterMethods<SBLaunchInfo>(Registry &R) {
());
LLDB_REGISTER_METHOD(void, SBLaunchInfo, SetDetachOnError, (bool));
LLDB_REGISTER_METHOD_CONST(bool, SBLaunchInfo, GetDetachOnError, ());
+ LLDB_REGISTER_METHOD_CONST(const char *, SBLaunchInfo,
+ GetScriptedProcessClassName, ());
+ LLDB_REGISTER_METHOD(void, SBLaunchInfo, SetScriptedProcessClassName,
+ (const char *));
+ LLDB_REGISTER_METHOD_CONST(lldb::SBStructuredData, SBLaunchInfo,
+ GetScriptedProcessDictionary, ());
+ LLDB_REGISTER_METHOD(void, SBLaunchInfo, SetScriptedProcessDictionary,
+ (lldb::SBStructuredData));
LLDB_REGISTER_METHOD(void, SBLaunchInfo, SetEnvironment,
(const lldb::SBEnvironment &, bool));
LLDB_REGISTER_METHOD(lldb::SBEnvironment, SBLaunchInfo, GetEnvironment, ());
diff --git a/lldb/source/API/SBLineEntry.cpp b/lldb/source/API/SBLineEntry.cpp
index 9866acbcbec3..29ffda9b0471 100644
--- a/lldb/source/API/SBLineEntry.cpp
+++ b/lldb/source/API/SBLineEntry.cpp
@@ -14,7 +14,7 @@
#include "lldb/Symbol/LineEntry.h"
#include "lldb/Utility/StreamString.h"
-#include <limits.h>
+#include <climits>
using namespace lldb;
using namespace lldb_private;
diff --git a/lldb/source/API/SBListener.cpp b/lldb/source/API/SBListener.cpp
index f3463268b3b5..6e5e15de7b3d 100644
--- a/lldb/source/API/SBListener.cpp
+++ b/lldb/source/API/SBListener.cpp
@@ -20,7 +20,7 @@
using namespace lldb;
using namespace lldb_private;
-SBListener::SBListener() : m_opaque_sp(), m_unused_ptr(nullptr) {
+SBListener::SBListener() : m_opaque_sp() {
LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBListener);
}
diff --git a/lldb/source/API/SBMemoryRegionInfo.cpp b/lldb/source/API/SBMemoryRegionInfo.cpp
index 2a28b99c72d7..ab74d559387f 100644
--- a/lldb/source/API/SBMemoryRegionInfo.cpp
+++ b/lldb/source/API/SBMemoryRegionInfo.cpp
@@ -116,6 +116,42 @@ const char *SBMemoryRegionInfo::GetName() {
return m_opaque_up->GetName().AsCString();
}
+bool SBMemoryRegionInfo::HasDirtyMemoryPageList() {
+ LLDB_RECORD_METHOD_NO_ARGS(bool, SBMemoryRegionInfo, HasDirtyMemoryPageList);
+
+ return m_opaque_up->GetDirtyPageList().hasValue();
+}
+
+uint32_t SBMemoryRegionInfo::GetNumDirtyPages() {
+ LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBMemoryRegionInfo, GetNumDirtyPages);
+
+ uint32_t num_dirty_pages = 0;
+ llvm::Optional<std::vector<addr_t>> dirty_page_list =
+ m_opaque_up->GetDirtyPageList();
+ if (dirty_page_list.hasValue())
+ num_dirty_pages = dirty_page_list.getValue().size();
+
+ return num_dirty_pages;
+}
+
+addr_t SBMemoryRegionInfo::GetDirtyPageAddressAtIndex(uint32_t idx) {
+ LLDB_RECORD_METHOD(addr_t, SBMemoryRegionInfo, GetDirtyPageAddressAtIndex,
+ (uint32_t), idx);
+
+ addr_t dirty_page_addr = LLDB_INVALID_ADDRESS;
+ const llvm::Optional<std::vector<addr_t>> &dirty_page_list =
+ m_opaque_up->GetDirtyPageList();
+ if (dirty_page_list.hasValue() && idx < dirty_page_list.getValue().size())
+ dirty_page_addr = dirty_page_list.getValue()[idx];
+
+ return dirty_page_addr;
+}
+
+int SBMemoryRegionInfo::GetPageSize() {
+ LLDB_RECORD_METHOD_NO_ARGS(int, SBMemoryRegionInfo, GetPageSize);
+ return m_opaque_up->GetPageSize();
+}
+
bool SBMemoryRegionInfo::GetDescription(SBStream &description) {
LLDB_RECORD_METHOD(bool, SBMemoryRegionInfo, GetDescription,
(lldb::SBStream &), description);
diff --git a/lldb/source/API/SBPlatform.cpp b/lldb/source/API/SBPlatform.cpp
index f118048156b9..496c40a0678f 100644
--- a/lldb/source/API/SBPlatform.cpp
+++ b/lldb/source/API/SBPlatform.cpp
@@ -32,7 +32,7 @@ using namespace lldb_private;
struct PlatformConnectOptions {
PlatformConnectOptions(const char *url = nullptr)
: m_url(), m_rsync_options(), m_rsync_remote_path_prefix(),
- m_rsync_enabled(false), m_rsync_omit_hostname_from_remote_path(false),
+
m_local_cache_directory() {
if (url && url[0])
m_url = url;
@@ -43,8 +43,8 @@ struct PlatformConnectOptions {
std::string m_url;
std::string m_rsync_options;
std::string m_rsync_remote_path_prefix;
- bool m_rsync_enabled;
- bool m_rsync_omit_hostname_from_remote_path;
+ bool m_rsync_enabled = false;
+ bool m_rsync_omit_hostname_from_remote_path = false;
ConstString m_local_cache_directory;
};
@@ -61,7 +61,7 @@ struct PlatformShellCommand {
}
PlatformShellCommand(llvm::StringRef shell_command = llvm::StringRef())
- : m_shell(), m_command(), m_working_dir(), m_status(0), m_signo(0) {
+ : m_shell(), m_command(), m_working_dir() {
if (!shell_command.empty())
m_command = shell_command.str();
}
@@ -72,8 +72,8 @@ struct PlatformShellCommand {
std::string m_command;
std::string m_working_dir;
std::string m_output;
- int m_status;
- int m_signo;
+ int m_status = 0;
+ int m_signo = 0;
Timeout<std::ratio<1>> m_timeout = llvm::None;
};
// SBPlatformConnectOptions
@@ -413,8 +413,7 @@ SBError SBPlatform::ConnectRemote(SBPlatformConnectOptions &connect_options) {
PlatformSP platform_sp(GetSP());
if (platform_sp && connect_options.GetURL()) {
Args args;
- args.AppendArgument(
- llvm::StringRef::withNullAsEmpty(connect_options.GetURL()));
+ args.AppendArgument(connect_options.GetURL());
sb_error.ref() = platform_sp->ConnectRemote(args);
} else {
sb_error.SetErrorString("invalid platform");
diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp
index d7b7fd7cacad..47c35a23b078 100644
--- a/lldb/source/API/SBProcess.cpp
+++ b/lldb/source/API/SBProcess.cpp
@@ -9,7 +9,7 @@
#include "lldb/API/SBProcess.h"
#include "SBReproducerPrivate.h"
-#include <inttypes.h>
+#include <cinttypes>
#include "lldb/lldb-defines.h"
#include "lldb/lldb-types.h"
@@ -44,7 +44,6 @@
#include "lldb/API/SBThread.h"
#include "lldb/API/SBThreadCollection.h"
#include "lldb/API/SBTrace.h"
-#include "lldb/API/SBTraceOptions.h"
#include "lldb/API/SBUnixSignals.h"
using namespace lldb;
@@ -312,26 +311,6 @@ size_t SBProcess::GetAsyncProfileData(char *dst, size_t dst_len) const {
return bytes_read;
}
-lldb::SBTrace SBProcess::StartTrace(SBTraceOptions &options,
- lldb::SBError &error) {
- LLDB_RECORD_METHOD(lldb::SBTrace, SBProcess, StartTrace,
- (lldb::SBTraceOptions &, lldb::SBError &), options, error);
-
- ProcessSP process_sp(GetSP());
- error.Clear();
- SBTrace trace_instance;
- trace_instance.SetSP(process_sp);
- lldb::user_id_t uid = LLDB_INVALID_UID;
-
- if (!process_sp) {
- error.SetErrorString("invalid process");
- } else {
- uid = process_sp->StartTrace(*(options.m_traceoptions_sp), error.ref());
- trace_instance.SetTraceUID(uid);
- }
- return LLDB_RECORD_RESULT(trace_instance);
-}
-
void SBProcess::ReportEventState(const SBEvent &event, SBFile out) const {
LLDB_RECORD_METHOD_CONST(void, SBProcess, ReportEventState,
(const SBEvent &, SBFile), event, out);
@@ -1248,7 +1227,8 @@ lldb::SBError SBProcess::SaveCore(const char *file_name) {
}
FileSpec core_file(file_name);
- error.ref() = PluginManager::SaveCore(process_sp, core_file);
+ SaveCoreStyle core_style = SaveCoreStyle::eSaveCoreFull;
+ error.ref() = PluginManager::SaveCore(process_sp, core_file, core_style);
return LLDB_RECORD_RESULT(error);
}
@@ -1308,6 +1288,51 @@ lldb::SBProcessInfo SBProcess::GetProcessInfo() {
return LLDB_RECORD_RESULT(sb_proc_info);
}
+lldb::addr_t SBProcess::AllocateMemory(size_t size, uint32_t permissions,
+ lldb::SBError &sb_error) {
+ LLDB_RECORD_METHOD(lldb::addr_t, SBProcess, AllocateMemory,
+ (size_t, uint32_t, lldb::SBError &), size, permissions,
+ sb_error);
+
+ lldb::addr_t addr = LLDB_INVALID_ADDRESS;
+ ProcessSP process_sp(GetSP());
+ if (process_sp) {
+ Process::StopLocker stop_locker;
+ if (stop_locker.TryLock(&process_sp->GetRunLock())) {
+ std::lock_guard<std::recursive_mutex> guard(
+ process_sp->GetTarget().GetAPIMutex());
+ addr = process_sp->AllocateMemory(size, permissions, sb_error.ref());
+ } else {
+ sb_error.SetErrorString("process is running");
+ }
+ } else {
+ sb_error.SetErrorString("SBProcess is invalid");
+ }
+ return addr;
+}
+
+lldb::SBError SBProcess::DeallocateMemory(lldb::addr_t ptr) {
+ LLDB_RECORD_METHOD(lldb::SBError, SBProcess, DeallocateMemory, (lldb::addr_t),
+ ptr);
+
+ lldb::SBError sb_error;
+ ProcessSP process_sp(GetSP());
+ if (process_sp) {
+ Process::StopLocker stop_locker;
+ if (stop_locker.TryLock(&process_sp->GetRunLock())) {
+ std::lock_guard<std::recursive_mutex> guard(
+ process_sp->GetTarget().GetAPIMutex());
+ Status error = process_sp->DeallocateMemory(ptr);
+ sb_error.SetError(error);
+ } else {
+ sb_error.SetErrorString("process is running");
+ }
+ } else {
+ sb_error.SetErrorString("SBProcess is invalid");
+ }
+ return sb_error;
+}
+
namespace lldb_private {
namespace repro {
@@ -1338,8 +1363,6 @@ void RegisterMethods<SBProcess>(Registry &R) {
(lldb::tid_t, lldb::addr_t));
LLDB_REGISTER_METHOD_CONST(lldb::SBTarget, SBProcess, GetTarget, ());
LLDB_REGISTER_METHOD(size_t, SBProcess, PutSTDIN, (const char *, size_t));
- LLDB_REGISTER_METHOD(lldb::SBTrace, SBProcess, StartTrace,
- (lldb::SBTraceOptions &, lldb::SBError &));
LLDB_REGISTER_METHOD_CONST(void, SBProcess, ReportEventState,
(const lldb::SBEvent &, FILE *));
LLDB_REGISTER_METHOD_CONST(void, SBProcess, ReportEventState,
@@ -1439,6 +1462,10 @@ void RegisterMethods<SBProcess>(Registry &R) {
LLDB_REGISTER_METHOD(lldb::SBMemoryRegionInfoList, SBProcess,
GetMemoryRegions, ());
LLDB_REGISTER_METHOD(lldb::SBProcessInfo, SBProcess, GetProcessInfo, ());
+ LLDB_REGISTER_METHOD(lldb::addr_t, SBProcess, AllocateMemory,
+ (size_t, uint32_t, lldb::SBError &));
+ LLDB_REGISTER_METHOD(lldb::SBError, SBProcess, DeallocateMemory,
+ (lldb::addr_t));
LLDB_REGISTER_CHAR_PTR_METHOD_CONST(size_t, SBProcess, GetSTDOUT);
LLDB_REGISTER_CHAR_PTR_METHOD_CONST(size_t, SBProcess, GetSTDERR);
diff --git a/lldb/source/API/SBProcessInfo.cpp b/lldb/source/API/SBProcessInfo.cpp
index 29a9c7b24b5a..cba3bdc179f3 100644
--- a/lldb/source/API/SBProcessInfo.cpp
+++ b/lldb/source/API/SBProcessInfo.cpp
@@ -179,6 +179,21 @@ lldb::pid_t SBProcessInfo::GetParentProcessID() {
return proc_id;
}
+const char *SBProcessInfo::GetTriple() {
+ LLDB_RECORD_METHOD_NO_ARGS(const char *, SBProcessInfo, GetTriple);
+
+ const char *triple = nullptr;
+ if (m_opaque_up) {
+ const auto &arch = m_opaque_up->GetArchitecture();
+ if (arch.IsValid()) {
+ // Const-ify the string so we don't need to worry about the lifetime of
+ // the string
+ triple = ConstString(arch.GetTriple().getTriple().c_str()).GetCString();
+ }
+ }
+ return triple;
+}
+
namespace lldb_private {
namespace repro {
@@ -204,6 +219,7 @@ void RegisterMethods<SBProcessInfo>(Registry &R) {
LLDB_REGISTER_METHOD(bool, SBProcessInfo, EffectiveUserIDIsValid, ());
LLDB_REGISTER_METHOD(bool, SBProcessInfo, EffectiveGroupIDIsValid, ());
LLDB_REGISTER_METHOD(lldb::pid_t, SBProcessInfo, GetParentProcessID, ());
+ LLDB_REGISTER_METHOD(const char *, SBProcessInfo, GetTriple, ());
}
}
diff --git a/lldb/source/API/SBQueue.cpp b/lldb/source/API/SBQueue.cpp
index 2e6571392ea1..746df9e79d61 100644
--- a/lldb/source/API/SBQueue.cpp
+++ b/lldb/source/API/SBQueue.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <inttypes.h>
+#include <cinttypes>
#include "SBReproducerPrivate.h"
#include "lldb/API/SBQueue.h"
@@ -27,9 +27,7 @@ namespace lldb_private {
class QueueImpl {
public:
- QueueImpl()
- : m_queue_wp(), m_threads(), m_thread_list_fetched(false),
- m_pending_items(), m_pending_items_fetched(false) {}
+ QueueImpl() : m_queue_wp(), m_threads(), m_pending_items() {}
QueueImpl(const lldb::QueueSP &queue_sp)
: m_queue_wp(), m_threads(), m_thread_list_fetched(false),
@@ -210,10 +208,11 @@ private:
lldb::QueueWP m_queue_wp;
std::vector<lldb::ThreadWP>
m_threads; // threads currently executing this queue's items
- bool
- m_thread_list_fetched; // have we tried to fetch the threads list already?
+ bool m_thread_list_fetched =
+ false; // have we tried to fetch the threads list already?
std::vector<lldb::QueueItemSP> m_pending_items; // items currently enqueued
- bool m_pending_items_fetched; // have we tried to fetch the item list already?
+ bool m_pending_items_fetched =
+ false; // have we tried to fetch the item list already?
};
}
diff --git a/lldb/source/API/SBReproducer.cpp b/lldb/source/API/SBReproducer.cpp
index 4d25fcc4a8f6..68e632da1bde 100644
--- a/lldb/source/API/SBReproducer.cpp
+++ b/lldb/source/API/SBReproducer.cpp
@@ -117,7 +117,6 @@ SBRegistry::SBRegistry() {
RegisterMethods<SBThreadCollection>(R);
RegisterMethods<SBThreadPlan>(R);
RegisterMethods<SBTrace>(R);
- RegisterMethods<SBTraceOptions>(R);
RegisterMethods<SBType>(R);
RegisterMethods<SBTypeCategory>(R);
RegisterMethods<SBTypeEnumMember>(R);
diff --git a/lldb/source/API/SBStream.cpp b/lldb/source/API/SBStream.cpp
index eb81153084e8..66172d248bf3 100644
--- a/lldb/source/API/SBStream.cpp
+++ b/lldb/source/API/SBStream.cpp
@@ -19,7 +19,7 @@
using namespace lldb;
using namespace lldb_private;
-SBStream::SBStream() : m_opaque_up(new StreamString()), m_is_file(false) {
+SBStream::SBStream() : m_opaque_up(new StreamString()) {
LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBStream);
}
diff --git a/lldb/source/API/SBStructuredData.cpp b/lldb/source/API/SBStructuredData.cpp
index 2ae3005fd8d1..97a9eadcaf07 100644
--- a/lldb/source/API/SBStructuredData.cpp
+++ b/lldb/source/API/SBStructuredData.cpp
@@ -29,7 +29,7 @@ SBStructuredData::SBStructuredData() : m_impl_up(new StructuredDataImpl()) {
}
SBStructuredData::SBStructuredData(const lldb::SBStructuredData &rhs)
- : m_impl_up(new StructuredDataImpl(*rhs.m_impl_up.get())) {
+ : m_impl_up(new StructuredDataImpl(*rhs.m_impl_up)) {
LLDB_RECORD_CONSTRUCTOR(SBStructuredData, (const lldb::SBStructuredData &),
rhs);
}
@@ -40,7 +40,7 @@ SBStructuredData::SBStructuredData(const lldb::EventSP &event_sp)
}
SBStructuredData::SBStructuredData(lldb_private::StructuredDataImpl *impl)
- : m_impl_up(impl) {
+ : m_impl_up(impl ? impl : new StructuredDataImpl()) {
LLDB_RECORD_CONSTRUCTOR(SBStructuredData,
(lldb_private::StructuredDataImpl *), impl);
}
@@ -72,10 +72,19 @@ lldb::SBError SBStructuredData::SetFromJSON(lldb::SBStream &stream) {
return LLDB_RECORD_RESULT(error);
}
+lldb::SBError SBStructuredData::SetFromJSON(const char *json) {
+ LLDB_RECORD_METHOD(lldb::SBError, SBStructuredData, SetFromJSON,
+ (const char *), json);
+ lldb::SBStream s;
+ s.Print(json);
+ return LLDB_RECORD_RESULT(SetFromJSON(s));
+}
+
bool SBStructuredData::IsValid() const {
LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBStructuredData, IsValid);
return this->operator bool();
}
+
SBStructuredData::operator bool() const {
LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBStructuredData, operator bool);
@@ -111,22 +120,19 @@ StructuredDataType SBStructuredData::GetType() const {
LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::StructuredDataType, SBStructuredData,
GetType);
- return (m_impl_up ? m_impl_up->GetType() : eStructuredDataTypeInvalid);
+ return m_impl_up->GetType();
}
size_t SBStructuredData::GetSize() const {
LLDB_RECORD_METHOD_CONST_NO_ARGS(size_t, SBStructuredData, GetSize);
- return (m_impl_up ? m_impl_up->GetSize() : 0);
+ return m_impl_up->GetSize();
}
bool SBStructuredData::GetKeys(lldb::SBStringList &keys) const {
LLDB_RECORD_METHOD_CONST(bool, SBStructuredData, GetKeys,
(lldb::SBStringList &), keys);
- if (!m_impl_up)
- return false;
-
if (GetType() != eStructuredDataTypeDictionary)
return false;
@@ -154,9 +160,6 @@ lldb::SBStructuredData SBStructuredData::GetValueForKey(const char *key) const {
LLDB_RECORD_METHOD_CONST(lldb::SBStructuredData, SBStructuredData,
GetValueForKey, (const char *), key);
- if (!m_impl_up)
- return LLDB_RECORD_RESULT(SBStructuredData());
-
SBStructuredData result;
result.m_impl_up->SetObjectSP(m_impl_up->GetValueForKey(key));
return LLDB_RECORD_RESULT(result);
@@ -166,9 +169,6 @@ lldb::SBStructuredData SBStructuredData::GetItemAtIndex(size_t idx) const {
LLDB_RECORD_METHOD_CONST(lldb::SBStructuredData, SBStructuredData,
GetItemAtIndex, (size_t), idx);
- if (!m_impl_up)
- return LLDB_RECORD_RESULT(SBStructuredData());
-
SBStructuredData result;
result.m_impl_up->SetObjectSP(m_impl_up->GetItemAtIndex(idx));
return LLDB_RECORD_RESULT(result);
@@ -178,28 +178,28 @@ uint64_t SBStructuredData::GetIntegerValue(uint64_t fail_value) const {
LLDB_RECORD_METHOD_CONST(uint64_t, SBStructuredData, GetIntegerValue,
(uint64_t), fail_value);
- return (m_impl_up ? m_impl_up->GetIntegerValue(fail_value) : fail_value);
+ return m_impl_up->GetIntegerValue(fail_value);
}
double SBStructuredData::GetFloatValue(double fail_value) const {
LLDB_RECORD_METHOD_CONST(double, SBStructuredData, GetFloatValue, (double),
fail_value);
- return (m_impl_up ? m_impl_up->GetFloatValue(fail_value) : fail_value);
+ return m_impl_up->GetFloatValue(fail_value);
}
bool SBStructuredData::GetBooleanValue(bool fail_value) const {
LLDB_RECORD_METHOD_CONST(bool, SBStructuredData, GetBooleanValue, (bool),
fail_value);
- return (m_impl_up ? m_impl_up->GetBooleanValue(fail_value) : fail_value);
+ return m_impl_up->GetBooleanValue(fail_value);
}
size_t SBStructuredData::GetStringValue(char *dst, size_t dst_len) const {
LLDB_RECORD_CHAR_PTR_METHOD_CONST(size_t, SBStructuredData, GetStringValue,
(char *, size_t), dst, "", dst_len);
- return (m_impl_up ? m_impl_up->GetStringValue(dst, dst_len) : 0);
+ return m_impl_up->GetStringValue(dst, dst_len);
}
namespace lldb_private {
@@ -216,6 +216,8 @@ template <> void RegisterMethods<SBStructuredData>(Registry &R) {
SBStructuredData, operator=,(const lldb::SBStructuredData &));
LLDB_REGISTER_METHOD(lldb::SBError, SBStructuredData, SetFromJSON,
(lldb::SBStream &));
+ LLDB_REGISTER_METHOD(lldb::SBError, SBStructuredData, SetFromJSON,
+ (const char *));
LLDB_REGISTER_METHOD_CONST(bool, SBStructuredData, IsValid, ());
LLDB_REGISTER_METHOD_CONST(bool, SBStructuredData, operator bool, ());
LLDB_REGISTER_METHOD(void, SBStructuredData, Clear, ());
diff --git a/lldb/source/API/SBSymbol.cpp b/lldb/source/API/SBSymbol.cpp
index eafc3e630bcd..d3abc13675f5 100644
--- a/lldb/source/API/SBSymbol.cpp
+++ b/lldb/source/API/SBSymbol.cpp
@@ -18,9 +18,7 @@
using namespace lldb;
using namespace lldb_private;
-SBSymbol::SBSymbol() : m_opaque_ptr(nullptr) {
- LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBSymbol);
-}
+SBSymbol::SBSymbol() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBSymbol); }
SBSymbol::SBSymbol(lldb_private::Symbol *lldb_object_ptr)
: m_opaque_ptr(lldb_object_ptr) {}
@@ -132,10 +130,10 @@ SBInstructionList SBSymbol::GetInstructions(SBTarget target,
ModuleSP module_sp = symbol_addr.GetModule();
if (module_sp) {
AddressRange symbol_range(symbol_addr, m_opaque_ptr->GetByteSize());
- const bool prefer_file_cache = false;
+ const bool force_live_memory = true;
sb_instructions.SetDisassembler(Disassembler::DisassembleRange(
module_sp->GetArchitecture(), nullptr, flavor_string, *target_sp,
- symbol_range, prefer_file_cache));
+ symbol_range, force_live_memory));
}
}
}
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index 6128c04de32b..6f0633288a2b 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -26,13 +26,13 @@
#include "lldb/API/SBStringList.h"
#include "lldb/API/SBStructuredData.h"
#include "lldb/API/SBSymbolContextList.h"
+#include "lldb/API/SBTrace.h"
#include "lldb/Breakpoint/BreakpointID.h"
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/BreakpointList.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/AddressResolver.h"
-#include "lldb/Core/AddressResolverName.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Module.h"
@@ -706,7 +706,7 @@ size_t SBTarget::ReadMemory(const SBAddress addr, void *buf, size_t size,
if (target_sp) {
std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
bytes_read =
- target_sp->ReadMemory(addr.ref(), false, buf, size, sb_error.ref());
+ target_sp->ReadMemory(addr.ref(), buf, size, sb_error.ref(), true);
} else {
sb_error.SetErrorString("invalid target");
}
@@ -2086,12 +2086,12 @@ lldb::SBInstructionList SBTarget::ReadInstructions(lldb::SBAddress base_addr,
if (addr_ptr) {
DataBufferHeap data(
target_sp->GetArchitecture().GetMaximumOpcodeByteSize() * count, 0);
- bool prefer_file_cache = false;
+ bool force_live_memory = true;
lldb_private::Status error;
lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
const size_t bytes_read =
- target_sp->ReadMemory(*addr_ptr, prefer_file_cache, data.GetBytes(),
- data.GetByteSize(), error, &load_addr);
+ target_sp->ReadMemory(*addr_ptr, data.GetBytes(), data.GetByteSize(),
+ error, force_live_memory, &load_addr);
const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
sb_instructions.SetDisassembler(Disassembler::DisassembleBytes(
target_sp->GetArchitecture(), nullptr, flavor_string, *addr_ptr,
@@ -2410,6 +2410,21 @@ lldb::addr_t SBTarget::GetStackRedZoneSize() {
return 0;
}
+bool SBTarget::IsLoaded(const SBModule &module) const {
+ LLDB_RECORD_METHOD_CONST(bool, SBTarget, IsLoaded, (const lldb::SBModule &),
+ module);
+
+ TargetSP target_sp(GetSP());
+ if (!target_sp)
+ return false;
+
+ ModuleSP module_sp(module.GetSP());
+ if (!module_sp)
+ return false;
+
+ return module_sp->IsLoadedInTarget(target_sp.get());
+}
+
lldb::SBLaunchInfo SBTarget::GetLaunchInfo() const {
LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBLaunchInfo, SBTarget, GetLaunchInfo);
@@ -2440,6 +2455,34 @@ SBEnvironment SBTarget::GetEnvironment() {
return LLDB_RECORD_RESULT(SBEnvironment());
}
+lldb::SBTrace SBTarget::GetTrace() {
+ LLDB_RECORD_METHOD_NO_ARGS(lldb::SBTrace, SBTarget, GetTrace);
+ TargetSP target_sp(GetSP());
+
+ if (target_sp)
+ return LLDB_RECORD_RESULT(SBTrace(target_sp->GetTrace()));
+
+ return LLDB_RECORD_RESULT(SBTrace());
+}
+
+lldb::SBTrace SBTarget::CreateTrace(lldb::SBError &error) {
+ LLDB_RECORD_METHOD(lldb::SBTrace, SBTarget, CreateTrace, (lldb::SBError &),
+ error);
+ TargetSP target_sp(GetSP());
+ error.Clear();
+
+ if (target_sp) {
+ if (llvm::Expected<lldb::TraceSP> trace_sp = target_sp->CreateTrace()) {
+ return LLDB_RECORD_RESULT(SBTrace(*trace_sp));
+ } else {
+ error.SetErrorString(llvm::toString(trace_sp.takeError()).c_str());
+ }
+ } else {
+ error.SetErrorString("missing target");
+ }
+ return LLDB_RECORD_RESULT(SBTrace());
+}
+
namespace lldb_private {
namespace repro {
@@ -2682,6 +2725,8 @@ void RegisterMethods<SBTarget>(Registry &R) {
LLDB_REGISTER_METHOD(lldb::SBValue, SBTarget, EvaluateExpression,
(const char *, const lldb::SBExpressionOptions &));
LLDB_REGISTER_METHOD(lldb::addr_t, SBTarget, GetStackRedZoneSize, ());
+ LLDB_REGISTER_METHOD_CONST(bool, SBTarget, IsLoaded,
+ (const lldb::SBModule &));
LLDB_REGISTER_METHOD_CONST(lldb::SBLaunchInfo, SBTarget, GetLaunchInfo, ());
LLDB_REGISTER_METHOD(void, SBTarget, SetLaunchInfo,
(const lldb::SBLaunchInfo &));
@@ -2699,6 +2744,8 @@ void RegisterMethods<SBTarget>(Registry &R) {
GetInstructionsWithFlavor,
(lldb::addr_t, const char *, const void *, size_t));
LLDB_REGISTER_METHOD(lldb::SBEnvironment, SBTarget, GetEnvironment, ());
+ LLDB_REGISTER_METHOD(lldb::SBTrace, SBTarget, GetTrace, ());
+ LLDB_REGISTER_METHOD(lldb::SBTrace, SBTarget, CreateTrace, (lldb::SBError &));
}
}
diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp
index 0d50aceee5e4..e0ab8b2e9fa8 100644
--- a/lldb/source/API/SBThread.cpp
+++ b/lldb/source/API/SBThread.cpp
@@ -172,6 +172,8 @@ size_t SBThread::GetStopReasonDataCount() {
case eStopReasonPlanComplete:
case eStopReasonThreadExiting:
case eStopReasonInstrumentation:
+ case eStopReasonProcessorTrace:
+ case eStopReasonVForkDone:
// There is no data for these stop reasons.
return 0;
@@ -194,6 +196,12 @@ size_t SBThread::GetStopReasonDataCount() {
case eStopReasonException:
return 1;
+
+ case eStopReasonFork:
+ return 1;
+
+ case eStopReasonVFork:
+ return 1;
}
}
}
@@ -223,6 +231,8 @@ uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) {
case eStopReasonPlanComplete:
case eStopReasonThreadExiting:
case eStopReasonInstrumentation:
+ case eStopReasonProcessorTrace:
+ case eStopReasonVForkDone:
// There is no data for these stop reasons.
return 0;
@@ -256,6 +266,12 @@ uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) {
case eStopReasonException:
return stop_info_sp->GetValue();
+
+ case eStopReasonFork:
+ return stop_info_sp->GetValue();
+
+ case eStopReasonVFork:
+ return stop_info_sp->GetValue();
}
}
}
@@ -841,12 +857,13 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
std::vector<addr_t> step_over_until_addrs;
const bool abort_other_plans = false;
const bool stop_other_threads = false;
- const bool check_inlines = true;
- const bool exact = false;
+ // TODO: Handle SourceLocationSpec column information
+ SourceLocationSpec location_spec(
+ step_file_spec, line, /*column=*/llvm::None, /*check_inlines=*/true,
+ /*exact_match=*/false);
SymbolContextList sc_list;
- frame_sc.comp_unit->ResolveSymbolContext(step_file_spec, line,
- check_inlines, exact,
+ frame_sc.comp_unit->ResolveSymbolContext(location_spec,
eSymbolContextLineEntry, sc_list);
const uint32_t num_matches = sc_list.GetSize();
if (num_matches > 0) {
diff --git a/lldb/source/API/SBTrace.cpp b/lldb/source/API/SBTrace.cpp
index 3fdabaa29ac2..079c33a562c0 100644
--- a/lldb/source/API/SBTrace.cpp
+++ b/lldb/source/API/SBTrace.cpp
@@ -9,123 +9,88 @@
#include "SBReproducerPrivate.h"
#include "lldb/Target/Process.h"
+#include "lldb/API/SBStructuredData.h"
+#include "lldb/API/SBThread.h"
#include "lldb/API/SBTrace.h"
-#include "lldb/API/SBTraceOptions.h"
+
+#include "lldb/Core/StructuredDataImpl.h"
#include <memory>
using namespace lldb;
using namespace lldb_private;
-class TraceImpl {
-public:
- lldb::user_id_t uid;
-};
-
-lldb::ProcessSP SBTrace::GetSP() const { return m_opaque_wp.lock(); }
-
-size_t SBTrace::GetTraceData(SBError &error, void *buf, size_t size,
- size_t offset, lldb::tid_t thread_id) {
- LLDB_RECORD_DUMMY(size_t, SBTrace, GetTraceData,
- (lldb::SBError &, void *, size_t, size_t, lldb::tid_t),
- error, buf, size, offset, thread_id);
+SBTrace::SBTrace() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBTrace); }
- ProcessSP process_sp(GetSP());
- llvm::MutableArrayRef<uint8_t> buffer(static_cast<uint8_t *>(buf), size);
- error.Clear();
-
- if (!process_sp) {
- error.SetErrorString("invalid process");
- } else {
- error.SetError(
- process_sp->GetData(GetTraceUID(), thread_id, buffer, offset));
- }
- return buffer.size();
+SBTrace::SBTrace(const lldb::TraceSP &trace_sp) : m_opaque_sp(trace_sp) {
+ LLDB_RECORD_CONSTRUCTOR(SBTrace, (const lldb::TraceSP &), trace_sp);
}
-size_t SBTrace::GetMetaData(SBError &error, void *buf, size_t size,
- size_t offset, lldb::tid_t thread_id) {
- LLDB_RECORD_DUMMY(size_t, SBTrace, GetMetaData,
- (lldb::SBError &, void *, size_t, size_t, lldb::tid_t),
- error, buf, size, offset, thread_id);
-
- ProcessSP process_sp(GetSP());
- llvm::MutableArrayRef<uint8_t> buffer(static_cast<uint8_t *>(buf), size);
- error.Clear();
-
- if (!process_sp) {
- error.SetErrorString("invalid process");
- } else {
- error.SetError(
- process_sp->GetMetaData(GetTraceUID(), thread_id, buffer, offset));
- }
- return buffer.size();
+const char *SBTrace::GetStartConfigurationHelp() {
+ LLDB_RECORD_METHOD_NO_ARGS(const char *, SBTrace, GetStartConfigurationHelp);
+ return LLDB_RECORD_RESULT(
+ m_opaque_sp ? m_opaque_sp->GetStartConfigurationHelp() : nullptr);
}
-void SBTrace::StopTrace(SBError &error, lldb::tid_t thread_id) {
- LLDB_RECORD_METHOD(void, SBTrace, StopTrace, (lldb::SBError &, lldb::tid_t),
- error, thread_id);
-
- ProcessSP process_sp(GetSP());
- error.Clear();
-
- if (!process_sp) {
- error.SetErrorString("invalid process");
- return;
- }
- error.SetError(process_sp->StopTrace(GetTraceUID(), thread_id));
+SBError SBTrace::Start(const SBStructuredData &configuration) {
+ LLDB_RECORD_METHOD(SBError, SBTrace, Start, (const SBStructuredData &),
+ configuration);
+ SBError error;
+ if (!m_opaque_sp)
+ error.SetErrorString("error: invalid trace");
+ else if (llvm::Error err =
+ m_opaque_sp->Start(configuration.m_impl_up->GetObjectSP()))
+ error.SetErrorString(llvm::toString(std::move(err)).c_str());
+ return LLDB_RECORD_RESULT(error);
}
-void SBTrace::GetTraceConfig(SBTraceOptions &options, SBError &error) {
- LLDB_RECORD_METHOD(void, SBTrace, GetTraceConfig,
- (lldb::SBTraceOptions &, lldb::SBError &), options, error);
-
- ProcessSP process_sp(GetSP());
- error.Clear();
+SBError SBTrace::Start(const SBThread &thread,
+ const SBStructuredData &configuration) {
+ LLDB_RECORD_METHOD(SBError, SBTrace, Start,
+ (const SBThread &, const SBStructuredData &), thread,
+ configuration);
- if (!process_sp) {
- error.SetErrorString("invalid process");
- } else {
- error.SetError(process_sp->GetTraceConfig(GetTraceUID(),
- *(options.m_traceoptions_sp)));
+ SBError error;
+ if (!m_opaque_sp)
+ error.SetErrorString("error: invalid trace");
+ else {
+ if (llvm::Error err =
+ m_opaque_sp->Start(std::vector<lldb::tid_t>{thread.GetThreadID()},
+ configuration.m_impl_up->GetObjectSP()))
+ error.SetErrorString(llvm::toString(std::move(err)).c_str());
}
-}
-
-lldb::user_id_t SBTrace::GetTraceUID() {
- LLDB_RECORD_METHOD_NO_ARGS(lldb::user_id_t, SBTrace, GetTraceUID);
- if (m_trace_impl_sp)
- return m_trace_impl_sp->uid;
- return LLDB_INVALID_UID;
+ return LLDB_RECORD_RESULT(error);
}
-void SBTrace::SetTraceUID(lldb::user_id_t uid) {
- if (m_trace_impl_sp)
- m_trace_impl_sp->uid = uid;
+SBError SBTrace::Stop() {
+ LLDB_RECORD_METHOD_NO_ARGS(SBError, SBTrace, Stop);
+ SBError error;
+ if (!m_opaque_sp)
+ error.SetErrorString("error: invalid trace");
+ else if (llvm::Error err = m_opaque_sp->Stop())
+ error.SetErrorString(llvm::toString(std::move(err)).c_str());
+ return LLDB_RECORD_RESULT(error);
}
-SBTrace::SBTrace() {
- LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBTrace);
-
- m_trace_impl_sp = std::make_shared<TraceImpl>();
- if (m_trace_impl_sp)
- m_trace_impl_sp->uid = LLDB_INVALID_UID;
+SBError SBTrace::Stop(const SBThread &thread) {
+ LLDB_RECORD_METHOD(SBError, SBTrace, Stop, (const SBThread &), thread);
+ SBError error;
+ if (!m_opaque_sp)
+ error.SetErrorString("error: invalid trace");
+ else if (llvm::Error err = m_opaque_sp->Stop({thread.GetThreadID()}))
+ error.SetErrorString(llvm::toString(std::move(err)).c_str());
+ return LLDB_RECORD_RESULT(error);
}
-void SBTrace::SetSP(const ProcessSP &process_sp) { m_opaque_wp = process_sp; }
-
bool SBTrace::IsValid() {
LLDB_RECORD_METHOD_NO_ARGS(bool, SBTrace, IsValid);
return this->operator bool();
}
+
SBTrace::operator bool() const {
LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTrace, operator bool);
-
- if (!m_trace_impl_sp)
- return false;
- if (!GetSP())
- return false;
- return true;
+ return (bool)m_opaque_sp;
}
namespace lldb_private {
@@ -133,13 +98,15 @@ namespace repro {
template <>
void RegisterMethods<SBTrace>(Registry &R) {
- LLDB_REGISTER_METHOD(void, SBTrace, StopTrace,
- (lldb::SBError &, lldb::tid_t));
- LLDB_REGISTER_METHOD(void, SBTrace, GetTraceConfig,
- (lldb::SBTraceOptions &, lldb::SBError &));
- LLDB_REGISTER_METHOD(lldb::user_id_t, SBTrace, GetTraceUID, ());
LLDB_REGISTER_CONSTRUCTOR(SBTrace, ());
+ LLDB_REGISTER_CONSTRUCTOR(SBTrace, (const lldb::TraceSP &));
+ LLDB_REGISTER_METHOD(SBError, SBTrace, Start, (const SBStructuredData &));
+ LLDB_REGISTER_METHOD(SBError, SBTrace, Start,
+ (const SBThread &, const SBStructuredData &));
+ LLDB_REGISTER_METHOD(SBError, SBTrace, Stop, (const SBThread &));
+ LLDB_REGISTER_METHOD(SBError, SBTrace, Stop, ());
LLDB_REGISTER_METHOD(bool, SBTrace, IsValid, ());
+ LLDB_REGISTER_METHOD(const char *, SBTrace, GetStartConfigurationHelp, ());
LLDB_REGISTER_METHOD_CONST(bool, SBTrace, operator bool, ());
}
diff --git a/lldb/source/API/SBTraceOptions.cpp b/lldb/source/API/SBTraceOptions.cpp
deleted file mode 100644
index f1f5a63edf06..000000000000
--- a/lldb/source/API/SBTraceOptions.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-//===-- SBTraceOptions.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 "lldb/API/SBTraceOptions.h"
-#include "SBReproducerPrivate.h"
-#include "lldb/API/SBError.h"
-#include "lldb/API/SBStructuredData.h"
-#include "lldb/Core/StructuredDataImpl.h"
-#include "lldb/Utility/Log.h"
-#include "lldb/Utility/TraceOptions.h"
-
-#include <memory>
-
-using namespace lldb;
-using namespace lldb_private;
-
-SBTraceOptions::SBTraceOptions() {
- LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBTraceOptions);
-
- m_traceoptions_sp = std::make_shared<TraceOptions>();
-}
-
-lldb::TraceType SBTraceOptions::getType() const {
- LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::TraceType, SBTraceOptions, getType);
-
- if (m_traceoptions_sp)
- return m_traceoptions_sp->getType();
- return lldb::TraceType::eTraceTypeNone;
-}
-
-uint64_t SBTraceOptions::getTraceBufferSize() const {
- LLDB_RECORD_METHOD_CONST_NO_ARGS(uint64_t, SBTraceOptions,
- getTraceBufferSize);
-
- if (m_traceoptions_sp)
- return m_traceoptions_sp->getTraceBufferSize();
- return 0;
-}
-
-lldb::SBStructuredData SBTraceOptions::getTraceParams(lldb::SBError &error) {
- LLDB_RECORD_METHOD(lldb::SBStructuredData, SBTraceOptions, getTraceParams,
- (lldb::SBError &), error);
-
- error.Clear();
- const lldb_private::StructuredData::DictionarySP dict_obj =
- m_traceoptions_sp->getTraceParams();
- lldb::SBStructuredData structData;
- if (dict_obj && structData.m_impl_up)
- structData.m_impl_up->SetObjectSP(dict_obj->shared_from_this());
- else
- error.SetErrorString("Empty trace params");
- return LLDB_RECORD_RESULT(structData);
-}
-
-uint64_t SBTraceOptions::getMetaDataBufferSize() const {
- LLDB_RECORD_METHOD_CONST_NO_ARGS(uint64_t, SBTraceOptions,
- getMetaDataBufferSize);
-
- if (m_traceoptions_sp)
- return m_traceoptions_sp->getTraceBufferSize();
- return 0;
-}
-
-void SBTraceOptions::setTraceParams(lldb::SBStructuredData &params) {
- LLDB_RECORD_METHOD(void, SBTraceOptions, setTraceParams,
- (lldb::SBStructuredData &), params);
-
- if (m_traceoptions_sp && params.m_impl_up) {
- StructuredData::ObjectSP obj_sp = params.m_impl_up->GetObjectSP();
- if (obj_sp && obj_sp->GetAsDictionary() != nullptr)
- m_traceoptions_sp->setTraceParams(
- std::static_pointer_cast<StructuredData::Dictionary>(obj_sp));
- }
- return;
-}
-
-void SBTraceOptions::setType(lldb::TraceType type) {
- LLDB_RECORD_METHOD(void, SBTraceOptions, setType, (lldb::TraceType), type);
-
- if (m_traceoptions_sp)
- m_traceoptions_sp->setType(type);
-}
-
-void SBTraceOptions::setTraceBufferSize(uint64_t size) {
- LLDB_RECORD_METHOD(void, SBTraceOptions, setTraceBufferSize, (uint64_t),
- size);
-
- if (m_traceoptions_sp)
- m_traceoptions_sp->setTraceBufferSize(size);
-}
-
-void SBTraceOptions::setMetaDataBufferSize(uint64_t size) {
- LLDB_RECORD_METHOD(void, SBTraceOptions, setMetaDataBufferSize, (uint64_t),
- size);
-
- if (m_traceoptions_sp)
- m_traceoptions_sp->setMetaDataBufferSize(size);
-}
-
-bool SBTraceOptions::IsValid() {
- LLDB_RECORD_METHOD_NO_ARGS(bool, SBTraceOptions, IsValid);
- return this->operator bool();
-}
-SBTraceOptions::operator bool() const {
- LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTraceOptions, operator bool);
-
- if (m_traceoptions_sp)
- return true;
- return false;
-}
-
-void SBTraceOptions::setThreadID(lldb::tid_t thread_id) {
- LLDB_RECORD_METHOD(void, SBTraceOptions, setThreadID, (lldb::tid_t),
- thread_id);
-
- if (m_traceoptions_sp)
- m_traceoptions_sp->setThreadID(thread_id);
-}
-
-lldb::tid_t SBTraceOptions::getThreadID() {
- LLDB_RECORD_METHOD_NO_ARGS(lldb::tid_t, SBTraceOptions, getThreadID);
-
- if (m_traceoptions_sp)
- return m_traceoptions_sp->getThreadID();
- return LLDB_INVALID_THREAD_ID;
-}
-
-namespace lldb_private {
-namespace repro {
-
-template <>
-void RegisterMethods<SBTraceOptions>(Registry &R) {
- LLDB_REGISTER_CONSTRUCTOR(SBTraceOptions, ());
- LLDB_REGISTER_METHOD_CONST(lldb::TraceType, SBTraceOptions, getType, ());
- LLDB_REGISTER_METHOD_CONST(uint64_t, SBTraceOptions, getTraceBufferSize,
- ());
- LLDB_REGISTER_METHOD(lldb::SBStructuredData, SBTraceOptions, getTraceParams,
- (lldb::SBError &));
- LLDB_REGISTER_METHOD_CONST(uint64_t, SBTraceOptions, getMetaDataBufferSize,
- ());
- LLDB_REGISTER_METHOD(void, SBTraceOptions, setTraceParams,
- (lldb::SBStructuredData &));
- LLDB_REGISTER_METHOD(void, SBTraceOptions, setType, (lldb::TraceType));
- LLDB_REGISTER_METHOD(void, SBTraceOptions, setTraceBufferSize, (uint64_t));
- LLDB_REGISTER_METHOD(void, SBTraceOptions, setMetaDataBufferSize,
- (uint64_t));
- LLDB_REGISTER_METHOD(bool, SBTraceOptions, IsValid, ());
- LLDB_REGISTER_METHOD_CONST(bool, SBTraceOptions, operator bool, ());
- LLDB_REGISTER_METHOD(void, SBTraceOptions, setThreadID, (lldb::tid_t));
- LLDB_REGISTER_METHOD(lldb::tid_t, SBTraceOptions, getThreadID, ());
-}
-
-}
-}
diff --git a/lldb/source/API/SBTypeCategory.cpp b/lldb/source/API/SBTypeCategory.cpp
index 9ce1a57ec4f7..e7432959b260 100644
--- a/lldb/source/API/SBTypeCategory.cpp
+++ b/lldb/source/API/SBTypeCategory.cpp
@@ -363,9 +363,7 @@ bool SBTypeCategory::AddTypeFormat(SBTypeNameSpecifier type_name,
if (type_name.IsRegex())
m_opaque_sp->GetRegexTypeFormatsContainer()->Add(
- RegularExpression(
- llvm::StringRef::withNullAsEmpty(type_name.GetName())),
- format.GetSP());
+ RegularExpression(type_name.GetName()), format.GetSP());
else
m_opaque_sp->GetTypeFormatsContainer()->Add(
ConstString(type_name.GetName()), format.GetSP());
@@ -442,9 +440,7 @@ bool SBTypeCategory::AddTypeSummary(SBTypeNameSpecifier type_name,
if (type_name.IsRegex())
m_opaque_sp->GetRegexTypeSummariesContainer()->Add(
- RegularExpression(
- llvm::StringRef::withNullAsEmpty(type_name.GetName())),
- summary.GetSP());
+ RegularExpression(type_name.GetName()), summary.GetSP());
else
m_opaque_sp->GetTypeSummariesContainer()->Add(
ConstString(type_name.GetName()), summary.GetSP());
@@ -487,9 +483,7 @@ bool SBTypeCategory::AddTypeFilter(SBTypeNameSpecifier type_name,
if (type_name.IsRegex())
m_opaque_sp->GetRegexTypeFiltersContainer()->Add(
- RegularExpression(
- llvm::StringRef::withNullAsEmpty(type_name.GetName())),
- filter.GetSP());
+ RegularExpression(type_name.GetName()), filter.GetSP());
else
m_opaque_sp->GetTypeFiltersContainer()->Add(
ConstString(type_name.GetName()), filter.GetSP());
@@ -566,9 +560,7 @@ bool SBTypeCategory::AddTypeSynthetic(SBTypeNameSpecifier type_name,
if (type_name.IsRegex())
m_opaque_sp->GetRegexTypeSyntheticsContainer()->Add(
- RegularExpression(
- llvm::StringRef::withNullAsEmpty(type_name.GetName())),
- synth.GetSP());
+ RegularExpression(type_name.GetName()), synth.GetSP());
else
m_opaque_sp->GetTypeSyntheticsContainer()->Add(
ConstString(type_name.GetName()), synth.GetSP());
diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp
index 0a95cf41263d..9faee102c5e3 100644
--- a/lldb/source/API/SBValue.cpp
+++ b/lldb/source/API/SBValue.cpp
@@ -17,6 +17,7 @@
#include "lldb/API/SBTypeSynthetic.h"
#include "lldb/Breakpoint/Watchpoint.h"
+#include "lldb/Core/Declaration.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamFile.h"
@@ -25,7 +26,6 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Symbol/Block.h"
-#include "lldb/Symbol/Declaration.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/Variable.h"
diff --git a/lldb/source/API/SBVariablesOptions.cpp b/lldb/source/API/SBVariablesOptions.cpp
index 4ef16364e628..1af582a0c3d7 100644
--- a/lldb/source/API/SBVariablesOptions.cpp
+++ b/lldb/source/API/SBVariablesOptions.cpp
@@ -21,9 +21,7 @@ public:
VariablesOptionsImpl()
: m_include_arguments(false), m_include_locals(false),
m_include_statics(false), m_in_scope_only(false),
- m_include_runtime_support_values(false),
- m_include_recognized_arguments(eLazyBoolCalculate),
- m_use_dynamic(lldb::eNoDynamicValues) {}
+ m_include_runtime_support_values(false) {}
VariablesOptionsImpl(const VariablesOptionsImpl &) = default;
@@ -75,8 +73,9 @@ private:
bool m_include_statics : 1;
bool m_in_scope_only : 1;
bool m_include_runtime_support_values : 1;
- LazyBool m_include_recognized_arguments; // can be overridden with a setting
- lldb::DynamicValueType m_use_dynamic;
+ LazyBool m_include_recognized_arguments =
+ eLazyBoolCalculate; // can be overridden with a setting
+ lldb::DynamicValueType m_use_dynamic = lldb::eNoDynamicValues;
};
SBVariablesOptions::SBVariablesOptions()
diff --git a/lldb/source/API/SystemInitializerFull.cpp b/lldb/source/API/SystemInitializerFull.cpp
index 0530f94580b3..cc6cb6925bd0 100644
--- a/lldb/source/API/SystemInitializerFull.cpp
+++ b/lldb/source/API/SystemInitializerFull.cpp
@@ -17,6 +17,7 @@
#include "lldb/Target/ProcessTrace.h"
#include "lldb/Utility/Reproducer.h"
#include "lldb/Utility/Timer.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/TargetSelect.h"
#pragma clang diagnostic push
@@ -29,9 +30,22 @@
#define LLDB_PLUGIN(p) LLDB_PLUGIN_DECLARE(p)
#include "Plugins/Plugins.def"
+#if LLDB_ENABLE_PYTHON
+#include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h"
+
+constexpr lldb_private::HostInfo::SharedLibraryDirectoryHelper
+ *g_shlib_dir_helper =
+ lldb_private::ScriptInterpreterPython::SharedLibraryDirectoryHelper;
+
+#else
+constexpr lldb_private::HostInfo::SharedLibraryDirectoryHelper
+ *g_shlib_dir_helper = 0;
+#endif
+
using namespace lldb_private;
-SystemInitializerFull::SystemInitializerFull() = default;
+SystemInitializerFull::SystemInitializerFull()
+ : SystemInitializerCommon(g_shlib_dir_helper) {}
SystemInitializerFull::~SystemInitializerFull() = default;
llvm::Error SystemInitializerFull::Initialize() {
@@ -51,6 +65,13 @@ llvm::Error SystemInitializerFull::Initialize() {
llvm::InitializeAllAsmPrinters();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllDisassemblers();
+ // Initialize the command line parser in LLVM. This usually isn't necessary
+ // as we aren't dealing with command line options here, but otherwise some
+ // other code in Clang/LLVM might be tempted to call this function from a
+ // different thread later on which won't work (as the function isn't
+ // thread-safe).
+ const char *arg0 = "lldb";
+ llvm::cl::ParseCommandLineOptions(1, &arg0);
#define LLDB_PLUGIN(p) LLDB_PLUGIN_INITIALIZE(p);
#include "Plugins/Plugins.def"
diff --git a/lldb/source/Breakpoint/Breakpoint.cpp b/lldb/source/Breakpoint/Breakpoint.cpp
index d7bca308ca99..8d5d5a31337c 100644
--- a/lldb/source/Breakpoint/Breakpoint.cpp
+++ b/lldb/source/Breakpoint/Breakpoint.cpp
@@ -49,17 +49,16 @@ Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp,
BreakpointResolverSP &resolver_sp, bool hardware,
bool resolve_indirect_symbols)
: m_being_created(true), m_hardware(hardware), m_target(target),
- m_filter_sp(filter_sp), m_resolver_sp(resolver_sp),
- m_options_up(new BreakpointOptions(true)), m_locations(*this),
- m_resolve_indirect_symbols(resolve_indirect_symbols), m_hit_counter() {
+ m_filter_sp(filter_sp), m_resolver_sp(resolver_sp), m_options(true),
+ m_locations(*this), m_resolve_indirect_symbols(resolve_indirect_symbols),
+ m_hit_counter() {
m_being_created = false;
}
Breakpoint::Breakpoint(Target &new_target, const Breakpoint &source_bp)
: m_being_created(true), m_hardware(source_bp.m_hardware),
m_target(new_target), m_name_list(source_bp.m_name_list),
- m_options_up(new BreakpointOptions(*source_bp.m_options_up)),
- m_locations(*this),
+ m_options(source_bp.m_options), m_locations(*this),
m_resolve_indirect_symbols(source_bp.m_resolve_indirect_symbols),
m_hit_counter() {}
@@ -116,7 +115,7 @@ StructuredData::ObjectSP Breakpoint::SerializeToStructuredData() {
filter_dict_sp);
StructuredData::ObjectSP options_dict_sp(
- m_options_up->SerializeToStructuredData());
+ m_options.SerializeToStructuredData());
if (!options_dict_sp)
return StructuredData::ObjectSP();
@@ -201,7 +200,7 @@ lldb::BreakpointSP Breakpoint::CreateFromStructuredData(
hardware, true);
if (result_sp && options_up) {
- result_sp->m_options_up = std::move(options_up);
+ result_sp->m_options = *options_up;
}
StructuredData::Array *names_array;
@@ -293,10 +292,10 @@ void Breakpoint::RemoveInvalidLocations(const ArchSpec &arch) {
// individual settings.
void Breakpoint::SetEnabled(bool enable) {
- if (enable == m_options_up->IsEnabled())
+ if (enable == m_options.IsEnabled())
return;
- m_options_up->SetEnabled(enable);
+ m_options.SetEnabled(enable);
if (enable)
m_locations.ResolveAllBreakpointSites();
else
@@ -306,123 +305,107 @@ void Breakpoint::SetEnabled(bool enable) {
: eBreakpointEventTypeDisabled);
}
-bool Breakpoint::IsEnabled() { return m_options_up->IsEnabled(); }
+bool Breakpoint::IsEnabled() { return m_options.IsEnabled(); }
void Breakpoint::SetIgnoreCount(uint32_t n) {
- if (m_options_up->GetIgnoreCount() == n)
+ if (m_options.GetIgnoreCount() == n)
return;
- m_options_up->SetIgnoreCount(n);
+ m_options.SetIgnoreCount(n);
SendBreakpointChangedEvent(eBreakpointEventTypeIgnoreChanged);
}
void Breakpoint::DecrementIgnoreCount() {
- uint32_t ignore = m_options_up->GetIgnoreCount();
+ uint32_t ignore = m_options.GetIgnoreCount();
if (ignore != 0)
- m_options_up->SetIgnoreCount(ignore - 1);
+ m_options.SetIgnoreCount(ignore - 1);
}
uint32_t Breakpoint::GetIgnoreCount() const {
- return m_options_up->GetIgnoreCount();
-}
-
-bool Breakpoint::IgnoreCountShouldStop() {
- uint32_t ignore = GetIgnoreCount();
- if (ignore != 0) {
- // When we get here we know the location that caused the stop doesn't have
- // an ignore count, since by contract we call it first... So we don't have
- // to find & decrement it, we only have to decrement our own ignore count.
- DecrementIgnoreCount();
- return false;
- } else
- return true;
+ return m_options.GetIgnoreCount();
}
uint32_t Breakpoint::GetHitCount() const { return m_hit_counter.GetValue(); }
-bool Breakpoint::IsOneShot() const { return m_options_up->IsOneShot(); }
+bool Breakpoint::IsOneShot() const { return m_options.IsOneShot(); }
-void Breakpoint::SetOneShot(bool one_shot) {
- m_options_up->SetOneShot(one_shot);
-}
+void Breakpoint::SetOneShot(bool one_shot) { m_options.SetOneShot(one_shot); }
-bool Breakpoint::IsAutoContinue() const {
- return m_options_up->IsAutoContinue();
-}
+bool Breakpoint::IsAutoContinue() const { return m_options.IsAutoContinue(); }
void Breakpoint::SetAutoContinue(bool auto_continue) {
- m_options_up->SetAutoContinue(auto_continue);
+ m_options.SetAutoContinue(auto_continue);
}
void Breakpoint::SetThreadID(lldb::tid_t thread_id) {
- if (m_options_up->GetThreadSpec()->GetTID() == thread_id)
+ if (m_options.GetThreadSpec()->GetTID() == thread_id)
return;
- m_options_up->GetThreadSpec()->SetTID(thread_id);
+ m_options.GetThreadSpec()->SetTID(thread_id);
SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);
}
lldb::tid_t Breakpoint::GetThreadID() const {
- if (m_options_up->GetThreadSpecNoCreate() == nullptr)
+ if (m_options.GetThreadSpecNoCreate() == nullptr)
return LLDB_INVALID_THREAD_ID;
else
- return m_options_up->GetThreadSpecNoCreate()->GetTID();
+ return m_options.GetThreadSpecNoCreate()->GetTID();
}
void Breakpoint::SetThreadIndex(uint32_t index) {
- if (m_options_up->GetThreadSpec()->GetIndex() == index)
+ if (m_options.GetThreadSpec()->GetIndex() == index)
return;
- m_options_up->GetThreadSpec()->SetIndex(index);
+ m_options.GetThreadSpec()->SetIndex(index);
SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);
}
uint32_t Breakpoint::GetThreadIndex() const {
- if (m_options_up->GetThreadSpecNoCreate() == nullptr)
+ if (m_options.GetThreadSpecNoCreate() == nullptr)
return 0;
else
- return m_options_up->GetThreadSpecNoCreate()->GetIndex();
+ return m_options.GetThreadSpecNoCreate()->GetIndex();
}
void Breakpoint::SetThreadName(const char *thread_name) {
- if (m_options_up->GetThreadSpec()->GetName() != nullptr &&
- ::strcmp(m_options_up->GetThreadSpec()->GetName(), thread_name) == 0)
+ if (m_options.GetThreadSpec()->GetName() != nullptr &&
+ ::strcmp(m_options.GetThreadSpec()->GetName(), thread_name) == 0)
return;
- m_options_up->GetThreadSpec()->SetName(thread_name);
+ m_options.GetThreadSpec()->SetName(thread_name);
SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);
}
const char *Breakpoint::GetThreadName() const {
- if (m_options_up->GetThreadSpecNoCreate() == nullptr)
+ if (m_options.GetThreadSpecNoCreate() == nullptr)
return nullptr;
else
- return m_options_up->GetThreadSpecNoCreate()->GetName();
+ return m_options.GetThreadSpecNoCreate()->GetName();
}
void Breakpoint::SetQueueName(const char *queue_name) {
- if (m_options_up->GetThreadSpec()->GetQueueName() != nullptr &&
- ::strcmp(m_options_up->GetThreadSpec()->GetQueueName(), queue_name) == 0)
+ if (m_options.GetThreadSpec()->GetQueueName() != nullptr &&
+ ::strcmp(m_options.GetThreadSpec()->GetQueueName(), queue_name) == 0)
return;
- m_options_up->GetThreadSpec()->SetQueueName(queue_name);
+ m_options.GetThreadSpec()->SetQueueName(queue_name);
SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);
}
const char *Breakpoint::GetQueueName() const {
- if (m_options_up->GetThreadSpecNoCreate() == nullptr)
+ if (m_options.GetThreadSpecNoCreate() == nullptr)
return nullptr;
else
- return m_options_up->GetThreadSpecNoCreate()->GetQueueName();
+ return m_options.GetThreadSpecNoCreate()->GetQueueName();
}
void Breakpoint::SetCondition(const char *condition) {
- m_options_up->SetCondition(condition);
+ m_options.SetCondition(condition);
SendBreakpointChangedEvent(eBreakpointEventTypeConditionChanged);
}
const char *Breakpoint::GetConditionText() const {
- return m_options_up->GetConditionText();
+ return m_options.GetConditionText();
}
// This function is used when "baton" doesn't need to be freed
@@ -430,8 +413,8 @@ void Breakpoint::SetCallback(BreakpointHitCallback callback, void *baton,
bool is_synchronous) {
// The default "Baton" class will keep a copy of "baton" and won't free or
// delete it when it goes goes out of scope.
- m_options_up->SetCallback(callback, std::make_shared<UntypedBaton>(baton),
- is_synchronous);
+ m_options.SetCallback(callback, std::make_shared<UntypedBaton>(baton),
+ is_synchronous);
SendBreakpointChangedEvent(eBreakpointEventTypeCommandChanged);
}
@@ -441,21 +424,19 @@ void Breakpoint::SetCallback(BreakpointHitCallback callback, void *baton,
void Breakpoint::SetCallback(BreakpointHitCallback callback,
const BatonSP &callback_baton_sp,
bool is_synchronous) {
- m_options_up->SetCallback(callback, callback_baton_sp, is_synchronous);
+ m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
}
-void Breakpoint::ClearCallback() { m_options_up->ClearCallback(); }
+void Breakpoint::ClearCallback() { m_options.ClearCallback(); }
bool Breakpoint::InvokeCallback(StoppointCallbackContext *context,
break_id_t bp_loc_id) {
- return m_options_up->InvokeCallback(context, GetID(), bp_loc_id);
+ return m_options.InvokeCallback(context, GetID(), bp_loc_id);
}
-BreakpointOptions *Breakpoint::GetOptions() { return m_options_up.get(); }
+BreakpointOptions &Breakpoint::GetOptions() { return m_options; }
-const BreakpointOptions *Breakpoint::GetOptions() const {
- return m_options_up.get();
-}
+const BreakpointOptions &Breakpoint::GetOptions() const { return m_options; }
void Breakpoint::ResolveBreakpoint() {
if (m_resolver_sp)
@@ -902,7 +883,7 @@ void Breakpoint::GetDescription(Stream *s, lldb::DescriptionLevel level,
s->Printf(", locations = 0 (pending)");
}
- GetOptions()->GetDescription(s, level);
+ m_options.GetDescription(s, level);
if (m_precondition_sp)
m_precondition_sp->GetDescription(*s, level);
@@ -944,7 +925,7 @@ void Breakpoint::GetDescription(Stream *s, lldb::DescriptionLevel level,
Dump(s);
s->EOL();
// s->Indent();
- GetOptions()->GetDescription(s, level);
+ m_options.GetDescription(s, level);
break;
default:
@@ -980,9 +961,12 @@ bool Breakpoint::GetMatchingFileLine(ConstString filename,
if (m_resolver_sp) {
BreakpointResolverFileLine *resolverFileLine =
dyn_cast<BreakpointResolverFileLine>(m_resolver_sp.get());
+
+ // TODO: Handle SourceLocationSpec column information
if (resolverFileLine &&
- resolverFileLine->m_file_spec.GetFilename() == filename &&
- resolverFileLine->m_line_number == line_number) {
+ resolverFileLine->m_location_spec.GetFileSpec().GetFilename() ==
+ filename &&
+ resolverFileLine->m_location_spec.GetLine() == line_number) {
return true;
}
}
diff --git a/lldb/source/Breakpoint/BreakpointID.cpp b/lldb/source/Breakpoint/BreakpointID.cpp
index a37abcfa52ab..f20572144068 100644
--- a/lldb/source/Breakpoint/BreakpointID.cpp
+++ b/lldb/source/Breakpoint/BreakpointID.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <stdio.h>
+#include <cstdio>
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointID.h"
diff --git a/lldb/source/Breakpoint/BreakpointIDList.cpp b/lldb/source/Breakpoint/BreakpointIDList.cpp
index e6a5dceeb93b..172674dc2dd2 100644
--- a/lldb/source/Breakpoint/BreakpointIDList.cpp
+++ b/lldb/source/Breakpoint/BreakpointIDList.cpp
@@ -141,7 +141,6 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target,
if (!error.Success()) {
new_args.Clear();
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return;
} else
names_found.insert(std::string(current_arg));
@@ -170,7 +169,6 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target,
new_args.Clear();
result.AppendErrorWithFormat("'%d' is not a valid breakpoint ID.\n",
bp_id->GetBreakpointID());
- result.SetStatus(eReturnStatusFailed);
return;
}
const size_t num_locations = breakpoint_sp->GetNumLocations();
@@ -199,7 +197,6 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target,
new_args.Clear();
result.AppendErrorWithFormat("'%s' is not a valid breakpoint ID.\n",
range_from.str().c_str());
- result.SetStatus(eReturnStatusFailed);
return;
}
@@ -208,7 +205,6 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target,
new_args.Clear();
result.AppendErrorWithFormat("'%s' is not a valid breakpoint ID.\n",
range_to.str().c_str());
- result.SetStatus(eReturnStatusFailed);
return;
}
break_id_t start_bp_id = start_bp->GetBreakpointID();
@@ -224,7 +220,6 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target,
"both ends of range must specify"
" a breakpoint location, or neither can "
"specify a breakpoint location.");
- result.SetStatus(eReturnStatusFailed);
return;
}
@@ -247,7 +242,6 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target,
" must be within the same major breakpoint; you specified two"
" different major breakpoints, %d and %d.\n",
start_bp_id, end_bp_id);
- result.SetStatus(eReturnStatusFailed);
return;
}
}
diff --git a/lldb/source/Breakpoint/BreakpointList.cpp b/lldb/source/Breakpoint/BreakpointList.cpp
index a962703b9518..a00f6bed6181 100644
--- a/lldb/source/Breakpoint/BreakpointList.cpp
+++ b/lldb/source/Breakpoint/BreakpointList.cpp
@@ -26,7 +26,7 @@ BreakpointList::BreakpointList(bool is_internal)
: m_mutex(), m_breakpoints(), m_next_break_id(0),
m_is_internal(is_internal) {}
-BreakpointList::~BreakpointList() {}
+BreakpointList::~BreakpointList() = default;
break_id_t BreakpointList::Add(BreakpointSP &bp_sp, bool notify) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
diff --git a/lldb/source/Breakpoint/BreakpointLocation.cpp b/lldb/source/Breakpoint/BreakpointLocation.cpp
index d3d6ea08bdb3..0c4d3e052c53 100644
--- a/lldb/source/Breakpoint/BreakpointLocation.cpp
+++ b/lldb/source/Breakpoint/BreakpointLocation.cpp
@@ -52,11 +52,10 @@ lldb::addr_t BreakpointLocation::GetLoadAddress() const {
return m_address.GetOpcodeLoadAddress(&m_owner.GetTarget());
}
-const BreakpointOptions *
-BreakpointLocation::GetOptionsSpecifyingKind(BreakpointOptions::OptionKind kind)
-const {
+const BreakpointOptions &BreakpointLocation::GetOptionsSpecifyingKind(
+ BreakpointOptions::OptionKind kind) const {
if (m_options_up && m_options_up->IsOptionSet(kind))
- return m_options_up.get();
+ return *m_options_up;
else
return m_owner.GetOptions();
}
@@ -77,7 +76,7 @@ bool BreakpointLocation::IsEnabled() const {
}
void BreakpointLocation::SetEnabled(bool enabled) {
- GetLocationOptions()->SetEnabled(enabled);
+ GetLocationOptions().SetEnabled(enabled);
if (enabled) {
ResolveBreakpointSite();
} else {
@@ -96,13 +95,13 @@ bool BreakpointLocation::IsAutoContinue() const {
}
void BreakpointLocation::SetAutoContinue(bool auto_continue) {
- GetLocationOptions()->SetAutoContinue(auto_continue);
+ GetLocationOptions().SetAutoContinue(auto_continue);
SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged);
}
void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {
if (thread_id != LLDB_INVALID_THREAD_ID)
- GetLocationOptions()->SetThreadID(thread_id);
+ GetLocationOptions().SetThreadID(thread_id);
else {
// If we're resetting this to an invalid thread id, then don't make an
// options pointer just to do that.
@@ -113,9 +112,9 @@ void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {
}
lldb::tid_t BreakpointLocation::GetThreadID() {
- const ThreadSpec *thread_spec =
+ const ThreadSpec *thread_spec =
GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
- ->GetThreadSpecNoCreate();
+ .GetThreadSpecNoCreate();
if (thread_spec)
return thread_spec->GetTID();
else
@@ -124,7 +123,7 @@ lldb::tid_t BreakpointLocation::GetThreadID() {
void BreakpointLocation::SetThreadIndex(uint32_t index) {
if (index != 0)
- GetLocationOptions()->GetThreadSpec()->SetIndex(index);
+ GetLocationOptions().GetThreadSpec()->SetIndex(index);
else {
// If we're resetting this to an invalid thread id, then don't make an
// options pointer just to do that.
@@ -135,9 +134,9 @@ void BreakpointLocation::SetThreadIndex(uint32_t index) {
}
uint32_t BreakpointLocation::GetThreadIndex() const {
- const ThreadSpec *thread_spec =
+ const ThreadSpec *thread_spec =
GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
- ->GetThreadSpecNoCreate();
+ .GetThreadSpecNoCreate();
if (thread_spec)
return thread_spec->GetIndex();
else
@@ -146,7 +145,7 @@ uint32_t BreakpointLocation::GetThreadIndex() const {
void BreakpointLocation::SetThreadName(const char *thread_name) {
if (thread_name != nullptr)
- GetLocationOptions()->GetThreadSpec()->SetName(thread_name);
+ GetLocationOptions().GetThreadSpec()->SetName(thread_name);
else {
// If we're resetting this to an invalid thread id, then don't make an
// options pointer just to do that.
@@ -157,9 +156,9 @@ void BreakpointLocation::SetThreadName(const char *thread_name) {
}
const char *BreakpointLocation::GetThreadName() const {
- const ThreadSpec *thread_spec =
+ const ThreadSpec *thread_spec =
GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
- ->GetThreadSpecNoCreate();
+ .GetThreadSpecNoCreate();
if (thread_spec)
return thread_spec->GetName();
else
@@ -168,7 +167,7 @@ const char *BreakpointLocation::GetThreadName() const {
void BreakpointLocation::SetQueueName(const char *queue_name) {
if (queue_name != nullptr)
- GetLocationOptions()->GetThreadSpec()->SetQueueName(queue_name);
+ GetLocationOptions().GetThreadSpec()->SetQueueName(queue_name);
else {
// If we're resetting this to an invalid thread id, then don't make an
// options pointer just to do that.
@@ -179,9 +178,9 @@ void BreakpointLocation::SetQueueName(const char *queue_name) {
}
const char *BreakpointLocation::GetQueueName() const {
- const ThreadSpec *thread_spec =
+ const ThreadSpec *thread_spec =
GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
- ->GetThreadSpecNoCreate();
+ .GetThreadSpecNoCreate();
if (thread_spec)
return thread_spec->GetQueueName();
else
@@ -195,11 +194,18 @@ bool BreakpointLocation::InvokeCallback(StoppointCallbackContext *context) {
return m_owner.InvokeCallback(context, GetID());
}
+bool BreakpointLocation::IsCallbackSynchronous() {
+ if (m_options_up != nullptr && m_options_up->HasCallback())
+ return m_options_up->IsCallbackSynchronous();
+ else
+ return m_owner.GetOptions().IsCallbackSynchronous();
+}
+
void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
void *baton, bool is_synchronous) {
// The default "Baton" class will keep a copy of "baton" and won't free or
// delete it when it goes goes out of scope.
- GetLocationOptions()->SetCallback(
+ GetLocationOptions().SetCallback(
callback, std::make_shared<UntypedBaton>(baton), is_synchronous);
SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
}
@@ -207,22 +213,22 @@ void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
const BatonSP &baton_sp,
bool is_synchronous) {
- GetLocationOptions()->SetCallback(callback, baton_sp, is_synchronous);
+ GetLocationOptions().SetCallback(callback, baton_sp, is_synchronous);
SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
}
void BreakpointLocation::ClearCallback() {
- GetLocationOptions()->ClearCallback();
+ GetLocationOptions().ClearCallback();
}
void BreakpointLocation::SetCondition(const char *condition) {
- GetLocationOptions()->SetCondition(condition);
+ GetLocationOptions().SetCondition(condition);
SendBreakpointLocationChangedEvent(eBreakpointEventTypeConditionChanged);
}
const char *BreakpointLocation::GetConditionText(size_t *hash) const {
return GetOptionsSpecifyingKind(BreakpointOptions::eCondition)
- ->GetConditionText(hash);
+ .GetConditionText(hash);
}
bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
@@ -333,11 +339,11 @@ bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
uint32_t BreakpointLocation::GetIgnoreCount() const {
return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
- ->GetIgnoreCount();
+ .GetIgnoreCount();
}
void BreakpointLocation::SetIgnoreCount(uint32_t n) {
- GetLocationOptions()->SetIgnoreCount(n);
+ GetLocationOptions().SetIgnoreCount(n);
SendBreakpointLocationChangedEvent(eBreakpointEventTypeIgnoreChanged);
}
@@ -350,33 +356,34 @@ void BreakpointLocation::DecrementIgnoreCount() {
}
bool BreakpointLocation::IgnoreCountShouldStop() {
- if (m_options_up != nullptr) {
- uint32_t loc_ignore = m_options_up->GetIgnoreCount();
- if (loc_ignore != 0) {
- m_owner.DecrementIgnoreCount();
- DecrementIgnoreCount(); // Have to decrement our owners' ignore count,
- // since it won't get a
- // chance to.
- return false;
- }
+ uint32_t owner_ignore = GetBreakpoint().GetIgnoreCount();
+ uint32_t loc_ignore = 0;
+ if (m_options_up != nullptr)
+ loc_ignore = m_options_up->GetIgnoreCount();
+
+ if (loc_ignore != 0 || owner_ignore != 0) {
+ m_owner.DecrementIgnoreCount();
+ DecrementIgnoreCount(); // Have to decrement our owners' ignore count,
+ // since it won't get a chance to.
+ return false;
}
return true;
}
-BreakpointOptions *BreakpointLocation::GetLocationOptions() {
+BreakpointOptions &BreakpointLocation::GetLocationOptions() {
// If we make the copy we don't copy the callbacks because that is
// potentially expensive and we don't want to do that for the simple case
// where someone is just disabling the location.
if (m_options_up == nullptr)
m_options_up = std::make_unique<BreakpointOptions>(false);
- return m_options_up.get();
+ return *m_options_up;
}
-bool BreakpointLocation::ValidForThisThread(Thread *thread) {
- return thread
- ->MatchesSpec(GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
- ->GetThreadSpecNoCreate());
+bool BreakpointLocation::ValidForThisThread(Thread &thread) {
+ return thread.MatchesSpec(
+ GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
+ .GetThreadSpecNoCreate());
}
// RETURNS - true if we should stop at this breakpoint, false if we
@@ -393,12 +400,6 @@ bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context) {
if (!IsEnabled())
return false;
- if (!IgnoreCountShouldStop())
- return false;
-
- if (!m_owner.IgnoreCountShouldStop())
- return false;
-
// We only run synchronous callbacks in ShouldStop:
context->is_synchronous = true;
should_stop = InvokeCallback(context);
@@ -629,7 +630,8 @@ void BreakpointLocation::Dump(Stream *s) const {
m_bp_site_sp->GetHardwareIndex() : LLDB_INVALID_INDEX32;
lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
- ->GetThreadSpecNoCreate()->GetTID();
+ .GetThreadSpecNoCreate()
+ ->GetTID();
s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64
" load addr = 0x%8.8" PRIx64 " state = %s type = %s breakpoint "
"hw_index = %i hit_count = %-4u ignore_count = %-4u",
@@ -638,9 +640,10 @@ void BreakpointLocation::Dump(Stream *s) const {
(m_options_up ? m_options_up->IsEnabled() : m_owner.IsEnabled())
? "enabled "
: "disabled",
- is_hardware ? "hardware" : "software", hardware_index, GetHitCount(),
+ is_hardware ? "hardware" : "software", hardware_index,
+ GetHitCount(),
GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
- ->GetIgnoreCount());
+ .GetIgnoreCount());
}
void BreakpointLocation::SendBreakpointLocationChangedEvent(
diff --git a/lldb/source/Breakpoint/BreakpointLocationCollection.cpp b/lldb/source/Breakpoint/BreakpointLocationCollection.cpp
index 1eb13cb12ba3..6c55629b5aad 100644
--- a/lldb/source/Breakpoint/BreakpointLocationCollection.cpp
+++ b/lldb/source/Breakpoint/BreakpointLocationCollection.cpp
@@ -21,7 +21,7 @@ BreakpointLocationCollection::BreakpointLocationCollection()
: m_break_loc_collection(), m_collection_mutex() {}
// Destructor
-BreakpointLocationCollection::~BreakpointLocationCollection() {}
+BreakpointLocationCollection::~BreakpointLocationCollection() = default;
void BreakpointLocationCollection::Add(const BreakpointLocationSP &bp_loc) {
std::lock_guard<std::mutex> guard(m_collection_mutex);
@@ -134,7 +134,7 @@ bool BreakpointLocationCollection::ShouldStop(
return shouldStop;
}
-bool BreakpointLocationCollection::ValidForThisThread(Thread *thread) {
+bool BreakpointLocationCollection::ValidForThisThread(Thread &thread) {
std::lock_guard<std::mutex> guard(m_collection_mutex);
collection::iterator pos, begin = m_break_loc_collection.begin(),
end = m_break_loc_collection.end();
diff --git a/lldb/source/Breakpoint/BreakpointName.cpp b/lldb/source/Breakpoint/BreakpointName.cpp
index 37903a002363..cb513fb436d6 100644
--- a/lldb/source/Breakpoint/BreakpointName.cpp
+++ b/lldb/source/Breakpoint/BreakpointName.cpp
@@ -81,6 +81,6 @@ bool BreakpointName::GetDescription(Stream *s, lldb::DescriptionLevel level) {
void BreakpointName::ConfigureBreakpoint(lldb::BreakpointSP bp_sp)
{
- bp_sp->GetOptions()->CopyOverSetOptions(GetOptions());
- bp_sp->GetPermissions().MergeInto(GetPermissions());
+ bp_sp->GetOptions().CopyOverSetOptions(GetOptions());
+ bp_sp->GetPermissions().MergeInto(GetPermissions());
}
diff --git a/lldb/source/Breakpoint/BreakpointOptions.cpp b/lldb/source/Breakpoint/BreakpointOptions.cpp
index f6bb7633d0a9..86a7c483df83 100644
--- a/lldb/source/Breakpoint/BreakpointOptions.cpp
+++ b/lldb/source/Breakpoint/BreakpointOptions.cpp
@@ -332,7 +332,7 @@ std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData(
}
Status script_error;
script_error =
- interp->SetBreakpointCommandCallback(bp_options.get(), cmd_data_up);
+ interp->SetBreakpointCommandCallback(*bp_options, cmd_data_up);
if (script_error.Fail()) {
error.SetErrorStringWithFormat("Error generating script callback: %s.",
error.AsCString());
@@ -453,8 +453,6 @@ bool BreakpointOptions::InvokeCallback(StoppointCallbackContext *context,
: nullptr,
context, break_id, break_loc_id);
} else if (IsCallbackSynchronous()) {
- // If a synchronous callback is called at async time, it should not say
- // to stop.
return false;
}
}
@@ -649,7 +647,7 @@ bool BreakpointOptions::BreakpointOptionsCallbackFunction(
options.SetPrintErrors(true);
options.SetAddToHistory(false);
- debugger.GetCommandInterpreter().HandleCommands(commands, &exe_ctx,
+ debugger.GetCommandInterpreter().HandleCommands(commands, exe_ctx,
options, result);
result.GetImmediateOutputStream()->Flush();
result.GetImmediateErrorStream()->Flush();
diff --git a/lldb/source/Breakpoint/BreakpointResolver.cpp b/lldb/source/Breakpoint/BreakpointResolver.cpp
index cfd073367b00..d3d57a282d09 100644
--- a/lldb/source/Breakpoint/BreakpointResolver.cpp
+++ b/lldb/source/Breakpoint/BreakpointResolver.cpp
@@ -65,7 +65,7 @@ BreakpointResolver::BreakpointResolver(const BreakpointSP &bkpt,
lldb::addr_t offset)
: m_breakpoint(bkpt), m_offset(offset), SubclassID(resolverTy) {}
-BreakpointResolver::~BreakpointResolver() {}
+BreakpointResolver::~BreakpointResolver() = default;
BreakpointResolverSP BreakpointResolver::CreateFromStructuredData(
const StructuredData::Dictionary &resolver_dict, Status &error) {
@@ -180,29 +180,29 @@ void BreakpointResolver::ResolveBreakpoint(SearchFilter &filter) {
namespace {
struct SourceLoc {
uint32_t line = UINT32_MAX;
- uint32_t column;
- SourceLoc(uint32_t l, uint32_t c) : line(l), column(c ? c : UINT32_MAX) {}
+ uint16_t column;
+ SourceLoc(uint32_t l, llvm::Optional<uint16_t> c)
+ : line(l), column(c ? *c : LLDB_INVALID_COLUMN_NUMBER) {}
SourceLoc(const SymbolContext &sc)
: line(sc.line_entry.line),
- column(sc.line_entry.column ? sc.line_entry.column : UINT32_MAX) {}
+ column(sc.line_entry.column ? sc.line_entry.column
+ : LLDB_INVALID_COLUMN_NUMBER) {}
};
-bool operator<(const SourceLoc a, const SourceLoc b) {
- if (a.line < b.line)
+bool operator<(const SourceLoc lhs, const SourceLoc rhs) {
+ if (lhs.line < rhs.line)
return true;
- if (a.line > b.line)
+ if (lhs.line > rhs.line)
return false;
- uint32_t a_col = a.column ? a.column : UINT32_MAX;
- uint32_t b_col = b.column ? b.column : UINT32_MAX;
- return a_col < b_col;
+ // uint32_t a_col = lhs.column ? lhs.column : LLDB_INVALID_COLUMN_NUMBER;
+ // uint32_t b_col = rhs.column ? rhs.column : LLDB_INVALID_COLUMN_NUMBER;
+ return lhs.column < rhs.column;
}
} // namespace
-void BreakpointResolver::SetSCMatchesByLine(SearchFilter &filter,
- SymbolContextList &sc_list,
- bool skip_prologue,
- llvm::StringRef log_ident,
- uint32_t line, uint32_t column) {
+void BreakpointResolver::SetSCMatchesByLine(
+ SearchFilter &filter, SymbolContextList &sc_list, bool skip_prologue,
+ llvm::StringRef log_ident, uint32_t line, llvm::Optional<uint16_t> column) {
llvm::SmallVector<SymbolContext, 16> all_scs;
for (uint32_t i = 0; i < sc_list.GetSize(); ++i)
all_scs.push_back(sc_list[i]);
@@ -228,13 +228,13 @@ void BreakpointResolver::SetSCMatchesByLine(SearchFilter &filter,
if (column) {
// If a column was requested, do a more precise match and only
- // return the first location that comes after or at the
+ // return the first location that comes before or at the
// requested location.
- SourceLoc requested(line, column);
+ SourceLoc requested(line, *column);
// First, filter out all entries left of the requested column.
worklist_end = std::remove_if(
worklist_begin, worklist_end,
- [&](const SymbolContext &sc) { return SourceLoc(sc) < requested; });
+ [&](const SymbolContext &sc) { return requested < SourceLoc(sc); });
// Sort the remaining entries by (line, column).
llvm::sort(worklist_begin, worklist_end,
[](const SymbolContext &a, const SymbolContext &b) {
diff --git a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp
index 5ca4ef5834e0..1d1ac2e90bdc 100644
--- a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp
+++ b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp
@@ -20,20 +20,17 @@ using namespace lldb_private;
// BreakpointResolverFileLine:
BreakpointResolverFileLine::BreakpointResolverFileLine(
- const BreakpointSP &bkpt, const FileSpec &file_spec, uint32_t line_no,
- uint32_t column, lldb::addr_t offset, bool check_inlines,
- bool skip_prologue, bool exact_match)
+ const BreakpointSP &bkpt, lldb::addr_t offset, bool skip_prologue,
+ const SourceLocationSpec &location_spec)
: BreakpointResolver(bkpt, BreakpointResolver::FileLineResolver, offset),
- m_file_spec(file_spec), m_line_number(line_no), m_column(column),
- m_inlines(check_inlines), m_skip_prologue(skip_prologue),
- m_exact_match(exact_match) {}
+ m_location_spec(location_spec), m_skip_prologue(skip_prologue) {}
BreakpointResolver *BreakpointResolverFileLine::CreateFromStructuredData(
const BreakpointSP &bkpt, const StructuredData::Dictionary &options_dict,
Status &error) {
llvm::StringRef filename;
- uint32_t line_no;
- uint32_t column;
+ uint32_t line;
+ uint16_t column;
bool check_inlines;
bool skip_prologue;
bool exact_match;
@@ -49,7 +46,7 @@ BreakpointResolver *BreakpointResolverFileLine::CreateFromStructuredData(
}
success = options_dict.GetValueForKeyAsInteger(
- GetKey(OptionNames::LineNumber), line_no);
+ GetKey(OptionNames::LineNumber), line);
if (!success) {
error.SetErrorString("BRFL::CFSD: Couldn't find line number entry.");
return nullptr;
@@ -83,11 +80,13 @@ BreakpointResolver *BreakpointResolverFileLine::CreateFromStructuredData(
return nullptr;
}
- FileSpec file_spec(filename);
+ SourceLocationSpec location_spec(FileSpec(filename), line, column,
+ check_inlines, exact_match);
+ if (!location_spec)
+ return nullptr;
- return new BreakpointResolverFileLine(bkpt, file_spec, line_no, column,
- offset, check_inlines, skip_prologue,
- exact_match);
+ return new BreakpointResolverFileLine(bkpt, offset, skip_prologue,
+ location_spec);
}
StructuredData::ObjectSP
@@ -95,17 +94,19 @@ BreakpointResolverFileLine::SerializeToStructuredData() {
StructuredData::DictionarySP options_dict_sp(
new StructuredData::Dictionary());
- options_dict_sp->AddStringItem(GetKey(OptionNames::FileName),
- m_file_spec.GetPath());
- options_dict_sp->AddIntegerItem(GetKey(OptionNames::LineNumber),
- m_line_number);
- options_dict_sp->AddIntegerItem(GetKey(OptionNames::Column),
- m_column);
- options_dict_sp->AddBooleanItem(GetKey(OptionNames::Inlines), m_inlines);
options_dict_sp->AddBooleanItem(GetKey(OptionNames::SkipPrologue),
m_skip_prologue);
+ options_dict_sp->AddStringItem(GetKey(OptionNames::FileName),
+ m_location_spec.GetFileSpec().GetPath());
+ options_dict_sp->AddIntegerItem(GetKey(OptionNames::LineNumber),
+ m_location_spec.GetLine().getValueOr(0));
+ options_dict_sp->AddIntegerItem(
+ GetKey(OptionNames::Column),
+ m_location_spec.GetColumn().getValueOr(LLDB_INVALID_COLUMN_NUMBER));
+ options_dict_sp->AddBooleanItem(GetKey(OptionNames::Inlines),
+ m_location_spec.GetCheckInlines());
options_dict_sp->AddBooleanItem(GetKey(OptionNames::ExactMatch),
- m_exact_match);
+ m_location_spec.GetExactMatch());
return WrapOptionsDict(options_dict_sp);
}
@@ -119,12 +120,12 @@ BreakpointResolverFileLine::SerializeToStructuredData() {
// inlined into.
void BreakpointResolverFileLine::FilterContexts(SymbolContextList &sc_list,
bool is_relative) {
- if (m_exact_match)
+ if (m_location_spec.GetExactMatch())
return; // Nothing to do. Contexts are precise.
llvm::StringRef relative_path;
if (is_relative)
- relative_path = m_file_spec.GetDirectory().GetStringRef();
+ relative_path = m_location_spec.GetFileSpec().GetDirectory().GetStringRef();
Log * log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS);
for(uint32_t i = 0; i < sc_list.GetSize(); ++i) {
@@ -191,12 +192,13 @@ void BreakpointResolverFileLine::FilterContexts(SymbolContextList &sc_list,
// But only do this calculation if the line number we found in the SC
// was different from the one requested in the source file. If we actually
// found an exact match it must be valid.
-
- if (m_line_number == sc.line_entry.line)
+
+ if (m_location_spec.GetLine() == sc.line_entry.line)
continue;
const int decl_line_is_too_late_fudge = 1;
- if (line && m_line_number < line - decl_line_is_too_late_fudge) {
+ if (line &&
+ m_location_spec.GetLine() < line - decl_line_is_too_late_fudge) {
LLDB_LOG(log, "removing symbol context at {0}:{1}", file, line);
sc_list.RemoveContextAtIndex(i);
--i;
@@ -224,8 +226,11 @@ Searcher::CallbackReturn BreakpointResolverFileLine::SearchCallback(
// file. So we go through the match list and pull out the sets that have the
// same file spec in their line_entry and treat each set separately.
- FileSpec search_file_spec = m_file_spec;
- const bool is_relative = m_file_spec.IsRelative();
+ const uint32_t line = m_location_spec.GetLine().getValueOr(0);
+ const llvm::Optional<uint16_t> column = m_location_spec.GetColumn();
+
+ FileSpec search_file_spec = m_location_spec.GetFileSpec();
+ const bool is_relative = search_file_spec.IsRelative();
if (is_relative)
search_file_spec.GetDirectory().Clear();
@@ -234,8 +239,7 @@ Searcher::CallbackReturn BreakpointResolverFileLine::SearchCallback(
CompUnitSP cu_sp(context.module_sp->GetCompileUnitAtIndex(i));
if (cu_sp) {
if (filter.CompUnitPasses(*cu_sp))
- cu_sp->ResolveSymbolContext(search_file_spec, m_line_number, m_inlines,
- m_exact_match, eSymbolContextEverything,
+ cu_sp->ResolveSymbolContext(m_location_spec, eSymbolContextEverything,
sc_list);
}
}
@@ -243,11 +247,12 @@ Searcher::CallbackReturn BreakpointResolverFileLine::SearchCallback(
FilterContexts(sc_list, is_relative);
StreamString s;
- s.Printf("for %s:%d ", m_file_spec.GetFilename().AsCString("<Unknown>"),
- m_line_number);
+ s.Printf("for %s:%d ",
+ m_location_spec.GetFileSpec().GetFilename().AsCString("<Unknown>"),
+ line);
- SetSCMatchesByLine(filter, sc_list, m_skip_prologue, s.GetString(),
- m_line_number, m_column);
+ SetSCMatchesByLine(filter, sc_list, m_skip_prologue, s.GetString(), line,
+ column);
return Searcher::eCallbackReturnContinue;
}
@@ -257,11 +262,13 @@ lldb::SearchDepth BreakpointResolverFileLine::GetDepth() {
}
void BreakpointResolverFileLine::GetDescription(Stream *s) {
- s->Printf("file = '%s', line = %u, ", m_file_spec.GetPath().c_str(),
- m_line_number);
- if (m_column)
- s->Printf("column = %u, ", m_column);
- s->Printf("exact_match = %d", m_exact_match);
+ s->Printf("file = '%s', line = %u, ",
+ m_location_spec.GetFileSpec().GetPath().c_str(),
+ m_location_spec.GetLine().getValueOr(0));
+ auto column = m_location_spec.GetColumn();
+ if (column)
+ s->Printf("column = %u, ", *column);
+ s->Printf("exact_match = %d", m_location_spec.GetExactMatch());
}
void BreakpointResolverFileLine::Dump(Stream *s) const {}
@@ -269,8 +276,7 @@ void BreakpointResolverFileLine::Dump(Stream *s) const {}
lldb::BreakpointResolverSP
BreakpointResolverFileLine::CopyForBreakpoint(BreakpointSP &breakpoint) {
lldb::BreakpointResolverSP ret_sp(new BreakpointResolverFileLine(
- breakpoint, m_file_spec, m_line_number, m_column, GetOffset(), m_inlines,
- m_skip_prologue, m_exact_match));
+ breakpoint, GetOffset(), m_skip_prologue, m_location_spec));
return ret_sp;
}
diff --git a/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp b/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp
index 62462b2f5441..435983769c05 100644
--- a/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp
+++ b/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp
@@ -107,10 +107,11 @@ Searcher::CallbackReturn BreakpointResolverFileRegex::SearchCallback(
uint32_t num_matches = line_matches.size();
for (uint32_t i = 0; i < num_matches; i++) {
SymbolContextList sc_list;
- const bool search_inlines = false;
-
- cu->ResolveSymbolContext(cu_file_spec, line_matches[i], search_inlines,
- m_exact_match, eSymbolContextEverything, sc_list);
+ // TODO: Handle SourceLocationSpec column information
+ SourceLocationSpec location_spec(cu_file_spec, line_matches[i],
+ /*column=*/llvm::None,
+ /*search_inlines=*/false, m_exact_match);
+ cu->ResolveSymbolContext(location_spec, eSymbolContextEverything, sc_list);
// Find all the function names:
if (!m_function_names.empty()) {
std::vector<size_t> sc_to_remove;
diff --git a/lldb/source/Breakpoint/BreakpointResolverName.cpp b/lldb/source/Breakpoint/BreakpointResolverName.cpp
index 6fab20af5e59..121ac5690d70 100644
--- a/lldb/source/Breakpoint/BreakpointResolverName.cpp
+++ b/lldb/source/Breakpoint/BreakpointResolverName.cpp
@@ -31,7 +31,7 @@ BreakpointResolverName::BreakpointResolverName(const BreakpointSP &bkpt,
m_class_name(), m_regex(), m_match_type(type), m_language(language),
m_skip_prologue(skip_prologue) {
if (m_match_type == Breakpoint::Regexp) {
- m_regex = RegularExpression(llvm::StringRef::withNullAsEmpty(name_cstr));
+ m_regex = RegularExpression(name_cstr);
if (!m_regex.IsValid()) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
@@ -220,11 +220,15 @@ void BreakpointResolverName::AddNameLookup(ConstString name,
m_lookups.emplace_back(lookup);
auto add_variant_funcs = [&](Language *lang) {
- for (ConstString variant_name : lang->GetMethodNameVariants(name)) {
- Module::LookupInfo variant_lookup(name, name_type_mask,
- lang->GetLanguageType());
- variant_lookup.SetLookupName(variant_name);
- m_lookups.emplace_back(variant_lookup);
+ for (Language::MethodNameVariant variant :
+ lang->GetMethodNameVariants(name)) {
+ // FIXME: Should we be adding variants that aren't of type Full?
+ if (variant.GetType() & lldb::eFunctionNameTypeFull) {
+ Module::LookupInfo variant_lookup(name, variant.GetType(),
+ lang->GetLanguageType());
+ variant_lookup.SetLookupName(variant.GetName());
+ m_lookups.emplace_back(variant_lookup);
+ }
}
return true;
};
diff --git a/lldb/source/Breakpoint/BreakpointSite.cpp b/lldb/source/Breakpoint/BreakpointSite.cpp
index fb3f0cd06897..f0469326657c 100644
--- a/lldb/source/Breakpoint/BreakpointSite.cpp
+++ b/lldb/source/Breakpoint/BreakpointSite.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <inttypes.h>
+#include <cinttypes>
#include "lldb/Breakpoint/BreakpointSite.h"
@@ -144,7 +144,7 @@ BreakpointLocationSP BreakpointSite::GetOwnerAtIndex(size_t index) {
return m_owners.GetByIndex(index);
}
-bool BreakpointSite::ValidForThisThread(Thread *thread) {
+bool BreakpointSite::ValidForThisThread(Thread &thread) {
std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
return m_owners.ValidForThisThread(thread);
}
diff --git a/lldb/source/Breakpoint/BreakpointSiteList.cpp b/lldb/source/Breakpoint/BreakpointSiteList.cpp
index 873ba6236a72..c6966145e42b 100644
--- a/lldb/source/Breakpoint/BreakpointSiteList.cpp
+++ b/lldb/source/Breakpoint/BreakpointSiteList.cpp
@@ -16,7 +16,7 @@ using namespace lldb_private;
BreakpointSiteList::BreakpointSiteList() : m_mutex(), m_bp_site_list() {}
-BreakpointSiteList::~BreakpointSiteList() {}
+BreakpointSiteList::~BreakpointSiteList() = default;
// Add breakpoint site to the list. However, if the element already exists in
// the list, then we don't add it, and return LLDB_INVALID_BREAK_ID.
diff --git a/lldb/source/Breakpoint/Stoppoint.cpp b/lldb/source/Breakpoint/Stoppoint.cpp
index b5c8334333cf..94e97cd4542f 100644
--- a/lldb/source/Breakpoint/Stoppoint.cpp
+++ b/lldb/source/Breakpoint/Stoppoint.cpp
@@ -14,10 +14,10 @@ using namespace lldb;
using namespace lldb_private;
// Stoppoint constructor
-Stoppoint::Stoppoint() : m_bid(LLDB_INVALID_BREAK_ID) {}
+Stoppoint::Stoppoint() = default;
// Destructor
-Stoppoint::~Stoppoint() {}
+Stoppoint::~Stoppoint() = default;
break_id_t Stoppoint::GetID() const { return m_bid; }
diff --git a/lldb/source/Breakpoint/StoppointCallbackContext.cpp b/lldb/source/Breakpoint/StoppointCallbackContext.cpp
index 640db8bb9c96..a561c99b1d92 100644
--- a/lldb/source/Breakpoint/StoppointCallbackContext.cpp
+++ b/lldb/source/Breakpoint/StoppointCallbackContext.cpp
@@ -10,8 +10,7 @@
using namespace lldb_private;
-StoppointCallbackContext::StoppointCallbackContext()
- : event(nullptr), exe_ctx_ref(), is_synchronous(false) {}
+StoppointCallbackContext::StoppointCallbackContext() : exe_ctx_ref() {}
StoppointCallbackContext::StoppointCallbackContext(
Event *e, const ExecutionContext &exe_ctx, bool synchronously)
diff --git a/lldb/source/Breakpoint/WatchpointList.cpp b/lldb/source/Breakpoint/WatchpointList.cpp
index a6f651e84955..100c1e51ac5a 100644
--- a/lldb/source/Breakpoint/WatchpointList.cpp
+++ b/lldb/source/Breakpoint/WatchpointList.cpp
@@ -12,10 +12,9 @@
using namespace lldb;
using namespace lldb_private;
-WatchpointList::WatchpointList()
- : m_watchpoints(), m_mutex(), m_next_wp_id(0) {}
+WatchpointList::WatchpointList() : m_watchpoints(), m_mutex() {}
-WatchpointList::~WatchpointList() {}
+WatchpointList::~WatchpointList() = default;
// Add a watchpoint to the list.
lldb::watch_id_t WatchpointList::Add(const WatchpointSP &wp_sp, bool notify) {
diff --git a/lldb/source/Breakpoint/WatchpointOptions.cpp b/lldb/source/Breakpoint/WatchpointOptions.cpp
index f01f5ad3dd27..a578e8744efb 100644
--- a/lldb/source/Breakpoint/WatchpointOptions.cpp
+++ b/lldb/source/Breakpoint/WatchpointOptions.cpp
@@ -28,7 +28,7 @@ bool WatchpointOptions::NullCallback(void *baton,
// WatchpointOptions constructor
WatchpointOptions::WatchpointOptions()
: m_callback(WatchpointOptions::NullCallback), m_callback_baton_sp(),
- m_callback_is_synchronous(false), m_thread_spec_up() {}
+ m_thread_spec_up() {}
// WatchpointOptions copy constructor
WatchpointOptions::WatchpointOptions(const WatchpointOptions &rhs)
diff --git a/lldb/source/Commands/CommandCompletions.cpp b/lldb/source/Commands/CommandCompletions.cpp
index 0ea6d4288169..55018cef57d4 100644
--- a/lldb/source/Commands/CommandCompletions.cpp
+++ b/lldb/source/Commands/CommandCompletions.cpp
@@ -331,7 +331,7 @@ static void DiskFilesOrDirectories(const llvm::Twine &partial_name,
llvm::StringRef PartialItem;
if (CompletionBuffer.startswith("~")) {
- llvm::StringRef Buffer(CompletionBuffer);
+ llvm::StringRef Buffer = CompletionBuffer;
size_t FirstSep =
Buffer.find_if([](char c) { return path::is_separator(c); });
@@ -774,9 +774,7 @@ void CommandCompletions::WatchPointIDs(CommandInterpreter &interpreter,
return;
const WatchpointList &wp_list = exe_ctx.GetTargetPtr()->GetWatchpointList();
- const size_t wp_num = wp_list.GetSize();
- for (size_t idx = 0; idx < wp_num; ++idx) {
- const lldb::WatchpointSP wp_sp = wp_list.GetByIndex(idx);
+ for (lldb::WatchpointSP wp_sp : wp_list.Watchpoints()) {
StreamString strm;
wp_sp->Dump(&strm);
request.TryCompleteCurrentArg(std::to_string(wp_sp->GetID()),
diff --git a/lldb/source/Commands/CommandObjectApropos.cpp b/lldb/source/Commands/CommandObjectApropos.cpp
index 6e1e1f061733..656487169a34 100644
--- a/lldb/source/Commands/CommandObjectApropos.cpp
+++ b/lldb/source/Commands/CommandObjectApropos.cpp
@@ -86,11 +86,9 @@ bool CommandObjectApropos::DoExecute(Args &args, CommandReturnObject &result) {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
result.AppendError("'' is not a valid search word.\n");
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError("'apropos' must be called with exactly one argument.\n");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp
index 0844c56cef2f..722d5c4d8f47 100644
--- a/lldb/source/Commands/CommandObjectBreakpoint.cpp
+++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp
@@ -242,15 +242,8 @@ 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),
- m_exception_language(eLanguageTypeUnknown),
- m_language(lldb::eLanguageTypeUnknown),
- m_skip_prologue(eLazyBoolCalculate), m_all_files(false),
- m_move_to_nearest_code(eLazyBoolCalculate) {}
+ : OptionGroup(), m_condition(), m_filenames(), m_func_names(),
+ m_func_regexp(), m_source_text_regexp(), m_modules() {}
~CommandOptions() override = default;
@@ -500,25 +493,25 @@ public:
std::string m_condition;
FileSpecList m_filenames;
- uint32_t m_line_num;
- uint32_t m_column;
+ uint32_t m_line_num = 0;
+ uint32_t m_column = 0;
std::vector<std::string> m_func_names;
std::vector<std::string> m_breakpoint_names;
- lldb::FunctionNameType m_func_name_type_mask;
+ lldb::FunctionNameType m_func_name_type_mask = eFunctionNameTypeNone;
std::string m_func_regexp;
std::string m_source_text_regexp;
FileSpecList m_modules;
- lldb::addr_t m_load_addr;
+ lldb::addr_t m_load_addr = 0;
lldb::addr_t m_offset_addr;
- bool m_catch_bp;
- bool m_throw_bp;
- bool m_hardware; // Request to use hardware breakpoints
- lldb::LanguageType m_exception_language;
- lldb::LanguageType m_language;
- LazyBool m_skip_prologue;
- bool m_all_files;
+ bool m_catch_bp = false;
+ bool m_throw_bp = true;
+ bool m_hardware = false; // Request to use hardware breakpoints
+ lldb::LanguageType m_exception_language = eLanguageTypeUnknown;
+ lldb::LanguageType m_language = lldb::eLanguageTypeUnknown;
+ LazyBool m_skip_prologue = eLazyBoolCalculate;
+ bool m_all_files = false;
Args m_exception_extra_args;
- LazyBool m_move_to_nearest_code;
+ LazyBool m_move_to_nearest_code = eLazyBoolCalculate;
std::unordered_set<std::string> m_source_regex_func_names;
std::string m_current_key;
};
@@ -573,13 +566,11 @@ protected:
if (num_files == 0) {
if (!GetDefaultFile(target, file, result)) {
result.AppendError("No file supplied and no default file available.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else if (num_files > 1) {
result.AppendError("Only one file at a time is allowed for file and "
"line breakpoints.");
- result.SetStatus(eReturnStatusFailed);
return false;
} else
file = m_options.m_filenames.GetFileSpecAtIndex(0);
@@ -611,7 +602,6 @@ protected:
} else {
result.AppendError("Only one shared library can be specified for "
"address breakpoints.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
break;
@@ -646,7 +636,6 @@ protected:
result.AppendWarning(
"Function name regex does not accept glob patterns.");
}
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -664,7 +653,6 @@ protected:
if (!GetDefaultFile(target, file, result)) {
result.AppendError(
"No files provided and could not find default file.");
- result.SetStatus(eReturnStatusFailed);
return false;
} else {
m_options.m_filenames.Append(file);
@@ -676,7 +664,6 @@ protected:
result.AppendErrorWithFormat(
"Source text regular expression could not be compiled: \"%s\"",
llvm::toString(std::move(err)).c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
bp_sp = target.CreateSourceRegexBreakpoint(
@@ -695,7 +682,6 @@ protected:
"Error setting extra exception arguments: %s",
precond_error.AsCString());
target.RemoveBreakpointByID(bp_sp->GetID());
- result.SetStatus(eReturnStatusFailed);
return false;
}
} break;
@@ -710,7 +696,6 @@ protected:
result.AppendErrorWithFormat(
"Error setting extra exception arguments: %s", error.AsCString());
target.RemoveBreakpointByID(bp_sp->GetID());
- result.SetStatus(eReturnStatusFailed);
return false;
}
} break;
@@ -720,7 +705,7 @@ protected:
// Now set the various options that were passed in:
if (bp_sp) {
- bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
+ bp_sp->GetOptions().CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
if (!m_options.m_breakpoint_names.empty()) {
Status name_error;
@@ -730,7 +715,6 @@ protected:
result.AppendErrorWithFormat("Invalid breakpoint name: %s",
name.c_str());
target.RemoveBreakpointByID(bp_sp->GetID());
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -757,7 +741,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishResult);
} else if (!bp_sp) {
result.AppendError("Breakpoint creation failed: No breakpoint created.");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
@@ -774,12 +757,10 @@ private:
if (cur_frame == nullptr) {
result.AppendError(
"No selected frame to use to find the default file.");
- result.SetStatus(eReturnStatusFailed);
return false;
} else if (!cur_frame->HasDebugInformation()) {
result.AppendError("Cannot use the selected frame to find the default "
"file, it has no debug info.");
- result.SetStatus(eReturnStatusFailed);
return false;
} else {
const SymbolContext &sc =
@@ -789,7 +770,6 @@ private:
} else {
result.AppendError("Can't find the file for the selected frame to "
"use as the default file.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -870,10 +850,10 @@ protected:
BreakpointLocation *location =
bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
if (location)
- location->GetLocationOptions()->CopyOverSetOptions(
+ location->GetLocationOptions().CopyOverSetOptions(
m_bp_opts.GetBreakpointOptions());
} else {
- bp->GetOptions()->CopyOverSetOptions(
+ bp->GetOptions().CopyOverSetOptions(
m_bp_opts.GetBreakpointOptions());
}
}
@@ -930,7 +910,6 @@ protected:
if (num_breakpoints == 0) {
result.AppendError("No breakpoints exist to be enabled.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1044,7 +1023,6 @@ protected:
if (num_breakpoints == 0) {
result.AppendError("No breakpoints exist to be disabled.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1133,9 +1111,7 @@ public:
class CommandOptions : public Options {
public:
- CommandOptions()
- : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
- }
+ CommandOptions() : Options() {}
~CommandOptions() override = default;
@@ -1179,10 +1155,10 @@ public:
// Instance variables to hold the values for command options.
- lldb::DescriptionLevel m_level;
+ lldb::DescriptionLevel m_level = lldb::eDescriptionLevelBrief;
bool m_internal;
- bool m_use_dummy;
+ bool m_use_dummy = false;
};
protected:
@@ -1232,7 +1208,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
result.AppendError("Invalid breakpoint ID.");
- result.SetStatus(eReturnStatusFailed);
}
}
@@ -1268,7 +1243,7 @@ public:
class CommandOptions : public Options {
public:
- CommandOptions() : Options(), m_filename(), m_line_num(0) {}
+ CommandOptions() : Options(), m_filename() {}
~CommandOptions() override = default;
@@ -1305,7 +1280,7 @@ public:
// Instance variables to hold the values for command options.
std::string m_filename;
- uint32_t m_line_num;
+ uint32_t m_line_num = 0;
};
protected:
@@ -1330,7 +1305,6 @@ protected:
// Early return if there's no breakpoint at all.
if (num_breakpoints == 0) {
result.AppendError("Breakpoint clear: No breakpoint cleared.");
- result.SetStatus(eReturnStatusFailed);
return result.Succeeded();
}
@@ -1377,7 +1351,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
result.AppendError("Breakpoint clear: No breakpoint cleared.");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
@@ -1423,8 +1396,7 @@ public:
class CommandOptions : public Options {
public:
- CommandOptions() : Options(), m_use_dummy(false), m_force(false),
- m_delete_disabled(false) {}
+ CommandOptions() : Options() {}
~CommandOptions() override = default;
@@ -1464,9 +1436,9 @@ public:
}
// Instance variables to hold the values for command options.
- bool m_use_dummy;
- bool m_force;
- bool m_delete_disabled;
+ bool m_use_dummy = false;
+ bool m_force = false;
+ bool m_delete_disabled = false;
};
protected:
@@ -1483,10 +1455,10 @@ protected:
if (num_breakpoints == 0) {
result.AppendError("No breakpoints exist to be deleted.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
+ // Handle the delete all breakpoints case:
if (command.empty() && !m_options.m_delete_disabled) {
if (!m_options.m_force &&
!m_interpreter.Confirm(
@@ -1500,68 +1472,73 @@ protected:
(uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
}
result.SetStatus(eReturnStatusSuccessFinishNoResult);
- } else {
- // Particular breakpoint selected; disable that breakpoint.
- BreakpointIDList valid_bp_ids;
-
- if (m_options.m_delete_disabled) {
- BreakpointIDList excluded_bp_ids;
+ return result.Succeeded();
+ }
+
+ // Either we have some kind of breakpoint specification(s),
+ // or we are handling "break disable --deleted". Gather the list
+ // of breakpoints to delete here, the we'll delete them below.
+ BreakpointIDList valid_bp_ids;
+
+ if (m_options.m_delete_disabled) {
+ BreakpointIDList excluded_bp_ids;
- if (!command.empty()) {
- CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
- command, &target, result, &excluded_bp_ids,
- BreakpointName::Permissions::PermissionKinds::deletePerm);
- }
- for (auto breakpoint_sp : breakpoints.Breakpoints()) {
- if (!breakpoint_sp->IsEnabled() && breakpoint_sp->AllowDelete()) {
- BreakpointID bp_id(breakpoint_sp->GetID());
- size_t pos = 0;
- if (!excluded_bp_ids.FindBreakpointID(bp_id, &pos))
- valid_bp_ids.AddBreakpointID(breakpoint_sp->GetID());
- }
- }
- if (valid_bp_ids.GetSize() == 0) {
- result.AppendError("No disabled breakpoints.");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- } else {
+ if (!command.empty()) {
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
- command, &target, result, &valid_bp_ids,
+ command, &target, result, &excluded_bp_ids,
BreakpointName::Permissions::PermissionKinds::deletePerm);
+ if (!result.Succeeded())
+ return false;
}
-
- if (result.Succeeded()) {
- int delete_count = 0;
- int disable_count = 0;
- const size_t count = valid_bp_ids.GetSize();
- for (size_t i = 0; i < count; ++i) {
- BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
- if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
- if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
- Breakpoint *breakpoint =
- target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
- BreakpointLocation *location =
- breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
- // It makes no sense to try to delete individual locations, so we
- // disable them instead.
- if (location) {
- location->SetEnabled(false);
- ++disable_count;
- }
- } else {
- target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
- ++delete_count;
- }
+ for (auto breakpoint_sp : breakpoints.Breakpoints()) {
+ if (!breakpoint_sp->IsEnabled() && breakpoint_sp->AllowDelete()) {
+ BreakpointID bp_id(breakpoint_sp->GetID());
+ size_t pos = 0;
+ if (!excluded_bp_ids.FindBreakpointID(bp_id, &pos))
+ valid_bp_ids.AddBreakpointID(breakpoint_sp->GetID());
+ }
+ }
+ if (valid_bp_ids.GetSize() == 0) {
+ result.AppendError("No disabled breakpoints.");
+ return false;
+ }
+ } else {
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
+ command, &target, result, &valid_bp_ids,
+ BreakpointName::Permissions::PermissionKinds::deletePerm);
+ if (!result.Succeeded())
+ return false;
+ }
+
+ int delete_count = 0;
+ int disable_count = 0;
+ const size_t count = valid_bp_ids.GetSize();
+ for (size_t i = 0; i < count; ++i) {
+ BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
+
+ if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
+ if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
+ Breakpoint *breakpoint =
+ target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
+ BreakpointLocation *location =
+ breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
+ // It makes no sense to try to delete individual locations, so we
+ // disable them instead.
+ if (location) {
+ location->SetEnabled(false);
+ ++disable_count;
}
+ } else {
+ target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
+ ++delete_count;
}
- result.AppendMessageWithFormat(
- "%d breakpoints deleted; %d breakpoint locations disabled.\n",
- delete_count, disable_count);
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
}
}
+ result.AppendMessageWithFormat(
+ "%d breakpoints deleted; %d breakpoint locations disabled.\n",
+ delete_count, disable_count);
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
return result.Succeeded();
}
@@ -1736,7 +1713,6 @@ protected:
const size_t argc = command.GetArgumentCount();
if (argc == 0) {
result.AppendError("No names provided.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1751,7 +1727,6 @@ protected:
if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) {
result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
entry.c_str(), error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -1764,7 +1739,6 @@ protected:
if (!bp_sp) {
result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
bp_id);
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -1779,7 +1753,7 @@ protected:
bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
if (bp_sp)
- target.ConfigureBreakpointName(*bp_name, *bp_sp->GetOptions(),
+ target.ConfigureBreakpointName(*bp_name, bp_sp->GetOptions(),
m_access_options.GetPermissions());
else
target.ConfigureBreakpointName(*bp_name,
@@ -1831,7 +1805,7 @@ public:
protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
if (!m_name_options.m_name.OptionWasSet()) {
- result.SetError("No name option provided.");
+ result.AppendError("No name option provided.");
return false;
}
@@ -1845,8 +1819,7 @@ protected:
size_t num_breakpoints = breakpoints.GetSize();
if (num_breakpoints == 0) {
- result.SetError("No breakpoints, cannot add names.");
- result.SetStatus(eReturnStatusFailed);
+ result.AppendError("No breakpoints, cannot add names.");
return false;
}
@@ -1858,8 +1831,7 @@ protected:
if (result.Succeeded()) {
if (valid_bp_ids.GetSize() == 0) {
- result.SetError("No breakpoints specified, cannot add names.");
- result.SetStatus(eReturnStatusFailed);
+ result.AppendError("No breakpoints specified, cannot add names.");
return false;
}
size_t num_valid_ids = valid_bp_ids.GetSize();
@@ -1918,7 +1890,7 @@ public:
protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
if (!m_name_options.m_name.OptionWasSet()) {
- result.SetError("No name option provided.");
+ result.AppendError("No name option provided.");
return false;
}
@@ -1932,8 +1904,7 @@ protected:
size_t num_breakpoints = breakpoints.GetSize();
if (num_breakpoints == 0) {
- result.SetError("No breakpoints, cannot delete names.");
- result.SetStatus(eReturnStatusFailed);
+ result.AppendError("No breakpoints, cannot delete names.");
return false;
}
@@ -1945,8 +1916,7 @@ protected:
if (result.Succeeded()) {
if (valid_bp_ids.GetSize() == 0) {
- result.SetError("No breakpoints specified, cannot delete names.");
- result.SetStatus(eReturnStatusFailed);
+ result.AppendError("No breakpoints specified, cannot delete names.");
return false;
}
ConstString bp_name(m_name_options.m_name.GetCurrentValue());
@@ -2222,7 +2192,6 @@ protected:
if (!error.Success()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -2351,7 +2320,6 @@ protected:
if (!error.Success()) {
result.AppendErrorWithFormat("error serializing breakpoints: %s.",
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -2444,7 +2412,6 @@ void CommandObjectMultiwordBreakpoint::VerifyIDs(
} else {
result.AppendError(
"No breakpoint specified and no last created breakpoint.");
- result.SetStatus(eReturnStatusFailed);
}
return;
}
@@ -2486,14 +2453,12 @@ void CommandObjectMultiwordBreakpoint::VerifyIDs(
result.AppendErrorWithFormat(
"'%s' is not a currently valid breakpoint/location id.\n",
id_str.GetData());
- result.SetStatus(eReturnStatusFailed);
}
} else {
i = valid_ids->GetSize() + 1;
result.AppendErrorWithFormat(
"'%d' is not a currently valid breakpoint ID.\n",
cur_bp_id.GetBreakpointID());
- result.SetStatus(eReturnStatusFailed);
}
}
}
diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
index caaf3bfb482f..26d35c82f57d 100644
--- a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
+++ b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
@@ -61,7 +61,9 @@ public:
CommandObjectBreakpointCommandAdd(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "add",
"Add LLDB commands to a breakpoint, to be executed "
- "whenever the breakpoint is hit."
+ "whenever the breakpoint is hit. "
+ "The commands added to the breakpoint replace any "
+ "commands previously added to it."
" If no breakpoint is specified, adds the "
"commands to the last created breakpoint.",
nullptr),
@@ -117,14 +119,22 @@ to supply the function name prepended by the module name:"
--python-function myutils.breakpoint_callback
-The function itself must have the following prototype:
+The function itself must have either of the following prototypes:
-def breakpoint_callback(frame, bp_loc, dict):
+def breakpoint_callback(frame, bp_loc, internal_dict):
+ # Your code goes here
+
+or:
+
+def breakpoint_callback(frame, bp_loc, extra_args, internal_dict):
# Your code goes here
)"
"The arguments are the same as the arguments passed to generated functions as \
-described above. Note that the global variable 'lldb.frame' will NOT be updated when \
+described above. In the second form, any -k and -v pairs provided to the command will \
+be packaged into a SBDictionary in an SBStructuredData and passed as the extra_args parameter. \
+\n\n\
+Note that the global variable 'lldb.frame' will NOT be updated when \
this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
can get you to the thread via frame.GetThread(), the thread can get you to the \
process via thread.GetProcess(), and the process can get you back to the target \
@@ -235,20 +245,18 @@ are no syntax errors may indicate that a function was declared but never called.
std::string &line) override {
io_handler.SetIsDone(true);
- std::vector<BreakpointOptions *> *bp_options_vec =
- (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
- for (BreakpointOptions *bp_options : *bp_options_vec) {
- if (!bp_options)
- continue;
-
+ std::vector<std::reference_wrapper<BreakpointOptions>> *bp_options_vec =
+ (std::vector<std::reference_wrapper<BreakpointOptions>> *)
+ io_handler.GetUserData();
+ for (BreakpointOptions &bp_options : *bp_options_vec) {
auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
cmd_data->user_source.SplitIntoLines(line.c_str(), line.size());
- bp_options->SetCommandDataCallback(cmd_data);
+ bp_options.SetCommandDataCallback(cmd_data);
}
}
void CollectDataForBreakpointCommandCallback(
- std::vector<BreakpointOptions *> &bp_options_vec,
+ std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
CommandReturnObject &result) {
m_interpreter.GetLLDBCommandsFromIOHandler(
"> ", // Prompt
@@ -258,25 +266,22 @@ are no syntax errors may indicate that a function was declared but never called.
}
/// Set a one-liner as the callback for the breakpoint.
- void
- SetBreakpointCommandCallback(std::vector<BreakpointOptions *> &bp_options_vec,
- const char *oneliner) {
- for (auto bp_options : bp_options_vec) {
+ void SetBreakpointCommandCallback(
+ std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
+ const char *oneliner) {
+ for (BreakpointOptions &bp_options : bp_options_vec) {
auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
cmd_data->user_source.AppendString(oneliner);
cmd_data->stop_on_error = m_options.m_stop_on_error;
- bp_options->SetCommandDataCallback(cmd_data);
+ bp_options.SetCommandDataCallback(cmd_data);
}
}
class CommandOptions : public OptionGroup {
public:
- CommandOptions()
- : OptionGroup(), m_use_commands(false), m_use_script_language(false),
- m_script_language(eScriptLanguageNone), m_use_one_liner(false),
- m_one_liner() {}
+ CommandOptions() : OptionGroup(), m_one_liner() {}
~CommandOptions() override = default;
@@ -346,12 +351,12 @@ are no syntax errors may indicate that a function was declared but never called.
// Instance variables to hold the values for command options.
- bool m_use_commands;
- bool m_use_script_language;
- lldb::ScriptLanguage m_script_language;
+ bool m_use_commands = false;
+ bool m_use_script_language = false;
+ lldb::ScriptLanguage m_script_language = eScriptLanguageNone;
// Instance variables to hold the values for one_liner options.
- bool m_use_one_liner;
+ bool m_use_one_liner = false;
std::string m_one_liner;
bool m_stop_on_error;
bool m_use_dummy;
@@ -366,7 +371,6 @@ protected:
if (num_breakpoints == 0) {
result.AppendError("No breakpoints exist to have commands added");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -393,20 +397,17 @@ protected:
if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
Breakpoint *bp =
target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
- BreakpointOptions *bp_options = nullptr;
if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID) {
// This breakpoint does not have an associated location.
- bp_options = bp->GetOptions();
+ m_bp_options_vec.push_back(bp->GetOptions());
} else {
BreakpointLocationSP bp_loc_sp(
bp->FindLocationByID(cur_bp_id.GetLocationID()));
// This breakpoint does have an associated location. Get its
// breakpoint options.
if (bp_loc_sp)
- bp_options = bp_loc_sp->GetLocationOptions();
+ m_bp_options_vec.push_back(bp_loc_sp->GetLocationOptions());
}
- if (bp_options)
- m_bp_options_vec.push_back(bp_options);
}
}
@@ -449,9 +450,10 @@ private:
OptionGroupPythonClassWithDict m_func_options;
OptionGroupOptions m_all_options;
- std::vector<BreakpointOptions *> m_bp_options_vec; // This stores the
- // breakpoint options that
- // we are currently
+ std::vector<std::reference_wrapper<BreakpointOptions>>
+ m_bp_options_vec; // This stores the
+ // breakpoint options that
+ // we are currently
// collecting commands for. In the CollectData... calls we need to hand this
// off to the IOHandler, which may run asynchronously. So we have to have
// some way to keep it alive, and not leak it. Making it an ivar of the
@@ -500,7 +502,7 @@ public:
class CommandOptions : public Options {
public:
- CommandOptions() : Options(), m_use_dummy(false) {}
+ CommandOptions() : Options() {}
~CommandOptions() override = default;
@@ -530,7 +532,7 @@ public:
}
// Instance variables to hold the values for command options.
- bool m_use_dummy;
+ bool m_use_dummy = false;
};
protected:
@@ -542,14 +544,12 @@ protected:
if (num_breakpoints == 0) {
result.AppendError("No breakpoints exist to have commands deleted");
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (command.empty()) {
result.AppendError(
"No breakpoint specified from which to delete the commands");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -574,7 +574,6 @@ protected:
result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
cur_bp_id.GetBreakpointID(),
cur_bp_id.GetLocationID());
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else {
@@ -625,14 +624,12 @@ protected:
if (num_breakpoints == 0) {
result.AppendError("No breakpoints exist for which to list commands");
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (command.empty()) {
result.AppendError(
"No breakpoint specified for which to list the commands");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -657,7 +654,6 @@ protected:
result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
cur_bp_id.GetBreakpointID(),
cur_bp_id.GetLocationID());
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -671,9 +667,9 @@ protected:
baton =
bp_loc_sp
->GetOptionsSpecifyingKind(BreakpointOptions::eCallback)
- ->GetBaton();
+ .GetBaton();
else
- baton = bp->GetOptions()->GetBaton();
+ baton = bp->GetOptions().GetBaton();
if (baton) {
result.GetOutputStream().Printf("Breakpoint %s:\n",
@@ -692,7 +688,6 @@ protected:
} else {
result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n",
cur_bp_id.GetBreakpointID());
- result.SetStatus(eReturnStatusFailed);
}
}
}
diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp
index 3b3cdde6ab9a..9a8b81c007ad 100644
--- a/lldb/source/Commands/CommandObjectCommands.cpp
+++ b/lldb/source/Commands/CommandObjectCommands.cpp
@@ -128,21 +128,17 @@ protected:
result.AppendErrorWithFormat(
"'%s' takes exactly one executable filename argument.\n",
GetCommandName().str().c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
FileSpec cmd_file(command[0].ref());
FileSystem::Instance().Resolve(cmd_file);
- ExecutionContext *exe_ctx = nullptr; // Just use the default context.
+ CommandInterpreterRunOptions options;
// If any options were set, then use them
if (m_options.m_stop_on_error.OptionWasSet() ||
m_options.m_silent_run.OptionWasSet() ||
m_options.m_stop_on_continue.OptionWasSet()) {
- // Use user set settings
- CommandInterpreterRunOptions options;
-
if (m_options.m_stop_on_continue.OptionWasSet())
options.SetStopOnContinue(
m_options.m_stop_on_continue.GetCurrentValue());
@@ -159,14 +155,9 @@ protected:
options.SetEchoCommands(m_interpreter.GetEchoCommands());
options.SetEchoCommentCommands(m_interpreter.GetEchoCommentCommands());
}
-
- m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result);
- } else {
- // No options were set, inherit any settings from nested "command source"
- // commands, or set to sane default settings...
- CommandInterpreterRunOptions options;
- m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result);
}
+
+ m_interpreter.HandleCommandsFromFile(cmd_file, options, result);
return result.Succeeded();
}
@@ -388,7 +379,6 @@ protected:
if (args.GetArgumentCount() < 2) {
result.AppendError("'command alias' requires at least two arguments");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -401,7 +391,6 @@ protected:
result.AppendWarning("if trying to pass options to 'command alias' add "
"a -- at the end of the options");
}
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -415,7 +404,6 @@ protected:
raw_command_string = raw_command_string.substr(pos);
} else {
result.AppendError("Error parsing command string. No alias created.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -424,7 +412,6 @@ protected:
result.AppendErrorWithFormat(
"'%s' is a permanent debugger command and cannot be redefined.\n",
args[0].c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -440,7 +427,6 @@ protected:
"'%s' does not begin with a valid command."
" No alias created.",
original_raw_command_string.str().c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
} else if (!cmd_obj->WantsRawCommandString()) {
// Note that args was initialized with the original command, and has not
@@ -480,12 +466,10 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
result.AppendError("Unable to create requested alias.\n");
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError("Unable to create requested alias.\n");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
@@ -496,7 +480,6 @@ protected:
if (argc < 2) {
result.AppendError("'command alias' requires at least two arguments");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -514,7 +497,6 @@ protected:
result.AppendErrorWithFormat(
"'%s' is a permanent debugger command and cannot be redefined.\n",
alias_command.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -525,7 +507,6 @@ protected:
if (!command_obj_sp) {
result.AppendErrorWithFormat("'%s' is not an existing command.\n",
actual_command.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
CommandObject *cmd_obj = command_obj_sp.get();
@@ -542,7 +523,6 @@ protected:
"'%s' is not a valid sub-command of '%s'. "
"Unable to create alias.\n",
args[0].c_str(), actual_command.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -581,7 +561,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
result.AppendError("Unable to create requested alias.\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -634,7 +613,6 @@ protected:
if (args.empty()) {
result.AppendError("must call 'unalias' with a valid alias");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -645,7 +623,6 @@ protected:
"'%s' is not a known command.\nTry 'help' to see a "
"current list of commands.\n",
args[0].c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -660,7 +637,6 @@ protected:
"'%s' is a permanent debugger command and cannot be removed.\n",
args[0].c_str());
}
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -672,7 +648,6 @@ protected:
else
result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
args[0].c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -728,7 +703,6 @@ protected:
result.AppendErrorWithFormat("must call '%s' with one or more valid user "
"defined regular expression command names",
GetCommandName().str().c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -741,7 +715,6 @@ protected:
&error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(),
generate_upropos, generate_type_lookup);
result.AppendError(error_msg_stream.GetString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -749,7 +722,6 @@ protected:
result.AppendErrorWithFormat(
"'%s' is a permanent debugger command and cannot be removed.\n",
args[0].c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -854,7 +826,6 @@ protected:
if (argc == 0) {
result.AppendError("usage: 'command regex <command-name> "
"[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -895,7 +866,6 @@ protected:
}
if (error.Fail()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
@@ -1111,7 +1081,6 @@ protected:
m_function_name.c_str(), raw_command_line, m_synchro,
result, error, m_exe_ctx)) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
} else {
// Don't change the status if the command already set it...
if (result.GetStatus() == eReturnStatusInvalid) {
@@ -1197,7 +1166,6 @@ protected:
!scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
m_synchro, result, error, m_exe_ctx)) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
} else {
// Don't change the status if the command already set it...
if (result.GetStatus() == eReturnStatusInvalid) {
@@ -1274,6 +1242,9 @@ protected:
case 'c':
relative_to_command_file = true;
break;
+ case 's':
+ silent = true;
+ break;
default:
llvm_unreachable("Unimplemented option");
}
@@ -1289,12 +1260,12 @@ protected:
return llvm::makeArrayRef(g_script_import_options);
}
bool relative_to_command_file = false;
+ bool silent = false;
};
bool DoExecute(Args &command, CommandReturnObject &result) override {
if (command.empty()) {
result.AppendError("command script import needs one or more arguments");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1304,7 +1275,6 @@ protected:
if (!source_dir) {
result.AppendError("command script import -c can only be specified "
"from a command file");
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -1312,7 +1282,10 @@ protected:
for (auto &entry : command.entries()) {
Status error;
- const bool init_session = true;
+ LoadScriptOptions options;
+ options.SetInitSession(true);
+ options.SetSilent(m_options.silent);
+
// FIXME: this is necessary because CommandObject::CheckRequirements()
// assumes that commands won't ever be recursively invoked, but it's
// actually possible to craft a Python script that does other "command
@@ -1323,12 +1296,12 @@ protected:
// more)
m_exe_ctx.Clear();
if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule(
- entry.c_str(), init_session, error, nullptr, source_dir)) {
+ entry.c_str(), options, error, /*module_sp=*/nullptr,
+ source_dir)) {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
result.AppendErrorWithFormat("module importing failed: %s",
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
}
@@ -1395,8 +1368,7 @@ protected:
class CommandOptions : public Options {
public:
CommandOptions()
- : Options(), m_class_name(), m_funct_name(), m_short_help(),
- m_synchronicity(eScriptedCommandSynchronicitySynchronous) {}
+ : Options(), m_class_name(), m_funct_name(), m_short_help() {}
~CommandOptions() override = default;
@@ -1450,7 +1422,8 @@ protected:
std::string m_class_name;
std::string m_funct_name;
std::string m_short_help;
- ScriptedCommandSynchronicity m_synchronicity;
+ ScriptedCommandSynchronicity m_synchronicity =
+ eScriptedCommandSynchronicitySynchronous;
};
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
@@ -1513,13 +1486,11 @@ protected:
if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) {
result.AppendError("only scripting language supported for scripted "
"commands is currently Python");
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (command.GetArgumentCount() != 1) {
result.AppendError("'command script add' requires one argument");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1541,14 +1512,12 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
result.AppendError("cannot add command");
- result.SetStatus(eReturnStatusFailed);
}
}
} else {
ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
if (!interpreter) {
result.AppendError("cannot find ScriptInterpreter");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1556,7 +1525,6 @@ protected:
m_options.m_class_name.c_str());
if (!cmd_obj_sp) {
result.AppendError("cannot create helper object");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1566,7 +1534,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
result.AppendError("cannot add command");
- result.SetStatus(eReturnStatusFailed);
}
}
@@ -1592,7 +1559,6 @@ public:
bool DoExecute(Args &command, CommandReturnObject &result) override {
if (command.GetArgumentCount() != 0) {
result.AppendError("'command script list' doesn't take any arguments");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1618,7 +1584,6 @@ protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
if (command.GetArgumentCount() != 0) {
result.AppendError("'command script clear' doesn't take any arguments");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1669,7 +1634,6 @@ protected:
if (command.GetArgumentCount() != 1) {
result.AppendError("'command script delete' requires one argument");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1678,7 +1642,6 @@ protected:
if (cmd_name.empty() || !m_interpreter.HasUserCommands() ||
!m_interpreter.UserCommandExists(cmd_name)) {
result.AppendErrorWithFormat("command %s not found", command[0].c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
diff --git a/lldb/source/Commands/CommandObjectDisassemble.cpp b/lldb/source/Commands/CommandObjectDisassemble.cpp
index cf4d8ed04f81..5e73fb8218ab 100644
--- a/lldb/source/Commands/CommandObjectDisassemble.cpp
+++ b/lldb/source/Commands/CommandObjectDisassemble.cpp
@@ -23,7 +23,6 @@
static constexpr unsigned default_disasm_byte_size = 32;
static constexpr unsigned default_disasm_num_ins = 4;
-static constexpr unsigned large_function_threshold = 8000;
using namespace lldb;
using namespace lldb_private;
@@ -32,10 +31,7 @@ using namespace lldb_private;
#include "CommandOptions.inc"
CommandObjectDisassemble::CommandOptions::CommandOptions()
- : Options(), num_lines_context(0), num_instructions(0), func_name(),
- current_function(false), start_addr(), end_addr(), at_pc(false),
- frame_line(false), plugin_name(), flavor_string(), arch(),
- some_location_specified(false), symbol_containing_addr() {
+ : Options(), func_name(), plugin_name(), flavor_string(), arch() {
OptionParsingStarting(nullptr);
}
@@ -223,7 +219,7 @@ CommandObjectDisassemble::~CommandObjectDisassemble() = default;
llvm::Error CommandObjectDisassemble::CheckRangeSize(const AddressRange &range,
llvm::StringRef what) {
if (m_options.num_instructions > 0 || m_options.force ||
- range.GetByteSize() < large_function_threshold)
+ range.GetByteSize() < GetDebugger().GetStopDisassemblyMaxSize())
return llvm::Error::success();
StreamString msg;
msg << "Not disassembling " << what << " because it is very large ";
@@ -418,7 +414,6 @@ bool CommandObjectDisassemble::DoExecute(Args &command,
if (!m_options.arch.IsValid()) {
result.AppendError(
"use the --arch option or set the target architecture to disassemble");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -438,7 +433,6 @@ bool CommandObjectDisassemble::DoExecute(Args &command,
result.AppendErrorWithFormat(
"Unable to find Disassembler plug-in for the '%s' architecture.\n",
m_options.arch.GetArchitectureName());
- result.SetStatus(eReturnStatusFailed);
return false;
} else if (flavor_string != nullptr && !disassembler->FlavorValidForArchSpec(
m_options.arch, flavor_string))
@@ -454,7 +448,6 @@ bool CommandObjectDisassemble::DoExecute(Args &command,
GetCommandInterpreter().GetDebugger().GetTerminalWidth();
GetOptions()->GenerateOptionUsage(result.GetErrorStream(), this,
terminal_width);
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -479,7 +472,6 @@ bool CommandObjectDisassemble::DoExecute(Args &command,
GetRangesForSelectedMode(result);
if (!ranges) {
result.AppendError(toString(ranges.takeError()));
- result.SetStatus(eReturnStatusFailed);
return result.Succeeded();
}
@@ -509,7 +501,6 @@ bool CommandObjectDisassemble::DoExecute(Args &command,
"Failed to disassemble memory at 0x%8.8" PRIx64 ".\n",
cur_range.GetBaseAddress().GetLoadAddress(target));
}
- result.SetStatus(eReturnStatusFailed);
}
if (print_sc_header)
result.GetOutputStream() << "\n";
diff --git a/lldb/source/Commands/CommandObjectDisassemble.h b/lldb/source/Commands/CommandObjectDisassemble.h
index 340bf648de17..a4b3df8724da 100644
--- a/lldb/source/Commands/CommandObjectDisassemble.h
+++ b/lldb/source/Commands/CommandObjectDisassemble.h
@@ -46,22 +46,22 @@ public:
bool show_mixed; // Show mixed source/assembly
bool show_bytes;
- uint32_t num_lines_context;
- uint32_t num_instructions;
+ uint32_t num_lines_context = 0;
+ uint32_t num_instructions = 0;
bool raw;
std::string func_name;
- bool current_function;
- lldb::addr_t start_addr;
- lldb::addr_t end_addr;
- bool at_pc;
- bool frame_line;
+ bool current_function = false;
+ lldb::addr_t start_addr = 0;
+ lldb::addr_t end_addr = 0;
+ bool at_pc = false;
+ bool frame_line = false;
std::string plugin_name;
std::string flavor_string;
ArchSpec arch;
- bool some_location_specified; // If no location was specified, we'll select
- // "at_pc". This should be set
+ bool some_location_specified = false; // If no location was specified, we'll
+ // select "at_pc". This should be set
// in SetOptionValue if anything the selects a location is set.
- lldb::addr_t symbol_containing_addr;
+ lldb::addr_t symbol_containing_addr = 0;
bool force = false;
};
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index 58eaa3f973cb..bf62f3f297cc 100644
--- a/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -292,18 +292,12 @@ void CommandObjectExpression::HandleCompletion(CompletionRequest &request) {
options.SetAutoApplyFixIts(false);
options.SetGenerateDebugInfo(false);
- // We need a valid execution context with a frame pointer for this
- // completion, so if we don't have one we should try to make a valid
- // execution context.
- if (m_interpreter.GetExecutionContext().GetFramePtr() == nullptr)
- m_interpreter.UpdateExecutionContext(nullptr);
+ ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
- // This didn't work, so let's get out before we start doing things that
- // expect a valid frame pointer.
- if (m_interpreter.GetExecutionContext().GetFramePtr() == nullptr)
+ // Get out before we start doing things that expect a valid frame pointer.
+ if (exe_ctx.GetFramePtr() == nullptr)
return;
- ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
Target *exe_target = exe_ctx.GetTargetPtr();
Target &target = exe_target ? *exe_target : GetDummyTarget();
@@ -414,6 +408,12 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
lldb::ValueObjectSP result_valobj_sp;
StackFrame *frame = exe_ctx.GetFramePtr();
+ if (m_command_options.top_level && !m_command_options.allow_jit) {
+ result.AppendErrorWithFormat(
+ "Can't disable JIT compilation for top-level expressions.\n");
+ return false;
+ }
+
const EvaluateExpressionOptions options = GetEvalOptions(target);
ExpressionResults success = target.EvaluateExpression(
expr, frame, result_valobj_sp, options, &m_fixed_expression);
@@ -440,7 +440,6 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
result.AppendErrorWithFormat(
"expression cannot be used with --element-count %s\n",
error.AsCString(""));
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp
index a656a99a1c71..d90e357bf1aa 100644
--- a/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/lldb/source/Commands/CommandObjectFrame.cpp
@@ -141,7 +141,6 @@ protected:
if (m_options.reg.hasValue() || m_options.offset.hasValue()) {
result.AppendError(
"`frame diagnose --address` is incompatible with other arguments.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
valobj_sp = frame_sp->GuessValueForAddress(m_options.address.getValue());
@@ -152,7 +151,6 @@ protected:
StopInfoSP stop_info_sp = thread->GetStopInfo();
if (!stop_info_sp) {
result.AppendError("No arguments provided, and no stop info.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -161,7 +159,6 @@ protected:
if (!valobj_sp) {
result.AppendError("No diagnosis available.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -323,7 +320,6 @@ protected:
// If you are already at the bottom of the stack, then just warn
// and don't reset the frame.
result.AppendError("Already at the bottom of the stack.");
- result.SetStatus(eReturnStatusFailed);
return false;
} else
frame_idx = 0;
@@ -342,7 +338,6 @@ protected:
// If we are already at the top of the stack, just warn and don't
// reset the frame.
result.AppendError("Already at the top of the stack.");
- result.SetStatus(eReturnStatusFailed);
return false;
} else
frame_idx = num_frames - 1;
@@ -363,7 +358,6 @@ protected:
if (command[0].ref().getAsInteger(0, frame_idx)) {
result.AppendErrorWithFormat("invalid frame index argument '%s'.",
command[0].c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else if (command.GetArgumentCount() == 0) {
@@ -382,7 +376,6 @@ protected:
} else {
result.AppendErrorWithFormat("Frame index (%u) out of range.\n",
frame_idx);
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
@@ -460,7 +453,7 @@ public:
protected:
llvm::StringRef GetScopeString(VariableSP var_sp) {
if (!var_sp)
- return llvm::StringRef::withNullAsEmpty(nullptr);
+ return llvm::StringRef();
switch (var_sp->GetScope()) {
case eValueTypeVariableGlobal:
@@ -477,7 +470,7 @@ protected:
break;
}
- return llvm::StringRef::withNullAsEmpty(nullptr);
+ return llvm::StringRef();
}
bool DoExecute(Args &command, CommandReturnObject &result) override {
@@ -850,14 +843,12 @@ bool CommandObjectFrameRecognizerAdd::DoExecute(Args &command,
if (m_options.m_class_name.empty()) {
result.AppendErrorWithFormat(
"%s needs a Python class name (-l argument).\n", m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (m_options.m_module.empty()) {
result.AppendErrorWithFormat("%s needs a module name (-s argument).\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -865,7 +856,6 @@ bool CommandObjectFrameRecognizerAdd::DoExecute(Args &command,
result.AppendErrorWithFormat(
"%s needs at least one symbol name (-n argument).\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -873,7 +863,6 @@ bool CommandObjectFrameRecognizerAdd::DoExecute(Args &command,
result.AppendErrorWithFormat(
"%s needs only one symbol regular expression (-n argument).\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -968,7 +957,6 @@ protected:
"About to delete all frame recognizers, do you want to do that?",
true)) {
result.AppendMessage("Operation cancelled...");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -982,7 +970,6 @@ protected:
if (command.GetArgumentCount() != 1) {
result.AppendErrorWithFormat("'%s' takes zero or one arguments.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -990,7 +977,6 @@ protected:
if (!llvm::to_integer(command.GetArgumentAtIndex(0), recognizer_id)) {
result.AppendErrorWithFormat("'%s' is not a valid recognizer id.\n",
command.GetArgumentAtIndex(0));
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -999,7 +985,6 @@ protected:
.RemoveRecognizerWithID(recognizer_id)) {
result.AppendErrorWithFormat("'%s' is not a valid recognizer id.\n",
command.GetArgumentAtIndex(0));
- result.SetStatus(eReturnStatusFailed);
return false;
}
result.SetStatus(eReturnStatusSuccessFinishResult);
@@ -1084,33 +1069,28 @@ protected:
if (!llvm::to_integer(frame_index_str, frame_index)) {
result.AppendErrorWithFormat("'%s' is not a valid frame index.",
frame_index_str);
- result.SetStatus(eReturnStatusFailed);
return false;
}
Process *process = m_exe_ctx.GetProcessPtr();
if (process == nullptr) {
result.AppendError("no process");
- result.SetStatus(eReturnStatusFailed);
return false;
}
Thread *thread = m_exe_ctx.GetThreadPtr();
if (thread == nullptr) {
result.AppendError("no thread");
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (command.GetArgumentCount() != 1) {
result.AppendErrorWithFormat(
"'%s' takes exactly one frame index argument.\n", m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_index);
if (!frame_sp) {
result.AppendErrorWithFormat("no frame with index %u", frame_index);
- result.SetStatus(eReturnStatusFailed);
return false;
}
diff --git a/lldb/source/Commands/CommandObjectGUI.cpp b/lldb/source/Commands/CommandObjectGUI.cpp
index 3f45a26de228..86c47a2f0634 100644
--- a/lldb/source/Commands/CommandObjectGUI.cpp
+++ b/lldb/source/Commands/CommandObjectGUI.cpp
@@ -22,7 +22,7 @@ CommandObjectGUI::CommandObjectGUI(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "gui",
"Switch into the curses based GUI mode.", "gui") {}
-CommandObjectGUI::~CommandObjectGUI() {}
+CommandObjectGUI::~CommandObjectGUI() = default;
bool CommandObjectGUI::DoExecute(Args &args, CommandReturnObject &result) {
#if LLDB_ENABLE_CURSES
@@ -39,11 +39,9 @@ bool CommandObjectGUI::DoExecute(Args &args, CommandReturnObject &result) {
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendError("the gui command requires an interactive terminal.");
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError("the gui command takes no arguments.");
- result.SetStatus(eReturnStatusFailed);
}
return true;
#else
diff --git a/lldb/source/Commands/CommandObjectHelp.cpp b/lldb/source/Commands/CommandObjectHelp.cpp
index 6dc1868a2aff..4643ee30f0f9 100644
--- a/lldb/source/Commands/CommandObjectHelp.cpp
+++ b/lldb/source/Commands/CommandObjectHelp.cpp
@@ -139,7 +139,6 @@ bool CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) {
}
s.Printf("\n");
result.AppendError(s.GetString());
- result.SetStatus(eReturnStatusFailed);
return false;
} else if (!sub_cmd_obj) {
StreamString error_msg_stream;
@@ -147,7 +146,6 @@ bool CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) {
&error_msg_stream, cmd_string.c_str(),
m_interpreter.GetCommandPrefix(), sub_command.c_str());
result.AppendError(error_msg_stream.GetString());
- result.SetStatus(eReturnStatusFailed);
return false;
} else {
GenerateAdditionalHelpAvenuesMessage(
@@ -193,7 +191,6 @@ bool CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) {
m_interpreter.GetCommandPrefix(),
"");
result.AppendError(error_msg_stream.GetString());
- result.SetStatus(eReturnStatusFailed);
}
}
}
diff --git a/lldb/source/Commands/CommandObjectHelp.h b/lldb/source/Commands/CommandObjectHelp.h
index 8f45db55666e..c924dda7c6d4 100644
--- a/lldb/source/Commands/CommandObjectHelp.h
+++ b/lldb/source/Commands/CommandObjectHelp.h
@@ -34,7 +34,7 @@ public:
public:
CommandOptions() : Options() {}
- ~CommandOptions() override {}
+ ~CommandOptions() override = default;
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
ExecutionContext *execution_context) override {
diff --git a/lldb/source/Commands/CommandObjectLanguage.cpp b/lldb/source/Commands/CommandObjectLanguage.cpp
index e6d22ec4ae40..925db599e4ab 100644
--- a/lldb/source/Commands/CommandObjectLanguage.cpp
+++ b/lldb/source/Commands/CommandObjectLanguage.cpp
@@ -23,4 +23,4 @@ CommandObjectLanguage::CommandObjectLanguage(CommandInterpreter &interpreter)
LanguageRuntime::InitializeCommands(this);
}
-CommandObjectLanguage::~CommandObjectLanguage() {}
+CommandObjectLanguage::~CommandObjectLanguage() = default;
diff --git a/lldb/source/Commands/CommandObjectLog.cpp b/lldb/source/Commands/CommandObjectLog.cpp
index 4016b07c91ed..05ffba27e65f 100644
--- a/lldb/source/Commands/CommandObjectLog.cpp
+++ b/lldb/source/Commands/CommandObjectLog.cpp
@@ -76,7 +76,7 @@ public:
class CommandOptions : public Options {
public:
- CommandOptions() : Options(), log_file(), log_options(0) {}
+ CommandOptions() : Options(), log_file() {}
~CommandOptions() override = default;
@@ -136,7 +136,7 @@ public:
// Instance variables to hold the values for command options.
FileSpec log_file;
- uint32_t log_options;
+ uint32_t log_options = 0;
};
void
@@ -151,7 +151,6 @@ protected:
result.AppendErrorWithFormat(
"%s takes a log channel and one or more log types.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -225,7 +224,6 @@ protected:
result.AppendErrorWithFormat(
"%s takes a log channel and one or more log types.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp
index 7d5c642d0131..5487d94c9019 100644
--- a/lldb/source/Commands/CommandObjectMemory.cpp
+++ b/lldb/source/Commands/CommandObjectMemory.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "CommandObjectMemory.h"
+#include "CommandObjectMemoryTag.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/ValueObjectMemory.h"
@@ -46,8 +47,8 @@ using namespace lldb_private;
class OptionGroupReadMemory : public OptionGroup {
public:
OptionGroupReadMemory()
- : m_num_per_line(1, 1), m_output_as_binary(false), m_view_as_type(),
- m_offset(0, 0), m_language_for_type(eLanguageTypeUnknown) {}
+ : m_num_per_line(1, 1), m_view_as_type(), m_offset(0, 0),
+ m_language_for_type(eLanguageTypeUnknown) {}
~OptionGroupReadMemory() override = default;
@@ -270,7 +271,7 @@ public:
}
OptionValueUInt64 m_num_per_line;
- bool m_output_as_binary;
+ bool m_output_as_binary = false;
OptionValueString m_view_as_type;
bool m_force;
OptionValueUInt64 m_offset;
@@ -356,9 +357,8 @@ protected:
result.AppendErrorWithFormat("%s takes a start address expression with "
"an optional end address expression.\n",
m_cmd_name.c_str());
- result.AppendRawWarning("Expressions should be quoted if they contain "
- "spaces or other special characters.\n");
- result.SetStatus(eReturnStatusFailed);
+ result.AppendWarning("Expressions should be quoted if they contain "
+ "spaces or other special characters.");
return false;
}
@@ -439,7 +439,6 @@ protected:
} else {
result.AppendErrorWithFormat("invalid type string: '%s'\n",
view_as_type_cstr);
- result.SetStatus(eReturnStatusFailed);
return false;
}
break;
@@ -489,7 +488,6 @@ protected:
"Mutiple types found matching raw type '%s', please disambiguate "
"by specifying the language with -x",
lookup_type_name.GetCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -504,7 +502,6 @@ protected:
"the raw type '%s' for full type '%s'\n",
lookup_type_name.GetCString(),
view_as_type_cstr);
- result.SetStatus(eReturnStatusFailed);
return false;
} else {
TypeSP type_sp(type_list.GetTypeAtIndex(0));
@@ -518,7 +515,6 @@ protected:
compiler_type = pointer_type;
else {
result.AppendError("unable make a pointer type\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
--pointer_count;
@@ -529,7 +525,6 @@ protected:
result.AppendErrorWithFormat(
"unable to get the byte size of the type '%s'\n",
view_as_type_cstr);
- result.SetStatus(eReturnStatusFailed);
return false;
}
m_format_options.GetByteSizeValue() = *size;
@@ -543,7 +538,6 @@ protected:
// Look for invalid combinations of settings
if (error.Fail()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -593,7 +587,6 @@ protected:
if (addr == LLDB_INVALID_ADDRESS) {
result.AppendError("invalid start address expression.");
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -603,21 +596,18 @@ protected:
if (end_addr == LLDB_INVALID_ADDRESS) {
result.AppendError("invalid end address expression.");
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
} else if (end_addr <= addr) {
result.AppendErrorWithFormat(
"end address (0x%" PRIx64
- ") must be greater that the start address (0x%" PRIx64 ").\n",
+ ") must be greater than the start address (0x%" PRIx64 ").\n",
end_addr, addr);
- result.SetStatus(eReturnStatusFailed);
return false;
} else if (m_format_options.GetCountValue().OptionWasSet()) {
result.AppendErrorWithFormat(
"specify either the end address (0x%" PRIx64
") or the count (--count %" PRIu64 "), not both.\n",
end_addr, (uint64_t)item_count);
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -664,13 +654,12 @@ protected:
"can't allocate 0x%" PRIx32
" bytes for the memory read buffer, specify a smaller size to read",
(uint32_t)total_byte_size);
- result.SetStatus(eReturnStatusFailed);
return false;
}
Address address(addr, nullptr);
- bytes_read = target->ReadMemory(address, false, data_sp->GetBytes(),
- data_sp->GetByteSize(), error);
+ bytes_read = target->ReadMemory(address, data_sp->GetBytes(),
+ data_sp->GetByteSize(), error, true);
if (bytes_read == 0) {
const char *error_cstr = error.AsCString();
if (error_cstr && error_cstr[0]) {
@@ -679,7 +668,6 @@ protected:
result.AppendErrorWithFormat(
"failed to read memory from 0x%" PRIx64 ".\n", addr);
}
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -706,7 +694,6 @@ protected:
"can't allocate 0x%" PRIx64
" bytes for the memory read buffer, specify a smaller size to read",
(uint64_t)((item_byte_size + 1) * item_count));
- result.SetStatus(eReturnStatusFailed);
return false;
}
uint8_t *data_ptr = data_sp->GetBytes();
@@ -723,7 +710,6 @@ protected:
if (error.Fail()) {
result.AppendErrorWithFormat(
"failed to read memory from 0x%" PRIx64 ".\n", addr);
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -767,10 +753,11 @@ protected:
std::string path = outfile_spec.GetPath();
if (outfile_spec) {
- auto open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
+ File::OpenOptions open_options =
+ File::eOpenOptionWrite | File::eOpenOptionCanCreate;
const bool append = m_outfile_options.GetAppend().GetCurrentValue();
- if (append)
- open_options |= File::eOpenOptionAppend;
+ open_options |=
+ append ? File::eOpenOptionAppend : File::eOpenOptionTruncate;
auto outfile = FileSystem::Instance().Open(outfile_spec, open_options);
@@ -789,7 +776,6 @@ protected:
result.AppendErrorWithFormat("Failed to write %" PRIu64
" bytes to '%s'.\n",
(uint64_t)bytes_read, path.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else {
@@ -803,7 +789,6 @@ protected:
path.c_str(), append ? "append" : "write");
result.AppendError(llvm::toString(outfile.takeError()));
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else {
@@ -832,7 +817,6 @@ protected:
result.AppendErrorWithFormat(
"failed to create a value object for: (%s) %s\n",
view_as_type_cstr, name_strm.GetData());
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -862,7 +846,6 @@ protected:
result.AppendErrorWithFormat(
"reading memory as characters of size %" PRIu64 " is not supported",
(uint64_t)item_byte_size);
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -1293,14 +1276,12 @@ protected:
result.AppendErrorWithFormat(
"%s takes a destination address when writing file contents.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else if (argc < 2) {
result.AppendErrorWithFormat(
"%s takes a destination address and at least one value.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1319,7 +1300,6 @@ protected:
if (addr == LLDB_INVALID_ADDRESS) {
result.AppendError("invalid address expression\n");
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1354,12 +1334,10 @@ protected:
result.AppendErrorWithFormat("Memory write to 0x%" PRIx64
" failed: %s.\n",
addr, error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
}
} else {
result.AppendErrorWithFormat("Unable to read contents of file.\n");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
} else if (item_byte_size == 0) {
@@ -1404,7 +1382,6 @@ protected:
case eFormatInstruction:
case eFormatVoid:
result.AppendError("unsupported format for writing memory");
- result.SetStatus(eReturnStatusFailed);
return false;
case eFormatDefault:
@@ -1423,14 +1400,12 @@ protected:
if (!success) {
result.AppendErrorWithFormat(
"'%s' is not a valid hex string value.\n", entry.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
} else if (!llvm::isUIntN(item_byte_size * 8, uval64)) {
result.AppendErrorWithFormat("Value 0x%" PRIx64
" is too large to fit in a %" PRIu64
" byte unsigned integer value.\n",
uval64, (uint64_t)item_byte_size);
- result.SetStatus(eReturnStatusFailed);
return false;
}
buffer.PutMaxHex64(uval64, item_byte_size);
@@ -1441,7 +1416,6 @@ protected:
if (!success) {
result.AppendErrorWithFormat(
"'%s' is not a valid boolean string value.\n", entry.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
buffer.PutMaxHex64(uval64, item_byte_size);
@@ -1451,14 +1425,12 @@ protected:
if (entry.ref().getAsInteger(2, uval64)) {
result.AppendErrorWithFormat(
"'%s' is not a valid binary string value.\n", entry.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
} else if (!llvm::isUIntN(item_byte_size * 8, uval64)) {
result.AppendErrorWithFormat("Value 0x%" PRIx64
" is too large to fit in a %" PRIu64
" byte unsigned integer value.\n",
uval64, (uint64_t)item_byte_size);
- result.SetStatus(eReturnStatusFailed);
return false;
}
buffer.PutMaxHex64(uval64, item_byte_size);
@@ -1481,7 +1453,6 @@ protected:
result.AppendErrorWithFormat("Memory write to 0x%" PRIx64
" failed: %s.\n",
addr, error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
break;
@@ -1490,14 +1461,12 @@ protected:
if (entry.ref().getAsInteger(0, sval64)) {
result.AppendErrorWithFormat(
"'%s' is not a valid signed decimal value.\n", entry.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
} else if (!llvm::isIntN(item_byte_size * 8, sval64)) {
result.AppendErrorWithFormat(
"Value %" PRIi64 " is too large or small to fit in a %" PRIu64
" byte signed integer value.\n",
sval64, (uint64_t)item_byte_size);
- result.SetStatus(eReturnStatusFailed);
return false;
}
buffer.PutMaxHex64(sval64, item_byte_size);
@@ -1505,18 +1474,16 @@ protected:
case eFormatUnsigned:
- if (!entry.ref().getAsInteger(0, uval64)) {
+ if (entry.ref().getAsInteger(0, uval64)) {
result.AppendErrorWithFormat(
"'%s' is not a valid unsigned decimal string value.\n",
entry.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
} else if (!llvm::isUIntN(item_byte_size * 8, uval64)) {
result.AppendErrorWithFormat("Value %" PRIu64
" is too large to fit in a %" PRIu64
" byte unsigned integer value.\n",
uval64, (uint64_t)item_byte_size);
- result.SetStatus(eReturnStatusFailed);
return false;
}
buffer.PutMaxHex64(uval64, item_byte_size);
@@ -1526,14 +1493,12 @@ protected:
if (entry.ref().getAsInteger(8, uval64)) {
result.AppendErrorWithFormat(
"'%s' is not a valid octal string value.\n", entry.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
} else if (!llvm::isUIntN(item_byte_size * 8, uval64)) {
result.AppendErrorWithFormat("Value %" PRIo64
" is too large to fit in a %" PRIu64
" byte unsigned integer value.\n",
uval64, (uint64_t)item_byte_size);
- result.SetStatus(eReturnStatusFailed);
return false;
}
buffer.PutMaxHex64(uval64, item_byte_size);
@@ -1551,7 +1516,6 @@ protected:
result.AppendErrorWithFormat("Memory write to 0x%" PRIx64
" failed: %s.\n",
addr, error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -1604,7 +1568,6 @@ protected:
if (argc == 0 || argc > 1) {
result.AppendErrorWithFormat("%s takes an address expression",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1615,7 +1578,6 @@ protected:
if (addr == LLDB_INVALID_ADDRESS) {
result.AppendError("invalid address expression");
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1627,7 +1589,6 @@ protected:
if (!memory_history) {
result.AppendError("no available memory history provider");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1666,7 +1627,6 @@ protected:
if (!process_sp) {
m_prev_end_addr = LLDB_INVALID_ADDRESS;
result.AppendError("invalid process");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1678,7 +1638,6 @@ protected:
if (argc > 1 || (argc == 0 && load_addr == LLDB_INVALID_ADDRESS)) {
result.AppendErrorWithFormat("'%s' takes one argument:\nUsage: %s\n",
m_cmd_name.c_str(), m_cmd_syntax.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1689,7 +1648,6 @@ protected:
if (error.Fail() || load_addr == LLDB_INVALID_ADDRESS) {
result.AppendErrorWithFormat("invalid address argument \"%s\": %s\n",
command[0].c_str(), error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -1721,12 +1679,33 @@ protected:
if (memory_tagged == MemoryRegionInfo::OptionalBool::eYes)
result.AppendMessage("memory tagging: enabled");
+ const llvm::Optional<std::vector<addr_t>> &dirty_page_list =
+ range_info.GetDirtyPageList();
+ if (dirty_page_list.hasValue()) {
+ const size_t page_count = dirty_page_list.getValue().size();
+ result.AppendMessageWithFormat(
+ "Modified memory (dirty) page list provided, %zu entries.\n",
+ page_count);
+ if (page_count > 0) {
+ bool print_comma = false;
+ result.AppendMessageWithFormat("Dirty pages: ");
+ for (size_t i = 0; i < page_count; i++) {
+ if (print_comma)
+ result.AppendMessageWithFormat(", ");
+ else
+ print_comma = true;
+ result.AppendMessageWithFormat("0x%" PRIx64,
+ dirty_page_list.getValue()[i]);
+ }
+ result.AppendMessageWithFormat(".\n");
+ }
+ }
+
m_prev_end_addr = range_info.GetRange().GetRangeEnd();
result.SetStatus(eReturnStatusSuccessFinishResult);
return true;
}
- result.SetStatus(eReturnStatusFailed);
result.AppendErrorWithFormat("%s\n", error.AsCString());
return false;
}
@@ -1758,6 +1737,8 @@ CommandObjectMemory::CommandObjectMemory(CommandInterpreter &interpreter)
CommandObjectSP(new CommandObjectMemoryHistory(interpreter)));
LoadSubCommand("region",
CommandObjectSP(new CommandObjectMemoryRegion(interpreter)));
+ LoadSubCommand("tag",
+ CommandObjectSP(new CommandObjectMemoryTag(interpreter)));
}
CommandObjectMemory::~CommandObjectMemory() = default;
diff --git a/lldb/source/Commands/CommandObjectMemoryTag.cpp b/lldb/source/Commands/CommandObjectMemoryTag.cpp
new file mode 100644
index 000000000000..1dfb32a92f3b
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectMemoryTag.cpp
@@ -0,0 +1,128 @@
+//===-- CommandObjectMemoryTag.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 "CommandObjectMemoryTag.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#define LLDB_OPTIONS_memory_tag_read
+#include "CommandOptions.inc"
+
+class CommandObjectMemoryTagRead : public CommandObjectParsed {
+public:
+ CommandObjectMemoryTagRead(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "tag",
+ "Read memory tags for the given range of memory.",
+ nullptr,
+ eCommandRequiresTarget | eCommandRequiresProcess |
+ eCommandProcessMustBePaused) {
+ // Address
+ m_arguments.push_back(
+ CommandArgumentEntry{CommandArgumentData(eArgTypeAddressOrExpression)});
+ // Optional end address
+ m_arguments.push_back(CommandArgumentEntry{
+ CommandArgumentData(eArgTypeAddressOrExpression, eArgRepeatOptional)});
+ }
+
+ ~CommandObjectMemoryTagRead() override = default;
+
+protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ if ((command.GetArgumentCount() < 1) || (command.GetArgumentCount() > 2)) {
+ result.AppendError(
+ "wrong number of arguments; expected at least <address-expression>, "
+ "at most <address-expression> <end-address-expression>");
+ return false;
+ }
+
+ Status error;
+ addr_t start_addr = OptionArgParser::ToAddress(
+ &m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error);
+ if (start_addr == LLDB_INVALID_ADDRESS) {
+ result.AppendErrorWithFormatv("Invalid address expression, {0}",
+ error.AsCString());
+ return false;
+ }
+
+ // Default 1 byte beyond start, rounds up to at most 1 granule later
+ addr_t end_addr = start_addr + 1;
+
+ if (command.GetArgumentCount() > 1) {
+ end_addr = OptionArgParser::ToAddress(&m_exe_ctx, command[1].ref(),
+ LLDB_INVALID_ADDRESS, &error);
+ if (end_addr == LLDB_INVALID_ADDRESS) {
+ result.AppendErrorWithFormatv("Invalid end address expression, {0}",
+ error.AsCString());
+ return false;
+ }
+ }
+
+ Process *process = m_exe_ctx.GetProcessPtr();
+ llvm::Expected<const MemoryTagManager *> tag_manager_or_err =
+ process->GetMemoryTagManager();
+
+ if (!tag_manager_or_err) {
+ result.SetError(Status(tag_manager_or_err.takeError()));
+ return false;
+ }
+
+ const MemoryTagManager *tag_manager = *tag_manager_or_err;
+
+ MemoryRegionInfos memory_regions;
+ // If this fails the list of regions is cleared, so we don't need to read
+ // the return status here.
+ process->GetMemoryRegions(memory_regions);
+ llvm::Expected<MemoryTagManager::TagRange> tagged_range =
+ tag_manager->MakeTaggedRange(start_addr, end_addr, memory_regions);
+
+ if (!tagged_range) {
+ result.SetError(Status(tagged_range.takeError()));
+ return false;
+ }
+
+ llvm::Expected<std::vector<lldb::addr_t>> tags = process->ReadMemoryTags(
+ tagged_range->GetRangeBase(), tagged_range->GetByteSize());
+
+ if (!tags) {
+ result.SetError(Status(tags.takeError()));
+ return false;
+ }
+
+ result.AppendMessageWithFormatv("Logical tag: {0:x}",
+ tag_manager->GetLogicalTag(start_addr));
+ result.AppendMessage("Allocation tags:");
+
+ addr_t addr = tagged_range->GetRangeBase();
+ for (auto tag : *tags) {
+ addr_t next_addr = addr + tag_manager->GetGranuleSize();
+ // Showing tagged adresses here until we have non address bit handling
+ result.AppendMessageWithFormatv("[{0:x}, {1:x}): {2:x}", addr, next_addr,
+ tag);
+ addr = next_addr;
+ }
+
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+};
+
+CommandObjectMemoryTag::CommandObjectMemoryTag(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "tag", "Commands for manipulating memory tags",
+ "memory tag <sub-command> [<sub-command-options>]") {
+ CommandObjectSP read_command_object(
+ new CommandObjectMemoryTagRead(interpreter));
+ read_command_object->SetCommandName("memory tag read");
+ LoadSubCommand("read", read_command_object);
+}
+
+CommandObjectMemoryTag::~CommandObjectMemoryTag() = default;
diff --git a/lldb/source/Commands/CommandObjectMemoryTag.h b/lldb/source/Commands/CommandObjectMemoryTag.h
new file mode 100644
index 000000000000..54909ac90811
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectMemoryTag.h
@@ -0,0 +1,25 @@
+//===-- CommandObjectMemoryTag.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_SOURCE_COMMANDS_COMMANDOBJECTMEMORYTAG_H
+#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTMEMORYTAG_H
+
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+class CommandObjectMemoryTag : public CommandObjectMultiword {
+public:
+ CommandObjectMemoryTag(CommandInterpreter &interpreter);
+
+ ~CommandObjectMemoryTag() override;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTMEMORYTAG_H
diff --git a/lldb/source/Commands/CommandObjectMultiword.cpp b/lldb/source/Commands/CommandObjectMultiword.cpp
index 0f20a1d88bd9..a523fd0b1560 100644
--- a/lldb/source/Commands/CommandObjectMultiword.cpp
+++ b/lldb/source/Commands/CommandObjectMultiword.cpp
@@ -98,7 +98,7 @@ bool CommandObjectMultiword::Execute(const char *args_string,
return result.Succeeded();
}
- if (sub_command.equals_lower("help")) {
+ if (sub_command.equals_insensitive("help")) {
this->CommandObject::GenerateHelpText(result);
return result.Succeeded();
}
@@ -106,7 +106,6 @@ bool CommandObjectMultiword::Execute(const char *args_string,
if (m_subcommand_dict.empty()) {
result.AppendErrorWithFormat("'%s' does not have any subcommands.\n",
GetCommandName().str().c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -144,7 +143,6 @@ bool CommandObjectMultiword::Execute(const char *args_string,
}
error_msg.append("\n");
result.AppendRawError(error_msg.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -398,6 +396,6 @@ bool CommandObjectProxy::Execute(const char *args_string,
CommandObject *proxy_command = GetProxyCommandObject();
if (proxy_command)
return proxy_command->Execute(args_string, result);
- result.SetError(GetUnsupportedError());
+ result.AppendError(GetUnsupportedError());
return false;
}
diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp
index f306da3c8543..bf23c4552aa8 100644
--- a/lldb/source/Commands/CommandObjectPlatform.cpp
+++ b/lldb/source/Commands/CommandObjectPlatform.cpp
@@ -60,7 +60,7 @@ static mode_t ParsePermissionString(llvm::StringRef permissions) {
class OptionPermissions : public OptionGroup {
public:
- OptionPermissions() {}
+ OptionPermissions() = default;
~OptionPermissions() override = default;
@@ -180,16 +180,13 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError("invalid platform name");
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError(
"platform create takes a platform name as an argument\n");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -232,7 +229,6 @@ protected:
if (idx == 0) {
result.AppendError("no platforms are available\n");
- result.SetStatus(eReturnStatusFailed);
} else
result.SetStatus(eReturnStatusSuccessFinishResult);
return result.Succeeded();
@@ -266,7 +262,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendError("no platform is currently selected\n");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -298,15 +293,12 @@ protected:
platform_sp->ConnectToWaitingProcesses(GetDebugger(), error);
if (error.Fail()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendErrorWithFormat("%s\n", error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError("no platform is currently selected\n");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -361,24 +353,20 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendErrorWithFormat("%s", error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
// Not connected...
result.AppendErrorWithFormat(
"not connected to '%s'",
platform_sp->GetPluginName().GetCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
// Bad args
result.AppendError(
"\"platform disconnect\" doesn't take any arguments");
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError("no platform is currently selected");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -412,7 +400,6 @@ protected:
m_option_working_dir.GetOptionValue().GetCurrentValue());
} else {
result.AppendError("no platform is currently selected");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -457,11 +444,9 @@ public:
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError("no platform currently selected\n");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -521,11 +506,9 @@ public:
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError("no platform currently selected\n");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -560,7 +543,6 @@ public:
if (!llvm::to_integer(cmd_line, fd)) {
result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.\n",
cmd_line);
- result.SetStatus(eReturnStatusFailed);
return result.Succeeded();
}
Status error;
@@ -570,11 +552,9 @@ public:
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError("no platform currently selected\n");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -605,7 +585,6 @@ public:
if (!llvm::to_integer(cmd_line, fd)) {
result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.\n",
cmd_line);
- result.SetStatus(eReturnStatusFailed);
return result.Succeeded();
}
std::string buffer(m_options.m_count, 0);
@@ -617,7 +596,6 @@ public:
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendError("no platform currently selected\n");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -698,7 +676,6 @@ public:
if (!llvm::to_integer(cmd_line, fd)) {
result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.",
cmd_line);
- result.SetStatus(eReturnStatusFailed);
return result.Succeeded();
}
uint32_t retcode =
@@ -708,7 +685,6 @@ public:
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendError("no platform currently selected\n");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -844,10 +820,8 @@ public:
bool DoExecute(Args &args, CommandReturnObject &result) override {
// If the number of arguments is incorrect, issue an error message.
if (args.GetArgumentCount() != 2) {
- result.GetErrorStream().Printf("error: required arguments missing; "
- "specify both the source and destination "
- "file paths\n");
- result.SetStatus(eReturnStatusFailed);
+ result.AppendError("required arguments missing; specify both the "
+ "source and destination file paths");
return false;
}
@@ -866,11 +840,9 @@ public:
} else {
result.AppendMessageWithFormat("get-file failed: %s\n",
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError("no platform currently selected\n");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -920,10 +892,8 @@ public:
bool DoExecute(Args &args, CommandReturnObject &result) override {
// If the number of arguments is incorrect, issue an error message.
if (args.GetArgumentCount() != 1) {
- result.GetErrorStream().Printf("error: required argument missing; "
- "specify the source file path as the only "
- "argument\n");
- result.SetStatus(eReturnStatusFailed);
+ result.AppendError("required argument missing; specify the source file "
+ "path as the only argument");
return false;
}
@@ -941,11 +911,9 @@ public:
result.AppendMessageWithFormat(
"Error getting file size of %s (remote)\n",
remote_file_path.c_str());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError("no platform currently selected\n");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -991,11 +959,9 @@ public:
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError("no platform currently selected\n");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -1009,11 +975,14 @@ public:
"Launch a new process on a remote platform.",
"platform process launch program",
eCommandRequiresTarget | eCommandTryTargetAPILock),
- m_options() {}
+ m_options(), m_all_options() {
+ m_all_options.Append(&m_options);
+ m_all_options.Finalize();
+ }
~CommandObjectPlatformProcessLaunch() override = default;
- Options *GetOptions() override { return &m_options; }
+ Options *GetOptions() override { return &m_all_options; }
protected:
bool DoExecute(Args &args, CommandReturnObject &result) override {
@@ -1070,12 +1039,10 @@ protected:
result.AppendError("process launch failed");
else
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
} else {
result.AppendError("'platform process launch' uses the current target "
"file and arguments, or the executable and its "
"arguments can be specified in this command");
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else {
@@ -1085,6 +1052,7 @@ protected:
}
CommandOptionsProcessLaunch m_options;
+ OptionGroupOptions m_all_options;
};
// "platform process list"
@@ -1136,7 +1104,6 @@ protected:
} else {
result.AppendErrorWithFormat(
"no process found with pid = %" PRIu64 "\n", pid);
- result.SetStatus(eReturnStatusFailed);
}
} else {
ProcessInstanceInfoList proc_infos;
@@ -1178,7 +1145,6 @@ protected:
result.AppendErrorWithFormat(
"no processes were found on the \"%s\" platform\n",
platform_sp->GetPluginName().GetCString());
- result.SetStatus(eReturnStatusFailed);
} else {
result.AppendMessageWithFormat(
"%u matching process%s found on \"%s\"", matches,
@@ -1200,19 +1166,16 @@ protected:
}
} else {
result.AppendError("invalid args: process list takes only options\n");
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError("no platform is selected\n");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
class CommandOptions : public Options {
public:
- CommandOptions()
- : Options(), match_info(), show_args(false), verbose(false) {}
+ CommandOptions() : Options(), match_info() {}
~CommandOptions() override = default;
@@ -1347,8 +1310,8 @@ protected:
// Instance variables to hold the values for command options.
ProcessInstanceInfoMatch match_info;
- bool show_args;
- bool verbose;
+ bool show_args = false;
+ bool verbose = false;
};
CommandOptions m_options;
@@ -1410,7 +1373,6 @@ protected:
if (entry.ref().getAsInteger(0, pid)) {
result.AppendErrorWithFormat("invalid process ID argument '%s'",
entry.ref().str().c_str());
- result.SetStatus(eReturnStatusFailed);
break;
} else {
ProcessInstanceInfo proc_info;
@@ -1431,16 +1393,13 @@ protected:
result.AppendErrorWithFormat(
"not connected to '%s'",
platform_sp->GetPluginName().GetCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
// No args
result.AppendError("one or more process id(s) must be specified");
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError("no platform is currently selected");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -1529,15 +1488,12 @@ public:
m_options.attach_info, GetDebugger(), nullptr, err);
if (err.Fail()) {
result.AppendError(err.AsCString());
- result.SetStatus(eReturnStatusFailed);
} else if (!remote_process_sp) {
result.AppendError("could not attach: unknown reason");
- result.SetStatus(eReturnStatusFailed);
} else
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendError("no platform is currently selected");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -1715,7 +1671,6 @@ public:
if (error.Fail()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
} else {
result.SetStatus(eReturnStatusSuccessFinishResult);
}
@@ -1749,7 +1704,6 @@ public:
bool DoExecute(Args &args, CommandReturnObject &result) override {
if (args.GetArgumentCount() != 2) {
result.AppendError("platform target-install takes two arguments");
- result.SetStatus(eReturnStatusFailed);
return false;
}
// TODO: move the bulk of this code over to the platform itself
@@ -1758,14 +1712,12 @@ public:
FileSpec dst(args.GetArgumentAtIndex(1));
if (!FileSystem::Instance().Exists(src)) {
result.AppendError("source location does not exist or is not accessible");
- result.SetStatus(eReturnStatusFailed);
return false;
}
PlatformSP platform_sp(
GetDebugger().GetPlatformList().GetSelectedPlatform());
if (!platform_sp) {
result.AppendError("no platform currently selected");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1774,7 +1726,6 @@ public:
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
result.AppendErrorWithFormat("install failed: %s", error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
diff --git a/lldb/source/Commands/CommandObjectPlugin.cpp b/lldb/source/Commands/CommandObjectPlugin.cpp
index 98a212eef0fa..881415a49472 100644
--- a/lldb/source/Commands/CommandObjectPlugin.cpp
+++ b/lldb/source/Commands/CommandObjectPlugin.cpp
@@ -50,7 +50,6 @@ protected:
if (argc != 1) {
result.AppendError("'plugin load' requires one argument");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -63,7 +62,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishResult);
else {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index 35835f638557..7aaba3731500 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "CommandObjectProcess.h"
+#include "CommandObjectTrace.h"
#include "CommandOptionsProcessLaunch.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
@@ -17,6 +18,7 @@
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
+#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
@@ -27,6 +29,8 @@
#include "lldb/Utility/Args.h"
#include "lldb/Utility/State.h"
+#include <bitset>
+
using namespace lldb;
using namespace lldb_private;
@@ -77,7 +81,6 @@ protected:
result.AppendErrorWithFormat(
"Failed to detach from process: %s\n",
detach_error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
Status destroy_error(process->Destroy(false));
@@ -87,7 +90,6 @@ protected:
} else {
result.AppendErrorWithFormat("Failed to kill process: %s\n",
destroy_error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
}
}
@@ -108,7 +110,14 @@ public:
interpreter, "process launch",
"Launch the executable in the debugger.", nullptr,
eCommandRequiresTarget, "restart"),
- m_options() {
+ m_options(),
+ m_class_options("scripted process", true, 'C', 'k', 'v', 0),
+ m_all_options() {
+ m_all_options.Append(&m_options);
+ m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
+ LLDB_OPT_SET_ALL);
+ m_all_options.Finalize();
+
CommandArgumentEntry arg;
CommandArgumentData run_args_arg;
@@ -135,7 +144,7 @@ public:
request, nullptr);
}
- Options *GetOptions() override { return &m_options; }
+ Options *GetOptions() override { return &m_all_options; }
const char *GetRepeatCommand(Args &current_command_args,
uint32_t index) override {
@@ -153,7 +162,6 @@ protected:
if (exe_module_sp == nullptr) {
result.AppendError("no file in target, create a debug target using the "
"'target create' command");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -180,6 +188,15 @@ protected:
disable_aslr = target->GetDisableASLR();
}
+ if (!m_class_options.GetName().empty()) {
+ m_options.launch_info.SetProcessPluginName("ScriptedProcess");
+ m_options.launch_info.SetScriptedProcessClassName(
+ m_class_options.GetName());
+ m_options.launch_info.SetScriptedProcessDictionarySP(
+ m_class_options.GetStructuredData());
+ target->SetProcessLaunchInfo(m_options.launch_info);
+ }
+
if (disable_aslr)
m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
else
@@ -243,16 +260,16 @@ protected:
} else {
result.AppendError(
"no error returned from Target::Launch, and target has no process");
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
CommandOptionsProcessLaunch m_options;
+ OptionGroupPythonClassWithDict m_class_options;
+ OptionGroupOptions m_all_options;
};
#define LLDB_OPTIONS_process_attach
@@ -377,11 +394,9 @@ protected:
if (command.GetArgumentCount()) {
result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n",
m_cmd_name.c_str(), m_cmd_syntax.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
- m_interpreter.UpdateExecutionContext(nullptr);
StreamString stream;
const auto error = target->Attach(m_options.attach_info, &stream);
if (error.Success()) {
@@ -393,11 +408,9 @@ protected:
} else {
result.AppendError(
"no error returned from Target::Attach, and target has no process");
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
if (!result.Succeeded())
@@ -517,7 +530,6 @@ protected:
result.AppendErrorWithFormat(
"The '%s' command does not take any arguments.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -589,13 +601,11 @@ protected:
} else {
result.AppendErrorWithFormat("Failed to resume process: %s.\n",
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendErrorWithFormat(
"Process cannot be continued from its current state (%s).\n",
StateAsCString(state));
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -687,7 +697,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
return result.Succeeded();
@@ -759,7 +768,6 @@ protected:
result.AppendErrorWithFormat(
"'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(),
m_cmd_syntax.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -769,7 +777,6 @@ protected:
"Process %" PRIu64
" is currently being debugged, kill the process before connecting.\n",
process->GetID());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -791,7 +798,6 @@ protected:
error);
if (error.Fail() || process_sp == nullptr) {
result.AppendError(error.AsCString("Error connecting to the process"));
- result.SetStatus(eReturnStatusFailed);
return false;
}
return true;
@@ -931,7 +937,6 @@ protected:
result.AppendErrorWithFormat("failed to load '%s': %s",
image_path.str().c_str(),
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
}
return result.Succeeded();
@@ -983,7 +988,6 @@ protected:
if (entry.ref().getAsInteger(0, image_token)) {
result.AppendErrorWithFormat("invalid image index argument '%s'",
entry.ref().str().c_str());
- result.SetStatus(eReturnStatusFailed);
break;
} else {
Status error(process->GetTarget().GetPlatform()->UnloadImage(
@@ -995,7 +999,6 @@ protected:
} else {
result.AppendErrorWithFormat("failed to unload image: %s",
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
break;
}
}
@@ -1040,7 +1043,7 @@ public:
UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals();
int signo = signals->GetFirstSignalNumber();
while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
- request.AddCompletion(signals->GetSignalAsCString(signo), "");
+ request.TryCompleteCurrentArg(signals->GetSignalAsCString(signo));
signo = signals->GetNextSignalNumber(signo);
}
}
@@ -1062,7 +1065,6 @@ protected:
if (signo == LLDB_INVALID_SIGNAL_NUMBER) {
result.AppendErrorWithFormat("Invalid signal argument '%s'.\n",
command.GetArgumentAtIndex(0));
- result.SetStatus(eReturnStatusFailed);
} else {
Status error(process->Signal(signo));
if (error.Success()) {
@@ -1070,14 +1072,12 @@ protected:
} else {
result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo,
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
}
} else {
result.AppendErrorWithFormat(
"'%s' takes exactly one signal number argument:\nUsage: %s\n",
m_cmd_name.c_str(), m_cmd_syntax.c_str());
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -1102,7 +1102,6 @@ protected:
Process *process = m_exe_ctx.GetProcessPtr();
if (process == nullptr) {
result.AppendError("no process to halt");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1114,12 +1113,10 @@ protected:
} else {
result.AppendErrorWithFormat("Failed to halt process: %s\n",
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
m_cmd_name.c_str(), m_cmd_syntax.c_str());
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -1144,7 +1141,6 @@ protected:
Process *process = m_exe_ctx.GetProcessPtr();
if (process == nullptr) {
result.AppendError("no process to kill");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1155,12 +1151,10 @@ protected:
} else {
result.AppendErrorWithFormat("Failed to kill process: %s\n",
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
m_cmd_name.c_str(), m_cmd_syntax.c_str());
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -1169,45 +1163,109 @@ protected:
// CommandObjectProcessSaveCore
#pragma mark CommandObjectProcessSaveCore
+static constexpr OptionEnumValueElement g_corefile_save_style[] = {
+ {eSaveCoreFull, "full", "Create a core file with all memory saved"},
+ {eSaveCoreDirtyOnly, "modified-memory",
+ "Create a corefile with only modified memory saved"}};
+
+static constexpr OptionEnumValues SaveCoreStyles() {
+ return OptionEnumValues(g_corefile_save_style);
+}
+
+#define LLDB_OPTIONS_process_save_core
+#include "CommandOptions.inc"
+
class CommandObjectProcessSaveCore : public CommandObjectParsed {
public:
CommandObjectProcessSaveCore(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "process save-core",
"Save the current process as a core file using an "
"appropriate file type.",
- "process save-core FILE",
+ "process save-core [-s corefile-style] FILE",
eCommandRequiresProcess | eCommandTryTargetAPILock |
eCommandProcessMustBeLaunched) {}
~CommandObjectProcessSaveCore() override = default;
+ Options *GetOptions() override { return &m_options; }
+
+ class CommandOptions : public Options {
+ public:
+ CommandOptions()
+ : Options(), m_requested_save_core_style(eSaveCoreUnspecified) {}
+
+ ~CommandOptions() override = default;
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+ return llvm::makeArrayRef(g_process_save_core_options);
+ }
+
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override {
+ const int short_option = m_getopt_table[option_idx].val;
+ Status error;
+
+ switch (short_option) {
+ case 's':
+ m_requested_save_core_style =
+ (lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum(
+ option_arg, GetDefinitions()[option_idx].enum_values,
+ eSaveCoreUnspecified, error);
+ break;
+ default:
+ llvm_unreachable("Unimplemented option");
+ }
+
+ return {};
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_requested_save_core_style = eSaveCoreUnspecified;
+ }
+
+ // Instance variables to hold the values for command options.
+ SaveCoreStyle m_requested_save_core_style;
+ };
+
protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
ProcessSP process_sp = m_exe_ctx.GetProcessSP();
if (process_sp) {
if (command.GetArgumentCount() == 1) {
FileSpec output_file(command.GetArgumentAtIndex(0));
- Status error = PluginManager::SaveCore(process_sp, output_file);
+ SaveCoreStyle corefile_style = m_options.m_requested_save_core_style;
+ Status error =
+ PluginManager::SaveCore(process_sp, output_file, corefile_style);
if (error.Success()) {
+ if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly) {
+ result.AppendMessageWithFormat(
+ "\nModified-memory only corefile "
+ "created. This corefile may not show \n"
+ "library/framework/app binaries "
+ "on a different system, or when \n"
+ "those binaries have "
+ "been updated/modified. Copies are not included\n"
+ "in this corefile. Use --style full to include all "
+ "process memory.\n");
+ }
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendErrorWithFormat(
"Failed to save core file for process: %s\n", error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n",
m_cmd_name.c_str(), m_cmd_syntax.c_str());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError("invalid process");
- result.SetStatus(eReturnStatusFailed);
return false;
}
return result.Succeeded();
}
+
+ CommandOptions m_options;
};
// CommandObjectProcessStatus
@@ -1231,7 +1289,7 @@ public:
class CommandOptions : public Options {
public:
- CommandOptions() : Options(), m_verbose(false) {}
+ CommandOptions() : Options() {}
~CommandOptions() override = default;
@@ -1259,7 +1317,7 @@ public:
}
// Instance variables to hold the values for command options.
- bool m_verbose;
+ bool m_verbose = false;
};
protected:
@@ -1269,7 +1327,6 @@ protected:
if (command.GetArgumentCount()) {
result.AppendError("'process status' takes no arguments");
- result.SetStatus(eReturnStatusFailed);
return result.Succeeded();
}
@@ -1286,10 +1343,21 @@ protected:
num_frames, num_frames_with_source, stop_format);
if (m_options.m_verbose) {
+ addr_t code_mask = process->GetCodeAddressMask();
+ addr_t data_mask = process->GetDataAddressMask();
+ if (code_mask != 0) {
+ int bits = std::bitset<64>(~code_mask).count();
+ result.AppendMessageWithFormat(
+ "Addressable code address mask: 0x%" PRIx64 "\n", code_mask);
+ result.AppendMessageWithFormat(
+ "Addressable data address mask: 0x%" PRIx64 "\n", data_mask);
+ result.AppendMessageWithFormat(
+ "Number of bits used in addressing (code): %d\n", bits);
+ }
+
PlatformSP platform_sp = process->GetTarget().GetPlatform();
if (!platform_sp) {
result.AppendError("Couldn'retrieve the target's platform");
- result.SetStatus(eReturnStatusFailed);
return result.Succeeded();
}
@@ -1298,7 +1366,6 @@ protected:
if (!expected_crash_info) {
result.AppendError(llvm::toString(expected_crash_info.takeError()));
- result.SetStatus(eReturnStatusFailed);
return result.Succeeded();
}
@@ -1467,7 +1534,6 @@ protected:
if (!process_sp) {
result.AppendError("No current process; cannot handle signals until you "
"have a valid process.\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1479,7 +1545,6 @@ protected:
!VerifyCommandOptionValue(m_options.stop, stop_action)) {
result.AppendError("Invalid argument for command option --stop; must be "
"true or false.\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1487,7 +1552,6 @@ protected:
!VerifyCommandOptionValue(m_options.notify, notify_action)) {
result.AppendError("Invalid argument for command option --notify; must "
"be true or false.\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1495,7 +1559,6 @@ protected:
!VerifyCommandOptionValue(m_options.pass, pass_action)) {
result.AppendError("Invalid argument for command option --pass; must be "
"true or false.\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1559,6 +1622,71 @@ protected:
CommandOptions m_options;
};
+// Next are the subcommands of CommandObjectMultiwordProcessTrace
+
+// CommandObjectProcessTraceStart
+class CommandObjectProcessTraceStart : public CommandObjectTraceProxy {
+public:
+ CommandObjectProcessTraceStart(CommandInterpreter &interpreter)
+ : CommandObjectTraceProxy(
+ /*live_debug_session_only*/ true, interpreter,
+ "process trace start",
+ "Start tracing this process with the corresponding trace "
+ "plug-in.",
+ "process trace start [<trace-options>]") {}
+
+protected:
+ lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override {
+ return trace.GetProcessTraceStartCommand(m_interpreter);
+ }
+};
+
+// CommandObjectProcessTraceStop
+class CommandObjectProcessTraceStop : public CommandObjectParsed {
+public:
+ CommandObjectProcessTraceStop(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "process trace stop",
+ "Stop tracing this process. This does not affect "
+ "traces started with the "
+ "\"thread trace start\" command.",
+ "process trace stop",
+ eCommandRequiresProcess | eCommandTryTargetAPILock |
+ eCommandProcessMustBeLaunched |
+ eCommandProcessMustBePaused |
+ eCommandProcessMustBeTraced) {}
+
+ ~CommandObjectProcessTraceStop() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ ProcessSP process_sp = m_exe_ctx.GetProcessSP();
+
+ TraceSP trace_sp = process_sp->GetTarget().GetTrace();
+
+ if (llvm::Error err = trace_sp->Stop())
+ result.AppendError(toString(std::move(err)));
+ else
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+
+ return result.Succeeded();
+ }
+};
+
+// CommandObjectMultiwordProcessTrace
+class CommandObjectMultiwordProcessTrace : public CommandObjectMultiword {
+public:
+ CommandObjectMultiwordProcessTrace(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "trace", "Commands for tracing the current process.",
+ "process trace <subcommand> [<subcommand objects>]") {
+ LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart(
+ interpreter)));
+ LoadSubCommand("stop", CommandObjectSP(
+ new CommandObjectProcessTraceStop(interpreter)));
+ }
+
+ ~CommandObjectMultiwordProcessTrace() override = default;
+};
+
// CommandObjectMultiwordProcess
CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(
@@ -1595,6 +1723,9 @@ CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(
CommandObjectSP(new CommandObjectProcessPlugin(interpreter)));
LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore(
interpreter)));
+ LoadSubCommand(
+ "trace",
+ CommandObjectSP(new CommandObjectMultiwordProcessTrace(interpreter)));
}
CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default;
diff --git a/lldb/source/Commands/CommandObjectQuit.cpp b/lldb/source/Commands/CommandObjectQuit.cpp
index d4d15bea9a8e..c6e2e21de6b6 100644
--- a/lldb/source/Commands/CommandObjectQuit.cpp
+++ b/lldb/source/Commands/CommandObjectQuit.cpp
@@ -22,7 +22,7 @@ CommandObjectQuit::CommandObjectQuit(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "quit", "Quit the LLDB debugger.",
"quit [exit-code]") {}
-CommandObjectQuit::~CommandObjectQuit() {}
+CommandObjectQuit::~CommandObjectQuit() = default;
// returns true if there is at least one alive process is_a_detach will be true
// if all alive processes will be detached when you quit and false if at least
@@ -75,7 +75,6 @@ bool CommandObjectQuit::DoExecute(Args &command, CommandReturnObject &result) {
if (command.GetArgumentCount() > 1) {
result.AppendError("Too many arguments for 'quit'. Only an optional exit "
"code is allowed");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -88,13 +87,11 @@ bool CommandObjectQuit::DoExecute(Args &command, CommandReturnObject &result) {
std::string arg_str = arg.str();
s.Printf("Couldn't parse '%s' as integer for exit code.", arg_str.data());
result.AppendError(s.GetString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (!m_interpreter.SetQuitExitCode(exit_code)) {
result.AppendError("The current driver doesn't allow custom exit codes"
" for the quit command.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -104,8 +101,5 @@ bool CommandObjectQuit::DoExecute(Args &command, CommandReturnObject &result) {
m_interpreter.BroadcastEvent(event_type);
result.SetStatus(eReturnStatusQuit);
- if (m_interpreter.GetSaveSessionOnQuit())
- m_interpreter.SaveTranscript(result);
-
return true;
}
diff --git a/lldb/source/Commands/CommandObjectRegexCommand.cpp b/lldb/source/Commands/CommandObjectRegexCommand.cpp
index 1bf29d3c047b..46295421834a 100644
--- a/lldb/source/Commands/CommandObjectRegexCommand.cpp
+++ b/lldb/source/Commands/CommandObjectRegexCommand.cpp
@@ -23,7 +23,7 @@ CommandObjectRegexCommand::CommandObjectRegexCommand(
m_entries(), m_is_removable(is_removable) {}
// Destructor
-CommandObjectRegexCommand::~CommandObjectRegexCommand() {}
+CommandObjectRegexCommand::~CommandObjectRegexCommand() = default;
bool CommandObjectRegexCommand::DoExecute(llvm::StringRef command,
CommandReturnObject &result) {
@@ -43,7 +43,7 @@ bool CommandObjectRegexCommand::DoExecute(llvm::StringRef command,
percent_var, idx)) != std::string::npos;) {
new_command.erase(percent_var_idx, percent_var_len);
new_command.insert(percent_var_idx, match_str);
- idx += percent_var_idx + match_str.size();
+ idx = percent_var_idx + match_str.size();
}
}
}
@@ -53,8 +53,8 @@ bool CommandObjectRegexCommand::DoExecute(llvm::StringRef command,
// Pass in true for "no context switching". The command that called us
// should have set up the context appropriately, we shouldn't have to
// redo that.
- return m_interpreter.HandleCommand(
- new_command.c_str(), eLazyBoolCalculate, result, nullptr, true, true);
+ return m_interpreter.HandleCommand(new_command.c_str(),
+ eLazyBoolCalculate, result);
}
}
result.SetStatus(eReturnStatusFailed);
diff --git a/lldb/source/Commands/CommandObjectRegister.cpp b/lldb/source/Commands/CommandObjectRegister.cpp
index 56e8c3fb4b84..6fd71c90c327 100644
--- a/lldb/source/Commands/CommandObjectRegister.cpp
+++ b/lldb/source/Commands/CommandObjectRegister.cpp
@@ -178,13 +178,11 @@ protected:
llvm::sys::StrError());
else
result.AppendError("unknown error while reading registers.\n");
- result.SetStatus(eReturnStatusFailed);
break;
}
} else {
result.AppendErrorWithFormat(
"invalid register set index: %" PRIu64 "\n", (uint64_t)set_idx);
- result.SetStatus(eReturnStatusFailed);
break;
}
}
@@ -203,11 +201,9 @@ protected:
if (m_command_options.dump_all_sets) {
result.AppendError("the --all option can't be used when registers "
"names are supplied as arguments\n");
- result.SetStatus(eReturnStatusFailed);
} else if (m_command_options.set_indexes.GetSize() > 0) {
result.AppendError("the --set <set> option can't be used when "
"registers names are supplied as arguments\n");
- result.SetStatus(eReturnStatusFailed);
} else {
for (auto &entry : command) {
// in most LLDB commands we accept $rbx as the name for register RBX
@@ -353,7 +349,6 @@ protected:
if (command.GetArgumentCount() != 2) {
result.AppendError(
"register write takes exactly 2 arguments: <reg-name> <value>");
- result.SetStatus(eReturnStatusFailed);
} else {
auto reg_name = command[0].ref();
auto value_str = command[1].ref();
@@ -390,11 +385,9 @@ protected:
"Failed to write register '%s' with value '%s'",
reg_name.str().c_str(), value_str.str().c_str());
}
- result.SetStatus(eReturnStatusFailed);
} else {
result.AppendErrorWithFormat("Register not found for '%s'.\n",
reg_name.str().c_str());
- result.SetStatus(eReturnStatusFailed);
}
}
return result.Succeeded();
diff --git a/lldb/source/Commands/CommandObjectReproducer.cpp b/lldb/source/Commands/CommandObjectReproducer.cpp
index 55f34c05d11d..01f9dc64e6f0 100644
--- a/lldb/source/Commands/CommandObjectReproducer.cpp
+++ b/lldb/source/Commands/CommandObjectReproducer.cpp
@@ -138,9 +138,7 @@ llvm::Expected<T> static ReadFromYAML(StringRef filename) {
}
static void SetError(CommandReturnObject &result, Error err) {
- result.GetErrorStream().Printf("error: %s\n",
- toString(std::move(err)).c_str());
- result.SetStatus(eReturnStatusFailed);
+ result.AppendError(toString(std::move(err)));
}
/// Create a loader from the given path if specified. Otherwise use the current
@@ -164,7 +162,8 @@ GetLoaderFromPathOrCurrent(llvm::Optional<Loader> &loader_storage,
return loader;
// This is a soft error because this is expected to fail during capture.
- result.SetError("Not specifying a reproducer is only support during replay.");
+ result.AppendError(
+ "Not specifying a reproducer is only support during replay.");
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return nullptr;
}
@@ -202,7 +201,6 @@ protected:
return result.Succeeded();
} else {
result.AppendErrorWithFormat("Unable to get the reproducer generator");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -279,7 +277,7 @@ protected:
auto &r = Reproducer::Instance();
if (!r.IsCapturing() && !r.IsReplaying()) {
- result.SetError(
+ result.AppendError(
"forcing a crash is only supported when capturing a reproducer.");
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return false;
@@ -586,7 +584,7 @@ protected:
return true;
}
case eReproducerProviderNone:
- result.SetError("No valid provider specified.");
+ result.AppendError("No valid provider specified.");
return false;
}
diff --git a/lldb/source/Commands/CommandObjectScript.cpp b/lldb/source/Commands/CommandObjectScript.cpp
index 9dadf11ebfc8..f53d6540bc04 100644
--- a/lldb/source/Commands/CommandObjectScript.cpp
+++ b/lldb/source/Commands/CommandObjectScript.cpp
@@ -84,7 +84,7 @@ CommandObjectScript::CommandObjectScript(CommandInterpreter &interpreter)
"results. Start the interactive interpreter if no code is supplied.",
"script [--language <scripting-language> --] [<script-code>]") {}
-CommandObjectScript::~CommandObjectScript() {}
+CommandObjectScript::~CommandObjectScript() = default;
bool CommandObjectScript::DoExecute(llvm::StringRef command,
CommandReturnObject &result) {
@@ -105,7 +105,6 @@ bool CommandObjectScript::DoExecute(llvm::StringRef command,
if (language == lldb::eScriptLanguageNone) {
result.AppendError(
"the script-lang setting is set to none - scripting not available");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -114,7 +113,6 @@ bool CommandObjectScript::DoExecute(llvm::StringRef command,
if (script_interpreter == nullptr) {
result.AppendError("no script interpreter");
- result.SetStatus(eReturnStatusFailed);
return false;
}
diff --git a/lldb/source/Commands/CommandObjectSettings.cpp b/lldb/source/Commands/CommandObjectSettings.cpp
index 87e0352636e1..cd79680e31f7 100644
--- a/lldb/source/Commands/CommandObjectSettings.cpp
+++ b/lldb/source/Commands/CommandObjectSettings.cpp
@@ -87,7 +87,7 @@ insert-before or insert-after.");
class CommandOptions : public Options {
public:
- CommandOptions() : Options(), m_global(false) {}
+ CommandOptions() : Options() {}
~CommandOptions() override = default;
@@ -120,7 +120,7 @@ insert-before or insert-after.");
}
// Instance variables to hold the values for command options.
- bool m_global;
+ bool m_global = false;
bool m_force;
};
@@ -177,7 +177,6 @@ protected:
if ((argc < min_argc) && (!m_options.m_global)) {
result.AppendError("'settings set' takes more arguments");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -185,7 +184,6 @@ protected:
if ((var_name == nullptr) || (var_name[0] == '\0')) {
result.AppendError(
"'settings set' command requires a valid variable name");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -196,7 +194,6 @@ protected:
&m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));
if (error.Fail()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
return result.Succeeded();
@@ -225,7 +222,6 @@ protected:
if (error.Fail()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
} else {
result.SetStatus(eReturnStatusSuccessFinishResult);
@@ -285,7 +281,6 @@ protected:
result.GetOutputStream().EOL();
} else {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
}
} else {
@@ -385,7 +380,6 @@ protected:
if (!out_file.GetFile().IsValid()) {
result.AppendErrorWithFormat("%s: unable to write to file", path.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -403,7 +397,6 @@ protected:
&clean_ctx, out_file, arg.ref(), OptionValue::eDumpGroupExport));
if (!error.Success()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
}
@@ -469,14 +462,13 @@ protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
FileSpec file(m_options.m_filename);
FileSystem::Instance().Resolve(file);
- ExecutionContext clean_ctx;
CommandInterpreterRunOptions options;
options.SetAddToHistory(false);
options.SetEchoCommands(false);
options.SetPrintResults(true);
options.SetPrintErrors(true);
options.SetStopOnError(false);
- m_interpreter.HandleCommandsFromFile(file, &clean_ctx, options, result);
+ m_interpreter.HandleCommandsFromFile(file, options, result);
return result.Succeeded();
}
@@ -544,7 +536,6 @@ protected:
} else {
result.AppendErrorWithFormat("invalid property path '%s'",
property_path);
- result.SetStatus(eReturnStatusFailed);
}
}
} else {
@@ -625,7 +616,6 @@ protected:
"or an array followed by one or more indexes, or a "
"dictionary followed by one or more key names to "
"remove");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -633,7 +623,6 @@ protected:
if ((var_name == nullptr) || (var_name[0] == '\0')) {
result.AppendError(
"'settings remove' command requires a valid variable name");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -645,7 +634,6 @@ protected:
&m_exe_ctx, eVarSetOperationRemove, var_name, var_value));
if (error.Fail()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -729,7 +717,6 @@ protected:
if ((var_name == nullptr) || (var_name[0] == '\0')) {
result.AppendError("'settings replace' command requires a valid variable "
"name; No value supplied");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -741,7 +728,6 @@ protected:
&m_exe_ctx, eVarSetOperationReplace, var_name, var_value));
if (error.Fail()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
} else {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
@@ -823,7 +809,6 @@ protected:
if (argc < 3) {
result.AppendError("'settings insert-before' takes more arguments");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -831,7 +816,6 @@ protected:
if ((var_name == nullptr) || (var_name[0] == '\0')) {
result.AppendError("'settings insert-before' command requires a valid "
"variable name; No value supplied");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -843,7 +827,6 @@ protected:
&m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value));
if (error.Fail()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -922,7 +905,6 @@ protected:
if (argc < 3) {
result.AppendError("'settings insert-after' takes more arguments");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -930,7 +912,6 @@ protected:
if ((var_name == nullptr) || (var_name[0] == '\0')) {
result.AppendError("'settings insert-after' command requires a valid "
"variable name; No value supplied");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -942,7 +923,6 @@ protected:
&m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value));
if (error.Fail()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1009,7 +989,6 @@ protected:
if (argc < 2) {
result.AppendError("'settings append' takes more arguments");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1017,7 +996,6 @@ protected:
if ((var_name == nullptr) || (var_name[0] == '\0')) {
result.AppendError("'settings append' command requires a valid variable "
"name; No value supplied");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1032,7 +1010,6 @@ protected:
&m_exe_ctx, eVarSetOperationAppend, var_name, var_value));
if (error.Fail()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1118,7 +1095,6 @@ protected:
if (m_options.m_clear_all) {
if (argc != 0) {
result.AppendError("'settings clear --all' doesn't take any arguments");
- result.SetStatus(eReturnStatusFailed);
return false;
}
GetDebugger().GetValueProperties()->Clear();
@@ -1127,7 +1103,6 @@ protected:
if (argc != 1) {
result.AppendError("'settings clear' takes exactly one argument");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1135,7 +1110,6 @@ protected:
if ((var_name == nullptr) || (var_name[0] == '\0')) {
result.AppendError("'settings clear' command requires a valid variable "
"name; No value supplied");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1143,7 +1117,6 @@ protected:
&m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));
if (error.Fail()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
diff --git a/lldb/source/Commands/CommandObjectSource.cpp b/lldb/source/Commands/CommandObjectSource.cpp
index 8fff22a06366..7a0338e35bc7 100644
--- a/lldb/source/Commands/CommandObjectSource.cpp
+++ b/lldb/source/Commands/CommandObjectSource.cpp
@@ -541,7 +541,6 @@ protected:
if (argc != 0) {
result.AppendErrorWithFormat("'%s' takes no arguments, only flags.\n",
GetCommandName().str().c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -551,7 +550,6 @@ protected:
if (target == nullptr) {
result.AppendError("invalid target, create a debug target using the "
"'target create' command.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -575,12 +573,10 @@ protected:
}
if (!m_module_list.GetSize()) {
result.AppendError("No modules match the input.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else if (target->GetImages().GetSize() == 0) {
result.AppendError("The target has no associated executable images.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -811,7 +807,6 @@ protected:
result.AppendErrorWithFormat("Could not find line information for "
"start of function: \"%s\".\n",
source_info.function.GetCString());
- result.SetStatus(eReturnStatusFailed);
return 0;
}
sc.function->GetEndLineSourceInfo(end_file, end_line);
@@ -933,7 +928,6 @@ protected:
if (argc != 0) {
result.AppendErrorWithFormat("'%s' takes no arguments, only flags.\n",
GetCommandName().str().c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -971,7 +965,6 @@ protected:
if (num_matches == 0) {
result.AppendErrorWithFormat("Could not find function named: \"%s\".\n",
m_options.symbol_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1038,7 +1031,6 @@ protected:
"no modules have source information for file address 0x%" PRIx64
".\n",
m_options.address);
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else {
@@ -1061,7 +1053,6 @@ protected:
"is no line table information "
"available for this address.\n",
error_strm.GetData());
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -1071,7 +1062,6 @@ protected:
result.AppendErrorWithFormat(
"no modules contain load address 0x%" PRIx64 ".\n",
m_options.address);
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -1191,7 +1181,6 @@ protected:
if (num_matches == 0) {
result.AppendErrorWithFormat("Could not find source file \"%s\".\n",
m_options.file_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1215,7 +1204,6 @@ protected:
result.AppendErrorWithFormat(
"Multiple source files found matching: \"%s.\"\n",
m_options.file_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -1245,7 +1233,6 @@ protected:
} else {
result.AppendErrorWithFormat("No comp unit found for: \"%s.\"\n",
m_options.file_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
diff --git a/lldb/source/Commands/CommandObjectStats.cpp b/lldb/source/Commands/CommandObjectStats.cpp
index 6b06581f5a8f..23c7dbbaf373 100644
--- a/lldb/source/Commands/CommandObjectStats.cpp
+++ b/lldb/source/Commands/CommandObjectStats.cpp
@@ -28,7 +28,6 @@ protected:
if (target.GetCollectingStats()) {
result.AppendError("statistics already enabled");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -53,7 +52,6 @@ protected:
if (!target.GetCollectingStats()) {
result.AppendError("need to enable statistics before disabling them");
- result.SetStatus(eReturnStatusFailed);
return false;
}
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index 1cb21384fd2a..b25514b1ffbc 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -158,9 +158,9 @@ static constexpr OptionEnumValueElement g_dependents_enumaration[] = {
class OptionGroupDependents : public OptionGroup {
public:
- OptionGroupDependents() {}
+ OptionGroupDependents() = default;
- ~OptionGroupDependents() override {}
+ ~OptionGroupDependents() override = default;
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
return llvm::makeArrayRef(g_target_dependents_options);
@@ -278,7 +278,6 @@ protected:
result.AppendErrorWithFormatv("Cannot open '{0}': {1}.",
core_file.GetPath(),
llvm::toString(file.takeError()));
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -293,7 +292,6 @@ protected:
result.AppendErrorWithFormatv("Cannot open '{0}': {1}.",
symfile.GetPath(),
llvm::toString(file.takeError()));
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -320,7 +318,6 @@ protected:
if (!target_sp) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -344,7 +341,6 @@ protected:
Status err = platform_sp->PutFile(file_spec, remote_file);
if (err.Fail()) {
result.AppendError(err.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -359,20 +355,17 @@ protected:
Status err = platform_sp->GetFile(remote_file, file_spec);
if (err.Fail()) {
result.AppendError(err.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else {
// make up a local file
result.AppendError("remote --> local transfer without local "
"path is not implemented yet");
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
} else {
result.AppendError("no platform found for target");
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -414,7 +407,6 @@ protected:
if (error.Fail()) {
result.AppendError(
error.AsCString("can't find plug-in for core file"));
- result.SetStatus(eReturnStatusFailed);
return false;
} else {
result.AppendMessageWithFormatv(
@@ -427,7 +419,6 @@ protected:
result.AppendErrorWithFormatv(
"Unable to find process plug-in for core file '{0}'\n",
core_file.GetPath());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendMessageWithFormat(
@@ -441,7 +432,6 @@ protected:
result.AppendErrorWithFormat("'%s' takes exactly one executable path "
"argument, or use the --core option.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
@@ -482,7 +472,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendError("the 'target list' command takes no arguments\n");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -524,17 +513,14 @@ protected:
"index %u is out of range since there are no active targets\n",
target_idx);
}
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendErrorWithFormat("invalid index string value '%s'\n",
target_idx_arg);
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError(
"'target select' takes a single argument: a target index\n");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -584,7 +570,6 @@ protected:
// Bail out if don't have any targets.
if (num_targets == 0) {
result.AppendError("no targets to delete");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -593,7 +578,6 @@ protected:
if (entry.ref().getAsInteger(0, target_idx)) {
result.AppendErrorWithFormat("invalid target index '%s'\n",
entry.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (target_idx < num_targets) {
@@ -612,14 +596,12 @@ protected:
"target index %u is out of range, the only valid index is 0\n",
target_idx);
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else {
target_sp = target_list.GetSelectedTarget();
if (!target_sp) {
result.AppendErrorWithFormat("no target is currently selected\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
delete_target_list.push_back(target_sp);
@@ -848,12 +830,10 @@ protected:
size_t matches = 0;
bool use_var_name = false;
if (m_option_variable.use_regex) {
- RegularExpression regex(
- llvm::StringRef::withNullAsEmpty(arg.c_str()));
+ RegularExpression regex(arg.ref());
if (!regex.IsValid()) {
result.GetErrorStream().Printf(
"error: invalid regular expression: '%s'\n", arg.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
use_var_name = true;
@@ -868,9 +848,8 @@ protected:
}
if (matches == 0) {
- result.GetErrorStream().Printf(
- "error: can't find global variable '%s'\n", arg.c_str());
- result.SetStatus(eReturnStatusFailed);
+ result.AppendErrorWithFormat("can't find global variable '%s'",
+ arg.c_str());
return false;
} else {
for (uint32_t global_idx = 0; global_idx < matches; ++global_idx) {
@@ -931,7 +910,6 @@ protected:
} else
result.AppendError("'target variable' takes one or more global "
"variable names as arguments\n");
- result.SetStatus(eReturnStatusFailed);
}
} else {
SymbolContextList sc_list;
@@ -1054,7 +1032,6 @@ protected:
const size_t argc = command.GetArgumentCount();
if (argc & 1) {
result.AppendError("add requires an even number of arguments\n");
- result.SetStatus(eReturnStatusFailed);
} else {
for (size_t i = 0; i < argc; i += 2) {
const char *from = command.GetArgumentAtIndex(i);
@@ -1078,7 +1055,6 @@ protected:
result.AppendError("<path-prefix> can't be empty\n");
else
result.AppendError("<new-path-prefix> can't be empty\n");
- result.SetStatus(eReturnStatusFailed);
}
}
}
@@ -1186,7 +1162,6 @@ protected:
result.AppendErrorWithFormat(
"<index> parameter is not an integer: '%s'.\n",
command.GetArgumentAtIndex(0));
- result.SetStatus(eReturnStatusFailed);
return result.Succeeded();
}
@@ -1208,13 +1183,11 @@ protected:
result.AppendError("<path-prefix> can't be empty\n");
else
result.AppendError("<new-path-prefix> can't be empty\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
} else {
result.AppendError("insert requires at least three arguments\n");
- result.SetStatus(eReturnStatusFailed);
return result.Succeeded();
}
return result.Succeeded();
@@ -1239,7 +1212,6 @@ protected:
Target *target = &GetSelectedTarget();
if (command.GetArgumentCount() != 0) {
result.AppendError("list takes no arguments\n");
- result.SetStatus(eReturnStatusFailed);
return result.Succeeded();
}
@@ -1280,7 +1252,6 @@ protected:
Target *target = &GetSelectedTarget();
if (command.GetArgumentCount() != 1) {
result.AppendError("query requires one argument\n");
- result.SetStatus(eReturnStatusFailed);
return result.Succeeded();
}
@@ -1900,7 +1871,6 @@ protected:
target->GetImages());
if (num_dumped == 0) {
result.AppendError("the target has no associated executable images");
- result.SetStatus(eReturnStatusFailed);
}
} else {
// Find the modules that match the basename or full path.
@@ -1925,7 +1895,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendError("no matching executable images found");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -1970,7 +1939,7 @@ public:
class CommandOptions : public Options {
public:
- CommandOptions() : Options(), m_sort_order(eSortOrderNone) {}
+ CommandOptions() : Options() {}
~CommandOptions() override = default;
@@ -2006,7 +1975,7 @@ public:
return llvm::makeArrayRef(g_target_modules_dump_symtab_options);
}
- SortOrder m_sort_order;
+ SortOrder m_sort_order = eSortOrderNone;
OptionValueBoolean m_prefer_mangled = {false, false};
};
@@ -2044,7 +2013,6 @@ protected:
}
} else {
result.AppendError("the target has no associated executable images");
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else {
@@ -2081,7 +2049,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishResult);
else {
result.AppendError("no matching executable images found");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -2119,7 +2086,6 @@ protected:
const size_t num_modules = target->GetImages().GetSize();
if (num_modules == 0) {
result.AppendError("the target has no associated executable images");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -2168,7 +2134,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishResult);
else {
result.AppendError("no matching executable images found");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -2198,7 +2163,6 @@ protected:
const size_t num_modules = module_list.GetSize();
if (num_modules == 0) {
result.AppendError("the target has no associated executable images");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -2276,7 +2240,6 @@ protected:
const size_t num_modules = target_modules.GetSize();
if (num_modules == 0) {
result.AppendError("the target has no associated executable images");
- result.SetStatus(eReturnStatusFailed);
return false;
}
result.GetOutputStream().Format(
@@ -2316,7 +2279,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishResult);
else {
result.AppendError("no matching executable images found");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -2352,7 +2314,6 @@ protected:
if (command.GetArgumentCount() == 0) {
result.AppendError("file option must be specified.");
- result.SetStatus(eReturnStatusFailed);
return result.Succeeded();
} else {
// Dump specified images (by basename or fullpath)
@@ -2389,7 +2350,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishResult);
else {
result.AppendError("no source filenames matched any command arguments");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -2535,7 +2495,6 @@ protected:
"or symbol file with UUID %s",
strm.GetData());
}
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else {
@@ -2544,13 +2503,11 @@ protected:
result.AppendErrorWithFormat(
"Unable to locate the executable or symbol file with UUID %s",
strm.GetData());
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else {
result.AppendError(
"one or more executable image paths must be specified");
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else {
@@ -2579,7 +2536,6 @@ protected:
else
result.AppendErrorWithFormat("unsupported module: %s",
entry.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
} else {
flush = true;
@@ -2587,7 +2543,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
std::string resolved_path = file_spec.GetPath();
- result.SetStatus(eReturnStatusFailed);
if (resolved_path != entry.ref()) {
result.AppendErrorWithFormat(
"invalid module path '%s' with resolved path '%s'\n",
@@ -2685,12 +2640,10 @@ protected:
search_using_module_spec = false;
result.AppendErrorWithFormat(
"more than 1 module matched by name '%s'\n", arg_cstr);
- result.SetStatus(eReturnStatusFailed);
} else {
search_using_module_spec = false;
result.AppendErrorWithFormat("no object file for module '%s'\n",
arg_cstr);
- result.SetStatus(eReturnStatusFailed);
}
}
@@ -2724,7 +2677,6 @@ protected:
} else {
result.AppendError("one or more section name + load "
"address pair must be specified");
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else {
@@ -2732,7 +2684,6 @@ protected:
result.AppendError("The \"--slide <offset>\" option can't "
"be used in conjunction with setting "
"section load addresses.\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -2751,7 +2702,6 @@ protected:
"thread specific sections are not yet "
"supported (section '%s')\n",
sect_name);
- result.SetStatus(eReturnStatusFailed);
break;
} else {
if (target->GetSectionLoadList()
@@ -2766,13 +2716,11 @@ protected:
"matches the section "
"name '%s'\n",
sect_name);
- result.SetStatus(eReturnStatusFailed);
break;
}
} else {
result.AppendErrorWithFormat(
"invalid load address string '%s'\n", load_addr_cstr);
- result.SetStatus(eReturnStatusFailed);
break;
}
} else {
@@ -2782,7 +2730,6 @@ protected:
else
result.AppendError("one or more section name + load "
"address pair must be specified.\n");
- result.SetStatus(eReturnStatusFailed);
break;
}
}
@@ -2825,7 +2772,6 @@ protected:
result.AppendErrorWithFormat("failed to set PC value to "
"0x%" PRIx64 "\n",
file_entry_addr);
- result.SetStatus(eReturnStatusFailed);
}
}
}
@@ -2833,13 +2779,11 @@ protected:
module->GetFileSpec().GetPath(path, sizeof(path));
result.AppendErrorWithFormat("no sections in object file '%s'\n",
path);
- result.SetStatus(eReturnStatusFailed);
}
} else {
module->GetFileSpec().GetPath(path, sizeof(path));
result.AppendErrorWithFormat("no object file for module '%s'\n",
path);
- result.SetStatus(eReturnStatusFailed);
}
} else {
FileSpec *module_spec_file = module_spec.GetFileSpecPtr();
@@ -2848,7 +2792,6 @@ protected:
result.AppendErrorWithFormat("invalid module '%s'.\n", path);
} else
result.AppendError("no module spec");
- result.SetStatus(eReturnStatusFailed);
}
} else {
std::string uuid_str;
@@ -2876,12 +2819,10 @@ protected:
path[0] ? " file=" : "", path, !uuid_str.empty() ? " uuid=" : "",
uuid_str.c_str());
}
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError("either the \"--file <module>\" or the \"--uuid "
"<uuid>\" option must be specified.\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
return result.Succeeded();
@@ -2903,9 +2844,7 @@ class CommandObjectTargetModulesList : public CommandObjectParsed {
public:
class CommandOptions : public Options {
public:
- CommandOptions()
- : Options(), m_format_array(), m_use_global_module_list(false),
- m_module_addr(LLDB_INVALID_ADDRESS) {}
+ CommandOptions() : Options(), m_format_array() {}
~CommandOptions() override = default;
@@ -2940,8 +2879,8 @@ public:
// Instance variables to hold the values for command options.
typedef std::vector<std::pair<char, uint32_t>> FormatWidthCollection;
FormatWidthCollection m_format_array;
- bool m_use_global_module_list;
- lldb::addr_t m_module_addr;
+ bool m_use_global_module_list = false;
+ lldb::addr_t m_module_addr = LLDB_INVALID_ADDRESS;
};
CommandObjectTargetModulesList(CommandInterpreter &interpreter)
@@ -2966,7 +2905,6 @@ protected:
if (target == nullptr && !use_global_module_list) {
result.AppendError("invalid target, create a debug target using the "
"'target create' command");
- result.SetStatus(eReturnStatusFailed);
return false;
} else {
if (target) {
@@ -2990,18 +2928,15 @@ protected:
result.AppendErrorWithFormat(
"Couldn't find module matching address: 0x%" PRIx64 ".",
m_options.m_module_addr);
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendErrorWithFormat(
"Couldn't find module containing address: 0x%" PRIx64 ".",
m_options.m_module_addr);
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError(
"Can only look up modules by address with a valid target.");
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -3033,7 +2968,6 @@ protected:
if (argc == 1) {
result.AppendErrorWithFormat("no modules found that match '%s'",
arg.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -3080,7 +3014,6 @@ protected:
result.AppendError(
"the target has no associated executable images");
}
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -3254,9 +3187,7 @@ public:
class CommandOptions : public Options {
public:
- CommandOptions()
- : Options(), m_type(eLookupTypeInvalid), m_str(),
- m_addr(LLDB_INVALID_ADDRESS) {}
+ CommandOptions() : Options(), m_str() {}
~CommandOptions() override = default;
@@ -3302,9 +3233,10 @@ public:
// Instance variables to hold the values for command options.
- int m_type; // Should be a eLookupTypeXXX enum after parsing options
+ int m_type = eLookupTypeInvalid; // Should be a eLookupTypeXXX enum after
+ // parsing options
std::string m_str; // Holds name lookup
- lldb::addr_t m_addr; // Holds the address to lookup
+ lldb::addr_t m_addr = LLDB_INVALID_ADDRESS; // Holds the address to lookup
};
CommandObjectTargetModulesShowUnwind(CommandInterpreter &interpreter)
@@ -3330,21 +3262,18 @@ protected:
if (process == nullptr) {
result.AppendError(
"You must have a process running to use this command.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
ThreadList threads(process->GetThreadList());
if (threads.GetSize() == 0) {
result.AppendError("The process must be paused to use this command.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
ThreadSP thread(threads.GetThreadAtIndex(0));
if (!thread) {
result.AppendError("The process must be paused to use this command.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -3369,7 +3298,6 @@ protected:
} else {
result.AppendError(
"address-expression or function name option must be specified.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -3377,7 +3305,6 @@ protected:
if (num_matches == 0) {
result.AppendErrorWithFormat("no unwind data found that matches '%s'.",
m_options.m_str.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -3894,7 +3821,6 @@ protected:
std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
if (target_modules.GetSize() == 0) {
result.AppendError("the target has no associated executable images");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4064,7 +3990,6 @@ protected:
if (!symbol_fspec) {
result.AppendError(
"one or more executable image paths must be specified");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4146,7 +4071,6 @@ protected:
"use the --uuid option to resolve the "
"ambiguity.\n",
symfile_path);
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4213,7 +4137,6 @@ protected:
!llvm::sys::fs::is_regular_file(symbol_fspec.GetPath())
? "\n please specify the full path to the symbol file"
: "");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4425,11 +4348,7 @@ class CommandObjectTargetStopHookAdd : public CommandObjectParsed,
public:
class CommandOptions : public OptionGroup {
public:
- CommandOptions()
- : OptionGroup(), m_line_start(0), m_line_end(UINT_MAX),
- m_func_name_type_mask(eFunctionNameTypeAuto),
- m_sym_ctx_specified(false), m_thread_specified(false),
- m_use_one_liner(false), m_one_liner() {}
+ CommandOptions() : OptionGroup(), m_line_end(UINT_MAX), m_one_liner() {}
~CommandOptions() override = default;
@@ -4556,20 +4475,21 @@ public:
std::string m_class_name;
std::string m_function_name;
- uint32_t m_line_start;
+ uint32_t m_line_start = 0;
uint32_t m_line_end;
std::string m_file_name;
std::string m_module_name;
- uint32_t m_func_name_type_mask; // A pick from lldb::FunctionNameType.
+ uint32_t m_func_name_type_mask =
+ eFunctionNameTypeAuto; // A pick from lldb::FunctionNameType.
lldb::tid_t m_thread_id;
uint32_t m_thread_index;
std::string m_thread_name;
std::string m_queue_name;
- bool m_sym_ctx_specified;
+ bool m_sym_ctx_specified = false;
bool m_no_inlines;
- bool m_thread_specified;
+ bool m_thread_specified = false;
// Instance variables to hold the values for one_liner options.
- bool m_use_one_liner;
+ bool m_use_one_liner = false;
std::vector<std::string> m_one_liner;
bool m_auto_continue;
@@ -4602,7 +4522,7 @@ Python Based Stop Hooks:
When the stop hook is added, the class is initialized by calling:
- def __init__(self, target, extra_args, dict):
+ def __init__(self, target, extra_args, internal_dict):
target: The target that the stop hook is being added to.
extra_args: An SBStructuredData Dictionary filled with the -key -value
@@ -4780,7 +4700,6 @@ protected:
// FIXME: Set the stop hook ID counter back.
result.AppendErrorWithFormat("Couldn't add stop hook: %s",
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
target.UndoCreateStopHook(new_hook_sp->GetID());
return false;
}
@@ -4841,13 +4760,11 @@ protected:
if (!llvm::to_integer(command.GetArgumentAtIndex(i), user_id)) {
result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
command.GetArgumentAtIndex(i));
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (!target.RemoveStopHookByID(user_id)) {
result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
command.GetArgumentAtIndex(i));
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -4896,14 +4813,12 @@ protected:
if (!llvm::to_integer(command.GetArgumentAtIndex(i), user_id)) {
result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
command.GetArgumentAtIndex(i));
- result.SetStatus(eReturnStatusFailed);
return false;
}
success = target.SetStopHookActiveStateByID(user_id, m_enable);
if (!success) {
result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
command.GetArgumentAtIndex(i));
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp
index f4ce5cc599cb..7247601b292b 100644
--- a/lldb/source/Commands/CommandObjectThread.cpp
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -8,9 +8,11 @@
#include "CommandObjectThread.h"
+#include <memory>
#include <sstream>
#include "CommandObjectThreadUtil.h"
+#include "CommandObjectTrace.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Host/OptionParser.h"
@@ -31,6 +33,7 @@
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanStepInRange.h"
#include "lldb/Target/Trace.h"
+#include "lldb/Target/TraceInstructionDumper.h"
#include "lldb/Utility/State.h"
using namespace lldb;
@@ -153,7 +156,6 @@ protected:
result.AppendErrorWithFormat(
"thread disappeared while computing backtraces: 0x%" PRIx64 "\n",
tid);
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -172,7 +174,6 @@ protected:
result.AppendErrorWithFormat(
"error displaying backtrace for thread: \"0x%4.4x\"\n",
thread->GetIndexID());
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (m_options.m_extended_backtrace) {
@@ -384,7 +385,6 @@ protected:
if (thread == nullptr) {
result.AppendError("no selected thread in process");
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else {
@@ -394,7 +394,6 @@ protected:
if (!llvm::to_integer(thread_idx_cstr, step_thread_idx)) {
result.AppendErrorWithFormat("invalid thread index '%s'.\n",
thread_idx_cstr);
- result.SetStatus(eReturnStatusFailed);
return false;
}
thread =
@@ -403,7 +402,6 @@ protected:
result.AppendErrorWithFormat(
"Thread index %u is out of range (valid values are 0 - %u).\n",
step_thread_idx, num_threads);
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -411,14 +409,12 @@ protected:
if (m_step_type == eStepTypeScripted) {
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.GetName().c_str())) {
result.AppendErrorWithFormat(
"class for scripted step: \"%s\" does not exist.",
m_class_options.GetName().c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -427,7 +423,6 @@ protected:
m_step_type != eStepTypeInto) {
result.AppendErrorWithFormat(
"end line option is only valid for step into");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -460,7 +455,6 @@ protected:
error)) {
result.AppendErrorWithFormat("invalid end-line option: %s.",
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else if (m_options.m_end_line_is_block_end) {
@@ -468,7 +462,6 @@ protected:
Block *block = frame->GetSymbolContext(eSymbolContextBlock).block;
if (!block) {
result.AppendErrorWithFormat("Could not find the current block.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -478,7 +471,6 @@ protected:
if (!block_range.GetBaseAddress().IsValid()) {
result.AppendErrorWithFormat(
"Could not find the current block address.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
lldb::addr_t pc_offset_in_block =
@@ -537,7 +529,6 @@ protected:
new_plan_status);
} else {
result.AppendError("step type is not supported");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -569,7 +560,6 @@ protected:
if (!error.Success()) {
result.AppendMessage(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -593,7 +583,6 @@ protected:
}
} else {
result.SetError(new_plan_status);
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -649,7 +638,6 @@ public:
Process *process = m_exe_ctx.GetProcessPtr();
if (process == nullptr) {
result.AppendError("no process exists. Cannot continue");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -670,7 +658,6 @@ public:
if (entry.ref().getAsInteger(0, thread_idx)) {
result.AppendErrorWithFormat(
"invalid thread index argument: \"%s\".\n", entry.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
Thread *thread =
@@ -681,14 +668,12 @@ public:
} else {
result.AppendErrorWithFormat("invalid thread index %u.\n",
thread_idx);
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
if (resume_threads.empty()) {
result.AppendError("no valid thread indexes were specified");
- result.SetStatus(eReturnStatusFailed);
return false;
} else {
if (resume_threads.size() == 1)
@@ -728,7 +713,6 @@ public:
Thread *current_thread = GetDefaultThread();
if (current_thread == nullptr) {
result.AppendError("the process doesn't have a current thread");
- result.SetStatus(eReturnStatusFailed);
return false;
}
// Set the actions that the threads should each take when resuming
@@ -771,13 +755,11 @@ public:
} else {
result.AppendErrorWithFormat("Failed to resume process: %s\n",
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendErrorWithFormat(
"Process cannot be continued from its current state (%s).\n",
StateAsCString(state));
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
@@ -801,12 +783,10 @@ class CommandObjectThreadUntil : public CommandObjectParsed {
public:
class CommandOptions : public Options {
public:
- uint32_t m_thread_idx;
- uint32_t m_frame_idx;
+ uint32_t m_thread_idx = LLDB_INVALID_THREAD_ID;
+ uint32_t m_frame_idx = LLDB_INVALID_FRAME_ID;
- CommandOptions()
- : Options(), m_thread_idx(LLDB_INVALID_THREAD_ID),
- m_frame_idx(LLDB_INVALID_FRAME_ID) {
+ CommandOptions() : Options() {
// Keep default values of all options in one place: OptionParsingStarting
// ()
OptionParsingStarting(nullptr);
@@ -917,7 +897,6 @@ protected:
Process *process = m_exe_ctx.GetProcessPtr();
if (process == nullptr) {
result.AppendError("need a valid process to step");
- result.SetStatus(eReturnStatusFailed);
} else {
Thread *thread = nullptr;
std::vector<uint32_t> line_numbers;
@@ -929,7 +908,6 @@ protected:
if (!llvm::to_integer(command.GetArgumentAtIndex(i), line_number)) {
result.AppendErrorWithFormat("invalid line number: '%s'.\n",
command.GetArgumentAtIndex(i));
- result.SetStatus(eReturnStatusFailed);
return false;
} else
line_numbers.push_back(line_number);
@@ -937,7 +915,6 @@ protected:
} else if (m_options.m_until_addrs.empty()) {
result.AppendErrorWithFormat("No line number or address provided:\n%s",
GetSyntax().str().c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -954,7 +931,6 @@ protected:
result.AppendErrorWithFormat(
"Thread index %u is out of range (valid values are 0 - %u).\n",
m_options.m_thread_idx, num_threads);
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -966,7 +942,6 @@ protected:
result.AppendErrorWithFormat(
"Frame index %u is out of range for thread %u.\n",
m_options.m_frame_idx, m_options.m_thread_idx);
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -986,7 +961,6 @@ protected:
"frame %u of thread index %u.\n",
m_options.m_frame_idx,
m_options.m_thread_idx);
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1046,7 +1020,6 @@ protected:
result.AppendErrorWithFormat(
"Until target outside of the current function.\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1062,14 +1035,12 @@ protected:
new_plan_sp->SetOkayToDiscard(false);
} else {
result.SetError(new_plan_status);
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else {
result.AppendErrorWithFormat(
"Frame index %u of thread %u has no debug information.\n",
m_options.m_frame_idx, m_options.m_thread_idx);
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1099,7 +1070,6 @@ protected:
} else {
result.AppendErrorWithFormat("Failed to resume process: %s.\n",
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
}
return result.Succeeded();
@@ -1151,13 +1121,11 @@ protected:
Process *process = m_exe_ctx.GetProcessPtr();
if (process == nullptr) {
result.AppendError("no process");
- result.SetStatus(eReturnStatusFailed);
return false;
} else if (command.GetArgumentCount() != 1) {
result.AppendErrorWithFormat(
"'%s' takes exactly one thread index argument:\nUsage: %s\n",
m_cmd_name.c_str(), m_cmd_syntax.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1165,7 +1133,6 @@ protected:
if (!llvm::to_integer(command.GetArgumentAtIndex(0), index_id)) {
result.AppendErrorWithFormat("Invalid thread index '%s'",
command.GetArgumentAtIndex(0));
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1174,7 +1141,6 @@ protected:
if (new_thread == nullptr) {
result.AppendErrorWithFormat("invalid thread #%s.\n",
command.GetArgumentAtIndex(0));
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1293,7 +1259,6 @@ public:
if (!thread_sp) {
result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n",
tid);
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1305,7 +1270,6 @@ public:
m_options.m_json_stopinfo)) {
result.AppendErrorWithFormat("error displaying info for thread: \"%d\"\n",
thread->GetIndexID());
- result.SetStatus(eReturnStatusFailed);
return false;
}
return true;
@@ -1343,7 +1307,6 @@ public:
if (!thread_sp) {
result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n",
tid);
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1373,7 +1336,7 @@ class CommandObjectThreadReturn : public CommandObjectRaw {
public:
class CommandOptions : public Options {
public:
- CommandOptions() : Options(), m_from_expression(false) {
+ CommandOptions() : Options() {
// Keep default values of all options in one place: OptionParsingStarting
// ()
OptionParsingStarting(nullptr);
@@ -1413,7 +1376,7 @@ public:
return llvm::makeArrayRef(g_thread_return_options);
}
- bool m_from_expression;
+ bool m_from_expression = false;
// Instance variables to hold the values for command options.
};
@@ -1466,7 +1429,6 @@ protected:
if (!error.Success()) {
result.AppendErrorWithFormat("Unwinding expression failed - %s.",
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
} else {
bool success =
thread->SetSelectedFrameByIndexNoisily(0, result.GetOutputStream());
@@ -1476,7 +1438,6 @@ protected:
} else {
result.AppendErrorWithFormat(
"Could not select 0th frame after unwinding expression.");
- result.SetStatus(eReturnStatusFailed);
}
}
return result.Succeeded();
@@ -1489,7 +1450,6 @@ protected:
if (frame_sp->IsInlined()) {
result.AppendError("Don't know how to return from inlined frames.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1511,7 +1471,6 @@ protected:
else
result.AppendErrorWithFormat(
"Unknown error evaluating result expression.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -1524,7 +1483,6 @@ protected:
result.AppendErrorWithFormat(
"Error returning from frame %d of thread %d: %s.", frame_idx,
thread_sp->GetIndexID(), error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1626,14 +1584,12 @@ protected:
lldb::addr_t callAddr = dest.GetCallableLoadAddress(target);
if (callAddr == LLDB_INVALID_ADDRESS) {
result.AppendErrorWithFormat("Invalid destination address.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (!reg_ctx->SetPC(callAddr)) {
result.AppendErrorWithFormat("Error changing PC value for thread %d.",
thread->GetIndexID());
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else {
@@ -1650,7 +1606,6 @@ protected:
if (!file) {
result.AppendErrorWithFormat(
"No source file available for the current location.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1775,9 +1730,8 @@ public:
true /* condense_trivial */, m_options.m_unreported);
// If we didn't find a TID, stop here and return an error.
if (!success) {
- result.SetError("Error dumping plans:");
+ result.AppendError("Error dumping plans:");
result.AppendError(tmp_strm.GetString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
// Otherwise, add our data to the output:
@@ -1854,7 +1808,6 @@ public:
result.AppendErrorWithFormat("Too many arguments, expected one - the "
"thread plan index - but got %zu.",
args.GetArgumentCount());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1863,14 +1816,12 @@ public:
result.AppendErrorWithFormat(
"Invalid thread index: \"%s\" - should be unsigned int.",
args.GetArgumentAtIndex(0));
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (thread_plan_idx == 0) {
result.AppendErrorWithFormat(
"You wouldn't really want me to discard the base thread plan.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1881,7 +1832,6 @@ public:
result.AppendErrorWithFormat(
"Could not find User thread plan with index %s.",
args.GetArgumentAtIndex(0));
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -1920,11 +1870,11 @@ public:
bool DoExecute(Args &args, CommandReturnObject &result) override {
Process *process = m_exe_ctx.GetProcessPtr();
-
+
if (args.GetArgumentCount() == 0) {
process->PruneThreadPlans();
result.SetStatus(eReturnStatusSuccessFinishNoResult);
- return true;
+ return true;
}
const size_t num_args = args.GetArgumentCount();
@@ -1937,13 +1887,11 @@ public:
if (!llvm::to_integer(args.GetArgumentAtIndex(i), tid)) {
result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n",
args.GetArgumentAtIndex(i));
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (!process->PruneThreadPlansForTID(tid)) {
result.AppendErrorWithFormat("Could not find unreported tid: \"%s\"\n",
args.GetArgumentAtIndex(i));
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -1976,77 +1924,61 @@ public:
// Next are the subcommands of CommandObjectMultiwordTrace
-// CommandObjectTraceStart
+// CommandObjectTraceExport
-/// This class works by delegating the logic to the actual trace plug-in that
-/// can support the current process.
-class CommandObjectTraceStart : public CommandObjectProxy {
+class CommandObjectTraceExport : public CommandObjectMultiword {
public:
- CommandObjectTraceStart(CommandInterpreter &interpreter)
- : CommandObjectProxy(interpreter, "thread trace start",
- "Start tracing threads with the corresponding trace "
- "plug-in for the current process.",
- "thread trace start [<trace-options>]") {}
-
-protected:
- llvm::Expected<CommandObjectSP> DoGetProxyCommandObject() {
- ProcessSP process_sp = m_interpreter.GetExecutionContext().GetProcessSP();
-
- if (!process_sp)
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "Process not available.");
- if (!process_sp->IsAlive())
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "Process must be launched.");
-
- llvm::Expected<TraceTypeInfo> trace_type =
- process_sp->GetSupportedTraceType();
-
- if (!trace_type)
- return llvm::createStringError(
- llvm::inconvertibleErrorCode(), "Tracing is not supported. %s",
- llvm::toString(trace_type.takeError()).c_str());
-
- CommandObjectSP delegate_sp =
- PluginManager::GetTraceStartCommand(trace_type->name, m_interpreter);
- if (!delegate_sp)
- return llvm::createStringError(
- llvm::inconvertibleErrorCode(),
- "No trace plug-in matches the specified type: \"%s\"",
- trace_type->name.c_str());
- return delegate_sp;
- }
+ CommandObjectTraceExport(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "trace thread export",
+ "Commands for exporting traces of the threads in the current "
+ "process to different formats.",
+ "thread trace export <export-plugin> [<subcommand objects>]") {
- CommandObject *GetProxyCommandObject() override {
- if (llvm::Expected<CommandObjectSP> delegate = DoGetProxyCommandObject()) {
- m_delegate_sp = *delegate;
- m_delegate_error.clear();
- return m_delegate_sp.get();
- } else {
- m_delegate_sp.reset();
- m_delegate_error = llvm::toString(delegate.takeError());
- return nullptr;
+ for (uint32_t i = 0; true; i++) {
+ if (const char *plugin_name =
+ PluginManager::GetTraceExporterPluginNameAtIndex(i)) {
+ if (ThreadTraceExportCommandCreator command_creator =
+ PluginManager::GetThreadTraceExportCommandCreatorAtIndex(i)) {
+ LoadSubCommand(plugin_name, command_creator(interpreter));
+ }
+ } else {
+ break;
+ }
}
}
+};
+
+// CommandObjectTraceStart
-private:
- llvm::StringRef GetUnsupportedError() override { return m_delegate_error; }
+class CommandObjectTraceStart : public CommandObjectTraceProxy {
+public:
+ CommandObjectTraceStart(CommandInterpreter &interpreter)
+ : CommandObjectTraceProxy(
+ /*live_debug_session_only=*/true, interpreter, "thread trace start",
+ "Start tracing threads with the corresponding trace "
+ "plug-in for the current process.",
+ "thread trace start [<trace-options>]") {}
- CommandObjectSP m_delegate_sp;
- std::string m_delegate_error;
+protected:
+ lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override {
+ return trace.GetThreadTraceStartCommand(m_interpreter);
+ }
};
// CommandObjectTraceStop
-class CommandObjectTraceStop : public CommandObjectIterateOverThreads {
+class CommandObjectTraceStop : public CommandObjectMultipleThreads {
public:
CommandObjectTraceStop(CommandInterpreter &interpreter)
- : CommandObjectIterateOverThreads(
+ : CommandObjectMultipleThreads(
interpreter, "thread trace stop",
- "Stop tracing threads. "
+ "Stop tracing threads, including the ones traced with the "
+ "\"process trace start\" command."
"Defaults to the current thread. Thread indices can be "
- "specified as arguments.\n Use the thread-index \"all\" to trace "
- "all threads.",
+ "specified as arguments.\n Use the thread-index \"all\" to stop "
+ "tracing "
+ "for all existing threads.",
"thread trace stop [<thread-index> <thread-index> ...]",
eCommandRequiresProcess | eCommandTryTargetAPILock |
eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
@@ -2054,20 +1986,18 @@ public:
~CommandObjectTraceStop() override = default;
- bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
- const Thread &thread =
- *m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
- Trace &trace = *m_exe_ctx.GetTargetSP()->GetTrace();
+ bool DoExecuteOnThreads(Args &command, CommandReturnObject &result,
+ llvm::ArrayRef<lldb::tid_t> tids) override {
+ ProcessSP process_sp = m_exe_ctx.GetProcessSP();
- if (llvm::Error err = trace.StopTracingThread(thread)) {
- result.AppendErrorWithFormat("Failed stopping thread %" PRIu64 ": %s\n",
- tid, toString(std::move(err)).c_str());
- result.SetStatus(eReturnStatusFailed);
- }
+ TraceSP trace_sp = process_sp->GetTarget().GetTrace();
- // We don't return false on errors to try to stop as many threads as
- // possible.
- return true;
+ if (llvm::Error err = trace_sp->Stop(tids))
+ result.AppendError(toString(std::move(err)));
+ else
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+
+ return result.Succeeded();
}
};
@@ -2101,21 +2031,28 @@ public:
m_count = count;
break;
}
- case 'p': {
- int32_t position;
- if (option_arg.empty() || option_arg.getAsInteger(0, position) ||
- position < 0)
+ case 's': {
+ int32_t skip;
+ if (option_arg.empty() || option_arg.getAsInteger(0, skip) || skip < 0)
error.SetErrorStringWithFormat(
"invalid integer value for option '%s'",
option_arg.str().c_str());
else
- m_position = position;
+ m_skip = skip;
break;
}
case 'r': {
m_raw = true;
break;
}
+ case 'f': {
+ m_forwards = true;
+ break;
+ }
+ case 't': {
+ m_show_tsc = true;
+ break;
+ }
default:
llvm_unreachable("Unimplemented option");
}
@@ -2124,8 +2061,10 @@ public:
void OptionParsingStarting(ExecutionContext *execution_context) override {
m_count = kDefaultCount;
- m_position = llvm::None;
+ m_skip = 0;
m_raw = false;
+ m_forwards = false;
+ m_show_tsc = false;
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@@ -2136,14 +2075,16 @@ public:
// Instance variables to hold the values for command options.
size_t m_count;
- llvm::Optional<ssize_t> m_position;
+ size_t m_skip;
bool m_raw;
+ bool m_forwards;
+ bool m_show_tsc;
};
CommandObjectTraceDumpInstructions(CommandInterpreter &interpreter)
: CommandObjectIterateOverThreads(
interpreter, "thread trace dump instructions",
- "Dump the traced instructions for one or more threads. If no "
+ "Dump the traced instructions for one or more threads. If no "
"threads are specified, show the current thread. Use the "
"thread-index \"all\" to see all threads.",
nullptr,
@@ -2160,14 +2101,14 @@ public:
uint32_t index) override {
current_command_args.GetCommandString(m_repeat_command);
m_create_repeat_command_just_invoked = true;
- m_consecutive_repetitions = 0;
return m_repeat_command.c_str();
}
protected:
bool DoExecute(Args &args, CommandReturnObject &result) override {
- if (IsRepeatCommand())
- m_consecutive_repetitions++;
+ if (!IsRepeatCommand())
+ m_dumpers.clear();
+
bool status = CommandObjectIterateOverThreads::DoExecute(args, result);
m_create_repeat_command_just_invoked = false;
@@ -2179,19 +2120,38 @@ protected:
}
bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
+ Stream &s = result.GetOutputStream();
+
const TraceSP &trace_sp = m_exe_ctx.GetTargetSP()->GetTrace();
ThreadSP thread_sp =
m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
- size_t count = m_options.m_count;
- ssize_t position = m_options.m_position.getValueOr(
- trace_sp->GetCursorPosition(*thread_sp)) -
- m_consecutive_repetitions * count;
- if (position < 0)
- result.SetError("error: no more data");
- else
- trace_sp->DumpTraceInstructions(*thread_sp, result.GetOutputStream(),
- count, position, m_options.m_raw);
+ if (!m_dumpers.count(thread_sp->GetID())) {
+ lldb::TraceCursorUP cursor_up = trace_sp->GetCursor(*thread_sp);
+ // Set up the cursor and return the presentation index of the first
+ // instruction to dump after skipping instructions.
+ auto setUpCursor = [&]() {
+ cursor_up->SetForwards(m_options.m_forwards);
+ if (m_options.m_forwards)
+ return cursor_up->Seek(m_options.m_skip, TraceCursor::SeekType::Set);
+ return -cursor_up->Seek(-m_options.m_skip, TraceCursor::SeekType::End);
+ };
+
+ int initial_index = setUpCursor();
+
+ auto dumper = std::make_unique<TraceInstructionDumper>(
+ std::move(cursor_up), initial_index, m_options.m_raw,
+ m_options.m_show_tsc);
+
+ // This happens when the seek value was more than the number of available
+ // instructions.
+ if (std::abs(initial_index) < (int)m_options.m_skip)
+ dumper->SetNoMoreData();
+
+ m_dumpers[thread_sp->GetID()] = std::move(dumper);
+ }
+
+ m_dumpers[thread_sp->GetID()]->DumpInstructions(s, m_options.m_count);
return true;
}
@@ -2200,7 +2160,84 @@ protected:
// Repeat command helpers
std::string m_repeat_command;
bool m_create_repeat_command_just_invoked;
- size_t m_consecutive_repetitions = 0;
+ std::map<lldb::tid_t, std::unique_ptr<TraceInstructionDumper>> m_dumpers;
+};
+
+// CommandObjectTraceDumpInfo
+#define LLDB_OPTIONS_thread_trace_dump_info
+#include "CommandOptions.inc"
+
+class CommandObjectTraceDumpInfo : public CommandObjectIterateOverThreads {
+public:
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options() { OptionParsingStarting(nullptr); }
+
+ ~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;
+
+ switch (short_option) {
+ case 'v': {
+ m_verbose = true;
+ break;
+ }
+ default:
+ llvm_unreachable("Unimplemented option");
+ }
+ return error;
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_verbose = false;
+ }
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+ return llvm::makeArrayRef(g_thread_trace_dump_info_options);
+ }
+
+ // Instance variables to hold the values for command options.
+ bool m_verbose;
+ };
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ Target &target = m_exe_ctx.GetTargetRef();
+ result.GetOutputStream().Printf(
+ "Trace technology: %s\n",
+ target.GetTrace()->GetPluginName().AsCString());
+ return CommandObjectIterateOverThreads::DoExecute(command, result);
+ }
+
+ CommandObjectTraceDumpInfo(CommandInterpreter &interpreter)
+ : CommandObjectIterateOverThreads(
+ interpreter, "thread trace dump info",
+ "Dump the traced information for one or more threads. If no "
+ "threads are specified, show the current thread. Use the "
+ "thread-index \"all\" to see all threads.",
+ nullptr,
+ eCommandRequiresProcess | eCommandTryTargetAPILock |
+ eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
+ eCommandProcessMustBeTraced),
+ m_options() {}
+
+ ~CommandObjectTraceDumpInfo() override = default;
+
+ Options *GetOptions() override { return &m_options; }
+
+protected:
+ bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
+ const TraceSP &trace_sp = m_exe_ctx.GetTargetSP()->GetTrace();
+ ThreadSP thread_sp =
+ m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
+ trace_sp->DumpTraceInfo(*thread_sp, result.GetOutputStream(),
+ m_options.m_verbose);
+ return true;
+ }
+
+ CommandOptions m_options;
};
// CommandObjectMultiwordTraceDump
@@ -2215,6 +2252,8 @@ public:
LoadSubCommand(
"instructions",
CommandObjectSP(new CommandObjectTraceDumpInstructions(interpreter)));
+ LoadSubCommand(
+ "info", CommandObjectSP(new CommandObjectTraceDumpInfo(interpreter)));
}
~CommandObjectMultiwordTraceDump() override = default;
};
@@ -2234,6 +2273,8 @@ public:
CommandObjectSP(new CommandObjectTraceStart(interpreter)));
LoadSubCommand("stop",
CommandObjectSP(new CommandObjectTraceStop(interpreter)));
+ LoadSubCommand("export",
+ CommandObjectSP(new CommandObjectTraceExport(interpreter)));
}
~CommandObjectMultiwordTrace() override = default;
diff --git a/lldb/source/Commands/CommandObjectThreadUtil.cpp b/lldb/source/Commands/CommandObjectThreadUtil.cpp
index b93698c7be60..d330da7e684e 100644
--- a/lldb/source/Commands/CommandObjectThreadUtil.cpp
+++ b/lldb/source/Commands/CommandObjectThreadUtil.cpp
@@ -58,7 +58,6 @@ bool CommandObjectIterateOverThreads::DoExecute(Args &command,
if (!llvm::to_integer(command.GetArgumentAtIndex(i), thread_idx)) {
result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n",
command.GetArgumentAtIndex(i));
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -68,7 +67,6 @@ bool CommandObjectIterateOverThreads::DoExecute(Args &command,
if (!thread) {
result.AppendErrorWithFormat("no thread with index: \"%s\"\n",
command.GetArgumentAtIndex(i));
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -129,7 +127,6 @@ bool CommandObjectIterateOverThreads::BucketThread(
Thread *thread = process->GetThreadList().FindThreadByID(tid).get();
if (thread == nullptr) {
result.AppendErrorWithFormatv("Failed to process thread #{0}.\n", tid);
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -156,3 +153,45 @@ bool CommandObjectIterateOverThreads::BucketThread(
}
return true;
}
+
+bool CommandObjectMultipleThreads::DoExecute(Args &command,
+ CommandReturnObject &result) {
+ Process &process = m_exe_ctx.GetProcessRef();
+
+ std::vector<lldb::tid_t> tids;
+ const size_t num_args = command.GetArgumentCount();
+
+ std::lock_guard<std::recursive_mutex> guard(
+ process.GetThreadList().GetMutex());
+
+ if (num_args > 0 && ::strcmp(command.GetArgumentAtIndex(0), "all") == 0) {
+ for (ThreadSP thread_sp : process.Threads())
+ tids.push_back(thread_sp->GetID());
+ } else {
+ if (num_args == 0) {
+ Thread &thread = m_exe_ctx.GetThreadRef();
+ tids.push_back(thread.GetID());
+ }
+
+ for (size_t i = 0; i < num_args; i++) {
+ uint32_t thread_idx;
+ if (!llvm::to_integer(command.GetArgumentAtIndex(i), thread_idx)) {
+ result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n",
+ command.GetArgumentAtIndex(i));
+ return false;
+ }
+
+ ThreadSP thread = process.GetThreadList().FindThreadByIndexID(thread_idx);
+
+ if (!thread) {
+ result.AppendErrorWithFormat("no thread with index: \"%s\"\n",
+ command.GetArgumentAtIndex(i));
+ return false;
+ }
+
+ tids.push_back(thread->GetID());
+ }
+ }
+
+ return DoExecuteOnThreads(command, result, tids);
+}
diff --git a/lldb/source/Commands/CommandObjectThreadUtil.h b/lldb/source/Commands/CommandObjectThreadUtil.h
index 7122982d8943..289ffdfc1894 100644
--- a/lldb/source/Commands/CommandObjectThreadUtil.h
+++ b/lldb/source/Commands/CommandObjectThreadUtil.h
@@ -76,6 +76,26 @@ protected:
bool m_add_return = true;
};
+/// Class similar to \a CommandObjectIterateOverThreads, but which performs
+/// an action on multiple threads at once instead of iterating over each thread.
+class CommandObjectMultipleThreads : public CommandObjectParsed {
+public:
+ using CommandObjectParsed::CommandObjectParsed;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override;
+
+protected:
+ /// Method that handles the command after the main arguments have been parsed.
+ ///
+ /// \param[in] tids
+ /// The thread ids passed as arguments.
+ ///
+ /// \return
+ /// A boolean result similar to the one expected from \a DoExecute.
+ virtual bool DoExecuteOnThreads(Args &command, CommandReturnObject &result,
+ llvm::ArrayRef<lldb::tid_t> tids) = 0;
+};
+
} // namespace lldb_private
#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTTHREADUTIL_H
diff --git a/lldb/source/Commands/CommandObjectTrace.cpp b/lldb/source/Commands/CommandObjectTrace.cpp
index 170630b85b2e..c55fed45d4f4 100644
--- a/lldb/source/Commands/CommandObjectTrace.cpp
+++ b/lldb/source/Commands/CommandObjectTrace.cpp
@@ -23,6 +23,7 @@
#include "lldb/Interpreter/OptionValueLanguage.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Interpreter/Options.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/Trace.h"
using namespace lldb;
@@ -86,14 +87,12 @@ protected:
result.AppendError(
"a single path to a JSON file containing a trace session"
"is required");
- result.SetStatus(eReturnStatusFailed);
return false;
}
auto end_with_failure = [&result](llvm::Error err) -> bool {
result.AppendErrorWithFormat("%s\n",
llvm::toString(std::move(err)).c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
};
@@ -113,10 +112,11 @@ protected:
return end_with_failure(session_file.takeError());
if (Expected<lldb::TraceSP> traceOrErr =
- Trace::FindPlugin(GetDebugger(), *session_file,
- json_file.GetDirectory().AsCString())) {
+ Trace::FindPluginForPostMortemProcess(
+ GetDebugger(), *session_file,
+ json_file.GetDirectory().AsCString())) {
lldb::TraceSP trace_sp = traceOrErr.get();
- if (m_options.m_verbose)
+ if (m_options.m_verbose && trace_sp)
result.AppendMessageWithFormat("loading trace with plugin %s\n",
trace_sp->GetPluginName().AsCString());
} else
@@ -188,7 +188,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendErrorWithFormat("%s\n", error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -252,7 +251,7 @@ protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
Status error;
if (command.empty()) {
- result.SetError(
+ result.AppendError(
"trace schema cannot be invoked without a plug-in as argument");
return false;
}
@@ -279,7 +278,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendErrorWithFormat("%s\n", error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -303,3 +301,33 @@ CommandObjectTrace::CommandObjectTrace(CommandInterpreter &interpreter)
}
CommandObjectTrace::~CommandObjectTrace() = default;
+
+Expected<CommandObjectSP> CommandObjectTraceProxy::DoGetProxyCommandObject() {
+ ProcessSP process_sp = m_interpreter.GetExecutionContext().GetProcessSP();
+
+ if (!process_sp)
+ return createStringError(inconvertibleErrorCode(),
+ "Process not available.");
+ if (m_live_debug_session_only && !process_sp->IsLiveDebugSession())
+ return createStringError(inconvertibleErrorCode(),
+ "Process must be alive.");
+
+ if (Expected<TraceSP> trace_sp = process_sp->GetTarget().GetTraceOrCreate())
+ return GetDelegateCommand(**trace_sp);
+ else
+ return createStringError(inconvertibleErrorCode(),
+ "Tracing is not supported. %s",
+ toString(trace_sp.takeError()).c_str());
+}
+
+CommandObject *CommandObjectTraceProxy::GetProxyCommandObject() {
+ if (Expected<CommandObjectSP> delegate = DoGetProxyCommandObject()) {
+ m_delegate_sp = *delegate;
+ m_delegate_error.clear();
+ return m_delegate_sp.get();
+ } else {
+ m_delegate_sp.reset();
+ m_delegate_error = toString(delegate.takeError());
+ return nullptr;
+ }
+}
diff --git a/lldb/source/Commands/CommandObjectTrace.h b/lldb/source/Commands/CommandObjectTrace.h
index 2dca0e26b243..b96a3094cefc 100644
--- a/lldb/source/Commands/CommandObjectTrace.h
+++ b/lldb/source/Commands/CommandObjectTrace.h
@@ -9,7 +9,7 @@
#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTTRACE_H
#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTTRACE_H
-#include "lldb/Interpreter/CommandObjectMultiword.h"
+#include "CommandObjectThreadUtil.h"
namespace lldb_private {
@@ -20,6 +20,32 @@ public:
~CommandObjectTrace() override;
};
+/// This class works by delegating the logic to the actual trace plug-in that
+/// can support the current process.
+class CommandObjectTraceProxy : public CommandObjectProxy {
+public:
+ CommandObjectTraceProxy(bool live_debug_session_only,
+ CommandInterpreter &interpreter, const char *name,
+ const char *help = nullptr,
+ const char *syntax = nullptr, uint32_t flags = 0)
+ : CommandObjectProxy(interpreter, name, help, syntax, flags),
+ m_live_debug_session_only(live_debug_session_only) {}
+
+protected:
+ virtual lldb::CommandObjectSP GetDelegateCommand(Trace &trace) = 0;
+
+ llvm::Expected<lldb::CommandObjectSP> DoGetProxyCommandObject();
+
+ CommandObject *GetProxyCommandObject() override;
+
+private:
+ llvm::StringRef GetUnsupportedError() override { return m_delegate_error; }
+
+ bool m_live_debug_session_only;
+ lldb::CommandObjectSP m_delegate_sp;
+ std::string m_delegate_error;
+};
+
} // namespace lldb_private
#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTTRACE_H
diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp
index 004c066b57aa..90e224867e2a 100644
--- a/lldb/source/Commands/CommandObjectType.cpp
+++ b/lldb/source/Commands/CommandObjectType.cpp
@@ -270,7 +270,7 @@ protected:
static const char *g_synth_addreader_instructions =
"Enter your Python command(s). Type 'DONE' to end.\n"
"You must define a Python class with these methods:\n"
- " def __init__(self, valobj, dict):\n"
+ " def __init__(self, valobj, internal_dict):\n"
" def num_children(self):\n"
" def get_child_at_index(self, index):\n"
" def get_child_index(self, name):\n"
@@ -377,7 +377,6 @@ protected:
result.AppendError("must either provide a children list, a Python class "
"name, or use -P and type a Python class "
"line-by-line");
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -639,7 +638,6 @@ protected:
if (argc < 1) {
result.AppendErrorWithFormat("%s takes one or more args.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -648,7 +646,6 @@ protected:
m_command_options.m_custom_type_name.empty()) {
result.AppendErrorWithFormat("%s needs a valid format.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -681,7 +678,6 @@ protected:
for (auto &arg_entry : command.entries()) {
if (arg_entry.ref().empty()) {
result.AppendError("empty typenames not allowed");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -691,7 +687,6 @@ protected:
if (!typeRX.IsValid()) {
result.AppendError(
"regex format error (maybe this is not really a regex?)");
- result.SetStatus(eReturnStatusFailed);
return false;
}
category_sp->GetRegexTypeSummariesContainer()->Delete(typeCS);
@@ -821,7 +816,6 @@ protected:
if (argc != 1) {
result.AppendErrorWithFormat("%s takes 1 arg.\n", m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -830,7 +824,6 @@ protected:
if (!typeCS) {
result.AppendError("empty typenames not allowed");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -868,7 +861,6 @@ protected:
return result.Succeeded();
} else {
result.AppendErrorWithFormat("no custom formatter for %s.\n", typeA);
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -1073,19 +1065,16 @@ protected:
result.AppendErrorWithFormat(
"syntax error in category regular expression '%s'",
m_options.m_category_regex.GetCurrentValueAsRef().str().c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
if (argc == 1) {
const char *arg = command.GetArgumentAtIndex(0);
- formatter_regex = std::make_unique<RegularExpression>(
- llvm::StringRef::withNullAsEmpty(arg));
+ formatter_regex = std::make_unique<RegularExpression>(arg);
if (!formatter_regex->IsValid()) {
result.AppendErrorWithFormat("syntax error in regular expression '%s'",
arg);
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -1167,9 +1156,7 @@ protected:
bool escape = true;
if (category->GetName() == category_regex->GetText()) {
escape = false;
- } else if (category_regex->Execute(
- llvm::StringRef::withNullAsEmpty(
- category->GetName()))) {
+ } else if (category_regex->Execute(category->GetName())) {
escape = false;
}
@@ -1296,7 +1283,6 @@ bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
if (argc < 1 && !m_options.m_name) {
result.AppendErrorWithFormat("%s takes one or more args.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1308,7 +1294,6 @@ bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
const char *funct_name = m_options.m_python_function.c_str();
if (!funct_name || !funct_name[0]) {
result.AppendError("function name empty.\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1332,7 +1317,6 @@ bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
if (!interpreter) {
result.AppendError("script interpreter missing - unable to generate "
"function wrapper.\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
StringList funct_sl;
@@ -1340,13 +1324,11 @@ bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
std::string funct_name_str;
if (!interpreter->GenerateTypeScriptFunction(funct_sl, funct_name_str)) {
result.AppendError("unable to generate function wrapper.\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (funct_name_str.empty()) {
result.AppendError(
"script interpreter failed to generate a valid function name.\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1363,7 +1345,6 @@ bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
for (auto &entry : command.entries()) {
if (entry.ref().empty()) {
result.AppendError("empty typenames not allowed");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1392,7 +1373,6 @@ bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
m_options.m_category, &error);
if (error.Fail()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -1403,7 +1383,6 @@ bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
if (error.Fail()) {
result.AppendError(error.AsCString());
result.AppendError("added to types, but not given a name");
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -1420,14 +1399,12 @@ bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
if (argc < 1 && !m_options.m_name) {
result.AppendErrorWithFormat("%s takes one or more args.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (!m_options.m_flags.GetShowMembersOneLiner() &&
m_options.m_format_string.empty()) {
result.AppendError("empty summary strings not allowed");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1438,7 +1415,6 @@ bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
// ${var%S} is an endless recursion, prevent it
if (strcmp(format_cstr, "${var%S}") == 0) {
result.AppendError("recursive summary not allowed");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1446,13 +1422,11 @@ bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
new StringSummaryFormat(m_options.m_flags, format_cstr));
if (!string_format) {
result.AppendError("summary creation failed");
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (string_format->m_error.Fail()) {
result.AppendErrorWithFormat("syntax error: %s",
string_format->m_error.AsCString("<unknown>"));
- result.SetStatus(eReturnStatusFailed);
return false;
}
lldb::TypeSummaryImplSP entry(string_format.release());
@@ -1462,7 +1436,6 @@ bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
for (auto &arg_entry : command.entries()) {
if (arg_entry.ref().empty()) {
result.AppendError("empty typenames not allowed");
- result.SetStatus(eReturnStatusFailed);
return false;
}
ConstString typeCS(arg_entry.ref());
@@ -1473,7 +1446,6 @@ bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
if (error.Fail()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -1484,7 +1456,6 @@ bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
if (error.Fail()) {
result.AppendError(error.AsCString());
result.AppendError("added to types, but not given a name");
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -1613,7 +1584,6 @@ bool CommandObjectTypeSummaryAdd::DoExecute(Args &command,
return Execute_ScriptSummary(command, result);
#else
result.AppendError("python is disabled");
- result.SetStatus(eReturnStatusFailed);
return false;
#endif
}
@@ -1820,7 +1790,6 @@ protected:
if (argc < 1) {
result.AppendErrorWithFormat("%s takes 1 or more args.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1924,7 +1893,6 @@ protected:
if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
result.AppendErrorWithFormat("%s takes arguments and/or a language",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1937,7 +1905,6 @@ protected:
if (!typeCS) {
result.AppendError("empty category name not allowed");
- result.SetStatus(eReturnStatusFailed);
return false;
}
DataVisualization::Categories::Enable(typeCS);
@@ -1994,7 +1961,6 @@ protected:
if (argc < 1) {
result.AppendErrorWithFormat("%s takes 1 or more arg.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -2007,7 +1973,6 @@ protected:
if (!typeCS) {
result.AppendError("empty category name not allowed");
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (!DataVisualization::Categories::Delete(typeCS))
@@ -2018,7 +1983,6 @@ protected:
return result.Succeeded();
} else {
result.AppendError("cannot delete one or more categories\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -2107,7 +2071,6 @@ protected:
if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
result.AppendErrorWithFormat("%s takes arguments and/or a language",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -2121,7 +2084,6 @@ protected:
if (!typeCS) {
result.AppendError("empty category name not allowed");
- result.SetStatus(eReturnStatusFailed);
return false;
}
DataVisualization::Categories::Disable(typeCS);
@@ -2175,18 +2137,15 @@ protected:
if (argc == 1) {
const char *arg = command.GetArgumentAtIndex(0);
- regex = std::make_unique<RegularExpression>(
- llvm::StringRef::withNullAsEmpty(arg));
+ regex = std::make_unique<RegularExpression>(arg);
if (!regex->IsValid()) {
result.AppendErrorWithFormat(
"syntax error in category regular expression '%s'", arg);
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else if (argc != 0) {
result.AppendErrorWithFormat("%s takes 0 or one arg.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -2196,8 +2155,7 @@ protected:
bool escape = true;
if (regex->GetText() == category_sp->GetName()) {
escape = false;
- } else if (regex->Execute(llvm::StringRef::withNullAsEmpty(
- category_sp->GetName()))) {
+ } else if (regex->Execute(category_sp->GetName())) {
escape = false;
}
@@ -2305,7 +2263,6 @@ bool CommandObjectTypeSynthAdd::Execute_HandwritePython(
for (auto &entry : command.entries()) {
if (entry.ref().empty()) {
result.AppendError("empty typenames not allowed");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -2328,7 +2285,6 @@ bool CommandObjectTypeSynthAdd::Execute_PythonClass(
if (argc < 1) {
result.AppendErrorWithFormat("%s takes one or more args.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -2336,7 +2292,6 @@ bool CommandObjectTypeSynthAdd::Execute_PythonClass(
result.AppendErrorWithFormat("%s needs either a Python class name or -P to "
"directly input Python code.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -2369,7 +2324,6 @@ bool CommandObjectTypeSynthAdd::Execute_PythonClass(
for (auto &arg_entry : command.entries()) {
if (arg_entry.ref().empty()) {
result.AppendError("empty typenames not allowed");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -2378,7 +2332,6 @@ bool CommandObjectTypeSynthAdd::Execute_PythonClass(
m_options.m_regex ? eRegexSynth : eRegularSynth,
m_options.m_category, &error)) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -2633,14 +2586,12 @@ protected:
if (argc < 1) {
result.AppendErrorWithFormat("%s takes one or more args.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (m_options.m_expr_paths.empty()) {
result.AppendErrorWithFormat("%s needs one or more children.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -2670,7 +2621,6 @@ protected:
for (auto &arg_entry : command.entries()) {
if (arg_entry.ref().empty()) {
result.AppendError("empty typenames not allowed");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -2679,7 +2629,6 @@ protected:
m_options.m_regex ? eRegexFilter : eRegularFilter,
m_options.m_category, &error)) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -2717,8 +2666,7 @@ protected:
class CommandOptions : public OptionGroup {
public:
- CommandOptions()
- : OptionGroup(), m_show_help(false), m_language(eLanguageTypeUnknown) {}
+ CommandOptions() : OptionGroup() {}
~CommandOptions() override = default;
@@ -2755,8 +2703,8 @@ protected:
// Options table: Required for subclasses of Options.
- bool m_show_help;
- lldb::LanguageType m_language;
+ bool m_show_help = false;
+ lldb::LanguageType m_language = eLanguageTypeUnknown;
};
OptionGroupOptions m_option_group;
@@ -2796,7 +2744,7 @@ public:
bool DoExecute(llvm::StringRef raw_command_line,
CommandReturnObject &result) override {
if (raw_command_line.empty()) {
- result.SetError(
+ result.AppendError(
"type lookup cannot be invoked without a type name as argument");
return false;
}
@@ -2927,7 +2875,6 @@ protected:
Thread *thread = GetDefaultThread();
if (!thread) {
result.AppendError("no default thread");
- result.SetStatus(lldb::eReturnStatusFailed);
return false;
}
@@ -2960,7 +2907,6 @@ protected:
return true;
} else {
result.AppendError("failed to evaluate expression");
- result.SetStatus(lldb::eReturnStatusFailed);
return false;
}
}
diff --git a/lldb/source/Commands/CommandObjectVersion.cpp b/lldb/source/Commands/CommandObjectVersion.cpp
index 065cbe4660d3..20c2d25b745c 100644
--- a/lldb/source/Commands/CommandObjectVersion.cpp
+++ b/lldb/source/Commands/CommandObjectVersion.cpp
@@ -20,7 +20,7 @@ CommandObjectVersion::CommandObjectVersion(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "version",
"Show the LLDB debugger version.", "version") {}
-CommandObjectVersion::~CommandObjectVersion() {}
+CommandObjectVersion::~CommandObjectVersion() = default;
bool CommandObjectVersion::DoExecute(Args &args, CommandReturnObject &result) {
if (args.GetArgumentCount() == 0) {
@@ -28,7 +28,6 @@ bool CommandObjectVersion::DoExecute(Args &args, CommandReturnObject &result) {
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendError("the version command takes no arguments.");
- result.SetStatus(eReturnStatusFailed);
}
return true;
}
diff --git a/lldb/source/Commands/CommandObjectWatchpoint.cpp b/lldb/source/Commands/CommandObjectWatchpoint.cpp
index e7b1f31f3960..d7a446fc366c 100644
--- a/lldb/source/Commands/CommandObjectWatchpoint.cpp
+++ b/lldb/source/Commands/CommandObjectWatchpoint.cpp
@@ -42,7 +42,6 @@ static bool CheckTargetForWatchpointOperations(Target *target,
target->GetProcessSP() && target->GetProcessSP()->IsAlive();
if (!process_is_valid) {
result.AppendError("There's no process or it is not alive.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
// Target passes our checks, return true.
@@ -166,11 +165,7 @@ public:
class CommandOptions : public Options {
public:
- CommandOptions()
- : Options(),
- m_level(lldb::eDescriptionLevelBrief) // Watchpoint List defaults to
- // brief descriptions
- {}
+ CommandOptions() : Options() {}
~CommandOptions() override = default;
@@ -206,7 +201,7 @@ public:
// Instance variables to hold the values for command options.
- lldb::DescriptionLevel m_level;
+ lldb::DescriptionLevel m_level = lldb::eDescriptionLevelBrief;
};
protected:
@@ -252,7 +247,6 @@ protected:
if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
target, command, wp_ids)) {
result.AppendError("Invalid watchpoints specification.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -315,7 +309,6 @@ protected:
if (num_watchpoints == 0) {
result.AppendError("No watchpoints exist to be enabled.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -332,7 +325,6 @@ protected:
if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
target, command, wp_ids)) {
result.AppendError("Invalid watchpoints specification.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -392,7 +384,6 @@ protected:
if (num_watchpoints == 0) {
result.AppendError("No watchpoints exist to be disabled.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -405,7 +396,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
result.AppendError("Disable all watchpoints failed\n");
- result.SetStatus(eReturnStatusFailed);
}
} else {
// Particular watchpoints selected; disable them.
@@ -413,7 +403,6 @@ protected:
if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
target, command, wp_ids)) {
result.AppendError("Invalid watchpoints specification.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -467,7 +456,7 @@ public:
class CommandOptions : public Options {
public:
- CommandOptions() : Options(), m_force(false) {}
+ CommandOptions() : Options() {}
~CommandOptions() override = default;
@@ -495,7 +484,7 @@ public:
}
// Instance variables to hold the values for command options.
- bool m_force;
+ bool m_force = false;
};
protected:
@@ -513,7 +502,6 @@ protected:
if (num_watchpoints == 0) {
result.AppendError("No watchpoints exist to be deleted.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -538,7 +526,6 @@ protected:
if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command,
wp_ids)) {
result.AppendError("Invalid watchpoints specification.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -593,7 +580,7 @@ public:
class CommandOptions : public Options {
public:
- CommandOptions() : Options(), m_ignore_count(0) {}
+ CommandOptions() : Options() {}
~CommandOptions() override = default;
@@ -625,7 +612,7 @@ public:
// Instance variables to hold the values for command options.
- uint32_t m_ignore_count;
+ uint32_t m_ignore_count = 0;
};
protected:
@@ -643,7 +630,6 @@ protected:
if (num_watchpoints == 0) {
result.AppendError("No watchpoints exist to be ignored.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -659,7 +645,6 @@ protected:
if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
target, command, wp_ids)) {
result.AppendError("Invalid watchpoints specification.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -721,7 +706,7 @@ public:
class CommandOptions : public Options {
public:
- CommandOptions() : Options(), m_condition(), m_condition_passed(false) {}
+ CommandOptions() : Options(), m_condition() {}
~CommandOptions() override = default;
@@ -754,7 +739,7 @@ public:
// Instance variables to hold the values for command options.
std::string m_condition;
- bool m_condition_passed;
+ bool m_condition_passed = false;
};
protected:
@@ -772,7 +757,6 @@ protected:
if (num_watchpoints == 0) {
result.AppendError("No watchpoints exist to be modified.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -786,7 +770,6 @@ protected:
if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
target, command, wp_ids)) {
result.AppendError("Invalid watchpoints specification.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -893,10 +876,8 @@ protected:
// If no argument is present, issue an error message. There's no way to
// set a watchpoint.
if (command.GetArgumentCount() <= 0) {
- result.GetErrorStream().Printf("error: required argument missing; "
- "specify your program variable to watch "
- "for\n");
- result.SetStatus(eReturnStatusFailed);
+ result.AppendError("required argument missing; "
+ "specify your program variable to watch for");
return false;
}
@@ -916,9 +897,7 @@ protected:
// A simple watch variable gesture allows only one argument.
if (command.GetArgumentCount() != 1) {
- result.GetErrorStream().Printf(
- "error: specify exactly one variable to watch for\n");
- result.SetStatus(eReturnStatusFailed);
+ result.AppendError("specify exactly one variable to watch for");
return false;
}
@@ -962,11 +941,11 @@ protected:
} else {
const char *error_cstr = error.AsCString(nullptr);
if (error_cstr)
- result.GetErrorStream().Printf("error: %s\n", error_cstr);
+ result.AppendError(error_cstr);
else
- result.GetErrorStream().Printf("error: unable to find any variable "
- "expression path that matches '%s'\n",
- command.GetArgumentAtIndex(0));
+ result.AppendErrorWithFormat("unable to find any variable "
+ "expression path that matches '%s'",
+ command.GetArgumentAtIndex(0));
return false;
}
@@ -997,7 +976,6 @@ protected:
addr, (uint64_t)size, command.GetArgumentAtIndex(0));
if (error.AsCString(nullptr))
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
@@ -1087,10 +1065,8 @@ protected:
// If no argument is present, issue an error message. There's no way to
// set a watchpoint.
if (raw_command.trim().empty()) {
- result.GetErrorStream().Printf("error: required argument missing; "
- "specify an expression to evaluate into "
- "the address to watch for\n");
- result.SetStatus(eReturnStatusFailed);
+ result.AppendError("required argument missing; specify an expression "
+ "to evaluate into the address to watch for");
return false;
}
@@ -1117,12 +1093,10 @@ protected:
ExpressionResults expr_result =
target->EvaluateExpression(expr, frame, valobj_sp, options);
if (expr_result != eExpressionCompleted) {
- result.GetErrorStream().Printf(
- "error: expression evaluation of address to watch failed\n");
- result.GetErrorStream() << "expression evaluated: \n" << expr << "\n";
+ result.AppendError("expression evaluation of address to watch failed");
+ result.AppendErrorWithFormat("expression evaluated: \n%s", expr.data());
if (valobj_sp && !valobj_sp->GetError().Success())
- result.GetErrorStream() << valobj_sp->GetError().AsCString() << "\n";
- result.SetStatus(eReturnStatusFailed);
+ result.AppendError(valobj_sp->GetError().AsCString());
return false;
}
@@ -1130,9 +1104,7 @@ protected:
bool success = false;
addr = valobj_sp->GetValueAsUnsigned(0, &success);
if (!success) {
- result.GetErrorStream().Printf(
- "error: expression did not evaluate to an address\n");
- result.SetStatus(eReturnStatusFailed);
+ result.AppendError("expression did not evaluate to an address");
return false;
}
@@ -1165,7 +1137,6 @@ protected:
addr, (uint64_t)size);
if (error.AsCString(nullptr))
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
diff --git a/lldb/source/Commands/CommandObjectWatchpointCommand.cpp b/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
index fe3052a775a2..1f4e95366385 100644
--- a/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
+++ b/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
@@ -61,7 +61,9 @@ public:
CommandObjectWatchpointCommandAdd(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "add",
"Add a set of LLDB commands to a watchpoint, to be "
- "executed whenever the watchpoint is hit.",
+ "executed whenever the watchpoint is hit. "
+ "The commands added to the watchpoint replace any "
+ "commands previously added to it.",
nullptr, eCommandRequiresTarget),
IOHandlerDelegateMultiline("DONE",
IOHandlerDelegate::Completion::LLDBCommand),
@@ -301,7 +303,7 @@ are no syntax errors may indicate that a function was declared but never called.
options.SetPrintErrors(true);
options.SetAddToHistory(false);
- debugger.GetCommandInterpreter().HandleCommands(commands, &exe_ctx,
+ debugger.GetCommandInterpreter().HandleCommands(commands, exe_ctx,
options, result);
result.GetImmediateOutputStream()->Flush();
result.GetImmediateErrorStream()->Flush();
@@ -312,10 +314,7 @@ are no syntax errors may indicate that a function was declared but never called.
class CommandOptions : public Options {
public:
- CommandOptions()
- : Options(), m_use_commands(false), m_use_script_language(false),
- m_script_language(eScriptLanguageNone), m_use_one_liner(false),
- m_one_liner(), m_function_name() {}
+ CommandOptions() : Options(), m_one_liner(), m_function_name() {}
~CommandOptions() override = default;
@@ -385,12 +384,12 @@ are no syntax errors may indicate that a function was declared but never called.
// Instance variables to hold the values for command options.
- bool m_use_commands;
- bool m_use_script_language;
- lldb::ScriptLanguage m_script_language;
+ bool m_use_commands = false;
+ bool m_use_script_language = false;
+ lldb::ScriptLanguage m_script_language = eScriptLanguageNone;
// Instance variables to hold the values for one_liner options.
- bool m_use_one_liner;
+ bool m_use_one_liner = false;
std::string m_one_liner;
bool m_stop_on_error;
std::string m_function_name;
@@ -405,7 +404,6 @@ protected:
if (num_watchpoints == 0) {
result.AppendError("No watchpoints exist to have commands added");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -420,7 +418,6 @@ protected:
if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command,
valid_wp_ids)) {
result.AppendError("Invalid watchpoints specification.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -515,14 +512,12 @@ protected:
if (num_watchpoints == 0) {
result.AppendError("No watchpoints exist to have commands deleted");
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (command.GetArgumentCount() == 0) {
result.AppendError(
"No watchpoint specified from which to delete the commands");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -530,7 +525,6 @@ protected:
if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command,
valid_wp_ids)) {
result.AppendError("Invalid watchpoints specification.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -544,7 +538,6 @@ protected:
wp->ClearCallback();
} else {
result.AppendErrorWithFormat("Invalid watchpoint ID: %u.\n", cur_wp_id);
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -587,14 +580,12 @@ protected:
if (num_watchpoints == 0) {
result.AppendError("No watchpoints exist for which to list commands");
- result.SetStatus(eReturnStatusFailed);
return false;
}
if (command.GetArgumentCount() == 0) {
result.AppendError(
"No watchpoint specified for which to list the commands");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -602,7 +593,6 @@ protected:
if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command,
valid_wp_ids)) {
result.AppendError("Invalid watchpoints specification.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -634,7 +624,6 @@ protected:
} else {
result.AppendErrorWithFormat("Invalid watchpoint ID: %u.\n",
cur_wp_id);
- result.SetStatus(eReturnStatusFailed);
}
}
}
diff --git a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
index 4445457ca852..a618796156a6 100644
--- a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
+++ b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
@@ -30,7 +30,7 @@ Status CommandOptionsProcessLaunch::SetOptionValue(
uint32_t option_idx, llvm::StringRef option_arg,
ExecutionContext *execution_context) {
Status error;
- const int short_option = m_getopt_table[option_idx].val;
+ const int short_option = g_process_launch_options[option_idx].short_option;
switch (short_option) {
case 's': // Stop at program entry point
@@ -130,7 +130,7 @@ Status CommandOptionsProcessLaunch::SetOptionValue(
launch_info.SetShell(HostInfo::GetDefaultShell());
break;
- case 'v':
+ case 'E':
launch_info.GetEnvironment().insert(option_arg);
break;
diff --git a/lldb/source/Commands/CommandOptionsProcessLaunch.h b/lldb/source/Commands/CommandOptionsProcessLaunch.h
index 4028d8e02cb2..d18a23245080 100644
--- a/lldb/source/Commands/CommandOptionsProcessLaunch.h
+++ b/lldb/source/Commands/CommandOptionsProcessLaunch.h
@@ -1,4 +1,4 @@
-//===-- CommandOptionsProcessLaunch.h -------------------------------------===//
+//===-- CommandOptionsProcessLaunch.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.
@@ -16,9 +16,9 @@ namespace lldb_private {
// CommandOptionsProcessLaunch
-class CommandOptionsProcessLaunch : public lldb_private::Options {
+class CommandOptionsProcessLaunch : public lldb_private::OptionGroup {
public:
- CommandOptionsProcessLaunch() : lldb_private::Options() {
+ CommandOptionsProcessLaunch() : lldb_private::OptionGroup() {
// Keep default values of all options in one place: OptionParsingStarting
// ()
OptionParsingStarting(nullptr);
@@ -44,6 +44,6 @@ public:
lldb_private::LazyBool disable_aslr;
}; // CommandOptionsProcessLaunch
-}; // namespace lldb_private
+} // namespace lldb_private
#endif // LLDB_SOURCE_COMMANDS_COMMANDOPTIONSPROCESSLAUNCH_H
diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td
index d3329078893a..9c9b7c6e9b82 100644
--- a/lldb/source/Commands/Options.td
+++ b/lldb/source/Commands/Options.td
@@ -125,7 +125,7 @@ let Command = "breakpoint set" in {
def breakpoint_set_address : Option<"address", "a">, Group<2>,
Arg<"AddressOrExpression">, Required,
Desc<"Set the breakpoint at the specified address. If the address maps "
- "uniquely toa particular binary, then the address will be converted to "
+ "uniquely to a particular binary, then the address will be converted to "
"a \"file\"address, so that the breakpoint will track that binary+offset "
"no matter where the binary eventually loads. Alternately, if you also "
"specify the module - with the -s option - then the address will be "
@@ -200,7 +200,7 @@ let Command = "breakpoint set" in {
def breakpoint_set_move_to_nearest_code : Option<"move-to-nearest-code", "m">,
Groups<[1,9,12]>, Arg<"Boolean">,
Desc<"Move breakpoints to nearest code. If not set the "
- "target.move-to-nearest-codesetting is used.">;
+ "target.move-to-nearest-code setting is used.">;
def breakpoint_set_file_colon_line : Option<"joint-specifier", "y">, Group<12>, Arg<"FileLineColumn">,
Required, Completion<"SourceFile">,
Desc<"A specifier in the form filename:line[:column] for setting file & line breakpoints.">;
@@ -655,7 +655,7 @@ let Command = "process launch" in {
Desc<"Set the current working directory to <path> when running the inferior.">;
def process_launch_arch : Option<"arch", "a">, Arg<"Architecture">,
Desc<"Set the architecture for the process to launch when ambiguous.">;
- def process_launch_environment : Option<"environment", "v">,
+ def process_launch_environment : Option<"environment", "E">,
Arg<"None">, Desc<"Specify an environment variable name/value string "
"(--environment NAME=VALUE). Can be specified multiple times for subsequent "
"environment entries.">;
@@ -730,6 +730,12 @@ let Command = "process status" in {
Desc<"Show verbose process status including extended crash information.">;
}
+let Command = "process save_core" in {
+ def process_save_core_style : Option<"style", "s">, Group<1>,
+ EnumArg<"SaveCoreStyle", "SaveCoreStyles()">, Desc<"Request a specific style "
+ "of corefile to be saved.">;
+}
+
let Command = "script import" in {
def script_import_allow_reload : Option<"allow-reload", "r">, Group<1>,
Desc<"Allow the script to be loaded even if it was already loaded before. "
@@ -739,6 +745,8 @@ let Command = "script import" in {
Group<1>, Desc<"Resolve non-absolute paths relative to the location of the "
"current command file. This argument can only be used when the command is "
"being sourced from a file.">;
+ def silent : Option<"silent", "s">, Group<1>,
+ Desc<"If true don't print any script output while importing.">;
}
let Command = "script add" in {
@@ -1041,16 +1049,30 @@ let Command = "thread plan list" in {
}
let Command = "thread trace dump instructions" in {
+ def thread_trace_dump_instructions_forwards: Option<"forwards", "f">, Group<1>,
+ Desc<"If specified, the trace is traversed forwards chronologically "
+ "starting at the oldest instruction. Otherwise, it starts at the most "
+ "recent one and the traversal is backwards.">;
def thread_trace_dump_instructions_count : Option<"count", "c">, Group<1>,
Arg<"Count">,
- Desc<"The number of instructions to display ending at the current position.">;
- def thread_trace_dump_instructions_position : Option<"position", "p">,
+ Desc<"The number of instructions to display starting at the most recent "
+ "instruction, or the oldest if --forwards is provided.">;
+ def thread_trace_dump_instructions_skip: Option<"skip", "s">,
Group<1>,
Arg<"Index">,
- Desc<"The position to use instead of the current position of the trace.">;
+ Desc<"How many instruction to skip from the end of the trace to start "
+ "dumping instructions, or from the beginning if --forwards is provided">;
def thread_trace_dump_instructions_raw : Option<"raw", "r">,
Group<1>,
Desc<"Dump only instruction address without disassembly nor symbol information.">;
+ def thread_trace_dump_instructions_show_tsc : Option<"tsc", "t">,
+ Group<1>,
+ Desc<"For each instruction, print the corresponding timestamp counter if available.">;
+}
+
+let Command = "thread trace dump info" in {
+ def thread_trace_dump_info_verbose : Option<"verbose", "v">, Group<1>,
+ Desc<"show verbose thread trace dump info">;
}
let Command = "type summary add" in {
diff --git a/lldb/source/Core/Address.cpp b/lldb/source/Core/Address.cpp
index 9d52f1db8918..f0c7e2b34f99 100644
--- a/lldb/source/Core/Address.cpp
+++ b/lldb/source/Core/Address.cpp
@@ -7,12 +7,12 @@
//===----------------------------------------------------------------------===//
#include "lldb/Core/Address.h"
+#include "lldb/Core/Declaration.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/Block.h"
-#include "lldb/Symbol/Declaration.h"
#include "lldb/Symbol/LineEntry.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
@@ -43,9 +43,9 @@
#include <memory>
#include <vector>
-#include <assert.h>
-#include <inttypes.h>
-#include <string.h>
+#include <cassert>
+#include <cinttypes>
+#include <cstring>
namespace lldb_private {
class CompileUnit;
@@ -65,9 +65,9 @@ static size_t ReadBytes(ExecutionContextScope *exe_scope,
TargetSP target_sp(exe_scope->CalculateTarget());
if (target_sp) {
Status error;
- bool prefer_file_cache = false;
- return target_sp->ReadMemory(address, prefer_file_cache, dst, dst_len,
- error);
+ bool force_live_memory = true;
+ return target_sp->ReadMemory(address, dst, dst_len, error,
+ force_live_memory);
}
return 0;
}
diff --git a/lldb/source/Core/AddressRange.cpp b/lldb/source/Core/AddressRange.cpp
index 0868ac5e0888..af6e31a67da3 100644
--- a/lldb/source/Core/AddressRange.cpp
+++ b/lldb/source/Core/AddressRange.cpp
@@ -8,6 +8,7 @@
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/Section.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/FileSpec.h"
@@ -18,7 +19,7 @@
#include <memory>
-#include <inttypes.h>
+#include <cinttypes>
namespace lldb_private {
class SectionList;
@@ -27,7 +28,7 @@ class SectionList;
using namespace lldb;
using namespace lldb_private;
-AddressRange::AddressRange() : m_base_addr(), m_byte_size(0) {}
+AddressRange::AddressRange() : m_base_addr() {}
AddressRange::AddressRange(addr_t file_addr, addr_t byte_size,
const SectionList *section_list)
@@ -40,16 +41,24 @@ AddressRange::AddressRange(const lldb::SectionSP &section, addr_t offset,
AddressRange::AddressRange(const Address &so_addr, addr_t byte_size)
: m_base_addr(so_addr), m_byte_size(byte_size) {}
-AddressRange::~AddressRange() {}
+AddressRange::~AddressRange() = default;
+
+bool AddressRange::Contains(const Address &addr) const {
+ SectionSP range_sect_sp = GetBaseAddress().GetSection();
+ SectionSP addr_sect_sp = addr.GetSection();
+ if (range_sect_sp) {
+ if (!addr_sect_sp ||
+ range_sect_sp->GetModule() != addr_sect_sp->GetModule())
+ return false; // Modules do not match.
+ } else if (addr_sect_sp) {
+ return false; // Range has no module but "addr" does because addr has a
+ // section
+ }
+ // Either the modules match, or both have no module, so it is ok to compare
+ // the file addresses in this case only.
+ return ContainsFileAddress(addr);
+}
-// bool
-// AddressRange::Contains (const Address &addr) const
-//{
-// const addr_t byte_size = GetByteSize();
-// if (byte_size)
-// return addr.GetSection() == m_base_addr.GetSection() &&
-// (addr.GetOffset() - m_base_addr.GetOffset()) < byte_size;
-//}
//
// bool
// AddressRange::Contains (const Address *addr) const
diff --git a/lldb/source/Core/AddressResolver.cpp b/lldb/source/Core/AddressResolver.cpp
index 16b849b721de..87b0abd34e52 100644
--- a/lldb/source/Core/AddressResolver.cpp
+++ b/lldb/source/Core/AddressResolver.cpp
@@ -17,9 +17,9 @@ class ModuleList;
using namespace lldb_private;
// AddressResolver:
-AddressResolver::AddressResolver() {}
+AddressResolver::AddressResolver() = default;
-AddressResolver::~AddressResolver() {}
+AddressResolver::~AddressResolver() = default;
void AddressResolver::ResolveAddressInModules(SearchFilter &filter,
ModuleList &modules) {
diff --git a/lldb/source/Core/AddressResolverFileLine.cpp b/lldb/source/Core/AddressResolverFileLine.cpp
index b0d8dcdde2de..fb61a6100b0e 100644
--- a/lldb/source/Core/AddressResolverFileLine.cpp
+++ b/lldb/source/Core/AddressResolverFileLine.cpp
@@ -21,20 +21,18 @@
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-types.h"
-#include <inttypes.h>
+#include <cinttypes>
#include <vector>
using namespace lldb;
using namespace lldb_private;
// AddressResolverFileLine:
-AddressResolverFileLine::AddressResolverFileLine(const FileSpec &file_spec,
- uint32_t line_no,
- bool check_inlines)
- : AddressResolver(), m_file_spec(file_spec), m_line_number(line_no),
- m_inlines(check_inlines) {}
+AddressResolverFileLine::AddressResolverFileLine(
+ SourceLocationSpec location_spec)
+ : AddressResolver(), m_src_location_spec(location_spec) {}
-AddressResolverFileLine::~AddressResolverFileLine() {}
+AddressResolverFileLine::~AddressResolverFileLine() = default;
Searcher::CallbackReturn
AddressResolverFileLine::SearchCallback(SearchFilter &filter,
@@ -44,8 +42,9 @@ AddressResolverFileLine::SearchCallback(SearchFilter &filter,
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
- cu->ResolveSymbolContext(m_file_spec, m_line_number, m_inlines, false,
- eSymbolContextEverything, sc_list);
+ // TODO: Handle SourceLocationSpec column information
+ cu->ResolveSymbolContext(m_src_location_spec, eSymbolContextEverything,
+ sc_list);
uint32_t sc_list_size = sc_list.GetSize();
for (uint32_t i = 0; i < sc_list_size; i++) {
SymbolContext sc;
@@ -55,18 +54,14 @@ AddressResolverFileLine::SearchCallback(SearchFilter &filter,
if (line_start.IsValid()) {
AddressRange new_range(line_start, byte_size);
m_address_ranges.push_back(new_range);
- if (log) {
- StreamString s;
- // new_bp_loc->GetDescription (&s, lldb::eDescriptionLevelVerbose);
- // LLDB_LOGF(log, "Added address: %s\n", s.GetData());
- }
} else {
LLDB_LOGF(log,
"error: Unable to resolve address at file address 0x%" PRIx64
" for %s:%d\n",
line_start.GetFileAddress(),
- m_file_spec.GetFilename().AsCString("<Unknown>"),
- m_line_number);
+ m_src_location_spec.GetFileSpec().GetFilename().AsCString(
+ "<Unknown>"),
+ m_src_location_spec.GetLine().getValueOr(0));
}
}
}
@@ -78,6 +73,8 @@ lldb::SearchDepth AddressResolverFileLine::GetDepth() {
}
void AddressResolverFileLine::GetDescription(Stream *s) {
- s->Printf("File and line address - file: \"%s\" line: %u",
- m_file_spec.GetFilename().AsCString("<Unknown>"), m_line_number);
+ s->Printf(
+ "File and line address - file: \"%s\" line: %u",
+ m_src_location_spec.GetFileSpec().GetFilename().AsCString("<Unknown>"),
+ m_src_location_spec.GetLine().getValueOr(0));
}
diff --git a/lldb/source/Core/AddressResolverName.cpp b/lldb/source/Core/AddressResolverName.cpp
deleted file mode 100644
index 51ab6435e8fb..000000000000
--- a/lldb/source/Core/AddressResolverName.cpp
+++ /dev/null
@@ -1,198 +0,0 @@
-//===-- AddressResolverName.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 "lldb/Core/AddressResolverName.h"
-
-#include "lldb/Core/Address.h"
-#include "lldb/Core/AddressRange.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Symbol/Function.h"
-#include "lldb/Symbol/Symbol.h"
-#include "lldb/Symbol/SymbolContext.h"
-#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Logging.h"
-#include "lldb/Utility/Stream.h"
-#include "lldb/lldb-enumerations.h"
-#include "lldb/lldb-forward.h"
-#include "lldb/lldb-types.h"
-#include "llvm/ADT/StringRef.h"
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <stdint.h>
-
-using namespace lldb;
-using namespace lldb_private;
-
-AddressResolverName::AddressResolverName(const char *func_name,
- AddressResolver::MatchType type)
- : AddressResolver(), m_func_name(func_name), m_class_name(nullptr),
- m_regex(), m_match_type(type) {
- if (m_match_type == AddressResolver::Regexp) {
- m_regex = RegularExpression(m_func_name.GetStringRef());
- if (!m_regex.IsValid()) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
-
- if (log)
- log->Warning("function name regexp: \"%s\" did not compile.",
- m_func_name.AsCString());
- }
- }
-}
-
-AddressResolverName::AddressResolverName(RegularExpression func_regex)
- : AddressResolver(), m_func_name(nullptr), m_class_name(nullptr),
- m_regex(std::move(func_regex)), m_match_type(AddressResolver::Regexp) {}
-
-AddressResolverName::AddressResolverName(const char *class_name,
- const char *method,
- AddressResolver::MatchType type)
- : AddressResolver(), m_func_name(method), m_class_name(class_name),
- m_regex(), m_match_type(type) {}
-
-AddressResolverName::~AddressResolverName() = default;
-
-// FIXME: Right now we look at the module level, and call the module's
-// "FindFunctions".
-// Greg says he will add function tables, maybe at the CompileUnit level to
-// accelerate function lookup. At that point, we should switch the depth to
-// CompileUnit, and look in these tables.
-
-Searcher::CallbackReturn
-AddressResolverName::SearchCallback(SearchFilter &filter,
- SymbolContext &context, Address *addr) {
- SymbolContextList func_list;
- SymbolContextList sym_list;
-
- bool skip_prologue = true;
- uint32_t i;
- SymbolContext sc;
- Address func_addr;
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
-
- if (m_class_name) {
- if (log)
- log->Warning("Class/method function specification not supported yet.\n");
- return Searcher::eCallbackReturnStop;
- }
-
- const bool include_symbols = false;
- const bool include_inlines = true;
- switch (m_match_type) {
- case AddressResolver::Exact:
- if (context.module_sp) {
- context.module_sp->FindSymbolsWithNameAndType(m_func_name,
- eSymbolTypeCode, sym_list);
- context.module_sp->FindFunctions(m_func_name, CompilerDeclContext(),
- eFunctionNameTypeAuto, include_symbols,
- include_inlines, func_list);
- }
- break;
-
- case AddressResolver::Regexp:
- if (context.module_sp) {
- context.module_sp->FindSymbolsMatchingRegExAndType(
- m_regex, eSymbolTypeCode, sym_list);
- context.module_sp->FindFunctions(m_regex, include_symbols,
- include_inlines, func_list);
- }
- break;
-
- case AddressResolver::Glob:
- if (log)
- log->Warning("glob is not supported yet.");
- break;
- }
-
- // Remove any duplicates between the function list and the symbol list
- if (func_list.GetSize()) {
- for (i = 0; i < func_list.GetSize(); i++) {
- if (!func_list.GetContextAtIndex(i, sc))
- continue;
-
- if (sc.function == nullptr)
- continue;
- uint32_t j = 0;
- while (j < sym_list.GetSize()) {
- SymbolContext symbol_sc;
- if (sym_list.GetContextAtIndex(j, symbol_sc)) {
- if (symbol_sc.symbol && symbol_sc.symbol->ValueIsAddress()) {
- if (sc.function->GetAddressRange().GetBaseAddress() ==
- symbol_sc.symbol->GetAddressRef()) {
- sym_list.RemoveContextAtIndex(j);
- continue; // Don't increment j
- }
- }
- }
-
- j++;
- }
- }
-
- for (i = 0; i < func_list.GetSize(); i++) {
- if (func_list.GetContextAtIndex(i, sc)) {
- if (sc.function) {
- func_addr = sc.function->GetAddressRange().GetBaseAddress();
- addr_t byte_size = sc.function->GetAddressRange().GetByteSize();
- if (skip_prologue) {
- const uint32_t prologue_byte_size =
- sc.function->GetPrologueByteSize();
- if (prologue_byte_size) {
- func_addr.SetOffset(func_addr.GetOffset() + prologue_byte_size);
- byte_size -= prologue_byte_size;
- }
- }
-
- if (filter.AddressPasses(func_addr)) {
- AddressRange new_range(func_addr, byte_size);
- m_address_ranges.push_back(new_range);
- }
- }
- }
- }
- }
-
- for (i = 0; i < sym_list.GetSize(); i++) {
- if (sym_list.GetContextAtIndex(i, sc)) {
- if (sc.symbol && sc.symbol->ValueIsAddress()) {
- func_addr = sc.symbol->GetAddressRef();
- addr_t byte_size = sc.symbol->GetByteSize();
-
- if (skip_prologue) {
- const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
- if (prologue_byte_size) {
- func_addr.SetOffset(func_addr.GetOffset() + prologue_byte_size);
- byte_size -= prologue_byte_size;
- }
- }
-
- if (filter.AddressPasses(func_addr)) {
- AddressRange new_range(func_addr, byte_size);
- m_address_ranges.push_back(new_range);
- }
- }
- }
- }
- return Searcher::eCallbackReturnContinue;
-}
-
-lldb::SearchDepth AddressResolverName::GetDepth() {
- return lldb::eSearchDepthModule;
-}
-
-void AddressResolverName::GetDescription(Stream *s) {
- s->PutCString("Address by function name: ");
-
- if (m_match_type == AddressResolver::Regexp)
- s->Printf("'%s' (regular expression)", m_regex.GetText().str().c_str());
- else
- s->Printf("'%s'", m_func_name.AsCString());
-}
diff --git a/lldb/source/Core/Communication.cpp b/lldb/source/Core/Communication.cpp
index b50cd0ecab5c..5640e0510cf1 100644
--- a/lldb/source/Core/Communication.cpp
+++ b/lldb/source/Core/Communication.cpp
@@ -27,9 +27,9 @@
#include <cstring>
#include <memory>
-#include <errno.h>
-#include <inttypes.h>
-#include <stdio.h>
+#include <cerrno>
+#include <cinttypes>
+#include <cstdio>
using namespace lldb;
using namespace lldb_private;
diff --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td
index 96f67801553b..e48879660403 100644
--- a/lldb/source/Core/CoreProperties.td
+++ b/lldb/source/Core/CoreProperties.td
@@ -51,6 +51,10 @@ let Definition = "debugger" in {
DefaultEnumValue<"Debugger::eStopDisassemblyTypeNoDebugInfo">,
EnumValues<"OptionEnumValues(g_show_disassembly_enum_values)">,
Desc<"Control when to display disassembly when displaying a stopped context.">;
+ def StopDisassemblyMaxSize: Property<"stop-disassembly-max-size", "UInt64">,
+ Global,
+ DefaultUnsignedValue<32000>,
+ Desc<"The size limit to use when disassembling large functions (default: 32KB).">;
def StopLineCountAfter: Property<"stop-line-count-after", "SInt64">,
Global,
DefaultUnsignedValue<3>,
@@ -134,5 +138,5 @@ let Definition = "debugger" in {
def ShowAutosuggestion: Property<"show-autosuggestion", "Boolean">,
Global,
DefaultFalse,
- Desc<"If true, LLDB will show suggestions to complete the command the user typed.">;
+ Desc<"If true, LLDB will show suggestions to complete the command the user typed. Suggestions may be accepted using Ctrl-F.">;
}
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index b16ce68c2fd2..17c3ba426f71 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -23,6 +23,7 @@
#include "lldb/Host/Terminal.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionValue.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/OptionValueSInt64.h"
@@ -64,13 +65,13 @@
#include "llvm/Support/Threading.h"
#include "llvm/Support/raw_ostream.h"
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
#include <list>
#include <memory>
#include <mutex>
#include <set>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <string>
#include <system_error>
@@ -258,6 +259,12 @@ const FormatEntity::Entry *Debugger::GetFrameFormatUnique() const {
return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
}
+uint32_t Debugger::GetStopDisassemblyMaxSize() const {
+ const uint32_t idx = ePropertyStopDisassemblyMaxSize;
+ return m_collection_sp->GetPropertyAtIndexAsUInt64(
+ nullptr, idx, g_debugger_properties[idx].default_uint_value);
+}
+
bool Debugger::GetNotifyVoid() const {
const uint32_t idx = ePropertyNotiftVoid;
return m_collection_sp->GetPropertyAtIndexAsBoolean(
@@ -598,6 +605,17 @@ void Debugger::Destroy(DebuggerSP &debugger_sp) {
if (!debugger_sp)
return;
+ CommandInterpreter &cmd_interpreter = debugger_sp->GetCommandInterpreter();
+
+ if (cmd_interpreter.GetSaveSessionOnQuit()) {
+ CommandReturnObject result(debugger_sp->GetUseColor());
+ cmd_interpreter.SaveTranscript(result);
+ if (result.Succeeded())
+ debugger_sp->GetOutputStream() << result.GetOutputData() << '\n';
+ else
+ debugger_sp->GetErrorStream() << result.GetErrorData() << '\n';
+ }
+
debugger_sp->Clear();
if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
@@ -655,6 +673,11 @@ TargetSP Debugger::FindTargetWithProcess(Process *process) {
return target_sp;
}
+ConstString Debugger::GetStaticBroadcasterClass() {
+ static ConstString class_name("lldb.debugger");
+ return class_name;
+}
+
Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
: UserID(g_unique_id++),
Properties(std::make_shared<OptionValueProperties>()),
@@ -671,6 +694,8 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
m_io_handler_stack(), m_instance_name(), m_loaded_plugins(),
m_event_handler_thread(), m_io_handler_thread(),
m_sync_broadcaster(nullptr, "lldb.debugger.sync"),
+ m_broadcaster(m_broadcaster_manager_sp,
+ GetStaticBroadcasterClass().AsCString()),
m_forward_listener_sp(), m_clear_once() {
m_instance_name.SetString(llvm::formatv("debugger_{0}", GetID()).str());
if (log_callback)
@@ -748,12 +773,9 @@ void Debugger::Clear() {
StopIOHandlerThread();
StopEventHandlerThread();
m_listener_sp->Clear();
- int num_targets = m_target_list.GetNumTargets();
- for (int i = 0; i < num_targets; i++) {
- TargetSP target_sp(m_target_list.GetTargetAtIndex(i));
+ for (TargetSP target_sp : m_target_list.Targets()) {
if (target_sp) {
- ProcessSP process_sp(target_sp->GetProcessSP());
- if (process_sp)
+ if (ProcessSP process_sp = target_sp->GetProcessSP())
process_sp->Finalize();
target_sp->Destroy();
}
@@ -816,24 +838,9 @@ void Debugger::SaveInputTerminalState() {
void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); }
ExecutionContext Debugger::GetSelectedExecutionContext() {
- ExecutionContext exe_ctx;
- TargetSP target_sp(GetSelectedTarget());
- exe_ctx.SetTargetSP(target_sp);
-
- if (target_sp) {
- ProcessSP process_sp(target_sp->GetProcessSP());
- exe_ctx.SetProcessSP(process_sp);
- if (process_sp && !process_sp->IsRunning()) {
- ThreadSP thread_sp(process_sp->GetThreadList().GetSelectedThread());
- if (thread_sp) {
- exe_ctx.SetThreadSP(thread_sp);
- exe_ctx.SetFrameSP(thread_sp->GetSelectedFrame());
- if (exe_ctx.GetFramePtr() == nullptr)
- exe_ctx.SetFrameSP(thread_sp->GetStackFrameAtIndex(0));
- }
- }
- }
- return exe_ctx;
+ bool adopt_selected = true;
+ ExecutionContextRef exe_ctx_ref(GetSelectedTarget().get(), adopt_selected);
+ return ExecutionContext(exe_ctx_ref);
}
void Debugger::DispatchInputInterrupt() {
@@ -1146,6 +1153,74 @@ void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
std::make_shared<StreamCallback>(log_callback, baton);
}
+ConstString Debugger::ProgressEventData::GetFlavorString() {
+ static ConstString g_flavor("Debugger::ProgressEventData");
+ return g_flavor;
+}
+
+ConstString Debugger::ProgressEventData::GetFlavor() const {
+ return Debugger::ProgressEventData::GetFlavorString();
+}
+
+void Debugger::ProgressEventData::Dump(Stream *s) const {
+ s->Printf(" id = %" PRIu64 ", message = \"%s\"", m_id, m_message.c_str());
+ if (m_completed == 0 || m_completed == m_total)
+ s->Printf(", type = %s", m_completed == 0 ? "start" : "end");
+ else
+ s->PutCString(", type = update");
+ // If m_total is UINT64_MAX, there is no progress to report, just "start"
+ // and "end". If it isn't we will show the completed and total amounts.
+ if (m_total != UINT64_MAX)
+ s->Printf(", progress = %" PRIu64 " of %" PRIu64, m_completed, m_total);
+}
+
+const Debugger::ProgressEventData *
+Debugger::ProgressEventData::GetEventDataFromEvent(const Event *event_ptr) {
+ if (event_ptr)
+ if (const EventData *event_data = event_ptr->GetData())
+ if (event_data->GetFlavor() == ProgressEventData::GetFlavorString())
+ return static_cast<const ProgressEventData *>(event_ptr->GetData());
+ return nullptr;
+}
+
+static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id,
+ const std::string &message,
+ uint64_t completed, uint64_t total,
+ bool is_debugger_specific) {
+ // Only deliver progress events if we have any progress listeners.
+ const uint32_t event_type = Debugger::eBroadcastBitProgress;
+ if (!debugger.GetBroadcaster().EventTypeHasListeners(event_type))
+ return;
+ EventSP event_sp(new Event(event_type, new Debugger::ProgressEventData(
+ progress_id, message, completed,
+ total, is_debugger_specific)));
+ debugger.GetBroadcaster().BroadcastEvent(event_sp);
+}
+
+void Debugger::ReportProgress(uint64_t progress_id, const std::string &message,
+ uint64_t completed, uint64_t total,
+ llvm::Optional<lldb::user_id_t> debugger_id) {
+ // Check if this progress is for a specific debugger.
+ if (debugger_id.hasValue()) {
+ // It is debugger specific, grab it and deliver the event if the debugger
+ // still exists.
+ DebuggerSP debugger_sp = FindDebuggerWithID(*debugger_id);
+ if (debugger_sp)
+ PrivateReportProgress(*debugger_sp, progress_id, message, completed,
+ total, /*is_debugger_specific*/ true);
+ return;
+ }
+ // The progress event is not debugger specific, iterate over all debuggers
+ // and deliver a progress event to each one.
+ if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
+ std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
+ DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
+ for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos)
+ PrivateReportProgress(*(*pos), progress_id, message, completed, total,
+ /*is_debugger_specific*/ false);
+ }
+}
+
bool Debugger::EnableLog(llvm::StringRef channel,
llvm::ArrayRef<const char *> categories,
llvm::StringRef log_file, uint32_t log_options,
diff --git a/lldb/source/Symbol/Declaration.cpp b/lldb/source/Core/Declaration.cpp
index 48d8013811d9..579a3999d14e 100644
--- a/lldb/source/Symbol/Declaration.cpp
+++ b/lldb/source/Core/Declaration.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Symbol/Declaration.h"
+#include "lldb/Core/Declaration.h"
#include "lldb/Utility/Stream.h"
using namespace lldb_private;
@@ -20,22 +20,15 @@ void Declaration::Dump(Stream *s, bool show_fullpaths) const {
*s << m_file.GetFilename();
if (m_line > 0)
s->Printf(":%u", m_line);
-#ifdef LLDB_ENABLE_DECLARATION_COLUMNS
- if (m_column > 0)
+ if (m_column != LLDB_INVALID_COLUMN_NUMBER)
s->Printf(":%u", m_column);
-#endif
} else {
if (m_line > 0) {
s->Printf(", line = %u", m_line);
-#ifdef LLDB_ENABLE_DECLARATION_COLUMNS
- if (m_column > 0)
+ if (m_column != LLDB_INVALID_COLUMN_NUMBER)
s->Printf(":%u", m_column);
-#endif
- }
-#ifdef LLDB_ENABLE_DECLARATION_COLUMNS
- else if (m_column > 0)
+ } else if (m_column != LLDB_INVALID_COLUMN_NUMBER)
s->Printf(", column = %u", m_column);
-#endif
}
}
@@ -48,17 +41,13 @@ bool Declaration::DumpStopContext(Stream *s, bool show_fullpaths) const {
if (m_line > 0)
s->Printf(":%u", m_line);
-#ifdef LLDB_ENABLE_DECLARATION_COLUMNS
- if (m_column > 0)
+ if (m_column != LLDB_INVALID_COLUMN_NUMBER)
s->Printf(":%u", m_column);
-#endif
return true;
} else if (m_line > 0) {
s->Printf(" line %u", m_line);
-#ifdef LLDB_ENABLE_DECLARATION_COLUMNS
- if (m_column > 0)
+ if (m_column != LLDB_INVALID_COLUMN_NUMBER)
s->Printf(":%u", m_column);
-#endif
return true;
}
return false;
@@ -74,12 +63,10 @@ int Declaration::Compare(const Declaration &a, const Declaration &b) {
return -1;
else if (a.m_line > b.m_line)
return 1;
-#ifdef LLDB_ENABLE_DECLARATION_COLUMNS
if (a.m_column < b.m_column)
return -1;
else if (a.m_column > b.m_column)
return 1;
-#endif
return 0;
}
@@ -89,10 +76,8 @@ 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())
return false;
-#else
+
return lhs.GetLine() == rhs.GetLine() && lhs.GetFile() == rhs.GetFile();
-#endif
}
diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp
index 3a975d9296f4..704b3df4b2ac 100644
--- a/lldb/source/Core/Disassembler.cpp
+++ b/lldb/source/Core/Disassembler.cpp
@@ -48,7 +48,7 @@
#include <cstring>
#include <utility>
-#include <assert.h>
+#include <cassert>
#define DEFAULT_DISASM_BYTE_SIZE 32
@@ -122,7 +122,7 @@ static Address ResolveAddress(Target &target, const Address &addr) {
lldb::DisassemblerSP Disassembler::DisassembleRange(
const ArchSpec &arch, const char *plugin_name, const char *flavor,
- Target &target, const AddressRange &range, bool prefer_file_cache) {
+ Target &target, const AddressRange &range, bool force_live_memory) {
if (range.GetByteSize() <= 0)
return {};
@@ -137,7 +137,7 @@ lldb::DisassemblerSP Disassembler::DisassembleRange(
const size_t bytes_disassembled = disasm_sp->ParseInstructions(
target, range.GetBaseAddress(), {Limit::Bytes, range.GetByteSize()},
- nullptr, prefer_file_cache);
+ nullptr, force_live_memory);
if (bytes_disassembled == 0)
return {};
@@ -181,9 +181,9 @@ bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
if (!disasm_sp)
return false;
- const bool prefer_file_cache = false;
+ const bool force_live_memory = true;
size_t bytes_disassembled = disasm_sp->ParseInstructions(
- exe_ctx.GetTargetRef(), address, limit, &strm, prefer_file_cache);
+ exe_ctx.GetTargetRef(), address, limit, &strm, force_live_memory);
if (bytes_disassembled == 0)
return false;
@@ -1036,7 +1036,7 @@ InstructionList::GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr,
size_t Disassembler::ParseInstructions(Target &target, Address start,
Limit limit, Stream *error_strm_ptr,
- bool prefer_file_cache) {
+ bool force_live_memory) {
m_instruction_list.Clear();
if (!start.IsValid())
@@ -1052,8 +1052,8 @@ size_t Disassembler::ParseInstructions(Target &target, Address start,
Status error;
lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
const size_t bytes_read =
- target.ReadMemory(start, prefer_file_cache, data_sp->GetBytes(),
- data_sp->GetByteSize(), error, &load_addr);
+ target.ReadMemory(start, data_sp->GetBytes(), data_sp->GetByteSize(),
+ error, force_live_memory, &load_addr);
const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
if (bytes_read == 0) {
diff --git a/lldb/source/Core/DumpDataExtractor.cpp b/lldb/source/Core/DumpDataExtractor.cpp
index dbfedfae27a8..175ffef04a81 100644
--- a/lldb/source/Core/DumpDataExtractor.cpp
+++ b/lldb/source/Core/DumpDataExtractor.cpp
@@ -14,8 +14,10 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/ModuleList.h"
+#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ExecutionContextScope.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataExtractor.h"
@@ -32,10 +34,10 @@
#include <memory>
#include <string>
-#include <assert.h>
-#include <ctype.h>
-#include <inttypes.h>
-#include <math.h>
+#include <cassert>
+#include <cctype>
+#include <cinttypes>
+#include <cmath>
#include <bitset>
#include <sstream>
@@ -50,7 +52,9 @@ static float half2float(uint16_t half) {
float f;
uint32_t u;
} u;
- int32_t v = (int16_t)half;
+ // Sign extend to 4 byte.
+ int32_t sign_extended = static_cast<int16_t>(half);
+ uint32_t v = static_cast<uint32_t>(sign_extended);
if (0 == (v & 0x7c00)) {
u.u = v & 0x80007FFFU;
@@ -112,7 +116,7 @@ static lldb::offset_t DumpAPInt(Stream *s, const DataExtractor &data,
bool is_signed, unsigned radix) {
llvm::Optional<llvm::APInt> apint = GetAPInt(data, &offset, byte_size);
if (apint.hasValue()) {
- std::string apint_str(apint.getValue().toString(radix, is_signed));
+ std::string apint_str = toString(apint.getValue(), radix, is_signed);
switch (radix) {
case 2:
s->Write("0b", 2);
@@ -226,6 +230,29 @@ static void DumpCharacter(Stream &s, const char c) {
s.Printf("\\x%2.2x", c);
}
+/// Dump a floating point type.
+template <typename FloatT>
+void DumpFloatingPoint(std::ostringstream &ss, FloatT f) {
+ static_assert(std::is_floating_point<FloatT>::value,
+ "Only floating point types can be dumped.");
+ // NaN and Inf are potentially implementation defined and on Darwin it
+ // seems NaNs are printed without their sign. Manually implement dumping them
+ // here to avoid having to deal with platform differences.
+ if (std::isnan(f)) {
+ if (std::signbit(f))
+ ss << '-';
+ ss << "nan";
+ return;
+ }
+ if (std::isinf(f)) {
+ if (std::signbit(f))
+ ss << '-';
+ ss << "inf";
+ return;
+ }
+ ss << f;
+}
+
lldb::offset_t lldb_private::DumpDataExtractor(
const DataExtractor &DE, Stream *s, offset_t start_offset,
lldb::Format item_format, size_t item_byte_size, size_t item_count,
@@ -566,14 +593,14 @@ lldb::offset_t lldb_private::DumpDataExtractor(
f = DE.GetFloat(&offset);
}
ss.precision(std::numeric_limits<float>::digits10);
- ss << f;
+ DumpFloatingPoint(ss, f);
} else if (item_byte_size == sizeof(double)) {
ss.precision(std::numeric_limits<double>::digits10);
- ss << DE.GetDouble(&offset);
+ DumpFloatingPoint(ss, DE.GetDouble(&offset));
} else if (item_byte_size == sizeof(long double) ||
item_byte_size == 10) {
ss.precision(std::numeric_limits<long double>::digits10);
- ss << DE.GetLongDouble(&offset);
+ DumpFloatingPoint(ss, DE.GetLongDouble(&offset));
} else {
s->Printf("error: unsupported byte size (%" PRIu64
") for float format",
@@ -611,6 +638,21 @@ lldb::offset_t lldb_private::DumpDataExtractor(
so_addr.SetOffset(addr);
so_addr.Dump(s, exe_scope,
Address::DumpStyleResolvedPointerDescription);
+ if (ProcessSP process_sp = exe_scope->CalculateProcess()) {
+ if (ABISP abi_sp = process_sp->GetABI()) {
+ addr_t addr_fixed = abi_sp->FixCodeAddress(addr);
+ if (target_sp->GetSectionLoadList().ResolveLoadAddress(
+ addr_fixed, so_addr)) {
+ s->PutChar(' ');
+ s->Printf("(0x%*.*" PRIx64 ")", (int)(2 * item_byte_size),
+ (int)(2 * item_byte_size), addr_fixed);
+ s->PutChar(' ');
+ so_addr.Dump(s, exe_scope,
+ Address::DumpStyleResolvedDescription,
+ Address::DumpStyleModuleWithFileAddress);
+ }
+ }
+ }
}
}
}
diff --git a/lldb/source/Core/DynamicLoader.cpp b/lldb/source/Core/DynamicLoader.cpp
index 22cb9f18147a..10d2b7207018 100644
--- a/lldb/source/Core/DynamicLoader.cpp
+++ b/lldb/source/Core/DynamicLoader.cpp
@@ -24,7 +24,7 @@
#include <memory>
-#include <assert.h>
+#include <cassert>
using namespace lldb;
using namespace lldb_private;
diff --git a/lldb/source/Core/EmulateInstruction.cpp b/lldb/source/Core/EmulateInstruction.cpp
index f7f56e9fc54f..9b9111408209 100644
--- a/lldb/source/Core/EmulateInstruction.cpp
+++ b/lldb/source/Core/EmulateInstruction.cpp
@@ -30,8 +30,8 @@
#include <cstring>
#include <memory>
-#include <inttypes.h>
-#include <stdio.h>
+#include <cinttypes>
+#include <cstdio>
namespace lldb_private {
class Target;
diff --git a/lldb/source/Core/FileLineResolver.cpp b/lldb/source/Core/FileLineResolver.cpp
index 37435f9e9047..2cf7007165bc 100644
--- a/lldb/source/Core/FileLineResolver.cpp
+++ b/lldb/source/Core/FileLineResolver.cpp
@@ -29,7 +29,7 @@ FileLineResolver::FileLineResolver(const FileSpec &file_spec, uint32_t line_no,
: Searcher(), m_file_spec(file_spec), m_line_number(line_no),
m_inlines(check_inlines) {}
-FileLineResolver::~FileLineResolver() {}
+FileLineResolver::~FileLineResolver() = default;
Searcher::CallbackReturn
FileLineResolver::SearchCallback(SearchFilter &filter, SymbolContext &context,
diff --git a/lldb/source/Core/FileSpecList.cpp b/lldb/source/Core/FileSpecList.cpp
index 3ada7b495fdb..1a1cf284ea07 100644
--- a/lldb/source/Core/FileSpecList.cpp
+++ b/lldb/source/Core/FileSpecList.cpp
@@ -13,7 +13,7 @@
#include <utility>
-#include <stdint.h>
+#include <cstdint>
using namespace lldb_private;
using namespace std;
diff --git a/lldb/source/Core/FormatEntity.cpp b/lldb/source/Core/FormatEntity.cpp
index d491ac14bec8..6e6255b903bb 100644
--- a/lldb/source/Core/FormatEntity.cpp
+++ b/lldb/source/Core/FormatEntity.cpp
@@ -41,11 +41,13 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/AnsiTerminal.h"
#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Logging.h"
#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StringList.h"
@@ -57,12 +59,12 @@
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Compiler.h"
-#include <ctype.h>
-#include <inttypes.h>
+#include <cctype>
+#include <cinttypes>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
#include <memory>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <type_traits>
#include <utility>
@@ -76,203 +78,196 @@ struct RegisterInfo;
using namespace lldb;
using namespace lldb_private;
+using Definition = lldb_private::FormatEntity::Entry::Definition;
+using Entry = FormatEntity::Entry;
+using EntryType = FormatEntity::Entry::Type;
+
enum FileKind { FileError = 0, Basename, Dirname, Fullpath };
-#define ENTRY(n, t) \
- { n, nullptr, FormatEntity::Entry::Type::t, 0, 0, nullptr, false }
-#define ENTRY_VALUE(n, t, v) \
- { n, nullptr, FormatEntity::Entry::Type::t, v, 0, nullptr, false }
-#define ENTRY_CHILDREN(n, t, c) \
- { \
- n, nullptr, FormatEntity::Entry::Type::t, 0, \
- static_cast<uint32_t>(llvm::array_lengthof(c)), c, false \
- }
-#define ENTRY_CHILDREN_KEEP_SEP(n, t, c) \
- { \
- n, nullptr, FormatEntity::Entry::Type::t, 0, \
- static_cast<uint32_t>(llvm::array_lengthof(c)), c, true \
- }
-#define ENTRY_STRING(n, s) \
- { n, s, FormatEntity::Entry::Type::EscapeCode, 0, 0, nullptr, false }
-static FormatEntity::Entry::Definition g_string_entry[] = {
- ENTRY("*", ParentString)};
+constexpr Definition g_string_entry[] = {
+ Definition("*", EntryType::ParentString)};
-static FormatEntity::Entry::Definition g_addr_entries[] = {
- ENTRY("load", AddressLoad),
- ENTRY("file", AddressFile),
- ENTRY("load", AddressLoadOrFile),
-};
+constexpr Definition g_addr_entries[] = {
+ Definition("load", EntryType::AddressLoad),
+ Definition("file", EntryType::AddressFile)};
-static FormatEntity::Entry::Definition g_file_child_entries[] = {
- ENTRY_VALUE("basename", ParentNumber, FileKind::Basename),
- ENTRY_VALUE("dirname", ParentNumber, FileKind::Dirname),
- ENTRY_VALUE("fullpath", ParentNumber, FileKind::Fullpath)};
+constexpr Definition g_file_child_entries[] = {
+ Definition("basename", EntryType::ParentNumber, FileKind::Basename),
+ Definition("dirname", EntryType::ParentNumber, FileKind::Dirname),
+ Definition("fullpath", EntryType::ParentNumber, FileKind::Fullpath)};
-static FormatEntity::Entry::Definition g_frame_child_entries[] = {
- ENTRY("index", FrameIndex),
- ENTRY("pc", FrameRegisterPC),
- ENTRY("fp", FrameRegisterFP),
- ENTRY("sp", FrameRegisterSP),
- ENTRY("flags", FrameRegisterFlags),
- ENTRY("no-debug", FrameNoDebug),
- ENTRY_CHILDREN("reg", FrameRegisterByName, g_string_entry),
- ENTRY("is-artificial", FrameIsArtificial),
+constexpr Definition g_frame_child_entries[] = {
+ Definition("index", EntryType::FrameIndex),
+ Definition("pc", EntryType::FrameRegisterPC),
+ Definition("fp", EntryType::FrameRegisterFP),
+ Definition("sp", EntryType::FrameRegisterSP),
+ Definition("flags", EntryType::FrameRegisterFlags),
+ Definition("no-debug", EntryType::FrameNoDebug),
+ Entry::DefinitionWithChildren("reg", EntryType::FrameRegisterByName,
+ g_string_entry),
+ Definition("is-artificial", EntryType::FrameIsArtificial),
};
-static FormatEntity::Entry::Definition g_function_child_entries[] = {
- ENTRY("id", FunctionID),
- 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),
- ENTRY("pc-offset", FunctionPCOffset),
- ENTRY("initial-function", FunctionInitial),
- ENTRY("changed", FunctionChanged),
- ENTRY("is-optimized", FunctionIsOptimized)};
+constexpr Definition g_function_child_entries[] = {
+ Definition("id", EntryType::FunctionID),
+ Definition("name", EntryType::FunctionName),
+ Definition("name-without-args", EntryType::FunctionNameNoArgs),
+ Definition("name-with-args", EntryType::FunctionNameWithArgs),
+ Definition("mangled-name", EntryType::FunctionMangledName),
+ Definition("addr-offset", EntryType::FunctionAddrOffset),
+ Definition("concrete-only-addr-offset-no-padding",
+ EntryType::FunctionAddrOffsetConcrete),
+ Definition("line-offset", EntryType::FunctionLineOffset),
+ Definition("pc-offset", EntryType::FunctionPCOffset),
+ Definition("initial-function", EntryType::FunctionInitial),
+ Definition("changed", EntryType::FunctionChanged),
+ Definition("is-optimized", EntryType::FunctionIsOptimized)};
-static FormatEntity::Entry::Definition g_line_child_entries[] = {
- ENTRY_CHILDREN("file", LineEntryFile, g_file_child_entries),
- ENTRY("number", LineEntryLineNumber),
- ENTRY("column", LineEntryColumn),
- ENTRY("start-addr", LineEntryStartAddress),
- ENTRY("end-addr", LineEntryEndAddress),
+constexpr Definition g_line_child_entries[] = {
+ Entry::DefinitionWithChildren("file", EntryType::LineEntryFile,
+ g_file_child_entries),
+ Definition("number", EntryType::LineEntryLineNumber),
+ Definition("column", EntryType::LineEntryColumn),
+ Definition("start-addr", EntryType::LineEntryStartAddress),
+ Definition("end-addr", EntryType::LineEntryEndAddress),
};
-static FormatEntity::Entry::Definition g_module_child_entries[] = {
- ENTRY_CHILDREN("file", ModuleFile, g_file_child_entries),
-};
+constexpr Definition g_module_child_entries[] = {Entry::DefinitionWithChildren(
+ "file", EntryType::ModuleFile, g_file_child_entries)};
-static FormatEntity::Entry::Definition g_process_child_entries[] = {
- ENTRY("id", ProcessID),
- ENTRY_VALUE("name", ProcessFile, FileKind::Basename),
- ENTRY_CHILDREN("file", ProcessFile, g_file_child_entries),
-};
+constexpr Definition g_process_child_entries[] = {
+ Definition("id", EntryType::ProcessID),
+ Definition("name", EntryType::ProcessFile, FileKind::Basename),
+ Entry::DefinitionWithChildren("file", EntryType::ProcessFile,
+ g_file_child_entries)};
-static FormatEntity::Entry::Definition g_svar_child_entries[] = {
- ENTRY("*", ParentString)};
+constexpr Definition g_svar_child_entries[] = {
+ Definition("*", EntryType::ParentString)};
-static FormatEntity::Entry::Definition g_var_child_entries[] = {
- ENTRY("*", ParentString)};
+constexpr Definition g_var_child_entries[] = {
+ Definition("*", EntryType::ParentString)};
-static FormatEntity::Entry::Definition g_thread_child_entries[] = {
- ENTRY("id", ThreadID),
- ENTRY("protocol_id", ThreadProtocolID),
- ENTRY("index", ThreadIndexID),
- ENTRY_CHILDREN("info", ThreadInfo, g_string_entry),
- ENTRY("queue", ThreadQueue),
- ENTRY("name", ThreadName),
- ENTRY("stop-reason", ThreadStopReason),
- ENTRY("stop-reason-raw", ThreadStopReasonRaw),
- ENTRY("return-value", ThreadReturnValue),
- ENTRY("completed-expression", ThreadCompletedExpression),
-};
+constexpr Definition g_thread_child_entries[] = {
+ Definition("id", EntryType::ThreadID),
+ Definition("protocol_id", EntryType::ThreadProtocolID),
+ Definition("index", EntryType::ThreadIndexID),
+ Entry::DefinitionWithChildren("info", EntryType::ThreadInfo,
+ g_string_entry),
+ Definition("queue", EntryType::ThreadQueue),
+ Definition("name", EntryType::ThreadName),
+ Definition("stop-reason", EntryType::ThreadStopReason),
+ Definition("stop-reason-raw", EntryType::ThreadStopReasonRaw),
+ Definition("return-value", EntryType::ThreadReturnValue),
+ Definition("completed-expression", EntryType::ThreadCompletedExpression)};
-static FormatEntity::Entry::Definition g_target_child_entries[] = {
- ENTRY("arch", TargetArch),
-};
+constexpr Definition g_target_child_entries[] = {
+ Definition("arch", EntryType::TargetArch)};
#define _TO_STR2(_val) #_val
#define _TO_STR(_val) _TO_STR2(_val)
-static FormatEntity::Entry::Definition g_ansi_fg_entries[] = {
- ENTRY_STRING("black",
- ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END),
- ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END),
- ENTRY_STRING("green",
- ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END),
- ENTRY_STRING("yellow",
- ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END),
- ENTRY_STRING("blue",
- ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END),
- ENTRY_STRING("purple",
- ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END),
- ENTRY_STRING("cyan",
- ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END),
- ENTRY_STRING("white",
- ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END),
+constexpr Definition g_ansi_fg_entries[] = {
+ Definition("black",
+ ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END),
+ Definition("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END),
+ Definition("green",
+ ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END),
+ Definition("yellow",
+ ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END),
+ Definition("blue", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END),
+ Definition("purple",
+ ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END),
+ Definition("cyan", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END),
+ Definition("white",
+ ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END),
};
-static FormatEntity::Entry::Definition g_ansi_bg_entries[] = {
- ENTRY_STRING("black",
- ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END),
- ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END),
- ENTRY_STRING("green",
- ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END),
- ENTRY_STRING("yellow",
- ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END),
- ENTRY_STRING("blue",
- ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END),
- ENTRY_STRING("purple",
- ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END),
- ENTRY_STRING("cyan",
- ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END),
- ENTRY_STRING("white",
- ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END),
+constexpr Definition g_ansi_bg_entries[] = {
+ Definition("black",
+ ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END),
+ Definition("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END),
+ Definition("green",
+ ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END),
+ Definition("yellow",
+ ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END),
+ Definition("blue", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END),
+ Definition("purple",
+ ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END),
+ Definition("cyan", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END),
+ Definition("white",
+ ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END),
};
-static FormatEntity::Entry::Definition g_ansi_entries[] = {
- ENTRY_CHILDREN("fg", Invalid, g_ansi_fg_entries),
- ENTRY_CHILDREN("bg", Invalid, g_ansi_bg_entries),
- ENTRY_STRING("normal",
- ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END),
- ENTRY_STRING("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END),
- ENTRY_STRING("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END),
- ENTRY_STRING("italic",
- ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END),
- ENTRY_STRING("underline",
- ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END),
- ENTRY_STRING("slow-blink",
- ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END),
- ENTRY_STRING("fast-blink",
- ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END),
- ENTRY_STRING("negative",
- ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END),
- ENTRY_STRING("conceal",
- ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END),
- ENTRY_STRING("crossed-out",
- ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END),
+constexpr Definition g_ansi_entries[] = {
+ Entry::DefinitionWithChildren("fg", EntryType::Invalid, g_ansi_fg_entries),
+ Entry::DefinitionWithChildren("bg", EntryType::Invalid, g_ansi_bg_entries),
+ Definition("normal", ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END),
+ Definition("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END),
+ Definition("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END),
+ Definition("italic", ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END),
+ Definition("underline",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END),
+ Definition("slow-blink",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END),
+ Definition("fast-blink",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END),
+ Definition("negative",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END),
+ Definition("conceal",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END),
+ Definition("crossed-out",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END),
};
-static FormatEntity::Entry::Definition g_script_child_entries[] = {
- ENTRY("frame", ScriptFrame), ENTRY("process", ScriptProcess),
- ENTRY("target", ScriptTarget), ENTRY("thread", ScriptThread),
- ENTRY("var", ScriptVariable), ENTRY("svar", ScriptVariableSynthetic),
- ENTRY("thread", ScriptThread),
-};
+constexpr Definition g_script_child_entries[] = {
+ Definition("frame", EntryType::ScriptFrame),
+ Definition("process", EntryType::ScriptProcess),
+ Definition("target", EntryType::ScriptTarget),
+ Definition("thread", EntryType::ScriptThread),
+ Definition("var", EntryType::ScriptVariable),
+ Definition("svar", EntryType::ScriptVariableSynthetic),
+ Definition("thread", EntryType::ScriptThread)};
-static FormatEntity::Entry::Definition g_top_level_entries[] = {
- ENTRY_CHILDREN("addr", AddressLoadOrFile, g_addr_entries),
- ENTRY("addr-file-or-load", AddressLoadOrFile),
- ENTRY_CHILDREN("ansi", Invalid, g_ansi_entries),
- ENTRY("current-pc-arrow", CurrentPCArrow),
- ENTRY_CHILDREN("file", File, g_file_child_entries),
- ENTRY("language", Lang),
- ENTRY_CHILDREN("frame", Invalid, g_frame_child_entries),
- ENTRY_CHILDREN("function", Invalid, g_function_child_entries),
- ENTRY_CHILDREN("line", Invalid, g_line_child_entries),
- ENTRY_CHILDREN("module", Invalid, g_module_child_entries),
- ENTRY_CHILDREN("process", Invalid, g_process_child_entries),
- ENTRY_CHILDREN("script", Invalid, g_script_child_entries),
- ENTRY_CHILDREN_KEEP_SEP("svar", VariableSynthetic, g_svar_child_entries),
- ENTRY_CHILDREN("thread", Invalid, g_thread_child_entries),
- ENTRY_CHILDREN("target", Invalid, g_target_child_entries),
- ENTRY_CHILDREN_KEEP_SEP("var", Variable, g_var_child_entries),
-};
+constexpr Definition g_top_level_entries[] = {
+ Entry::DefinitionWithChildren("addr", EntryType::AddressLoadOrFile,
+ g_addr_entries),
+ Definition("addr-file-or-load", EntryType::AddressLoadOrFile),
+ Entry::DefinitionWithChildren("ansi", EntryType::Invalid, g_ansi_entries),
+ Definition("current-pc-arrow", EntryType::CurrentPCArrow),
+ Entry::DefinitionWithChildren("file", EntryType::File,
+ g_file_child_entries),
+ Definition("language", EntryType::Lang),
+ Entry::DefinitionWithChildren("frame", EntryType::Invalid,
+ g_frame_child_entries),
+ Entry::DefinitionWithChildren("function", EntryType::Invalid,
+ g_function_child_entries),
+ Entry::DefinitionWithChildren("line", EntryType::Invalid,
+ g_line_child_entries),
+ Entry::DefinitionWithChildren("module", EntryType::Invalid,
+ g_module_child_entries),
+ Entry::DefinitionWithChildren("process", EntryType::Invalid,
+ g_process_child_entries),
+ Entry::DefinitionWithChildren("script", EntryType::Invalid,
+ g_script_child_entries),
+ Entry::DefinitionWithChildren("svar", EntryType::VariableSynthetic,
+ g_svar_child_entries, true),
+ Entry::DefinitionWithChildren("thread", EntryType::Invalid,
+ g_thread_child_entries),
+ Entry::DefinitionWithChildren("target", EntryType::Invalid,
+ g_target_child_entries),
+ Entry::DefinitionWithChildren("var", EntryType::Variable,
+ g_var_child_entries, true)};
-static FormatEntity::Entry::Definition g_root =
- ENTRY_CHILDREN("<root>", Root, g_top_level_entries);
+constexpr Definition g_root = Entry::DefinitionWithChildren(
+ "<root>", EntryType::Root, g_top_level_entries);
FormatEntity::Entry::Entry(llvm::StringRef s)
: string(s.data(), s.size()), printf_format(), children(),
- definition(nullptr), type(Type::String), fmt(lldb::eFormatDefault),
- number(0), deref(false) {}
+ type(Type::String), fmt(lldb::eFormatDefault), number(0), deref(false) {}
FormatEntity::Entry::Entry(char ch)
- : string(1, ch), printf_format(), children(), definition(nullptr),
- type(Type::String), fmt(lldb::eFormatDefault), number(0), deref(false) {}
+ : string(1, ch), printf_format(), children(), type(Type::String),
+ fmt(lldb::eFormatDefault), number(0), deref(false) {}
void FormatEntity::Entry::AppendChar(char ch) {
if (children.empty() || children.back().type != Entry::Type::String)
@@ -598,9 +593,7 @@ static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) {
}
static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind,
- uint32_t reg_num, Format format)
-
-{
+ uint32_t reg_num, Format format) {
if (frame) {
RegisterContext *reg_ctx = frame->GetRegisterContext().get();
@@ -624,7 +617,6 @@ static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind,
}
static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index,
- StackFrame *frame,
bool deref_pointer) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
const char *ptr_deref_format = "[%d]";
@@ -956,9 +948,7 @@ static bool DumpValue(Stream &s, const SymbolContext *sc,
bool success = true;
for (int64_t index = index_lower; index <= index_higher; ++index) {
- ValueObject *item =
- ExpandIndexedExpression(target, index, exe_ctx->GetFramePtr(), false)
- .get();
+ ValueObject *item = ExpandIndexedExpression(target, index, false).get();
if (!item) {
LLDB_LOGF(log,
@@ -1523,17 +1513,22 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
return initial_function;
case Entry::Type::FunctionName: {
+ if (!sc)
+ return false;
+
Language *language_plugin = nullptr;
bool language_plugin_handled = false;
StreamString ss;
+
if (sc->function)
language_plugin = Language::FindPlugin(sc->function->GetLanguage());
else if (sc->symbol)
language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
- if (language_plugin) {
+
+ if (language_plugin)
language_plugin_handled = language_plugin->GetFunctionDisplayName(
sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss);
- }
+
if (language_plugin_handled) {
s << ss.GetString();
return true;
@@ -1543,6 +1538,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
name = sc->function->GetName().AsCString(nullptr);
else if (sc->symbol)
name = sc->symbol->GetName().AsCString(nullptr);
+
if (name) {
s.PutCString(name);
@@ -1564,6 +1560,9 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
return false;
case Entry::Type::FunctionNameNoArgs: {
+ if (!sc)
+ return false;
+
Language *language_plugin = nullptr;
bool language_plugin_handled = false;
StreamString ss;
@@ -1571,11 +1570,12 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
language_plugin = Language::FindPlugin(sc->function->GetLanguage());
else if (sc->symbol)
language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
- if (language_plugin) {
+
+ if (language_plugin)
language_plugin_handled = language_plugin->GetFunctionDisplayName(
sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs,
ss);
- }
+
if (language_plugin_handled) {
s << ss.GetString();
return true;
@@ -1594,6 +1594,9 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
return false;
case Entry::Type::FunctionNameWithArgs: {
+ if (!sc)
+ return false;
+
Language *language_plugin = nullptr;
bool language_plugin_handled = false;
StreamString ss;
@@ -1601,10 +1604,11 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
language_plugin = Language::FindPlugin(sc->function->GetLanguage());
else if (sc->symbol)
language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
- if (language_plugin) {
+
+ if (language_plugin)
language_plugin_handled = language_plugin->GetFunctionDisplayName(
sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss);
- }
+
if (language_plugin_handled) {
s << ss.GetString();
return true;
@@ -1756,6 +1760,9 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
return false;
case Entry::Type::FunctionMangledName: {
+ if (!sc)
+ return false;
+
const char *name = nullptr;
if (sc->symbol)
name =
@@ -1769,7 +1776,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
return false;
s.PutCString(name);
- if (sc->block->GetContainingInlinedBlock()) {
+ if (sc->block && sc->block->GetContainingInlinedBlock()) {
if (const InlineFunctionInfo *inline_info =
sc->block->GetInlinedFunctionInfo()) {
s.PutCString(" [inlined] ");
@@ -1778,7 +1785,6 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
}
return true;
}
-
case Entry::Type::FunctionAddrOffset:
if (addr) {
if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false,
@@ -1796,9 +1802,11 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
return false;
case Entry::Type::FunctionLineOffset:
- return (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
- sc->line_entry.range.GetBaseAddress(),
- false, false, false));
+ if (sc)
+ return (DumpAddressOffsetFromFunction(
+ s, sc, exe_ctx, sc->line_entry.range.GetBaseAddress(), false, false,
+ false));
+ return false;
case Entry::Type::FunctionPCOffset:
if (exe_ctx) {
@@ -1817,7 +1825,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
case Entry::Type::FunctionIsOptimized: {
bool is_optimized = false;
- if (sc->function && sc->function->GetIsOptimized()) {
+ if (sc && sc->function && sc->function->GetIsOptimized()) {
is_optimized = true;
}
return is_optimized;
@@ -1891,8 +1899,8 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
return false;
}
-static bool DumpCommaSeparatedChildEntryNames(
- Stream &s, const FormatEntity::Entry::Definition *parent) {
+static bool DumpCommaSeparatedChildEntryNames(Stream &s,
+ const Definition *parent) {
if (parent->children) {
const size_t n = parent->num_children;
for (size_t i = 0; i < n; ++i) {
@@ -1906,8 +1914,7 @@ static bool DumpCommaSeparatedChildEntryNames(
}
static Status ParseEntry(const llvm::StringRef &format_str,
- const FormatEntity::Entry::Definition *parent,
- FormatEntity::Entry &entry) {
+ const Definition *parent, FormatEntity::Entry &entry) {
Status error;
const size_t sep_pos = format_str.find_first_of(".[:");
@@ -1917,7 +1924,7 @@ static Status ParseEntry(const llvm::StringRef &format_str,
const size_t n = parent->num_children;
for (size_t i = 0; i < n; ++i) {
- const FormatEntity::Entry::Definition *entry_def = parent->children + i;
+ const Definition *entry_def = parent->children + i;
if (key.equals(entry_def->name) || entry_def->name[0] == '*') {
llvm::StringRef value;
if (sep_char)
@@ -1990,16 +1997,15 @@ static Status ParseEntry(const llvm::StringRef &format_str,
return error;
}
-static const FormatEntity::Entry::Definition *
-FindEntry(const llvm::StringRef &format_str,
- const FormatEntity::Entry::Definition *parent,
- llvm::StringRef &remainder) {
+static const Definition *FindEntry(const llvm::StringRef &format_str,
+ const Definition *parent,
+ llvm::StringRef &remainder) {
Status error;
std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.');
const size_t n = parent->num_children;
for (size_t i = 0; i < n; ++i) {
- const FormatEntity::Entry::Definition *entry_def = parent->children + i;
+ const Definition *entry_def = parent->children + i;
if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') {
if (p.second.empty()) {
if (format_str.back() == '.')
@@ -2363,8 +2369,7 @@ static std::string MakeMatch(const llvm::StringRef &prefix,
return match;
}
-static void AddMatches(const FormatEntity::Entry::Definition *def,
- const llvm::StringRef &prefix,
+static void AddMatches(const Definition *def, const llvm::StringRef &prefix,
const llvm::StringRef &match_prefix,
StringList &matches) {
const size_t n = def->num_children;
@@ -2418,8 +2423,7 @@ void FormatEntity::AutoComplete(CompletionRequest &request) {
// We have a partially specified variable, find it
llvm::StringRef remainder;
- const FormatEntity::Entry::Definition *entry_def =
- FindEntry(partial_variable, &g_root, remainder);
+ const Definition *entry_def = FindEntry(partial_variable, &g_root, remainder);
if (!entry_def)
return;
diff --git a/lldb/source/Core/IOHandler.cpp b/lldb/source/Core/IOHandler.cpp
index 8c654d9d8a98..c6f05d43a2a7 100644
--- a/lldb/source/Core/IOHandler.cpp
+++ b/lldb/source/Core/IOHandler.cpp
@@ -38,13 +38,13 @@
#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 <cassert>
+#include <cctype>
+#include <cerrno>
+#include <clocale>
+#include <cstdint>
+#include <cstdio>
+#include <cstring>
#include <type_traits>
using namespace lldb;
@@ -265,17 +265,31 @@ IOHandlerEditline::IOHandlerEditline(
m_editline_up = std::make_unique<Editline>(editline_name, GetInputFILE(),
GetOutputFILE(), GetErrorFILE(),
m_color_prompts);
- m_editline_up->SetIsInputCompleteCallback(IsInputCompleteCallback, this);
- m_editline_up->SetAutoCompleteCallback(AutoCompleteCallback, this);
- if (debugger.GetUseAutosuggestion() && debugger.GetUseColor())
- m_editline_up->SetSuggestionCallback(SuggestionCallback, this);
+ m_editline_up->SetIsInputCompleteCallback(
+ [this](Editline *editline, StringList &lines) {
+ return this->IsInputCompleteCallback(editline, lines);
+ });
+
+ m_editline_up->SetAutoCompleteCallback([this](CompletionRequest &request) {
+ this->AutoCompleteCallback(request);
+ });
+
+ if (debugger.GetUseAutosuggestion() && debugger.GetUseColor()) {
+ m_editline_up->SetSuggestionCallback([this](llvm::StringRef line) {
+ return this->SuggestionCallback(line);
+ });
+ }
// See if the delegate supports fixing indentation
const char *indent_chars = delegate.IOHandlerGetFixIndentationCharacters();
if (indent_chars) {
// The delegate does support indentation, hook it up so when any
// indentation character is typed, the delegate gets a chance to fix it
- m_editline_up->SetFixIndentationCallback(FixIndentationCallback, this,
- indent_chars);
+ FixIndentationCallbackType f = [this](Editline *editline,
+ const StringList &lines,
+ int cursor_position) {
+ return this->FixIndentationCallback(editline, lines, cursor_position);
+ };
+ m_editline_up->SetFixIndentationCallback(std::move(f), indent_chars);
}
}
#endif
@@ -425,37 +439,23 @@ bool IOHandlerEditline::GetLine(std::string &line, bool &interrupted) {
#if LLDB_ENABLE_LIBEDIT
bool IOHandlerEditline::IsInputCompleteCallback(Editline *editline,
- StringList &lines,
- void *baton) {
- IOHandlerEditline *editline_reader = (IOHandlerEditline *)baton;
- return editline_reader->m_delegate.IOHandlerIsInputComplete(*editline_reader,
- lines);
+ StringList &lines) {
+ return m_delegate.IOHandlerIsInputComplete(*this, lines);
}
int IOHandlerEditline::FixIndentationCallback(Editline *editline,
const StringList &lines,
- int cursor_position,
- void *baton) {
- IOHandlerEditline *editline_reader = (IOHandlerEditline *)baton;
- return editline_reader->m_delegate.IOHandlerFixIndentation(
- *editline_reader, lines, cursor_position);
+ int cursor_position) {
+ return m_delegate.IOHandlerFixIndentation(*this, lines, cursor_position);
}
llvm::Optional<std::string>
-IOHandlerEditline::SuggestionCallback(llvm::StringRef line, void *baton) {
- IOHandlerEditline *editline_reader = static_cast<IOHandlerEditline *>(baton);
- if (editline_reader)
- return editline_reader->m_delegate.IOHandlerSuggestion(*editline_reader,
- line);
-
- return llvm::None;
+IOHandlerEditline::SuggestionCallback(llvm::StringRef line) {
+ return m_delegate.IOHandlerSuggestion(*this, line);
}
-void IOHandlerEditline::AutoCompleteCallback(CompletionRequest &request,
- void *baton) {
- IOHandlerEditline *editline_reader = (IOHandlerEditline *)baton;
- if (editline_reader)
- editline_reader->m_delegate.IOHandlerComplete(*editline_reader, request);
+void IOHandlerEditline::AutoCompleteCallback(CompletionRequest &request) {
+ m_delegate.IOHandlerComplete(*this, request);
}
#endif
diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp
index 19066e6be623..4bed788d4863 100644
--- a/lldb/source/Core/IOHandlerCursesGUI.cpp
+++ b/lldb/source/Core/IOHandlerCursesGUI.cpp
@@ -26,6 +26,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/ValueObjectUpdater.h"
#include "lldb/Host/File.h"
#include "lldb/Utility/Predicate.h"
#include "lldb/Utility/Status.h"
@@ -39,6 +40,7 @@
#if LLDB_ENABLE_CURSES
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Symbol/Block.h"
@@ -63,13 +65,13 @@
#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 <cassert>
+#include <cctype>
+#include <cerrno>
+#include <cstdint>
+#include <cstdio>
+#include <cstring>
+#include <functional>
#include <type_traits>
using namespace lldb;
@@ -84,6 +86,8 @@ using llvm::StringRef;
#define KEY_RETURN 10
#define KEY_ESCAPE 27
+#define KEY_SHIFT_TAB (KEY_MAX + 1)
+
namespace curses {
class Menu;
class MenuDelegate;
@@ -335,93 +339,52 @@ protected:
int m_first_visible_line;
};
-class Window {
+// A surface is an abstraction for something than can be drawn on. The surface
+// have a width, a height, a cursor position, and a multitude of drawing
+// operations. This type should be sub-classed to get an actually useful ncurses
+// object, such as a Window, SubWindow, Pad, or a SubPad.
+class Surface {
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) {}
+ Surface() : m_window(nullptr) {}
- 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 *get() { return m_window; }
- 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));
- }
+ operator WINDOW *() { return m_window; }
- virtual ~Window() {
- RemoveSubWindows();
- Reset();
+ // Copy a region of the surface to another surface.
+ void CopyToSurface(Surface &target, Point source_origin, Point target_origin,
+ Size size) {
+ ::copywin(m_window, target.get(), source_origin.y, source_origin.x,
+ target_origin.y, target_origin.x,
+ target_origin.y + size.height - 1,
+ target_origin.x + size.width - 1, false);
}
- 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;
- }
- }
+ int GetCursorX() const { return getcurx(m_window); }
+ int GetCursorY() const { return getcury(m_window); }
+ void MoveCursor(int x, int y) { ::wmove(m_window, y, x); }
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() const {
- return Rect(GetParentOrigin(), GetSize());
- } // Get the rectangle in our parent window
- int GetChar() { return ::wgetch(m_window); }
- int GetCursorX() const { return getcurx(m_window); }
- int GetCursorY() const { return getcury(m_window); }
- Rect GetFrame() const {
- return Rect(Point(), GetSize());
- } // Get our rectangle in our own coordinate system
- Point GetParentOrigin() const { return Point(GetParentX(), GetParentY()); }
- Size GetSize() const { return Size(GetWidth(), GetHeight()); }
- int GetParentX() const { return getparx(m_window); }
- int GetParentY() const { return getpary(m_window); }
+
int GetMaxX() const { return getmaxx(m_window); }
int GetMaxY() const { return getmaxy(m_window); }
int GetWidth() const { return GetMaxX(); }
int GetHeight() const { 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); }
+ Size GetSize() const { return Size(GetWidth(), GetHeight()); }
+ // Get a zero origin rectangle width the surface size.
+ Rect GetFrame() const { return Rect(Point(), GetSize()); }
+
+ void Clear() { ::wclear(m_window); }
+ void Erase() { ::werase(m_window); }
+
void SetBackground(int color_pair_idx) {
::wbkgd(m_window, COLOR_PAIR(color_pair_idx));
}
+ void PutChar(int ch) { ::waddch(m_window, ch); }
+ void PutCString(const char *s, int len = -1) { ::waddnstr(m_window, s, len); }
+
void PutCStringTruncated(int right_pad, const char *s, int len = -1) {
int bytes_left = GetWidth() - GetCursorX();
if (bytes_left > right_pad) {
@@ -430,37 +393,10 @@ public:
}
}
- 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);
+ vw_printw(m_window, format, args);
va_end(args);
}
@@ -474,8 +410,54 @@ public:
PutCStringTruncated(right_pad, strm.GetData());
}
- size_t LimitLengthToRestOfLine(size_t length) const {
- return std::min<size_t>(length, std::max(0, GetWidth() - GetCursorX() - 1));
+ void VerticalLine(int n, chtype v_char = ACS_VLINE) {
+ ::wvline(m_window, v_char, n);
+ }
+ void HorizontalLine(int n, chtype h_char = ACS_HLINE) {
+ ::whline(m_window, h_char, n);
+ }
+ void Box(chtype v_char = ACS_VLINE, chtype h_char = ACS_HLINE) {
+ ::box(m_window, v_char, h_char);
+ }
+
+ void TitledBox(const char *title, chtype v_char = ACS_VLINE,
+ chtype h_char = ACS_HLINE) {
+ Box(v_char, h_char);
+ int title_offset = 2;
+ MoveCursor(title_offset, 0);
+ PutChar('[');
+ PutCString(title, GetWidth() - title_offset);
+ PutChar(']');
+ }
+
+ void Box(const Rect &bounds, chtype v_char = ACS_VLINE,
+ chtype h_char = ACS_HLINE) {
+ MoveCursor(bounds.origin.x, bounds.origin.y);
+ VerticalLine(bounds.size.height);
+ HorizontalLine(bounds.size.width);
+ PutChar(ACS_ULCORNER);
+
+ MoveCursor(bounds.origin.x + bounds.size.width - 1, bounds.origin.y);
+ VerticalLine(bounds.size.height);
+ PutChar(ACS_URCORNER);
+
+ MoveCursor(bounds.origin.x, bounds.origin.y + bounds.size.height - 1);
+ HorizontalLine(bounds.size.width);
+ PutChar(ACS_LLCORNER);
+
+ MoveCursor(bounds.origin.x + bounds.size.width - 1,
+ bounds.origin.y + bounds.size.height - 1);
+ PutChar(ACS_LRCORNER);
+ }
+
+ void TitledBox(const Rect &bounds, const char *title,
+ chtype v_char = ACS_VLINE, chtype h_char = ACS_HLINE) {
+ Box(bounds, v_char, h_char);
+ int title_offset = 2;
+ MoveCursor(bounds.origin.x + title_offset, bounds.origin.y);
+ PutChar('[');
+ PutCString(title, bounds.size.width - title_offset);
+ PutChar(']');
}
// Curses doesn't allow direct output of color escape sequences, but that's
@@ -551,6 +533,130 @@ public:
return result;
}
+protected:
+ WINDOW *m_window;
+};
+
+class Pad : public Surface {
+public:
+ Pad(Size size) { m_window = ::newpad(size.height, size.width); }
+
+ ~Pad() { ::delwin(m_window); }
+};
+
+class SubPad : public Surface {
+public:
+ SubPad(Pad &pad, Rect bounds) {
+ m_window = ::subpad(pad.get(), bounds.size.height, bounds.size.width,
+ bounds.origin.y, bounds.origin.x);
+ }
+ SubPad(SubPad &subpad, Rect bounds) {
+ m_window = ::subpad(subpad.get(), bounds.size.height, bounds.size.width,
+ bounds.origin.y, bounds.origin.x);
+ }
+
+ ~SubPad() { ::delwin(m_window); }
+};
+
+class Window : public Surface {
+public:
+ Window(const char *name)
+ : m_name(name), 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_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_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;
+ }
+ }
+
+ // Get the rectangle in our parent window
+ Rect GetBounds() const { return Rect(GetParentOrigin(), GetSize()); }
+
+ Rect GetCenteredRect(int width, int height) {
+ Size size = GetSize();
+ width = std::min(size.width, width);
+ height = std::min(size.height, height);
+ int x = (size.width - width) / 2;
+ int y = (size.height - height) / 2;
+ return Rect(Point(x, y), Size(width, height));
+ }
+
+ int GetChar() { return ::wgetch(m_window); }
+ Point GetParentOrigin() const { return Point(GetParentX(), GetParentY()); }
+ int GetParentX() const { return getparx(m_window); }
+ int GetParentY() const { return getpary(m_window); }
+ 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 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 Touch() {
::touchwin(m_window);
if (m_parent)
@@ -631,10 +737,6 @@ public:
::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;
@@ -851,7 +953,6 @@ public:
protected:
std::string m_name;
- WINDOW *m_window;
PANEL *m_panel;
Window *m_parent;
Windows m_subwindows;
@@ -868,6 +969,1688 @@ private:
const Window &operator=(const Window &) = delete;
};
+class DerivedWindow : public Surface {
+public:
+ DerivedWindow(Window &window, Rect bounds) {
+ m_window = ::derwin(window.get(), bounds.size.height, bounds.size.width,
+ bounds.origin.y, bounds.origin.x);
+ }
+ DerivedWindow(DerivedWindow &derived_window, Rect bounds) {
+ m_window = ::derwin(derived_window.get(), bounds.size.height,
+ bounds.size.width, bounds.origin.y, bounds.origin.x);
+ }
+
+ ~DerivedWindow() { ::delwin(m_window); }
+};
+
+/////////
+// Forms
+/////////
+
+// A scroll context defines a vertical region that needs to be visible in a
+// scrolling area. The region is defined by the index of the start and end lines
+// of the region. The start and end lines may be equal, in which case, the
+// region is a single line.
+struct ScrollContext {
+ int start;
+ int end;
+
+ ScrollContext(int line) : start(line), end(line) {}
+ ScrollContext(int _start, int _end) : start(_start), end(_end) {}
+
+ void Offset(int offset) {
+ start += offset;
+ end += offset;
+ }
+};
+
+class FieldDelegate {
+public:
+ virtual ~FieldDelegate() = default;
+
+ // Returns the number of lines needed to draw the field. The draw method will
+ // be given a surface that have exactly this number of lines.
+ virtual int FieldDelegateGetHeight() = 0;
+
+ // Returns the scroll context in the local coordinates of the field. By
+ // default, the scroll context spans the whole field. Bigger fields with
+ // internal navigation should override this method to provide a finer context.
+ // Typical override methods would first get the scroll context of the internal
+ // element then add the offset of the element in the field.
+ virtual ScrollContext FieldDelegateGetScrollContext() {
+ return ScrollContext(0, FieldDelegateGetHeight() - 1);
+ }
+
+ // Draw the field in the given subpad surface. The surface have a height that
+ // is equal to the height returned by FieldDelegateGetHeight(). If the field
+ // is selected in the form window, then is_selected will be true.
+ virtual void FieldDelegateDraw(SubPad &surface, bool is_selected) = 0;
+
+ // Handle the key that wasn't handled by the form window or a container field.
+ virtual HandleCharResult FieldDelegateHandleChar(int key) {
+ return eKeyNotHandled;
+ }
+
+ // This is executed once the user exists the field, that is, once the user
+ // navigates to the next or the previous field. This is particularly useful to
+ // do in-field validation and error setting. Fields with internal navigation
+ // should call this method on their fields.
+ virtual void FieldDelegateExitCallback() { return; }
+
+ // Fields may have internal navigation, for instance, a List Field have
+ // multiple internal elements, which needs to be navigated. To allow for this
+ // mechanism, the window shouldn't handle the navigation keys all the time,
+ // and instead call the key handing method of the selected field. It should
+ // only handle the navigation keys when the field contains a single element or
+ // have the last or first element selected depending on if the user is
+ // navigating forward or backward. Additionally, once a field is selected in
+ // the forward or backward direction, its first or last internal element
+ // should be selected. The following methods implements those mechanisms.
+
+ // Returns true if the first element in the field is selected or if the field
+ // contains a single element.
+ virtual bool FieldDelegateOnFirstOrOnlyElement() { return true; }
+
+ // Returns true if the last element in the field is selected or if the field
+ // contains a single element.
+ virtual bool FieldDelegateOnLastOrOnlyElement() { return true; }
+
+ // Select the first element in the field if multiple elements exists.
+ virtual void FieldDelegateSelectFirstElement() { return; }
+
+ // Select the last element in the field if multiple elements exists.
+ virtual void FieldDelegateSelectLastElement() { return; }
+
+ // Returns true if the field has an error, false otherwise.
+ virtual bool FieldDelegateHasError() { return false; }
+
+ bool FieldDelegateIsVisible() { return m_is_visible; }
+
+ void FieldDelegateHide() { m_is_visible = false; }
+
+ void FieldDelegateShow() { m_is_visible = true; }
+
+protected:
+ bool m_is_visible = true;
+};
+
+typedef std::unique_ptr<FieldDelegate> FieldDelegateUP;
+
+class TextFieldDelegate : public FieldDelegate {
+public:
+ TextFieldDelegate(const char *label, const char *content, bool required)
+ : m_label(label), m_required(required), m_cursor_position(0),
+ m_first_visibile_char(0) {
+ if (content)
+ m_content = content;
+ }
+
+ // Text fields are drawn as titled boxes of a single line, with a possible
+ // error messages at the end.
+ //
+ // __[Label]___________
+ // | |
+ // |__________________|
+ // - Error message if it exists.
+
+ // The text field has a height of 3 lines. 2 lines for borders and 1 line for
+ // the content.
+ int GetFieldHeight() { return 3; }
+
+ // The text field has a full height of 3 or 4 lines. 3 lines for the actual
+ // field and an optional line for an error if it exists.
+ int FieldDelegateGetHeight() override {
+ int height = GetFieldHeight();
+ if (FieldDelegateHasError())
+ height++;
+ return height;
+ }
+
+ // Get the cursor X position in the surface coordinate.
+ int GetCursorXPosition() { return m_cursor_position - m_first_visibile_char; }
+
+ int GetContentLength() { return m_content.length(); }
+
+ void DrawContent(SubPad &surface, bool is_selected) {
+ surface.MoveCursor(0, 0);
+ const char *text = m_content.c_str() + m_first_visibile_char;
+ surface.PutCString(text, surface.GetWidth());
+ m_last_drawn_content_width = surface.GetWidth();
+
+ // Highlight the cursor.
+ surface.MoveCursor(GetCursorXPosition(), 0);
+ if (is_selected)
+ surface.AttributeOn(A_REVERSE);
+ if (m_cursor_position == GetContentLength())
+ // Cursor is past the last character. Highlight an empty space.
+ surface.PutChar(' ');
+ else
+ surface.PutChar(m_content[m_cursor_position]);
+ if (is_selected)
+ surface.AttributeOff(A_REVERSE);
+ }
+
+ void DrawField(SubPad &surface, bool is_selected) {
+ surface.TitledBox(m_label.c_str());
+
+ Rect content_bounds = surface.GetFrame();
+ content_bounds.Inset(1, 1);
+ SubPad content_surface = SubPad(surface, content_bounds);
+
+ DrawContent(content_surface, is_selected);
+ }
+
+ void DrawError(SubPad &surface) {
+ if (!FieldDelegateHasError())
+ return;
+ surface.MoveCursor(0, 0);
+ surface.AttributeOn(COLOR_PAIR(RedOnBlack));
+ surface.PutChar(ACS_DIAMOND);
+ surface.PutChar(' ');
+ surface.PutCStringTruncated(1, GetError().c_str());
+ surface.AttributeOff(COLOR_PAIR(RedOnBlack));
+ }
+
+ void FieldDelegateDraw(SubPad &surface, bool is_selected) override {
+ Rect frame = surface.GetFrame();
+ Rect field_bounds, error_bounds;
+ frame.HorizontalSplit(GetFieldHeight(), field_bounds, error_bounds);
+ SubPad field_surface = SubPad(surface, field_bounds);
+ SubPad error_surface = SubPad(surface, error_bounds);
+
+ DrawField(field_surface, is_selected);
+ DrawError(error_surface);
+ }
+
+ // The cursor is allowed to move one character past the string.
+ // m_cursor_position is in range [0, GetContentLength()].
+ void MoveCursorRight() {
+ if (m_cursor_position < GetContentLength())
+ m_cursor_position++;
+ }
+
+ void MoveCursorLeft() {
+ if (m_cursor_position > 0)
+ m_cursor_position--;
+ }
+
+ // If the cursor moved past the last visible character, scroll right by one
+ // character.
+ void ScrollRightIfNeeded() {
+ if (m_cursor_position - m_first_visibile_char == m_last_drawn_content_width)
+ m_first_visibile_char++;
+ }
+
+ void ScrollLeft() {
+ if (m_first_visibile_char > 0)
+ m_first_visibile_char--;
+ }
+
+ // If the cursor moved past the first visible character, scroll left by one
+ // character.
+ void ScrollLeftIfNeeded() {
+ if (m_cursor_position < m_first_visibile_char)
+ m_first_visibile_char--;
+ }
+
+ // Insert a character at the current cursor position, advance the cursor
+ // position, and make sure to scroll right if needed.
+ void InsertChar(char character) {
+ m_content.insert(m_cursor_position, 1, character);
+ m_cursor_position++;
+ ScrollRightIfNeeded();
+ }
+
+ // Remove the character before the cursor position, retreat the cursor
+ // position, and make sure to scroll left if needed.
+ void RemoveChar() {
+ if (m_cursor_position == 0)
+ return;
+
+ m_content.erase(m_cursor_position - 1, 1);
+ m_cursor_position--;
+ ScrollLeft();
+ }
+
+ // True if the key represents a char that can be inserted in the field
+ // content, false otherwise.
+ virtual bool IsAcceptableChar(int key) { return isprint(key); }
+
+ HandleCharResult FieldDelegateHandleChar(int key) override {
+ if (IsAcceptableChar(key)) {
+ ClearError();
+ InsertChar((char)key);
+ return eKeyHandled;
+ }
+
+ switch (key) {
+ case KEY_RIGHT:
+ MoveCursorRight();
+ ScrollRightIfNeeded();
+ return eKeyHandled;
+ case KEY_LEFT:
+ MoveCursorLeft();
+ ScrollLeftIfNeeded();
+ return eKeyHandled;
+ case KEY_BACKSPACE:
+ ClearError();
+ RemoveChar();
+ return eKeyHandled;
+ default:
+ break;
+ }
+ return eKeyNotHandled;
+ }
+
+ bool FieldDelegateHasError() override { return !m_error.empty(); }
+
+ void FieldDelegateExitCallback() override {
+ if (!IsSpecified() && m_required)
+ SetError("This field is required!");
+ }
+
+ bool IsSpecified() { return !m_content.empty(); }
+
+ void ClearError() { m_error.clear(); }
+
+ const std::string &GetError() { return m_error; }
+
+ void SetError(const char *error) { m_error = error; }
+
+ const std::string &GetText() { return m_content; }
+
+protected:
+ std::string m_label;
+ bool m_required;
+ // The position of the top left corner character of the border.
+ std::string m_content;
+ // The cursor position in the content string itself. Can be in the range
+ // [0, GetContentLength()].
+ int m_cursor_position;
+ // The index of the first visible character in the content.
+ int m_first_visibile_char;
+ // The width of the fields content that was last drawn. Width can change, so
+ // this is used to determine if scrolling is needed dynamically.
+ int m_last_drawn_content_width;
+ // Optional error message. If empty, field is considered to have no error.
+ std::string m_error;
+};
+
+class IntegerFieldDelegate : public TextFieldDelegate {
+public:
+ IntegerFieldDelegate(const char *label, int content, bool required)
+ : TextFieldDelegate(label, std::to_string(content).c_str(), required) {}
+
+ // Only accept digits.
+ bool IsAcceptableChar(int key) override { return isdigit(key); }
+
+ // Returns the integer content of the field.
+ int GetInteger() { return std::stoi(m_content); }
+};
+
+class FileFieldDelegate : public TextFieldDelegate {
+public:
+ FileFieldDelegate(const char *label, const char *content, bool need_to_exist,
+ bool required)
+ : TextFieldDelegate(label, content, required),
+ m_need_to_exist(need_to_exist) {}
+
+ void FieldDelegateExitCallback() override {
+ TextFieldDelegate::FieldDelegateExitCallback();
+ if (!IsSpecified())
+ return;
+
+ if (!m_need_to_exist)
+ return;
+
+ FileSpec file = GetResolvedFileSpec();
+ if (!FileSystem::Instance().Exists(file)) {
+ SetError("File doesn't exist!");
+ return;
+ }
+ if (FileSystem::Instance().IsDirectory(file)) {
+ SetError("Not a file!");
+ return;
+ }
+ }
+
+ FileSpec GetFileSpec() {
+ FileSpec file_spec(GetPath());
+ return file_spec;
+ }
+
+ FileSpec GetResolvedFileSpec() {
+ FileSpec file_spec(GetPath());
+ FileSystem::Instance().Resolve(file_spec);
+ return file_spec;
+ }
+
+ const std::string &GetPath() { return m_content; }
+
+protected:
+ bool m_need_to_exist;
+};
+
+class DirectoryFieldDelegate : public TextFieldDelegate {
+public:
+ DirectoryFieldDelegate(const char *label, const char *content,
+ bool need_to_exist, bool required)
+ : TextFieldDelegate(label, content, required),
+ m_need_to_exist(need_to_exist) {}
+
+ void FieldDelegateExitCallback() override {
+ TextFieldDelegate::FieldDelegateExitCallback();
+ if (!IsSpecified())
+ return;
+
+ if (!m_need_to_exist)
+ return;
+
+ FileSpec file = GetResolvedFileSpec();
+ if (!FileSystem::Instance().Exists(file)) {
+ SetError("Directory doesn't exist!");
+ return;
+ }
+ if (!FileSystem::Instance().IsDirectory(file)) {
+ SetError("Not a directory!");
+ return;
+ }
+ }
+
+ FileSpec GetFileSpec() {
+ FileSpec file_spec(GetPath());
+ return file_spec;
+ }
+
+ FileSpec GetResolvedFileSpec() {
+ FileSpec file_spec(GetPath());
+ FileSystem::Instance().Resolve(file_spec);
+ return file_spec;
+ }
+
+ const std::string &GetPath() { return m_content; }
+
+protected:
+ bool m_need_to_exist;
+};
+
+class ArchFieldDelegate : public TextFieldDelegate {
+public:
+ ArchFieldDelegate(const char *label, const char *content, bool required)
+ : TextFieldDelegate(label, content, required) {}
+
+ void FieldDelegateExitCallback() override {
+ TextFieldDelegate::FieldDelegateExitCallback();
+ if (!IsSpecified())
+ return;
+
+ if (!GetArchSpec().IsValid())
+ SetError("Not a valid arch!");
+ }
+
+ const std::string &GetArchString() { return m_content; }
+
+ ArchSpec GetArchSpec() { return ArchSpec(GetArchString()); }
+};
+
+class BooleanFieldDelegate : public FieldDelegate {
+public:
+ BooleanFieldDelegate(const char *label, bool content)
+ : m_label(label), m_content(content) {}
+
+ // Boolean fields are drawn as checkboxes.
+ //
+ // [X] Label or [ ] Label
+
+ // Boolean fields are have a single line.
+ int FieldDelegateGetHeight() override { return 1; }
+
+ void FieldDelegateDraw(SubPad &surface, bool is_selected) override {
+ surface.MoveCursor(0, 0);
+ surface.PutChar('[');
+ if (is_selected)
+ surface.AttributeOn(A_REVERSE);
+ surface.PutChar(m_content ? ACS_DIAMOND : ' ');
+ if (is_selected)
+ surface.AttributeOff(A_REVERSE);
+ surface.PutChar(']');
+ surface.PutChar(' ');
+ surface.PutCString(m_label.c_str());
+ }
+
+ void ToggleContent() { m_content = !m_content; }
+
+ void SetContentToTrue() { m_content = true; }
+
+ void SetContentToFalse() { m_content = false; }
+
+ HandleCharResult FieldDelegateHandleChar(int key) override {
+ switch (key) {
+ case 't':
+ case '1':
+ SetContentToTrue();
+ return eKeyHandled;
+ case 'f':
+ case '0':
+ SetContentToFalse();
+ return eKeyHandled;
+ case ' ':
+ case '\r':
+ case '\n':
+ case KEY_ENTER:
+ ToggleContent();
+ return eKeyHandled;
+ default:
+ break;
+ }
+ return eKeyNotHandled;
+ }
+
+ // Returns the boolean content of the field.
+ bool GetBoolean() { return m_content; }
+
+protected:
+ std::string m_label;
+ bool m_content;
+};
+
+class ChoicesFieldDelegate : public FieldDelegate {
+public:
+ ChoicesFieldDelegate(const char *label, int number_of_visible_choices,
+ std::vector<std::string> choices)
+ : m_label(label), m_number_of_visible_choices(number_of_visible_choices),
+ m_choices(choices), m_choice(0), m_first_visibile_choice(0) {}
+
+ // Choices fields are drawn as titles boxses of a number of visible choices.
+ // The rest of the choices become visible as the user scroll. The selected
+ // choice is denoted by a diamond as the first character.
+ //
+ // __[Label]___________
+ // |-Choice 1 |
+ // | Choice 2 |
+ // | Choice 3 |
+ // |__________________|
+
+ // Choices field have two border characters plus the number of visible
+ // choices.
+ int FieldDelegateGetHeight() override {
+ return m_number_of_visible_choices + 2;
+ }
+
+ int GetNumberOfChoices() { return m_choices.size(); }
+
+ // Get the index of the last visible choice.
+ int GetLastVisibleChoice() {
+ int index = m_first_visibile_choice + m_number_of_visible_choices;
+ return std::min(index, GetNumberOfChoices()) - 1;
+ }
+
+ void DrawContent(SubPad &surface, bool is_selected) {
+ int choices_to_draw = GetLastVisibleChoice() - m_first_visibile_choice + 1;
+ for (int i = 0; i < choices_to_draw; i++) {
+ surface.MoveCursor(0, i);
+ int current_choice = m_first_visibile_choice + i;
+ const char *text = m_choices[current_choice].c_str();
+ bool highlight = is_selected && current_choice == m_choice;
+ if (highlight)
+ surface.AttributeOn(A_REVERSE);
+ surface.PutChar(current_choice == m_choice ? ACS_DIAMOND : ' ');
+ surface.PutCString(text);
+ if (highlight)
+ surface.AttributeOff(A_REVERSE);
+ }
+ }
+
+ void FieldDelegateDraw(SubPad &surface, bool is_selected) override {
+ UpdateScrolling();
+
+ surface.TitledBox(m_label.c_str());
+
+ Rect content_bounds = surface.GetFrame();
+ content_bounds.Inset(1, 1);
+ SubPad content_surface = SubPad(surface, content_bounds);
+
+ DrawContent(content_surface, is_selected);
+ }
+
+ void SelectPrevious() {
+ if (m_choice > 0)
+ m_choice--;
+ }
+
+ void SelectNext() {
+ if (m_choice < GetNumberOfChoices() - 1)
+ m_choice++;
+ }
+
+ void UpdateScrolling() {
+ if (m_choice > GetLastVisibleChoice()) {
+ m_first_visibile_choice = m_choice - (m_number_of_visible_choices - 1);
+ return;
+ }
+
+ if (m_choice < m_first_visibile_choice)
+ m_first_visibile_choice = m_choice;
+ }
+
+ HandleCharResult FieldDelegateHandleChar(int key) override {
+ switch (key) {
+ case KEY_UP:
+ SelectPrevious();
+ return eKeyHandled;
+ case KEY_DOWN:
+ SelectNext();
+ return eKeyHandled;
+ default:
+ break;
+ }
+ return eKeyNotHandled;
+ }
+
+ // Returns the content of the choice as a string.
+ std::string GetChoiceContent() { return m_choices[m_choice]; }
+
+ // Returns the index of the choice.
+ int GetChoice() { return m_choice; }
+
+ void SetChoice(const std::string &choice) {
+ for (int i = 0; i < GetNumberOfChoices(); i++) {
+ if (choice == m_choices[i]) {
+ m_choice = i;
+ return;
+ }
+ }
+ }
+
+protected:
+ std::string m_label;
+ int m_number_of_visible_choices;
+ std::vector<std::string> m_choices;
+ // The index of the selected choice.
+ int m_choice;
+ // The index of the first visible choice in the field.
+ int m_first_visibile_choice;
+};
+
+class PlatformPluginFieldDelegate : public ChoicesFieldDelegate {
+public:
+ PlatformPluginFieldDelegate(Debugger &debugger)
+ : ChoicesFieldDelegate("Platform Plugin", 3, GetPossiblePluginNames()) {
+ PlatformSP platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
+ if (platform_sp)
+ SetChoice(platform_sp->GetName().AsCString());
+ }
+
+ std::vector<std::string> GetPossiblePluginNames() {
+ std::vector<std::string> names;
+ size_t i = 0;
+ while (auto name = PluginManager::GetPlatformPluginNameAtIndex(i++))
+ names.push_back(name);
+ return names;
+ }
+
+ std::string GetPluginName() {
+ std::string plugin_name = GetChoiceContent();
+ return plugin_name;
+ }
+};
+
+class ProcessPluginFieldDelegate : public ChoicesFieldDelegate {
+public:
+ ProcessPluginFieldDelegate()
+ : ChoicesFieldDelegate("Process Plugin", 3, GetPossiblePluginNames()) {}
+
+ std::vector<std::string> GetPossiblePluginNames() {
+ std::vector<std::string> names;
+ names.push_back("<default>");
+
+ size_t i = 0;
+ while (auto name = PluginManager::GetProcessPluginNameAtIndex(i++))
+ names.push_back(name);
+ return names;
+ }
+
+ std::string GetPluginName() {
+ std::string plugin_name = GetChoiceContent();
+ if (plugin_name == "<default>")
+ return "";
+ return plugin_name;
+ }
+};
+
+template <class T> class ListFieldDelegate : public FieldDelegate {
+public:
+ ListFieldDelegate(const char *label, T default_field)
+ : m_label(label), m_default_field(default_field), m_selection_index(0),
+ m_selection_type(SelectionType::NewButton) {}
+
+ // Signify which element is selected. If a field or a remove button is
+ // selected, then m_selection_index signifies the particular field that
+ // is selected or the field that the remove button belongs to.
+ enum class SelectionType { Field, RemoveButton, NewButton };
+
+ // A List field is drawn as a titled box of a number of other fields of the
+ // same type. Each field has a Remove button next to it that removes the
+ // corresponding field. Finally, the last line contains a New button to add a
+ // new field.
+ //
+ // __[Label]___________
+ // | Field 0 [Remove] |
+ // | Field 1 [Remove] |
+ // | Field 2 [Remove] |
+ // | [New] |
+ // |__________________|
+
+ // List fields have two lines for border characters, 1 line for the New
+ // button, and the total height of the available fields.
+ int FieldDelegateGetHeight() override {
+ // 2 border characters.
+ int height = 2;
+ // Total height of the fields.
+ for (int i = 0; i < GetNumberOfFields(); i++) {
+ height += m_fields[i].FieldDelegateGetHeight();
+ }
+ // A line for the New button.
+ height++;
+ return height;
+ }
+
+ ScrollContext FieldDelegateGetScrollContext() override {
+ int height = FieldDelegateGetHeight();
+ if (m_selection_type == SelectionType::NewButton)
+ return ScrollContext(height - 2, height - 1);
+
+ FieldDelegate &field = m_fields[m_selection_index];
+ ScrollContext context = field.FieldDelegateGetScrollContext();
+
+ // Start at 1 because of the top border.
+ int offset = 1;
+ for (int i = 0; i < m_selection_index; i++) {
+ offset += m_fields[i].FieldDelegateGetHeight();
+ }
+ context.Offset(offset);
+
+ // If the scroll context is touching the top border, include it in the
+ // context to show the label.
+ if (context.start == 1)
+ context.start--;
+
+ // If the scroll context is touching the new button, include it as well as
+ // the bottom border in the context.
+ if (context.end == height - 3)
+ context.end += 2;
+
+ return context;
+ }
+
+ void DrawRemoveButton(SubPad &surface, int highlight) {
+ surface.MoveCursor(1, surface.GetHeight() / 2);
+ if (highlight)
+ surface.AttributeOn(A_REVERSE);
+ surface.PutCString("[Remove]");
+ if (highlight)
+ surface.AttributeOff(A_REVERSE);
+ }
+
+ void DrawFields(SubPad &surface, bool is_selected) {
+ int line = 0;
+ int width = surface.GetWidth();
+ for (int i = 0; i < GetNumberOfFields(); i++) {
+ int height = m_fields[i].FieldDelegateGetHeight();
+ Rect bounds = Rect(Point(0, line), Size(width, height));
+ Rect field_bounds, remove_button_bounds;
+ bounds.VerticalSplit(bounds.size.width - sizeof(" [Remove]"),
+ field_bounds, remove_button_bounds);
+ SubPad field_surface = SubPad(surface, field_bounds);
+ SubPad remove_button_surface = SubPad(surface, remove_button_bounds);
+
+ bool is_element_selected = m_selection_index == i && is_selected;
+ bool is_field_selected =
+ is_element_selected && m_selection_type == SelectionType::Field;
+ bool is_remove_button_selected =
+ is_element_selected &&
+ m_selection_type == SelectionType::RemoveButton;
+ m_fields[i].FieldDelegateDraw(field_surface, is_field_selected);
+ DrawRemoveButton(remove_button_surface, is_remove_button_selected);
+
+ line += height;
+ }
+ }
+
+ void DrawNewButton(SubPad &surface, bool is_selected) {
+ const char *button_text = "[New]";
+ int x = (surface.GetWidth() - sizeof(button_text) - 1) / 2;
+ surface.MoveCursor(x, 0);
+ bool highlight =
+ is_selected && m_selection_type == SelectionType::NewButton;
+ if (highlight)
+ surface.AttributeOn(A_REVERSE);
+ surface.PutCString(button_text);
+ if (highlight)
+ surface.AttributeOff(A_REVERSE);
+ }
+
+ void FieldDelegateDraw(SubPad &surface, bool is_selected) override {
+ surface.TitledBox(m_label.c_str());
+
+ Rect content_bounds = surface.GetFrame();
+ content_bounds.Inset(1, 1);
+ Rect fields_bounds, new_button_bounds;
+ content_bounds.HorizontalSplit(content_bounds.size.height - 1,
+ fields_bounds, new_button_bounds);
+ SubPad fields_surface = SubPad(surface, fields_bounds);
+ SubPad new_button_surface = SubPad(surface, new_button_bounds);
+
+ DrawFields(fields_surface, is_selected);
+ DrawNewButton(new_button_surface, is_selected);
+ }
+
+ void AddNewField() {
+ m_fields.push_back(m_default_field);
+ m_selection_index = GetNumberOfFields() - 1;
+ m_selection_type = SelectionType::Field;
+ FieldDelegate &field = m_fields[m_selection_index];
+ field.FieldDelegateSelectFirstElement();
+ }
+
+ void RemoveField() {
+ m_fields.erase(m_fields.begin() + m_selection_index);
+ if (m_selection_index != 0)
+ m_selection_index--;
+
+ if (GetNumberOfFields() > 0) {
+ m_selection_type = SelectionType::Field;
+ FieldDelegate &field = m_fields[m_selection_index];
+ field.FieldDelegateSelectFirstElement();
+ } else
+ m_selection_type = SelectionType::NewButton;
+ }
+
+ HandleCharResult SelectNext(int key) {
+ if (m_selection_type == SelectionType::NewButton)
+ return eKeyNotHandled;
+
+ if (m_selection_type == SelectionType::RemoveButton) {
+ if (m_selection_index == GetNumberOfFields() - 1) {
+ m_selection_type = SelectionType::NewButton;
+ return eKeyHandled;
+ }
+ m_selection_index++;
+ m_selection_type = SelectionType::Field;
+ FieldDelegate &next_field = m_fields[m_selection_index];
+ next_field.FieldDelegateSelectFirstElement();
+ return eKeyHandled;
+ }
+
+ FieldDelegate &field = m_fields[m_selection_index];
+ if (!field.FieldDelegateOnLastOrOnlyElement()) {
+ return field.FieldDelegateHandleChar(key);
+ }
+
+ field.FieldDelegateExitCallback();
+
+ m_selection_type = SelectionType::RemoveButton;
+ return eKeyHandled;
+ }
+
+ HandleCharResult SelectPrevious(int key) {
+ if (FieldDelegateOnFirstOrOnlyElement())
+ return eKeyNotHandled;
+
+ if (m_selection_type == SelectionType::RemoveButton) {
+ m_selection_type = SelectionType::Field;
+ FieldDelegate &field = m_fields[m_selection_index];
+ field.FieldDelegateSelectLastElement();
+ return eKeyHandled;
+ }
+
+ if (m_selection_type == SelectionType::NewButton) {
+ m_selection_type = SelectionType::RemoveButton;
+ m_selection_index = GetNumberOfFields() - 1;
+ return eKeyHandled;
+ }
+
+ FieldDelegate &field = m_fields[m_selection_index];
+ if (!field.FieldDelegateOnFirstOrOnlyElement()) {
+ return field.FieldDelegateHandleChar(key);
+ }
+
+ field.FieldDelegateExitCallback();
+
+ m_selection_type = SelectionType::RemoveButton;
+ m_selection_index--;
+ return eKeyHandled;
+ }
+
+ HandleCharResult FieldDelegateHandleChar(int key) override {
+ switch (key) {
+ case '\r':
+ case '\n':
+ case KEY_ENTER:
+ switch (m_selection_type) {
+ case SelectionType::NewButton:
+ AddNewField();
+ return eKeyHandled;
+ case SelectionType::RemoveButton:
+ RemoveField();
+ return eKeyHandled;
+ default:
+ break;
+ }
+ break;
+ case '\t':
+ SelectNext(key);
+ return eKeyHandled;
+ case KEY_SHIFT_TAB:
+ SelectPrevious(key);
+ return eKeyHandled;
+ default:
+ break;
+ }
+
+ // If the key wasn't handled and one of the fields is selected, pass the key
+ // to that field.
+ if (m_selection_type == SelectionType::Field) {
+ return m_fields[m_selection_index].FieldDelegateHandleChar(key);
+ }
+
+ return eKeyNotHandled;
+ }
+
+ bool FieldDelegateOnLastOrOnlyElement() override {
+ if (m_selection_type == SelectionType::NewButton) {
+ return true;
+ }
+ return false;
+ }
+
+ bool FieldDelegateOnFirstOrOnlyElement() override {
+ if (m_selection_type == SelectionType::NewButton &&
+ GetNumberOfFields() == 0)
+ return true;
+
+ if (m_selection_type == SelectionType::Field && m_selection_index == 0) {
+ FieldDelegate &field = m_fields[m_selection_index];
+ return field.FieldDelegateOnFirstOrOnlyElement();
+ }
+
+ return false;
+ }
+
+ void FieldDelegateSelectFirstElement() override {
+ if (GetNumberOfFields() == 0) {
+ m_selection_type = SelectionType::NewButton;
+ return;
+ }
+
+ m_selection_type = SelectionType::Field;
+ m_selection_index = 0;
+ }
+
+ void FieldDelegateSelectLastElement() override {
+ m_selection_type = SelectionType::NewButton;
+ return;
+ }
+
+ int GetNumberOfFields() { return m_fields.size(); }
+
+ // Returns the form delegate at the current index.
+ T &GetField(int index) { return m_fields[index]; }
+
+protected:
+ std::string m_label;
+ // The default field delegate instance from which new field delegates will be
+ // created though a copy.
+ T m_default_field;
+ std::vector<T> m_fields;
+ int m_selection_index;
+ // See SelectionType class enum.
+ SelectionType m_selection_type;
+};
+
+class FormAction {
+public:
+ FormAction(const char *label, std::function<void(Window &)> action)
+ : m_action(action) {
+ if (label)
+ m_label = label;
+ }
+
+ // Draw a centered [Label].
+ void Draw(SubPad &surface, bool is_selected) {
+ int x = (surface.GetWidth() - m_label.length()) / 2;
+ surface.MoveCursor(x, 0);
+ if (is_selected)
+ surface.AttributeOn(A_REVERSE);
+ surface.PutChar('[');
+ surface.PutCString(m_label.c_str());
+ surface.PutChar(']');
+ if (is_selected)
+ surface.AttributeOff(A_REVERSE);
+ }
+
+ void Execute(Window &window) { m_action(window); }
+
+ const std::string &GetLabel() { return m_label; }
+
+protected:
+ std::string m_label;
+ std::function<void(Window &)> m_action;
+};
+
+class FormDelegate {
+public:
+ FormDelegate() {}
+
+ virtual ~FormDelegate() = default;
+
+ virtual std::string GetName() = 0;
+
+ virtual void UpdateFieldsVisibility() { return; }
+
+ FieldDelegate *GetField(uint32_t field_index) {
+ if (field_index < m_fields.size())
+ return m_fields[field_index].get();
+ return nullptr;
+ }
+
+ FormAction &GetAction(int action_index) { return m_actions[action_index]; }
+
+ int GetNumberOfFields() { return m_fields.size(); }
+
+ int GetNumberOfActions() { return m_actions.size(); }
+
+ bool HasError() { return !m_error.empty(); }
+
+ void ClearError() { m_error.clear(); }
+
+ const std::string &GetError() { return m_error; }
+
+ void SetError(const char *error) { m_error = error; }
+
+ // If all fields are valid, true is returned. Otherwise, an error message is
+ // set and false is returned. This method is usually called at the start of an
+ // action that requires valid fields.
+ bool CheckFieldsValidity() {
+ for (int i = 0; i < GetNumberOfFields(); i++) {
+ if (GetField(i)->FieldDelegateHasError()) {
+ SetError("Some fields are invalid!");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // Factory methods to create and add fields of specific types.
+
+ TextFieldDelegate *AddTextField(const char *label, const char *content,
+ bool required) {
+ TextFieldDelegate *delegate =
+ new TextFieldDelegate(label, content, required);
+ m_fields.push_back(FieldDelegateUP(delegate));
+ return delegate;
+ }
+
+ FileFieldDelegate *AddFileField(const char *label, const char *content,
+ bool need_to_exist, bool required) {
+ FileFieldDelegate *delegate =
+ new FileFieldDelegate(label, content, need_to_exist, required);
+ m_fields.push_back(FieldDelegateUP(delegate));
+ return delegate;
+ }
+
+ DirectoryFieldDelegate *AddDirectoryField(const char *label,
+ const char *content,
+ bool need_to_exist, bool required) {
+ DirectoryFieldDelegate *delegate =
+ new DirectoryFieldDelegate(label, content, need_to_exist, required);
+ m_fields.push_back(FieldDelegateUP(delegate));
+ return delegate;
+ }
+
+ ArchFieldDelegate *AddArchField(const char *label, const char *content,
+ bool required) {
+ ArchFieldDelegate *delegate =
+ new ArchFieldDelegate(label, content, required);
+ m_fields.push_back(FieldDelegateUP(delegate));
+ return delegate;
+ }
+
+ IntegerFieldDelegate *AddIntegerField(const char *label, int content,
+ bool required) {
+ IntegerFieldDelegate *delegate =
+ new IntegerFieldDelegate(label, content, required);
+ m_fields.push_back(FieldDelegateUP(delegate));
+ return delegate;
+ }
+
+ BooleanFieldDelegate *AddBooleanField(const char *label, bool content) {
+ BooleanFieldDelegate *delegate = new BooleanFieldDelegate(label, content);
+ m_fields.push_back(FieldDelegateUP(delegate));
+ return delegate;
+ }
+
+ ChoicesFieldDelegate *AddChoicesField(const char *label, int height,
+ std::vector<std::string> choices) {
+ ChoicesFieldDelegate *delegate =
+ new ChoicesFieldDelegate(label, height, choices);
+ m_fields.push_back(FieldDelegateUP(delegate));
+ return delegate;
+ }
+
+ PlatformPluginFieldDelegate *AddPlatformPluginField(Debugger &debugger) {
+ PlatformPluginFieldDelegate *delegate =
+ new PlatformPluginFieldDelegate(debugger);
+ m_fields.push_back(FieldDelegateUP(delegate));
+ return delegate;
+ }
+
+ ProcessPluginFieldDelegate *AddProcessPluginField() {
+ ProcessPluginFieldDelegate *delegate = new ProcessPluginFieldDelegate();
+ m_fields.push_back(FieldDelegateUP(delegate));
+ return delegate;
+ }
+
+ template <class T>
+ ListFieldDelegate<T> *AddListField(const char *label, T default_field) {
+ ListFieldDelegate<T> *delegate =
+ new ListFieldDelegate<T>(label, default_field);
+ m_fields.push_back(FieldDelegateUP(delegate));
+ return delegate;
+ }
+
+ // Factory methods for adding actions.
+
+ void AddAction(const char *label, std::function<void(Window &)> action) {
+ m_actions.push_back(FormAction(label, action));
+ }
+
+protected:
+ std::vector<FieldDelegateUP> m_fields;
+ std::vector<FormAction> m_actions;
+ // Optional error message. If empty, form is considered to have no error.
+ std::string m_error;
+};
+
+typedef std::shared_ptr<FormDelegate> FormDelegateSP;
+
+class FormWindowDelegate : public WindowDelegate {
+public:
+ FormWindowDelegate(FormDelegateSP &delegate_sp)
+ : m_delegate_sp(delegate_sp), m_selection_index(0),
+ m_first_visible_line(0) {
+ assert(m_delegate_sp->GetNumberOfActions() > 0);
+ if (m_delegate_sp->GetNumberOfFields() > 0)
+ m_selection_type = SelectionType::Field;
+ else
+ m_selection_type = SelectionType::Action;
+ }
+
+ // Signify which element is selected. If a field or an action is selected,
+ // then m_selection_index signifies the particular field or action that is
+ // selected.
+ enum class SelectionType { Field, Action };
+
+ // A form window is padded by one character from all sides. First, if an error
+ // message exists, it is drawn followed by a separator. Then one or more
+ // fields are drawn. Finally, all available actions are drawn on a single
+ // line.
+ //
+ // ___<Form Name>_________________________________________________
+ // | |
+ // | - Error message if it exists. |
+ // |-------------------------------------------------------------|
+ // | Form elements here. |
+ // | Form actions here. |
+ // | |
+ // |______________________________________[Press Esc to cancel]__|
+ //
+
+ // One line for the error and another for the horizontal line.
+ int GetErrorHeight() {
+ if (m_delegate_sp->HasError())
+ return 2;
+ return 0;
+ }
+
+ // Actions span a single line.
+ int GetActionsHeight() {
+ if (m_delegate_sp->GetNumberOfActions() > 0)
+ return 1;
+ return 0;
+ }
+
+ // Get the total number of needed lines to draw the contents.
+ int GetContentHeight() {
+ int height = 0;
+ height += GetErrorHeight();
+ for (int i = 0; i < m_delegate_sp->GetNumberOfFields(); i++) {
+ if (!m_delegate_sp->GetField(i)->FieldDelegateIsVisible())
+ continue;
+ height += m_delegate_sp->GetField(i)->FieldDelegateGetHeight();
+ }
+ height += GetActionsHeight();
+ return height;
+ }
+
+ ScrollContext GetScrollContext() {
+ if (m_selection_type == SelectionType::Action)
+ return ScrollContext(GetContentHeight() - 1);
+
+ FieldDelegate *field = m_delegate_sp->GetField(m_selection_index);
+ ScrollContext context = field->FieldDelegateGetScrollContext();
+
+ int offset = GetErrorHeight();
+ for (int i = 0; i < m_selection_index; i++) {
+ if (!m_delegate_sp->GetField(i)->FieldDelegateIsVisible())
+ continue;
+ offset += m_delegate_sp->GetField(i)->FieldDelegateGetHeight();
+ }
+ context.Offset(offset);
+
+ // If the context is touching the error, include the error in the context as
+ // well.
+ if (context.start == GetErrorHeight())
+ context.start = 0;
+
+ return context;
+ }
+
+ void UpdateScrolling(DerivedWindow &surface) {
+ ScrollContext context = GetScrollContext();
+ int content_height = GetContentHeight();
+ int surface_height = surface.GetHeight();
+ int visible_height = std::min(content_height, surface_height);
+ int last_visible_line = m_first_visible_line + visible_height - 1;
+
+ // If the last visible line is bigger than the content, then it is invalid
+ // and needs to be set to the last line in the content. This can happen when
+ // a field has shrunk in height.
+ if (last_visible_line > content_height - 1) {
+ m_first_visible_line = content_height - visible_height;
+ }
+
+ if (context.start < m_first_visible_line) {
+ m_first_visible_line = context.start;
+ return;
+ }
+
+ if (context.end > last_visible_line) {
+ m_first_visible_line = context.end - visible_height + 1;
+ }
+ }
+
+ void DrawError(SubPad &surface) {
+ if (!m_delegate_sp->HasError())
+ return;
+ surface.MoveCursor(0, 0);
+ surface.AttributeOn(COLOR_PAIR(RedOnBlack));
+ surface.PutChar(ACS_DIAMOND);
+ surface.PutChar(' ');
+ surface.PutCStringTruncated(1, m_delegate_sp->GetError().c_str());
+ surface.AttributeOff(COLOR_PAIR(RedOnBlack));
+
+ surface.MoveCursor(0, 1);
+ surface.HorizontalLine(surface.GetWidth());
+ }
+
+ void DrawFields(SubPad &surface) {
+ int line = 0;
+ int width = surface.GetWidth();
+ bool a_field_is_selected = m_selection_type == SelectionType::Field;
+ for (int i = 0; i < m_delegate_sp->GetNumberOfFields(); i++) {
+ FieldDelegate *field = m_delegate_sp->GetField(i);
+ if (!field->FieldDelegateIsVisible())
+ continue;
+ bool is_field_selected = a_field_is_selected && m_selection_index == i;
+ int height = field->FieldDelegateGetHeight();
+ Rect bounds = Rect(Point(0, line), Size(width, height));
+ SubPad field_surface = SubPad(surface, bounds);
+ field->FieldDelegateDraw(field_surface, is_field_selected);
+ line += height;
+ }
+ }
+
+ void DrawActions(SubPad &surface) {
+ int number_of_actions = m_delegate_sp->GetNumberOfActions();
+ int width = surface.GetWidth() / number_of_actions;
+ bool an_action_is_selected = m_selection_type == SelectionType::Action;
+ int x = 0;
+ for (int i = 0; i < number_of_actions; i++) {
+ bool is_action_selected = an_action_is_selected && m_selection_index == i;
+ FormAction &action = m_delegate_sp->GetAction(i);
+ Rect bounds = Rect(Point(x, 0), Size(width, 1));
+ SubPad action_surface = SubPad(surface, bounds);
+ action.Draw(action_surface, is_action_selected);
+ x += width;
+ }
+ }
+
+ void DrawElements(SubPad &surface) {
+ Rect frame = surface.GetFrame();
+ Rect fields_bounds, actions_bounds;
+ frame.HorizontalSplit(surface.GetHeight() - GetActionsHeight(),
+ fields_bounds, actions_bounds);
+ SubPad fields_surface = SubPad(surface, fields_bounds);
+ SubPad actions_surface = SubPad(surface, actions_bounds);
+
+ DrawFields(fields_surface);
+ DrawActions(actions_surface);
+ }
+
+ // Contents are first drawn on a pad. Then a subset of that pad is copied to
+ // the derived window starting at the first visible line. This essentially
+ // provides scrolling functionality.
+ void DrawContent(DerivedWindow &surface) {
+ UpdateScrolling(surface);
+
+ int width = surface.GetWidth();
+ int height = GetContentHeight();
+ Pad pad = Pad(Size(width, height));
+
+ Rect frame = pad.GetFrame();
+ Rect error_bounds, elements_bounds;
+ frame.HorizontalSplit(GetErrorHeight(), error_bounds, elements_bounds);
+ SubPad error_surface = SubPad(pad, error_bounds);
+ SubPad elements_surface = SubPad(pad, elements_bounds);
+
+ DrawError(error_surface);
+ DrawElements(elements_surface);
+
+ int copy_height = std::min(surface.GetHeight(), pad.GetHeight());
+ pad.CopyToSurface(surface, Point(0, m_first_visible_line), Point(),
+ Size(width, copy_height));
+ }
+
+ bool WindowDelegateDraw(Window &window, bool force) override {
+ m_delegate_sp->UpdateFieldsVisibility();
+
+ window.Erase();
+
+ window.DrawTitleBox(m_delegate_sp->GetName().c_str(),
+ "Press Esc to cancel");
+
+ Rect content_bounds = window.GetFrame();
+ content_bounds.Inset(2, 2);
+ DerivedWindow content_surface = DerivedWindow(window, content_bounds);
+
+ DrawContent(content_surface);
+ return true;
+ }
+
+ void SkipNextHiddenFields() {
+ while (true) {
+ if (m_delegate_sp->GetField(m_selection_index)->FieldDelegateIsVisible())
+ return;
+
+ if (m_selection_index == m_delegate_sp->GetNumberOfFields() - 1) {
+ m_selection_type = SelectionType::Action;
+ m_selection_index = 0;
+ return;
+ }
+
+ m_selection_index++;
+ }
+ }
+
+ HandleCharResult SelectNext(int key) {
+ if (m_selection_type == SelectionType::Action) {
+ if (m_selection_index < m_delegate_sp->GetNumberOfActions() - 1) {
+ m_selection_index++;
+ return eKeyHandled;
+ }
+
+ m_selection_index = 0;
+ m_selection_type = SelectionType::Field;
+ SkipNextHiddenFields();
+ if (m_selection_type == SelectionType::Field) {
+ FieldDelegate *next_field = m_delegate_sp->GetField(m_selection_index);
+ next_field->FieldDelegateSelectFirstElement();
+ }
+ return eKeyHandled;
+ }
+
+ FieldDelegate *field = m_delegate_sp->GetField(m_selection_index);
+ if (!field->FieldDelegateOnLastOrOnlyElement()) {
+ return field->FieldDelegateHandleChar(key);
+ }
+
+ field->FieldDelegateExitCallback();
+
+ if (m_selection_index == m_delegate_sp->GetNumberOfFields() - 1) {
+ m_selection_type = SelectionType::Action;
+ m_selection_index = 0;
+ return eKeyHandled;
+ }
+
+ m_selection_index++;
+ SkipNextHiddenFields();
+
+ if (m_selection_type == SelectionType::Field) {
+ FieldDelegate *next_field = m_delegate_sp->GetField(m_selection_index);
+ next_field->FieldDelegateSelectFirstElement();
+ }
+
+ return eKeyHandled;
+ }
+
+ void SkipPreviousHiddenFields() {
+ while (true) {
+ if (m_delegate_sp->GetField(m_selection_index)->FieldDelegateIsVisible())
+ return;
+
+ if (m_selection_index == 0) {
+ m_selection_type = SelectionType::Action;
+ m_selection_index = 0;
+ return;
+ }
+
+ m_selection_index--;
+ }
+ }
+
+ HandleCharResult SelectPrevious(int key) {
+ if (m_selection_type == SelectionType::Action) {
+ if (m_selection_index > 0) {
+ m_selection_index--;
+ return eKeyHandled;
+ }
+ m_selection_index = m_delegate_sp->GetNumberOfFields() - 1;
+ m_selection_type = SelectionType::Field;
+ SkipPreviousHiddenFields();
+ if (m_selection_type == SelectionType::Field) {
+ FieldDelegate *previous_field =
+ m_delegate_sp->GetField(m_selection_index);
+ previous_field->FieldDelegateSelectLastElement();
+ }
+ return eKeyHandled;
+ }
+
+ FieldDelegate *field = m_delegate_sp->GetField(m_selection_index);
+ if (!field->FieldDelegateOnFirstOrOnlyElement()) {
+ return field->FieldDelegateHandleChar(key);
+ }
+
+ field->FieldDelegateExitCallback();
+
+ if (m_selection_index == 0) {
+ m_selection_type = SelectionType::Action;
+ m_selection_index = m_delegate_sp->GetNumberOfActions() - 1;
+ return eKeyHandled;
+ }
+
+ m_selection_index--;
+ SkipPreviousHiddenFields();
+
+ if (m_selection_type == SelectionType::Field) {
+ FieldDelegate *previous_field =
+ m_delegate_sp->GetField(m_selection_index);
+ previous_field->FieldDelegateSelectLastElement();
+ }
+
+ return eKeyHandled;
+ }
+
+ void ExecuteAction(Window &window) {
+ FormAction &action = m_delegate_sp->GetAction(m_selection_index);
+ action.Execute(window);
+ if (m_delegate_sp->HasError()) {
+ m_first_visible_line = 0;
+ m_selection_index = 0;
+ m_selection_type = SelectionType::Field;
+ }
+ }
+
+ HandleCharResult WindowDelegateHandleChar(Window &window, int key) override {
+ switch (key) {
+ case '\r':
+ case '\n':
+ case KEY_ENTER:
+ if (m_selection_type == SelectionType::Action) {
+ ExecuteAction(window);
+ return eKeyHandled;
+ }
+ break;
+ case '\t':
+ return SelectNext(key);
+ case KEY_SHIFT_TAB:
+ return SelectPrevious(key);
+ case KEY_ESCAPE:
+ window.GetParent()->RemoveSubWindow(&window);
+ return eKeyHandled;
+ default:
+ break;
+ }
+
+ // If the key wasn't handled and one of the fields is selected, pass the key
+ // to that field.
+ if (m_selection_type == SelectionType::Field) {
+ FieldDelegate *field = m_delegate_sp->GetField(m_selection_index);
+ return field->FieldDelegateHandleChar(key);
+ }
+
+ return eKeyNotHandled;
+ }
+
+protected:
+ FormDelegateSP m_delegate_sp;
+ // The index of the currently selected SelectionType.
+ int m_selection_index;
+ // See SelectionType class enum.
+ SelectionType m_selection_type;
+ // The first visible line from the pad.
+ int m_first_visible_line;
+};
+
+///////////////////////////
+// Form Delegate Instances
+///////////////////////////
+
+class DetachOrKillProcessFormDelegate : public FormDelegate {
+public:
+ DetachOrKillProcessFormDelegate(Process *process) : m_process(process) {
+ SetError("There is a running process, either detach or kill it.");
+
+ m_keep_stopped_field =
+ AddBooleanField("Keep process stopped when detaching.", false);
+
+ AddAction("Detach", [this](Window &window) { Detach(window); });
+ AddAction("Kill", [this](Window &window) { Kill(window); });
+ }
+
+ std::string GetName() override { return "Detach/Kill Process"; }
+
+ void Kill(Window &window) {
+ Status destroy_status(m_process->Destroy(false));
+ if (destroy_status.Fail()) {
+ SetError("Failed to kill process.");
+ return;
+ }
+ window.GetParent()->RemoveSubWindow(&window);
+ }
+
+ void Detach(Window &window) {
+ Status detach_status(m_process->Detach(m_keep_stopped_field->GetBoolean()));
+ if (detach_status.Fail()) {
+ SetError("Failed to detach from process.");
+ return;
+ }
+ window.GetParent()->RemoveSubWindow(&window);
+ }
+
+protected:
+ Process *m_process;
+ BooleanFieldDelegate *m_keep_stopped_field;
+};
+
+class ProcessAttachFormDelegate : public FormDelegate {
+public:
+ ProcessAttachFormDelegate(Debugger &debugger, WindowSP main_window_sp)
+ : m_debugger(debugger), m_main_window_sp(main_window_sp) {
+ std::vector<std::string> types;
+ types.push_back(std::string("Name"));
+ types.push_back(std::string("PID"));
+ m_type_field = AddChoicesField("Attach By", 2, types);
+ m_pid_field = AddIntegerField("PID", 0, true);
+ m_name_field =
+ AddTextField("Process Name", GetDefaultProcessName().c_str(), true);
+ m_continue_field = AddBooleanField("Continue once attached.", false);
+ m_wait_for_field = AddBooleanField("Wait for process to launch.", false);
+ m_include_existing_field =
+ AddBooleanField("Include existing processes.", false);
+ m_show_advanced_field = AddBooleanField("Show advanced settings.", false);
+ m_plugin_field = AddProcessPluginField();
+
+ AddAction("Attach", [this](Window &window) { Attach(window); });
+ }
+
+ std::string GetName() override { return "Attach Process"; }
+
+ void UpdateFieldsVisibility() override {
+ if (m_type_field->GetChoiceContent() == "Name") {
+ m_pid_field->FieldDelegateHide();
+ m_name_field->FieldDelegateShow();
+ m_wait_for_field->FieldDelegateShow();
+ if (m_wait_for_field->GetBoolean())
+ m_include_existing_field->FieldDelegateShow();
+ else
+ m_include_existing_field->FieldDelegateHide();
+ } else {
+ m_pid_field->FieldDelegateShow();
+ m_name_field->FieldDelegateHide();
+ m_wait_for_field->FieldDelegateHide();
+ m_include_existing_field->FieldDelegateHide();
+ }
+ if (m_show_advanced_field->GetBoolean())
+ m_plugin_field->FieldDelegateShow();
+ else
+ m_plugin_field->FieldDelegateHide();
+ }
+
+ // Get the basename of the target's main executable if available, empty string
+ // otherwise.
+ std::string GetDefaultProcessName() {
+ Target *target = m_debugger.GetSelectedTarget().get();
+ if (target == nullptr)
+ return "";
+
+ ModuleSP module_sp = target->GetExecutableModule();
+ if (!module_sp->IsExecutable())
+ return "";
+
+ return module_sp->GetFileSpec().GetFilename().AsCString();
+ }
+
+ bool StopRunningProcess() {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+
+ if (!exe_ctx.HasProcessScope())
+ return false;
+
+ Process *process = exe_ctx.GetProcessPtr();
+ if (!(process && process->IsAlive()))
+ return false;
+
+ FormDelegateSP form_delegate_sp =
+ FormDelegateSP(new DetachOrKillProcessFormDelegate(process));
+ Rect bounds = m_main_window_sp->GetCenteredRect(85, 8);
+ WindowSP form_window_sp = m_main_window_sp->CreateSubWindow(
+ form_delegate_sp->GetName().c_str(), bounds, true);
+ WindowDelegateSP window_delegate_sp =
+ WindowDelegateSP(new FormWindowDelegate(form_delegate_sp));
+ form_window_sp->SetDelegate(window_delegate_sp);
+
+ return true;
+ }
+
+ Target *GetTarget() {
+ Target *target = m_debugger.GetSelectedTarget().get();
+
+ if (target != nullptr)
+ return target;
+
+ TargetSP new_target_sp;
+ m_debugger.GetTargetList().CreateTarget(
+ m_debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp);
+
+ target = new_target_sp.get();
+
+ if (target == nullptr)
+ SetError("Failed to create target.");
+
+ m_debugger.GetTargetList().SetSelectedTarget(new_target_sp);
+
+ return target;
+ }
+
+ ProcessAttachInfo GetAttachInfo() {
+ ProcessAttachInfo attach_info;
+ attach_info.SetContinueOnceAttached(m_continue_field->GetBoolean());
+ if (m_type_field->GetChoiceContent() == "Name") {
+ attach_info.GetExecutableFile().SetFile(m_name_field->GetText(),
+ FileSpec::Style::native);
+ attach_info.SetWaitForLaunch(m_wait_for_field->GetBoolean());
+ if (m_wait_for_field->GetBoolean())
+ attach_info.SetIgnoreExisting(!m_include_existing_field->GetBoolean());
+ } else {
+ attach_info.SetProcessID(m_pid_field->GetInteger());
+ }
+ attach_info.SetProcessPluginName(m_plugin_field->GetPluginName());
+
+ return attach_info;
+ }
+
+ void Attach(Window &window) {
+ ClearError();
+
+ bool all_fields_are_valid = CheckFieldsValidity();
+ if (!all_fields_are_valid)
+ return;
+
+ bool process_is_running = StopRunningProcess();
+ if (process_is_running)
+ return;
+
+ Target *target = GetTarget();
+ if (HasError())
+ return;
+
+ StreamString stream;
+ ProcessAttachInfo attach_info = GetAttachInfo();
+ Status status = target->Attach(attach_info, &stream);
+
+ if (status.Fail()) {
+ SetError(status.AsCString());
+ return;
+ }
+
+ ProcessSP process_sp(target->GetProcessSP());
+ if (!process_sp) {
+ SetError("Attached sucessfully but target has no process.");
+ return;
+ }
+
+ if (attach_info.GetContinueOnceAttached())
+ process_sp->Resume();
+
+ window.GetParent()->RemoveSubWindow(&window);
+ }
+
+protected:
+ Debugger &m_debugger;
+ WindowSP m_main_window_sp;
+
+ ChoicesFieldDelegate *m_type_field;
+ IntegerFieldDelegate *m_pid_field;
+ TextFieldDelegate *m_name_field;
+ BooleanFieldDelegate *m_continue_field;
+ BooleanFieldDelegate *m_wait_for_field;
+ BooleanFieldDelegate *m_include_existing_field;
+ BooleanFieldDelegate *m_show_advanced_field;
+ ProcessPluginFieldDelegate *m_plugin_field;
+};
+
class MenuDelegate {
public:
virtual ~MenuDelegate() = default;
@@ -1282,8 +3065,6 @@ public:
}
void Initialize() {
- ::setlocale(LC_ALL, "");
- ::setlocale(LC_CTYPE, "");
m_screen = ::newterm(nullptr, m_out, m_in);
::start_color();
::curs_set(0);
@@ -1390,8 +3171,6 @@ public:
ConstString broadcaster_class(
broadcaster->GetBroadcasterClass());
if (broadcaster_class == broadcaster_class_process) {
- debugger.GetCommandInterpreter().UpdateExecutionContext(
- nullptr);
m_update_screen = true;
continue; // Don't get any key, just update our view
}
@@ -1403,7 +3182,6 @@ public:
HandleCharResult key_result = m_window_sp->HandleChar(ch);
switch (key_result) {
case eKeyHandled:
- debugger.GetCommandInterpreter().UpdateExecutionContext(nullptr);
m_update_screen = true;
break;
case eKeyNotHandled:
@@ -1494,7 +3272,7 @@ protected:
using namespace curses;
struct Row {
- ValueObjectManager value;
+ ValueObjectUpdater value;
Row *parent;
// The process stop ID when the children were calculated.
uint32_t children_stop_id = 0;
@@ -1507,7 +3285,7 @@ struct Row {
std::vector<Row> children;
Row(const ValueObjectSP &v, Row *p)
- : value(v, lldb::eDynamicDontRunTarget, true), parent(p),
+ : value(v), parent(p),
might_have_children(v ? v->MightHaveChildren() : false) {}
size_t GetDepth() const {
@@ -1610,8 +3388,13 @@ public:
virtual void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) = 0;
virtual void TreeDelegateGenerateChildren(TreeItem &item) = 0;
+ virtual void TreeDelegateUpdateSelection(TreeItem &root, int &selection_index,
+ TreeItem *&selected_item) {
+ return;
+ }
virtual bool TreeDelegateItemSelected(
TreeItem &item) = 0; // Return true if we need to update views
+ virtual bool TreeDelegateExpandRootByDefault() { return false; }
};
typedef std::shared_ptr<TreeDelegate> TreeDelegateSP;
@@ -1621,7 +3404,10 @@ 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) {}
+ m_might_have_children(might_have_children), m_is_expanded(false) {
+ if (m_parent == nullptr)
+ m_is_expanded = m_delegate.TreeDelegateExpandRootByDefault();
+ }
TreeItem &operator=(const TreeItem &rhs) {
if (this != &rhs) {
@@ -1850,6 +3636,8 @@ public:
const int num_visible_rows = NumVisibleRows();
m_num_rows = 0;
m_root.CalculateRowIndexes(m_num_rows);
+ m_delegate_sp->TreeDelegateUpdateSelection(m_root, m_selected_row_idx,
+ m_selected_item);
// 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
@@ -2151,7 +3939,7 @@ class ThreadsTreeDelegate : public TreeDelegate {
public:
ThreadsTreeDelegate(Debugger &debugger)
: TreeDelegate(), m_thread_delegate_sp(), m_debugger(debugger),
- m_stop_id(UINT32_MAX) {
+ m_stop_id(UINT32_MAX), m_update_selection(false) {
FormatEntity::Parse("process ${process.id}{, name = ${process.name}}",
m_format);
}
@@ -2179,6 +3967,7 @@ public:
void TreeDelegateGenerateChildren(TreeItem &item) override {
ProcessSP process_sp = GetProcess();
+ m_update_selection = false;
if (process_sp && process_sp->IsAlive()) {
StateType state = process_sp->GetState();
if (StateIsStoppedState(state, true)) {
@@ -2187,6 +3976,7 @@ public:
return; // Children are already up to date
m_stop_id = stop_id;
+ m_update_selection = true;
if (!m_thread_delegate_sp) {
// Always expand the thread item the first time we show it
@@ -2198,11 +3988,15 @@ public:
TreeItem t(&item, *m_thread_delegate_sp, false);
ThreadList &threads = process_sp->GetThreadList();
std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
+ ThreadSP selected_thread = threads.GetSelectedThread();
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());
+ ThreadSP thread = threads.GetThreadAtIndex(i);
+ item[i].SetIdentifier(thread->GetID());
item[i].SetMightHaveChildren(true);
+ if (selected_thread->GetID() == thread->GetID())
+ item[i].Expand();
}
return;
}
@@ -2210,20 +4004,48 @@ public:
item.ClearChildren();
}
+ void TreeDelegateUpdateSelection(TreeItem &root, int &selection_index,
+ TreeItem *&selected_item) override {
+ if (!m_update_selection)
+ return;
+
+ ProcessSP process_sp = GetProcess();
+ if (!(process_sp && process_sp->IsAlive()))
+ return;
+
+ StateType state = process_sp->GetState();
+ if (!StateIsStoppedState(state, true))
+ return;
+
+ ThreadList &threads = process_sp->GetThreadList();
+ std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
+ ThreadSP selected_thread = threads.GetSelectedThread();
+ size_t num_threads = threads.GetSize();
+ for (size_t i = 0; i < num_threads; ++i) {
+ ThreadSP thread = threads.GetThreadAtIndex(i);
+ if (selected_thread->GetID() == thread->GetID()) {
+ selected_item = &root[i][thread->GetSelectedFrameIndex()];
+ selection_index = selected_item->GetRowIndex();
+ return;
+ }
+ }
+ }
+
bool TreeDelegateItemSelected(TreeItem &item) override { return false; }
+ bool TreeDelegateExpandRootByDefault() override { return true; }
+
protected:
std::shared_ptr<ThreadTreeDelegate> m_thread_delegate_sp;
Debugger &m_debugger;
uint32_t m_stop_id;
+ bool m_update_selection;
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() : m_rows() {}
ValueObjectListDelegate(ValueObjectList &valobj_list)
: m_rows(), m_selected_row(nullptr), m_selected_row_idx(0),
@@ -2411,14 +4233,14 @@ public:
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;
+ Row *m_selected_row = nullptr;
+ uint32_t m_selected_row_idx = 0;
+ uint32_t m_first_visible_row = 0;
+ uint32_t m_num_rows = 0;
int m_min_x;
int m_min_y;
- int m_max_x;
- int m_max_y;
+ int m_max_x = 0;
+ int m_max_y = 0;
static Format FormatForChar(int c) {
switch (c) {
@@ -3042,7 +4864,7 @@ public:
window.SelectNextWindowAsActive();
return eKeyHandled;
- case KEY_BTAB:
+ case KEY_SHIFT_TAB:
window.SelectPreviousWindowAsActive();
return eKeyHandled;
@@ -3122,6 +4944,19 @@ public:
}
return MenuActionResult::Handled;
+ case eMenuID_ProcessAttach: {
+ WindowSP main_window_sp = m_app.GetMainWindow();
+ FormDelegateSP form_delegate_sp = FormDelegateSP(
+ new ProcessAttachFormDelegate(m_debugger, main_window_sp));
+ Rect bounds = main_window_sp->GetCenteredRect(80, 22);
+ WindowSP form_window_sp = main_window_sp->CreateSubWindow(
+ form_delegate_sp->GetName().c_str(), bounds, true);
+ WindowDelegateSP window_delegate_sp =
+ WindowDelegateSP(new FormWindowDelegate(form_delegate_sp));
+ form_window_sp->SetDelegate(window_delegate_sp);
+ return MenuActionResult::Handled;
+ }
+
case eMenuID_ProcessContinue: {
ExecutionContext exe_ctx =
m_debugger.GetCommandInterpreter().GetExecutionContext();
@@ -3394,10 +5229,10 @@ 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_first_visible_column(0), m_min_x(0), m_min_y(0), m_max_x(0),
- m_max_y(0) {}
+ m_title(), m_tid(LLDB_INVALID_THREAD_ID), 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_first_visible_column(0), m_min_x(0),
+ m_min_y(0), m_max_x(0), m_max_y(0) {}
~SourceFileWindowDelegate() override = default;
@@ -3552,7 +5387,7 @@ public:
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);
+ exe_ctx, nullptr, !prefer_file_cache);
if (m_disassembly_sp) {
set_selected_line_to_pc = true;
m_disassembly_range = m_sc.function->GetAddressRange();
@@ -3956,7 +5791,7 @@ public:
false, // request_hardware
eLazyBoolCalculate); // move_to_nearest_code
// Make breakpoint one shot
- bp_sp->GetOptions()->SetOneShot(true);
+ bp_sp->GetOptions().SetOneShot(true);
exe_ctx.GetProcessRef().Resume();
}
} else if (m_selected_line < GetNumDisassemblyLines()) {
@@ -3972,7 +5807,7 @@ public:
false, // internal
false); // request_hardware
// Make breakpoint one shot
- bp_sp->GetOptions()->SetOneShot(true);
+ bp_sp->GetOptions().SetOneShot(true);
exe_ctx.GetProcessRef().Resume();
}
}
@@ -4339,6 +6174,8 @@ void IOHandlerCursesGUI::Activate() {
init_pair(17, COLOR_BLACK, COLOR_WHITE);
init_pair(18, COLOR_MAGENTA, COLOR_WHITE);
static_assert(LastColorPairIndex == 18, "Color indexes do not match.");
+
+ define_key("\033[Z", KEY_SHIFT_TAB);
}
}
diff --git a/lldb/source/Core/Mangled.cpp b/lldb/source/Core/Mangled.cpp
index 627be94a303c..fbaf9ff7151a 100644
--- a/lldb/source/Core/Mangled.cpp
+++ b/lldb/source/Core/Mangled.cpp
@@ -17,7 +17,6 @@
#include "lldb/lldb-enumerations.h"
#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
-#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Demangle/Demangle.h"
@@ -27,34 +26,16 @@
#include <string>
#include <utility>
-#include <stdlib.h>
-#include <string.h>
+#include <cstdlib>
+#include <cstring>
using namespace lldb_private;
static inline bool cstring_is_mangled(llvm::StringRef s) {
return Mangled::GetManglingScheme(s) != Mangled::eManglingSchemeNone;
}
-static ConstString
-get_demangled_name_without_arguments(ConstString mangled,
- ConstString demangled) {
- // This pair is <mangled name, demangled name without function arguments>
- static std::pair<ConstString, ConstString>
- g_most_recent_mangled_to_name_sans_args;
-
- // Need to have the mangled & demangled names we're currently examining as
- // statics so we can return a const ref to them at the end of the func if we
- // don't have anything better.
- static ConstString g_last_mangled;
- static ConstString g_last_demangled;
-
- if (mangled && g_most_recent_mangled_to_name_sans_args.first == mangled) {
- return g_most_recent_mangled_to_name_sans_args.second;
- }
-
- g_last_demangled = demangled;
- g_last_mangled = mangled;
-
+static ConstString GetDemangledNameWithoutArguments(ConstString mangled,
+ ConstString demangled) {
const char *mangled_name_cstr = mangled.GetCString();
if (demangled && mangled_name_cstr && mangled_name_cstr[0]) {
@@ -73,17 +54,13 @@ get_demangled_name_without_arguments(ConstString mangled,
if (!cxx_method.GetContext().empty())
shortname = cxx_method.GetContext().str() + "::";
shortname += cxx_method.GetBasename().str();
- ConstString result(shortname.c_str());
- g_most_recent_mangled_to_name_sans_args.first = mangled;
- g_most_recent_mangled_to_name_sans_args.second = result;
- return g_most_recent_mangled_to_name_sans_args.second;
+ return ConstString(shortname);
}
}
}
-
if (demangled)
- return g_last_demangled;
- return g_last_mangled;
+ return demangled;
+ return mangled;
}
#pragma mark Mangled
@@ -95,6 +72,9 @@ Mangled::ManglingScheme Mangled::GetManglingScheme(llvm::StringRef const name) {
if (name.startswith("?"))
return Mangled::eManglingSchemeMSVC;
+ if (name.startswith("_R"))
+ return Mangled::eManglingSchemeRustV0;
+
if (name.startswith("_Z"))
return Mangled::eManglingSchemeItanium;
@@ -222,6 +202,19 @@ static char *GetItaniumDemangledStr(const char *M) {
return demangled_cstr;
}
+static char *GetRustV0DemangledStr(const char *M) {
+ char *demangled_cstr = llvm::rustDemangle(M, nullptr, nullptr, nullptr);
+
+ if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) {
+ if (demangled_cstr && demangled_cstr[0])
+ LLDB_LOG(log, "demangled rustv0: {0} -> \"{1}\"", M, demangled_cstr);
+ else
+ LLDB_LOG(log, "demangled rustv0: {0} -> error: failed to demangle", M);
+ }
+
+ return demangled_cstr;
+}
+
// Explicit demangling for scheduled requests during batch processing. This
// makes use of ItaniumPartialDemangler's rich demangle info
bool Mangled::DemangleWithRichManglingInfo(
@@ -279,6 +272,10 @@ bool Mangled::DemangleWithRichManglingInfo(
return context.FromCxxMethodName(m_demangled);
}
}
+
+ case eManglingSchemeRustV0:
+ // Rich demangling scheme is not supported for Rust
+ return false;
}
llvm_unreachable("Fully covered switch above!");
}
@@ -307,6 +304,9 @@ ConstString Mangled::GetDemangledName() const {
demangled_name = GetItaniumDemangledStr(mangled_name);
break;
}
+ case eManglingSchemeRustV0:
+ demangled_name = GetRustV0DemangledStr(mangled_name);
+ break;
case eManglingSchemeNone:
llvm_unreachable("eManglingSchemeNone was handled already");
}
@@ -347,7 +347,7 @@ ConstString Mangled::GetName(Mangled::NamePreference preference) const {
ConstString demangled = GetDemangledName();
if (preference == ePreferDemangledWithoutArguments) {
- return get_demangled_name_without_arguments(m_mangled, demangled);
+ return GetDemangledNameWithoutArguments(m_mangled, demangled);
}
if (preference == ePreferDemangled) {
// Call the accessor to make sure we get a demangled name in case it hasn't
@@ -395,22 +395,16 @@ size_t Mangled::MemorySize() const {
// of mangling names from a given language, likewise the compilation units
// within those targets.
lldb::LanguageType Mangled::GuessLanguage() const {
- ConstString mangled = GetMangledName();
-
- if (mangled) {
- const char *mangled_name = mangled.GetCString();
- if (CPlusPlusLanguage::IsCPPMangledName(mangled_name))
- return lldb::eLanguageTypeC_plus_plus;
- } else {
- // ObjC names aren't really mangled, so they won't necessarily be in the
- // mangled name slot.
- ConstString demangled_name = GetDemangledName();
- if (demangled_name
- && ObjCLanguage::IsPossibleObjCMethodName(demangled_name.GetCString()))
- return lldb::eLanguageTypeObjC;
-
- }
- return lldb::eLanguageTypeUnknown;
+ lldb::LanguageType result = lldb::eLanguageTypeUnknown;
+ // Ask each language plugin to check if the mangled name belongs to it.
+ Language::ForEach([this, &result](Language *l) {
+ if (l->SymbolNameFitsToLanguage(*this)) {
+ result = l->GetLanguageType();
+ return false;
+ }
+ return true;
+ });
+ return result;
}
// Dump OBJ to the supplied stream S.
diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index 1f9987c21658..19c97be15066 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -59,12 +59,12 @@
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
-#include <assert.h>
+#include <cassert>
+#include <cinttypes>
+#include <cstdarg>
#include <cstdint>
-#include <inttypes.h>
+#include <cstring>
#include <map>
-#include <stdarg.h>
-#include <string.h>
#include <type_traits>
#include <utility>
@@ -257,9 +257,7 @@ Module::Module(const FileSpec &file_spec, const ArchSpec &arch,
m_object_name.IsEmpty() ? "" : ")");
}
-Module::Module()
- : m_object_offset(0), m_file_has_changed(false),
- m_first_file_changed_log(false) {
+Module::Module() : m_file_has_changed(false), m_first_file_changed_log(false) {
std::lock_guard<std::recursive_mutex> guard(
GetAllocationModuleCollectionMutex());
GetModuleCollection().push_back(this);
@@ -440,8 +438,6 @@ CompUnitSP Module::GetCompileUnitAtIndex(size_t index) {
bool Module::ResolveFileAddress(lldb::addr_t vm_addr, Address &so_addr) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- LLDB_SCOPED_TIMERF("Module::ResolveFileAddress (vm_addr = 0x%" PRIx64 ")",
- vm_addr);
SectionList *section_list = GetSectionList();
if (section_list)
return so_addr.ResolveAddressUsingFileSections(vm_addr, section_list);
@@ -598,9 +594,13 @@ uint32_t Module::ResolveSymbolContextsForFileSpec(
const uint32_t initial_count = sc_list.GetSize();
- if (SymbolFile *symbols = GetSymbolFile())
- symbols->ResolveSymbolContext(file_spec, line, check_inlines, resolve_scope,
- sc_list);
+ if (SymbolFile *symbols = GetSymbolFile()) {
+ // TODO: Handle SourceLocationSpec column information
+ SourceLocationSpec location_spec(file_spec, line, /*column=*/llvm::None,
+ check_inlines, /*exact_match=*/false);
+
+ symbols->ResolveSymbolContext(location_spec, resolve_scope, sc_list);
+ }
return sc_list.GetSize() - initial_count;
}
@@ -917,7 +917,12 @@ void Module::FindAddressesForLine(const lldb::TargetSP target_sp,
std::vector<Address> &output_local,
std::vector<Address> &output_extern) {
SearchFilterByModule filter(target_sp, m_file);
- AddressResolverFileLine resolver(file, line, true);
+
+ // TODO: Handle SourceLocationSpec column information
+ SourceLocationSpec location_spec(file, line, /*column=*/llvm::None,
+ /*check_inlines=*/true,
+ /*exact_match=*/false);
+ AddressResolverFileLine resolver(location_spec);
resolver.ResolveAddress(filter);
for (size_t n = 0; n < resolver.GetNumberOfAddresses(); n++) {
@@ -1072,8 +1077,6 @@ std::string Module::GetSpecificationDescription() const {
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 << llvm::formatv("({0}) ", m_arch.GetArchitectureName());
@@ -1525,9 +1528,9 @@ bool Module::LoadScriptingResourceInTarget(Target *target, Status &error,
}
StreamString scripting_stream;
scripting_fspec.Dump(scripting_stream.AsRawOstream());
- const bool init_lldb_globals = false;
+ LoadScriptOptions options;
bool did_load = script_interpreter->LoadScriptingModule(
- scripting_stream.GetData(), init_lldb_globals, error);
+ scripting_stream.GetData(), options, error);
if (!did_load)
return false;
}
@@ -1595,13 +1598,18 @@ bool Module::MatchesModuleSpec(const ModuleSpec &module_ref) {
bool Module::FindSourceFile(const FileSpec &orig_spec,
FileSpec &new_spec) const {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- return m_source_mappings.FindFile(orig_spec, new_spec);
+ if (auto remapped = m_source_mappings.FindFile(orig_spec)) {
+ new_spec = *remapped;
+ return true;
+ }
+ return false;
}
-bool Module::RemapSourceFile(llvm::StringRef path,
- std::string &new_path) const {
+llvm::Optional<std::string> Module::RemapSourceFile(llvm::StringRef path) const {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- return m_source_mappings.RemapPath(path, new_path);
+ if (auto remapped = m_source_mappings.RemapPath(path))
+ return remapped->GetPath();
+ return {};
}
void Module::RegisterXcodeSDK(llvm::StringRef sdk_name, llvm::StringRef sysroot) {
diff --git a/lldb/source/Core/ModuleChild.cpp b/lldb/source/Core/ModuleChild.cpp
index 6e04bb4589e3..7aaa8f2ac250 100644
--- a/lldb/source/Core/ModuleChild.cpp
+++ b/lldb/source/Core/ModuleChild.cpp
@@ -13,7 +13,7 @@ using namespace lldb_private;
ModuleChild::ModuleChild(const lldb::ModuleSP &module_sp)
: m_module_wp(module_sp) {}
-ModuleChild::~ModuleChild() {}
+ModuleChild::~ModuleChild() = default;
const ModuleChild &ModuleChild::operator=(const ModuleChild &rhs) {
if (this != &rhs)
diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp
index 98f6ae2c62b0..56bc4c72d8e9 100644
--- a/lldb/source/Core/ModuleList.cpp
+++ b/lldb/source/Core/ModuleList.cpp
@@ -132,8 +132,7 @@ PathMappingList ModuleListProperties::GetSymlinkMappings() const {
return m_symlink_paths;
}
-ModuleList::ModuleList()
- : m_modules(), m_modules_mutex(), m_notifier(nullptr) {}
+ModuleList::ModuleList() : m_modules(), m_modules_mutex() {}
ModuleList::ModuleList(const ModuleList &rhs)
: m_modules(), m_modules_mutex(), m_notifier(nullptr) {
diff --git a/lldb/source/Core/Opcode.cpp b/lldb/source/Core/Opcode.cpp
index b544064b061e..a3fc97f95266 100644
--- a/lldb/source/Core/Opcode.cpp
+++ b/lldb/source/Core/Opcode.cpp
@@ -16,7 +16,7 @@
#include <memory>
-#include <inttypes.h>
+#include <cinttypes>
using namespace lldb;
using namespace lldb_private;
diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp
index 97e1e8d14039..fcaa868b083e 100644
--- a/lldb/source/Core/PluginManager.cpp
+++ b/lldb/source/Core/PluginManager.cpp
@@ -20,7 +20,7 @@
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
-#include <assert.h>
+#include <cassert>
#include <map>
#include <memory>
#include <mutex>
@@ -38,11 +38,11 @@ typedef bool (*PluginInitCallback)();
typedef void (*PluginTermCallback)();
struct PluginInfo {
- PluginInfo() : plugin_init_callback(nullptr), plugin_term_callback(nullptr) {}
+ PluginInfo() = default;
llvm::sys::DynamicLibrary library;
- PluginInitCallback plugin_init_callback;
- PluginTermCallback plugin_term_callback;
+ PluginInitCallback plugin_init_callback = nullptr;
+ PluginTermCallback plugin_term_callback = nullptr;
};
typedef std::map<FileSpec, PluginInfo> PluginTerminateMap;
@@ -684,11 +684,13 @@ PluginManager::GetObjectFileCreateMemoryCallbackForPluginName(
}
Status PluginManager::SaveCore(const lldb::ProcessSP &process_sp,
- const FileSpec &outfile) {
+ const FileSpec &outfile,
+ lldb::SaveCoreStyle &core_style) {
Status error;
auto &instances = GetObjectFileInstances().GetInstances();
for (auto &instance : instances) {
- if (instance.save_core && instance.save_core(process_sp, outfile, error))
+ if (instance.save_core &&
+ instance.save_core(process_sp, outfile, core_style, error))
return error;
}
error.SetErrorString(
@@ -1008,16 +1010,20 @@ PluginManager::GetSymbolVendorCreateCallbackAtIndex(uint32_t idx) {
#pragma mark Trace
-struct TraceInstance : public PluginInstance<TraceCreateInstance> {
- TraceInstance(ConstString name, std::string description,
- CallbackType create_callback, llvm::StringRef schema,
- TraceGetStartCommand get_start_command)
- : PluginInstance<TraceCreateInstance>(name, std::move(description),
- create_callback),
- schema(schema), get_start_command(get_start_command) {}
+struct TraceInstance
+ : public PluginInstance<TraceCreateInstanceForSessionFile> {
+ TraceInstance(
+ ConstString name, std::string description,
+ CallbackType create_callback_for_session_file,
+ TraceCreateInstanceForLiveProcess create_callback_for_live_process,
+ llvm::StringRef schema)
+ : PluginInstance<TraceCreateInstanceForSessionFile>(
+ name, std::move(description), create_callback_for_session_file),
+ schema(schema),
+ create_callback_for_live_process(create_callback_for_live_process) {}
llvm::StringRef schema;
- TraceGetStartCommand get_start_command;
+ TraceCreateInstanceForLiveProcess create_callback_for_live_process;
};
typedef PluginInstances<TraceInstance> TraceInstances;
@@ -1027,37 +1033,40 @@ static TraceInstances &GetTracePluginInstances() {
return g_instances;
}
-bool PluginManager::RegisterPlugin(ConstString name, const char *description,
- TraceCreateInstance create_callback,
- llvm::StringRef schema,
- TraceGetStartCommand get_start_command) {
+bool PluginManager::RegisterPlugin(
+ ConstString name, const char *description,
+ TraceCreateInstanceForSessionFile create_callback_for_session_file,
+ TraceCreateInstanceForLiveProcess create_callback_for_live_process,
+ llvm::StringRef schema) {
return GetTracePluginInstances().RegisterPlugin(
- name, description, create_callback, schema, get_start_command);
+ name, description, create_callback_for_session_file,
+ create_callback_for_live_process, schema);
}
-bool PluginManager::UnregisterPlugin(TraceCreateInstance create_callback) {
- return GetTracePluginInstances().UnregisterPlugin(create_callback);
+bool PluginManager::UnregisterPlugin(
+ TraceCreateInstanceForSessionFile create_callback_for_session_file) {
+ return GetTracePluginInstances().UnregisterPlugin(
+ create_callback_for_session_file);
}
-TraceCreateInstance
+TraceCreateInstanceForSessionFile
PluginManager::GetTraceCreateCallback(ConstString plugin_name) {
return GetTracePluginInstances().GetCallbackForName(plugin_name);
}
-llvm::StringRef PluginManager::GetTraceSchema(ConstString plugin_name) {
+TraceCreateInstanceForLiveProcess
+PluginManager::GetTraceCreateCallbackForLiveProcess(ConstString plugin_name) {
for (const TraceInstance &instance : GetTracePluginInstances().GetInstances())
if (instance.name == plugin_name)
- return instance.schema;
- return llvm::StringRef();
+ return instance.create_callback_for_live_process;
+ return nullptr;
}
-CommandObjectSP
-PluginManager::GetTraceStartCommand(llvm::StringRef plugin_name,
- CommandInterpreter &interpreter) {
+llvm::StringRef PluginManager::GetTraceSchema(ConstString plugin_name) {
for (const TraceInstance &instance : GetTracePluginInstances().GetInstances())
- if (instance.name.GetStringRef() == plugin_name)
- return instance.get_start_command(interpreter);
- return CommandObjectSP();
+ if (instance.name == plugin_name)
+ return instance.schema;
+ return llvm::StringRef();
}
llvm::StringRef PluginManager::GetTraceSchema(size_t index) {
@@ -1067,6 +1076,59 @@ llvm::StringRef PluginManager::GetTraceSchema(size_t index) {
return llvm::StringRef();
}
+#pragma mark TraceExporter
+
+struct TraceExporterInstance
+ : public PluginInstance<TraceExporterCreateInstance> {
+ TraceExporterInstance(
+ ConstString name, std::string description,
+ TraceExporterCreateInstance create_instance,
+ ThreadTraceExportCommandCreator create_thread_trace_export_command)
+ : PluginInstance<TraceExporterCreateInstance>(
+ name, std::move(description), create_instance),
+ create_thread_trace_export_command(create_thread_trace_export_command) {
+ }
+
+ ThreadTraceExportCommandCreator create_thread_trace_export_command;
+};
+
+typedef PluginInstances<TraceExporterInstance> TraceExporterInstances;
+
+static TraceExporterInstances &GetTraceExporterInstances() {
+ static TraceExporterInstances g_instances;
+ return g_instances;
+}
+
+bool PluginManager::RegisterPlugin(
+ ConstString name, const char *description,
+ TraceExporterCreateInstance create_callback,
+ ThreadTraceExportCommandCreator create_thread_trace_export_command) {
+ return GetTraceExporterInstances().RegisterPlugin(
+ name, description, create_callback, create_thread_trace_export_command);
+}
+
+TraceExporterCreateInstance
+PluginManager::GetTraceExporterCreateCallback(ConstString plugin_name) {
+ return GetTraceExporterInstances().GetCallbackForName(plugin_name);
+}
+
+bool PluginManager::UnregisterPlugin(
+ TraceExporterCreateInstance create_callback) {
+ return GetTraceExporterInstances().UnregisterPlugin(create_callback);
+}
+
+ThreadTraceExportCommandCreator
+PluginManager::GetThreadTraceExportCommandCreatorAtIndex(uint32_t index) {
+ if (TraceExporterInstance *instance =
+ GetTraceExporterInstances().GetInstanceAtIndex(index))
+ return instance->create_thread_trace_export_command;
+ return nullptr;
+}
+
+const char *PluginManager::GetTraceExporterPluginNameAtIndex(uint32_t index) {
+ return GetTraceExporterInstances().GetNameAtIndex(index);
+}
+
#pragma mark UnwindAssembly
typedef PluginInstance<UnwindAssemblyCreateInstance> UnwindAssemblyInstance;
diff --git a/lldb/source/Core/Progress.cpp b/lldb/source/Core/Progress.cpp
new file mode 100644
index 000000000000..c54e7774adf3
--- /dev/null
+++ b/lldb/source/Core/Progress.cpp
@@ -0,0 +1,60 @@
+//===-- Progress.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 "lldb/Core/Progress.h"
+
+#include "lldb/Core/Debugger.h"
+#include "lldb/Utility/StreamString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+std::atomic<uint64_t> Progress::g_id(0);
+
+Progress::Progress(std::string title, uint64_t total,
+ lldb_private::Debugger *debugger)
+ : m_title(title), m_id(++g_id), m_completed(0), m_total(total) {
+ assert(total > 0);
+ if (debugger)
+ m_debugger_id = debugger->GetID();
+ std::lock_guard<std::mutex> guard(m_mutex);
+ ReportProgress();
+}
+
+Progress::~Progress() {
+ // Make sure to always report progress completed when this object is
+ // destructed so it indicates the progress dialog/activity should go away.
+ std::lock_guard<std::mutex> guard(m_mutex);
+ if (!m_completed) {
+ m_completed = m_total;
+ ReportProgress();
+ }
+}
+
+void Progress::Increment(uint64_t amount) {
+ if (amount > 0) {
+ std::lock_guard<std::mutex> guard(m_mutex);
+ // Watch out for unsigned overflow and make sure we don't increment too
+ // much and exceed m_total.
+ if (amount > (m_total - m_completed))
+ m_completed = m_total;
+ else
+ m_completed += amount;
+ ReportProgress();
+ }
+}
+
+void Progress::ReportProgress() {
+ if (!m_complete) {
+ // Make sure we only send one notification that indicates the progress is
+ // complete.
+ m_complete = m_completed == m_total;
+ Debugger::ReportProgress(m_id, m_title, m_completed, m_total,
+ m_debugger_id);
+ }
+}
diff --git a/lldb/source/Core/RichManglingContext.cpp b/lldb/source/Core/RichManglingContext.cpp
index 2094d96acd7c..2dcb1407e6c7 100644
--- a/lldb/source/Core/RichManglingContext.cpp
+++ b/lldb/source/Core/RichManglingContext.cpp
@@ -19,7 +19,12 @@ using namespace lldb;
using namespace lldb_private;
// RichManglingContext
-void RichManglingContext::ResetProvider(InfoProvider new_provider) {
+RichManglingContext::~RichManglingContext() {
+ std::free(m_ipd_buf);
+ ResetCxxMethodParser();
+}
+
+void RichManglingContext::ResetCxxMethodParser() {
// If we want to support parsers for other languages some day, we need a
// switch here to delete the correct parser type.
if (m_cxx_method_parser.hasValue()) {
@@ -27,6 +32,10 @@ void RichManglingContext::ResetProvider(InfoProvider new_provider) {
delete get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser);
m_cxx_method_parser.reset();
}
+}
+
+void RichManglingContext::ResetProvider(InfoProvider new_provider) {
+ ResetCxxMethodParser();
assert(new_provider != None && "Only reset to a valid provider");
m_provider = new_provider;
diff --git a/lldb/source/Core/SearchFilter.cpp b/lldb/source/Core/SearchFilter.cpp
index e3327ff5e750..4f9519b5cc9a 100644
--- a/lldb/source/Core/SearchFilter.cpp
+++ b/lldb/source/Core/SearchFilter.cpp
@@ -27,8 +27,8 @@
#include <mutex>
#include <string>
-#include <inttypes.h>
-#include <string.h>
+#include <cinttypes>
+#include <cstring>
namespace lldb_private {
class Address;
diff --git a/lldb/source/Core/Section.cpp b/lldb/source/Core/Section.cpp
index 9bf1c62c5ab8..a5a10141aa64 100644
--- a/lldb/source/Core/Section.cpp
+++ b/lldb/source/Core/Section.cpp
@@ -15,7 +15,7 @@
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/VMRange.h"
-#include <inttypes.h>
+#include <cinttypes>
#include <limits>
#include <utility>
diff --git a/lldb/source/Core/SourceLocationSpec.cpp b/lldb/source/Core/SourceLocationSpec.cpp
new file mode 100644
index 000000000000..610754bb187c
--- /dev/null
+++ b/lldb/source/Core/SourceLocationSpec.cpp
@@ -0,0 +1,81 @@
+//===-- SourceLocationSpec.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 "lldb/Core/SourceLocationSpec.h"
+#include "lldb/Utility/StreamString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SourceLocationSpec::SourceLocationSpec(FileSpec file_spec, uint32_t line,
+ llvm::Optional<uint16_t> column,
+ bool check_inlines, bool exact_match)
+ : m_declaration(file_spec, line,
+ column.getValueOr(LLDB_INVALID_COLUMN_NUMBER)),
+ m_check_inlines(check_inlines), m_exact_match(exact_match) {}
+
+SourceLocationSpec::operator bool() const { return m_declaration.IsValid(); }
+
+bool SourceLocationSpec::operator!() const { return !operator bool(); }
+
+bool SourceLocationSpec::operator==(const SourceLocationSpec &rhs) const {
+ return m_declaration == rhs.m_declaration &&
+ m_check_inlines == rhs.GetCheckInlines() &&
+ m_exact_match == rhs.GetExactMatch();
+}
+
+bool SourceLocationSpec::operator!=(const SourceLocationSpec &rhs) const {
+ return !(*this == rhs);
+}
+
+bool SourceLocationSpec::operator<(const SourceLocationSpec &rhs) const {
+ return SourceLocationSpec::Compare(*this, rhs) < 0;
+}
+
+Stream &lldb_private::operator<<(Stream &s, const SourceLocationSpec &loc) {
+ loc.Dump(s);
+ return s;
+}
+
+int SourceLocationSpec::Compare(const SourceLocationSpec &lhs,
+ const SourceLocationSpec &rhs) {
+ return Declaration::Compare(lhs.m_declaration, rhs.m_declaration);
+}
+
+bool SourceLocationSpec::Equal(const SourceLocationSpec &lhs,
+ const SourceLocationSpec &rhs, bool full) {
+ return full ? lhs == rhs
+ : (lhs.GetFileSpec() == rhs.GetFileSpec() &&
+ lhs.GetLine() == rhs.GetLine());
+}
+
+void SourceLocationSpec::Dump(Stream &s) const {
+ s << "check inlines = " << llvm::toStringRef(m_check_inlines);
+ s << ", exact match = " << llvm::toStringRef(m_exact_match);
+ m_declaration.Dump(&s, true);
+}
+
+std::string SourceLocationSpec::GetString() const {
+ StreamString ss;
+ Dump(ss);
+ return ss.GetString().str();
+}
+
+llvm::Optional<uint32_t> SourceLocationSpec::GetLine() const {
+ uint32_t line = m_declaration.GetLine();
+ if (line == 0 || line == LLDB_INVALID_LINE_NUMBER)
+ return llvm::None;
+ return line;
+}
+
+llvm::Optional<uint16_t> SourceLocationSpec::GetColumn() const {
+ uint16_t column = m_declaration.GetColumn();
+ if (column == LLDB_INVALID_COLUMN_NUMBER)
+ return llvm::None;
+ return column;
+}
diff --git a/lldb/source/Core/SourceManager.cpp b/lldb/source/Core/SourceManager.cpp
index e79fcb48742d..9c1112979c54 100644
--- a/lldb/source/Core/SourceManager.cpp
+++ b/lldb/source/Core/SourceManager.cpp
@@ -35,8 +35,8 @@
#include <memory>
#include <utility>
-#include <assert.h>
-#include <stdio.h>
+#include <cassert>
+#include <cstdio>
namespace lldb_private {
class ExecutionContext;
@@ -61,7 +61,7 @@ SourceManager::SourceManager(const DebuggerSP &debugger_sp)
m_debugger_wp(debugger_sp) {}
// Destructor
-SourceManager::~SourceManager() {}
+SourceManager::~SourceManager() = default;
SourceManager::FileSP SourceManager::GetFile(const FileSpec &file_spec) {
if (!file_spec)
@@ -441,13 +441,17 @@ void SourceManager::File::CommonInitializer(const FileSpec &file_spec,
}
// Try remapping if m_file_spec does not correspond to an existing file.
if (!FileSystem::Instance().Exists(m_file_spec)) {
- FileSpec new_file_spec;
- // Check target specific source remappings first, then fall back to
- // modules objects can have individual path remappings that were
- // detected when the debug info for a module was found. then
- if (target->GetSourcePathMap().FindFile(m_file_spec, new_file_spec) ||
- target->GetImages().FindSourceFile(m_file_spec, new_file_spec)) {
- m_file_spec = new_file_spec;
+ // Check target specific source remappings (i.e., the
+ // target.source-map setting), then fall back to the module
+ // specific remapping (i.e., the .dSYM remapping dictionary).
+ auto remapped = target->GetSourcePathMap().FindFile(m_file_spec);
+ if (!remapped) {
+ FileSpec new_spec;
+ if (target->GetImages().FindSourceFile(m_file_spec, new_spec))
+ remapped = new_spec;
+ }
+ if (remapped) {
+ m_file_spec = *remapped;
m_mod_time = FileSystem::Instance().GetModificationTime(m_file_spec);
}
}
diff --git a/lldb/source/Core/StreamFile.cpp b/lldb/source/Core/StreamFile.cpp
index 43a9df802f7e..2f922fe11440 100644
--- a/lldb/source/Core/StreamFile.cpp
+++ b/lldb/source/Core/StreamFile.cpp
@@ -10,7 +10,7 @@
#include "lldb/Host/FileSystem.h"
#include "lldb/Utility/Log.h"
-#include <stdio.h>
+#include <cstdio>
using namespace lldb;
using namespace lldb_private;
@@ -43,7 +43,7 @@ StreamFile::StreamFile(const char *path, File::OpenOptions options,
}
}
-StreamFile::~StreamFile() {}
+StreamFile::~StreamFile() = default;
void StreamFile::Flush() { m_file_sp->Flush(); }
diff --git a/lldb/source/Core/Value.cpp b/lldb/source/Core/Value.cpp
index cc8f3f4e2615..fb57c0fedf04 100644
--- a/lldb/source/Core/Value.cpp
+++ b/lldb/source/Core/Value.cpp
@@ -33,24 +33,21 @@
#include <memory>
#include <string>
-#include <inttypes.h>
+#include <cinttypes>
using namespace lldb;
using namespace lldb_private;
-Value::Value()
- : m_value(), m_compiler_type(), m_context(nullptr),
- m_value_type(eValueTypeScalar), m_context_type(eContextTypeInvalid),
- m_data_buffer() {}
+Value::Value() : m_value(), m_compiler_type(), m_data_buffer() {}
Value::Value(const Scalar &scalar)
: m_value(scalar), m_compiler_type(), m_context(nullptr),
- m_value_type(eValueTypeScalar), m_context_type(eContextTypeInvalid),
+ m_value_type(ValueType::Scalar), m_context_type(ContextType::Invalid),
m_data_buffer() {}
Value::Value(const void *bytes, int len)
: m_value(), m_compiler_type(), m_context(nullptr),
- m_value_type(eValueTypeHostAddress), m_context_type(eContextTypeInvalid),
+ m_value_type(ValueType::HostAddress), m_context_type(ContextType::Invalid),
m_data_buffer() {
SetBytes(bytes, len);
}
@@ -91,13 +88,13 @@ Value &Value::operator=(const Value &rhs) {
}
void Value::SetBytes(const void *bytes, int len) {
- m_value_type = eValueTypeHostAddress;
+ m_value_type = ValueType::HostAddress;
m_data_buffer.CopyData(bytes, len);
m_value = (uintptr_t)m_data_buffer.GetBytes();
}
void Value::AppendBytes(const void *bytes, int len) {
- m_value_type = eValueTypeHostAddress;
+ m_value_type = ValueType::HostAddress;
m_data_buffer.AppendData(bytes, len);
m_value = (uintptr_t)m_data_buffer.GetBytes();
}
@@ -113,26 +110,27 @@ Value::ValueType Value::GetValueType() const { return m_value_type; }
AddressType Value::GetValueAddressType() const {
switch (m_value_type) {
- case eValueTypeScalar:
+ case ValueType::Invalid:
+ case ValueType::Scalar:
break;
- case eValueTypeLoadAddress:
+ case ValueType::LoadAddress:
return eAddressTypeLoad;
- case eValueTypeFileAddress:
+ case ValueType::FileAddress:
return eAddressTypeFile;
- case eValueTypeHostAddress:
+ case ValueType::HostAddress:
return eAddressTypeHost;
}
return eAddressTypeInvalid;
}
RegisterInfo *Value::GetRegisterInfo() const {
- if (m_context_type == eContextTypeRegisterInfo)
+ if (m_context_type == ContextType::RegisterInfo)
return static_cast<RegisterInfo *>(m_context);
return nullptr;
}
Type *Value::GetType() {
- if (m_context_type == eContextTypeLLDBType)
+ if (m_context_type == ContextType::LLDBType)
return static_cast<Type *>(m_context);
return nullptr;
}
@@ -144,7 +142,9 @@ size_t Value::AppendDataToHostBuffer(const Value &rhs) {
size_t curr_size = m_data_buffer.GetByteSize();
Status error;
switch (rhs.GetValueType()) {
- case eValueTypeScalar: {
+ case ValueType::Invalid:
+ return 0;
+ case ValueType::Scalar: {
const size_t scalar_size = rhs.m_value.GetByteSize();
if (scalar_size > 0) {
const size_t new_size = curr_size + scalar_size;
@@ -156,9 +156,9 @@ size_t Value::AppendDataToHostBuffer(const Value &rhs) {
}
}
} break;
- case eValueTypeFileAddress:
- case eValueTypeLoadAddress:
- case eValueTypeHostAddress: {
+ case ValueType::FileAddress:
+ case ValueType::LoadAddress:
+ case ValueType::HostAddress: {
const uint8_t *src = rhs.GetBuffer().GetBytes();
const size_t src_len = rhs.GetBuffer().GetByteSize();
if (src && src_len > 0) {
@@ -174,7 +174,7 @@ size_t Value::AppendDataToHostBuffer(const Value &rhs) {
}
size_t Value::ResizeData(size_t len) {
- m_value_type = eValueTypeHostAddress;
+ m_value_type = ValueType::HostAddress;
m_data_buffer.SetByteSize(len);
m_value = (uintptr_t)m_data_buffer.GetBytes();
return m_data_buffer.GetByteSize();
@@ -182,12 +182,12 @@ size_t Value::ResizeData(size_t len) {
bool Value::ValueOf(ExecutionContext *exe_ctx) {
switch (m_context_type) {
- case eContextTypeInvalid:
- case eContextTypeRegisterInfo: // RegisterInfo *
- case eContextTypeLLDBType: // Type *
+ case ContextType::Invalid:
+ case ContextType::RegisterInfo: // RegisterInfo *
+ case ContextType::LLDBType: // Type *
break;
- case eContextTypeVariable: // Variable *
+ case ContextType::Variable: // Variable *
ResolveValue(exe_ctx);
return true;
}
@@ -196,7 +196,7 @@ bool Value::ValueOf(ExecutionContext *exe_ctx) {
uint64_t Value::GetValueByteSize(Status *error_ptr, ExecutionContext *exe_ctx) {
switch (m_context_type) {
- case eContextTypeRegisterInfo: // RegisterInfo *
+ case ContextType::RegisterInfo: // RegisterInfo *
if (GetRegisterInfo()) {
if (error_ptr)
error_ptr->Clear();
@@ -204,9 +204,9 @@ uint64_t Value::GetValueByteSize(Status *error_ptr, ExecutionContext *exe_ctx) {
}
break;
- case eContextTypeInvalid:
- case eContextTypeLLDBType: // Type *
- case eContextTypeVariable: // Variable *
+ case ContextType::Invalid:
+ case ContextType::LLDBType: // Type *
+ case ContextType::Variable: // Variable *
{
auto *scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
if (llvm::Optional<uint64_t> size = GetCompilerType().GetByteSize(scope)) {
@@ -225,19 +225,19 @@ uint64_t Value::GetValueByteSize(Status *error_ptr, ExecutionContext *exe_ctx) {
const CompilerType &Value::GetCompilerType() {
if (!m_compiler_type.IsValid()) {
switch (m_context_type) {
- case eContextTypeInvalid:
+ case ContextType::Invalid:
break;
- case eContextTypeRegisterInfo:
+ case ContextType::RegisterInfo:
break; // TODO: Eventually convert into a compiler type?
- case eContextTypeLLDBType: {
+ case ContextType::LLDBType: {
Type *lldb_type = GetType();
if (lldb_type)
m_compiler_type = lldb_type->GetForwardCompilerType();
} break;
- case eContextTypeVariable: {
+ case ContextType::Variable: {
Variable *variable = GetVariable();
if (variable) {
Type *variable_type = variable->GetType();
@@ -257,14 +257,14 @@ void Value::SetCompilerType(const CompilerType &compiler_type) {
lldb::Format Value::GetValueDefaultFormat() {
switch (m_context_type) {
- case eContextTypeRegisterInfo:
+ case ContextType::RegisterInfo:
if (GetRegisterInfo())
return GetRegisterInfo()->format;
break;
- case eContextTypeInvalid:
- case eContextTypeLLDBType:
- case eContextTypeVariable: {
+ case ContextType::Invalid:
+ case ContextType::LLDBType:
+ case ContextType::Variable: {
const CompilerType &ast_type = GetCompilerType();
if (ast_type.IsValid())
return ast_type.GetFormat();
@@ -277,14 +277,16 @@ lldb::Format Value::GetValueDefaultFormat() {
bool Value::GetData(DataExtractor &data) {
switch (m_value_type) {
- case eValueTypeScalar:
+ case ValueType::Invalid:
+ return false;
+ case ValueType::Scalar:
if (m_value.GetData(data))
return true;
break;
- case eValueTypeLoadAddress:
- case eValueTypeFileAddress:
- case eValueTypeHostAddress:
+ case ValueType::LoadAddress:
+ case ValueType::FileAddress:
+ case ValueType::HostAddress:
if (m_data_buffer.GetByteSize()) {
data.SetData(m_data_buffer.GetBytes(), m_data_buffer.GetByteSize(),
data.GetByteOrder());
@@ -312,7 +314,10 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
return error;
switch (m_value_type) {
- case eValueTypeScalar: {
+ case ValueType::Invalid:
+ error.SetErrorString("invalid value");
+ break;
+ case ValueType::Scalar: {
data.SetByteOrder(endian::InlHostByteOrder());
if (ast_type.IsValid())
data.SetAddressByteSize(ast_type.GetPointerByteSize());
@@ -332,7 +337,7 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
error.SetErrorString("extracting data from value failed");
break;
}
- case eValueTypeLoadAddress:
+ case ValueType::LoadAddress:
if (exe_ctx == nullptr) {
error.SetErrorString("can't read load address (no execution context)");
} else {
@@ -369,7 +374,7 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
}
break;
- case eValueTypeFileAddress:
+ case ValueType::FileAddress:
if (exe_ctx == nullptr) {
error.SetErrorString("can't read file address (no execution context)");
} else if (exe_ctx->GetTargetPtr() == nullptr) {
@@ -459,7 +464,7 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
}
break;
- case eValueTypeHostAddress:
+ case ValueType::HostAddress:
address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
address_type = eAddressTypeHost;
if (exe_ctx) {
@@ -517,15 +522,10 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
} else if ((address_type == eAddressTypeLoad) ||
(address_type == eAddressTypeFile)) {
if (file_so_addr.IsValid()) {
- // We have a file address that we were able to translate into a section
- // offset address so we might be able to read this from the object
- // files if we don't have a live process. Lets always try and read from
- // the process if we have one though since we want to read the actual
- // value by setting "prefer_file_cache" to false.
- const bool prefer_file_cache = false;
- if (exe_ctx->GetTargetRef().ReadMemory(file_so_addr, prefer_file_cache,
- dst, byte_size,
- error) != byte_size) {
+ const bool force_live_memory = true;
+ if (exe_ctx->GetTargetRef().ReadMemory(file_so_addr, dst, byte_size,
+ error, force_live_memory) !=
+ byte_size) {
error.SetErrorStringWithFormat(
"read memory from 0x%" PRIx64 " failed", (uint64_t)address);
}
@@ -564,12 +564,13 @@ Scalar &Value::ResolveValue(ExecutionContext *exe_ctx) {
const CompilerType &compiler_type = GetCompilerType();
if (compiler_type.IsValid()) {
switch (m_value_type) {
- case eValueTypeScalar: // raw scalar value
+ case ValueType::Invalid:
+ case ValueType::Scalar: // raw scalar value
break;
- case eValueTypeFileAddress:
- case eValueTypeLoadAddress: // load address value
- case eValueTypeHostAddress: // host address value (for memory in the process
+ case ValueType::FileAddress:
+ case ValueType::LoadAddress: // load address value
+ case ValueType::HostAddress: // host address value (for memory in the process
// that is using liblldb)
{
DataExtractor data;
@@ -581,17 +582,17 @@ Scalar &Value::ResolveValue(ExecutionContext *exe_ctx) {
data, 0, data.GetByteSize(), scalar,
exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr)) {
m_value = scalar;
- m_value_type = eValueTypeScalar;
+ m_value_type = ValueType::Scalar;
} else {
if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes()) {
m_value.Clear();
- m_value_type = eValueTypeScalar;
+ m_value_type = ValueType::Scalar;
}
}
} else {
if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes()) {
m_value.Clear();
- m_value_type = eValueTypeScalar;
+ m_value_type = ValueType::Scalar;
}
}
} break;
@@ -601,7 +602,7 @@ Scalar &Value::ResolveValue(ExecutionContext *exe_ctx) {
}
Variable *Value::GetVariable() {
- if (m_context_type == eContextTypeVariable)
+ if (m_context_type == ContextType::Variable)
return static_cast<Variable *>(m_context);
return nullptr;
}
@@ -609,42 +610,44 @@ Variable *Value::GetVariable() {
void Value::Clear() {
m_value.Clear();
m_compiler_type.Clear();
- m_value_type = eValueTypeScalar;
+ m_value_type = ValueType::Scalar;
m_context = nullptr;
- m_context_type = eContextTypeInvalid;
+ m_context_type = ContextType::Invalid;
m_data_buffer.Clear();
}
const char *Value::GetValueTypeAsCString(ValueType value_type) {
switch (value_type) {
- case eValueTypeScalar:
+ case ValueType::Invalid:
+ return "invalid";
+ case ValueType::Scalar:
return "scalar";
- case eValueTypeFileAddress:
+ case ValueType::FileAddress:
return "file address";
- case eValueTypeLoadAddress:
+ case ValueType::LoadAddress:
return "load address";
- case eValueTypeHostAddress:
+ case ValueType::HostAddress:
return "host address";
};
- return "???";
+ llvm_unreachable("enum cases exhausted.");
}
const char *Value::GetContextTypeAsCString(ContextType context_type) {
switch (context_type) {
- case eContextTypeInvalid:
+ case ContextType::Invalid:
return "invalid";
- case eContextTypeRegisterInfo:
+ case ContextType::RegisterInfo:
return "RegisterInfo *";
- case eContextTypeLLDBType:
+ case ContextType::LLDBType:
return "Type *";
- case eContextTypeVariable:
+ case ContextType::Variable:
return "Variable *";
};
- return "???";
+ llvm_unreachable("enum cases exhausted.");
}
void Value::ConvertToLoadAddress(Module *module, Target *target) {
- if (!module || !target || (GetValueType() != eValueTypeFileAddress))
+ if (!module || !target || (GetValueType() != ValueType::FileAddress))
return;
lldb::addr_t file_addr = GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
@@ -658,7 +661,7 @@ void Value::ConvertToLoadAddress(Module *module, Target *target) {
if (load_addr == LLDB_INVALID_ADDRESS)
return;
- SetValueType(Value::eValueTypeLoadAddress);
+ SetValueType(Value::ValueType::LoadAddress);
GetScalar() = load_addr;
}
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index da90092336d6..9c1ba99da1d0 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -9,6 +9,7 @@
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/Address.h"
+#include "lldb/Core/Declaration.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ValueObjectCast.h"
#include "lldb/Core/ValueObjectChild.h"
@@ -27,7 +28,6 @@
#include "lldb/Host/Config.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Symbol/Declaration.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/Variable.h"
@@ -57,10 +57,12 @@
#include <memory>
#include <tuple>
-#include <assert.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <string.h>
+#include <cassert>
+#include <cinttypes>
+#include <cstdio>
+#include <cstring>
+
+#include <lldb/Core/ValueObject.h>
namespace lldb_private {
class ExecutionContextScope;
@@ -76,27 +78,10 @@ static user_id_t g_value_obj_uid = 0;
// ValueObject constructor
ValueObject::ValueObject(ValueObject &parent)
- : UserID(++g_value_obj_uid), // Unique identifier for every value object
- 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_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),
- m_language_flags(0), m_value_is_valid(false), m_value_did_change(false),
- m_children_count_valid(false), m_old_value_valid(false),
- m_is_deref_of_parent(false), m_is_array_item_for_pointer(false),
- m_is_bitfield_for_scalar(false), m_is_child_at_offset(false),
- m_is_getting_summary(false),
- m_did_calculate_complete_objc_class_type(false),
- m_is_synthetic_children_generated(
- parent.m_is_synthetic_children_generated) {
+ : m_parent(&parent), m_update_point(parent.GetUpdatePoint()),
+ m_manager(parent.GetManager()), m_id(++g_value_obj_uid) {
+ m_flags.m_is_synthetic_children_generated =
+ parent.m_flags.m_is_synthetic_children_generated;
m_data.SetByteOrder(parent.GetDataExtractor().GetByteOrder());
m_data.SetAddressByteSize(parent.GetDataExtractor().GetAddressByteSize());
m_manager->ManageObject(this);
@@ -106,26 +91,9 @@ ValueObject::ValueObject(ValueObject &parent)
ValueObject::ValueObject(ExecutionContextScope *exe_scope,
ValueObjectManager &manager,
AddressType child_ptr_or_ref_addr_type)
- : UserID(++g_value_obj_uid), // Unique identifier for every value object
- 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_manager(&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_user_id_of_forced_summary(),
+ : m_update_point(exe_scope), m_manager(&manager),
m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type),
- m_value_checksum(),
- m_preferred_display_language(lldb::eLanguageTypeUnknown),
- m_language_flags(0), m_value_is_valid(false), m_value_did_change(false),
- m_children_count_valid(false), m_old_value_valid(false),
- m_is_deref_of_parent(false), m_is_array_item_for_pointer(false),
- m_is_bitfield_for_scalar(false), m_is_child_at_offset(false),
- m_is_getting_summary(false),
- m_did_calculate_complete_objc_class_type(false),
- m_is_synthetic_children_generated(false) {
+ m_id(++g_value_obj_uid) {
if (exe_scope) {
TargetSP target_sp(exe_scope->CalculateTarget());
if (target_sp) {
@@ -138,7 +106,7 @@ ValueObject::ValueObject(ExecutionContextScope *exe_scope,
}
// Destructor
-ValueObject::~ValueObject() {}
+ValueObject::~ValueObject() = default;
bool ValueObject::UpdateValueIfNeeded(bool update_format) {
@@ -170,9 +138,9 @@ bool ValueObject::UpdateValueIfNeeded(bool update_format) {
// Save the old value using swap to avoid a string copy which also will
// clear our m_value_str
if (m_value_str.empty()) {
- m_old_value_valid = false;
+ m_flags.m_old_value_valid = false;
} else {
- m_old_value_valid = true;
+ m_flags.m_old_value_valid = true;
m_old_value_str.swap(m_value_str);
ClearUserVisibleData(eClearUserVisibleDataItemsValue);
}
@@ -215,7 +183,7 @@ bool ValueObject::UpdateValueIfNeeded(bool update_format) {
if (first_update)
SetValueDidChange(false);
- else if (!m_value_did_change && !success) {
+ else if (!m_flags.m_value_did_change && !success) {
// The value wasn't gotten successfully, so we mark this as changed if
// the value used to be valid and now isn't
SetValueDidChange(value_was_valid);
@@ -266,8 +234,8 @@ void ValueObject::SetNeedsUpdate() {
}
void ValueObject::ClearDynamicTypeInformation() {
- m_children_count_valid = false;
- m_did_calculate_complete_objc_class_type = false;
+ m_flags.m_children_count_valid = false;
+ m_flags.m_did_calculate_complete_objc_class_type = false;
m_last_format_mgr_revision = 0;
m_override_type = CompilerType();
SetValueFormat(lldb::TypeFormatImplSP());
@@ -278,14 +246,14 @@ void ValueObject::ClearDynamicTypeInformation() {
CompilerType ValueObject::MaybeCalculateCompleteType() {
CompilerType compiler_type(GetCompilerTypeImpl());
- if (m_did_calculate_complete_objc_class_type) {
+ if (m_flags.m_did_calculate_complete_objc_class_type) {
if (m_override_type.IsValid())
return m_override_type;
else
return compiler_type;
}
- m_did_calculate_complete_objc_class_type = true;
+ m_flags.m_did_calculate_complete_objc_class_type = true;
ProcessSP process_sp(
GetUpdatePoint().GetExecutionContextRef().GetProcessSP());
@@ -305,11 +273,7 @@ CompilerType ValueObject::MaybeCalculateCompleteType() {
return compiler_type;
}
-CompilerType ValueObject::GetCompilerType() {
- return MaybeCalculateCompleteType();
-}
-TypeImpl ValueObject::GetTypeImpl() { return TypeImpl(GetCompilerType()); }
DataExtractor &ValueObject::GetDataExtractor() {
UpdateValueIfNeeded(false);
@@ -321,12 +285,6 @@ const Status &ValueObject::GetError() {
return m_error;
}
-ConstString ValueObject::GetName() const { return m_name; }
-
-const char *ValueObject::GetLocationAsCString() {
- return GetLocationAsCStringImpl(m_value, m_data);
-}
-
const char *ValueObject::GetLocationAsCStringImpl(const Value &value,
const DataExtractor &data) {
if (UpdateValueIfNeeded(false)) {
@@ -336,8 +294,11 @@ const char *ValueObject::GetLocationAsCStringImpl(const Value &value,
Value::ValueType value_type = value.GetValueType();
switch (value_type) {
- case Value::eValueTypeScalar:
- if (value.GetContextType() == Value::eContextTypeRegisterInfo) {
+ case Value::ValueType::Invalid:
+ m_location_str = "invalid";
+ break;
+ case Value::ValueType::Scalar:
+ if (value.GetContextType() == Value::ContextType::RegisterInfo) {
RegisterInfo *reg_info = value.GetRegisterInfo();
if (reg_info) {
if (reg_info->name)
@@ -354,9 +315,9 @@ const char *ValueObject::GetLocationAsCStringImpl(const Value &value,
m_location_str = "scalar";
break;
- case Value::eValueTypeLoadAddress:
- case Value::eValueTypeFileAddress:
- case Value::eValueTypeHostAddress: {
+ case Value::ValueType::LoadAddress:
+ case Value::ValueType::FileAddress:
+ case Value::ValueType::HostAddress: {
uint32_t addr_nibble_size = data.GetAddressByteSize() * 2;
sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size,
value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS));
@@ -368,10 +329,6 @@ const char *ValueObject::GetLocationAsCStringImpl(const Value &value,
return m_location_str.c_str();
}
-Value &ValueObject::GetValue() { return m_value; }
-
-const Value &ValueObject::GetValue() const { return m_value; }
-
bool ValueObject::ResolveValue(Scalar &scalar) {
if (UpdateValueIfNeeded(
false)) // make sure that you are up to date before returning anything
@@ -415,16 +372,6 @@ bool ValueObject::IsLogicalTrue(Status &error) {
return ret;
}
-bool ValueObject::GetValueIsValid() const { return m_value_is_valid; }
-
-void ValueObject::SetValueIsValid(bool b) { m_value_is_valid = b; }
-
-bool ValueObject::GetValueDidChange() { return m_value_did_change; }
-
-void ValueObject::SetValueDidChange(bool value_changed) {
- m_value_did_change = value_changed;
-}
-
ValueObjectSP ValueObject::GetChildAtIndex(size_t idx, bool can_create) {
ValueObjectSP child_sp;
// We may need to update our value if we are dynamic
@@ -550,14 +497,14 @@ size_t ValueObject::GetNumChildren(uint32_t max) {
UpdateValueIfNeeded();
if (max < UINT32_MAX) {
- if (m_children_count_valid) {
+ if (m_flags.m_children_count_valid) {
size_t children_count = m_children.GetChildrenCount();
return children_count <= max ? children_count : max;
} else
return CalculateNumChildren(max);
}
- if (!m_children_count_valid) {
+ if (!m_flags.m_children_count_valid) {
SetNumChildren(CalculateNumChildren());
}
return m_children.GetChildrenCount();
@@ -577,12 +524,10 @@ bool ValueObject::MightHaveChildren() {
// Should only be called by ValueObject::GetNumChildren()
void ValueObject::SetNumChildren(size_t num_children) {
- m_children_count_valid = true;
+ m_flags.m_children_count_valid = true;
m_children.SetChildrenCount(num_children);
}
-void ValueObject::SetName(ConstString name) { m_name = name; }
-
ValueObject *ValueObject::CreateChildAtIndex(size_t idx,
bool synthetic_array_member,
int32_t synthetic_index) {
@@ -651,10 +596,10 @@ bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
// ideally we would like to bail out if passing NULL, but if we do so we end
// up not providing the summary for function pointers anymore
- if (/*summary_ptr == NULL ||*/ m_is_getting_summary)
+ if (/*summary_ptr == NULL ||*/ m_flags.m_is_getting_summary)
return false;
- m_is_getting_summary = true;
+ m_flags.m_is_getting_summary = true;
TypeSummaryOptions actual_options(options);
@@ -677,7 +622,7 @@ bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
// up-to-date (e.g. ${svar%#})
summary_ptr->FormatObject(this, destination, actual_options);
}
- m_is_getting_summary = false;
+ m_flags.m_is_getting_summary = false;
return !destination.empty();
}
@@ -776,7 +721,7 @@ size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx,
if (target) {
heap_buf_ptr->SetByteSize(bytes);
size_t bytes_read = target->ReadMemory(
- so_addr, false, heap_buf_ptr->GetBytes(), bytes, error);
+ so_addr, heap_buf_ptr->GetBytes(), bytes, error, true);
if (error.Success()) {
data.SetData(data_sp);
return bytes_read;
@@ -852,7 +797,10 @@ bool ValueObject::SetData(DataExtractor &data, Status &error) {
Value::ValueType value_type = m_value.GetValueType();
switch (value_type) {
- case Value::eValueTypeScalar: {
+ case Value::ValueType::Invalid:
+ error.SetErrorString("invalid location");
+ return false;
+ case Value::ValueType::Scalar: {
Status set_error =
m_value.GetScalar().SetValueFromData(data, encoding, byte_size);
@@ -862,7 +810,7 @@ bool ValueObject::SetData(DataExtractor &data, Status &error) {
return false;
}
} break;
- case Value::eValueTypeLoadAddress: {
+ case Value::ValueType::LoadAddress: {
// If it is a load address, then the scalar value is the storage location
// of the data, and we have to shove this value down to that load location.
ExecutionContext exe_ctx(GetExecutionContextRef());
@@ -879,7 +827,7 @@ bool ValueObject::SetData(DataExtractor &data, Status &error) {
}
}
} break;
- case Value::eValueTypeHostAddress: {
+ case Value::ValueType::HostAddress: {
// If it is a host address, then we stuff the scalar as a DataBuffer into
// the Value's data.
DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
@@ -889,7 +837,7 @@ bool ValueObject::SetData(DataExtractor &data, Status &error) {
byte_size, m_data.GetByteOrder());
m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
} break;
- case Value::eValueTypeFileAddress:
+ case Value::ValueType::FileAddress:
break;
}
@@ -942,7 +890,7 @@ ValueObject::ReadPointedString(lldb::DataBufferSP &buffer_sp, Status &error,
if (is_array) {
// We have an array
uint64_t array_size = 0;
- if (compiler_type.IsArrayType(nullptr, &array_size, nullptr)) {
+ if (compiler_type.IsArrayType(nullptr, &array_size)) {
cstr_len = array_size;
if (cstr_len > max_length) {
capped_data = true;
@@ -1104,10 +1052,10 @@ const char *ValueObject::GetValueAsCString() {
if (m_type_format_sp)
format_sp = m_type_format_sp;
else {
- if (m_is_bitfield_for_scalar)
+ if (m_flags.m_is_bitfield_for_scalar)
my_format = eFormatUnsigned;
else {
- if (m_value.GetContextType() == Value::eContextTypeRegisterInfo) {
+ if (m_value.GetContextType() == Value::ContextType::RegisterInfo) {
const RegisterInfo *reg_info = m_value.GetRegisterInfo();
if (reg_info)
my_format = reg_info->format;
@@ -1122,7 +1070,7 @@ const char *ValueObject::GetValueAsCString() {
if (!format_sp)
format_sp = std::make_shared<TypeFormatImpl_Format>(my_format);
if (GetValueAsCString(*format_sp.get(), m_value_str)) {
- if (!m_value_did_change && m_old_value_valid) {
+ if (!m_flags.m_value_did_change && m_flags.m_old_value_valid) {
// The value was gotten successfully, so we consider the value as
// changed if the value string differs
SetValueDidChange(m_old_value_str != m_value_str);
@@ -1455,7 +1403,9 @@ addr_t ValueObject::GetAddressOf(bool scalar_is_load_address,
return LLDB_INVALID_ADDRESS;
switch (m_value.GetValueType()) {
- case Value::eValueTypeScalar:
+ case Value::ValueType::Invalid:
+ return LLDB_INVALID_ADDRESS;
+ case Value::ValueType::Scalar:
if (scalar_is_load_address) {
if (address_type)
*address_type = eAddressTypeLoad;
@@ -1463,13 +1413,13 @@ addr_t ValueObject::GetAddressOf(bool scalar_is_load_address,
}
break;
- case Value::eValueTypeLoadAddress:
- case Value::eValueTypeFileAddress: {
+ case Value::ValueType::LoadAddress:
+ case Value::ValueType::FileAddress: {
if (address_type)
*address_type = m_value.GetValueAddressType();
return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
} break;
- case Value::eValueTypeHostAddress: {
+ case Value::ValueType::HostAddress: {
if (address_type)
*address_type = m_value.GetValueAddressType();
return LLDB_INVALID_ADDRESS;
@@ -1489,13 +1439,15 @@ addr_t ValueObject::GetPointerValue(AddressType *address_type) {
return address;
switch (m_value.GetValueType()) {
- case Value::eValueTypeScalar:
+ case Value::ValueType::Invalid:
+ return LLDB_INVALID_ADDRESS;
+ case Value::ValueType::Scalar:
address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
break;
- case Value::eValueTypeHostAddress:
- case Value::eValueTypeLoadAddress:
- case Value::eValueTypeFileAddress: {
+ case Value::ValueType::HostAddress:
+ case Value::ValueType::LoadAddress:
+ case Value::ValueType::FileAddress: {
lldb::offset_t data_offset = 0;
address = m_data.GetAddress(&data_offset);
} break;
@@ -1523,7 +1475,7 @@ bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {
Value::ValueType value_type = m_value.GetValueType();
- if (value_type == Value::eValueTypeScalar) {
+ if (value_type == Value::ValueType::Scalar) {
// If the value is already a scalar, then let the scalar change itself:
m_value.GetScalar().SetValueFromCString(value_str, encoding, byte_size);
} else if (byte_size <= 16) {
@@ -1534,7 +1486,7 @@ bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {
error = new_scalar.SetValueFromCString(value_str, encoding, byte_size);
if (error.Success()) {
switch (value_type) {
- case Value::eValueTypeLoadAddress: {
+ case Value::ValueType::LoadAddress: {
// If it is a load address, then the scalar value is the storage
// location of the data, and we have to shove this value down to that
// load location.
@@ -1553,7 +1505,7 @@ bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {
}
}
} break;
- case Value::eValueTypeHostAddress: {
+ case Value::ValueType::HostAddress: {
// If it is a host address, then we stuff the scalar as a DataBuffer
// into the Value's data.
DataExtractor new_data;
@@ -1570,8 +1522,11 @@ bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {
m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
} break;
- case Value::eValueTypeFileAddress:
- case Value::eValueTypeScalar:
+ case Value::ValueType::Invalid:
+ error.SetErrorString("invalid location");
+ return false;
+ case Value::ValueType::FileAddress:
+ case Value::ValueType::Scalar:
break;
}
} else {
@@ -1594,20 +1549,6 @@ bool ValueObject::GetDeclaration(Declaration &decl) {
return false;
}
-ConstString ValueObject::GetTypeName() {
- return GetCompilerType().GetTypeName();
-}
-
-ConstString ValueObject::GetDisplayTypeName() { return GetTypeName(); }
-
-ConstString ValueObject::GetQualifiedTypeName() {
- return GetCompilerType().GetTypeName();
-}
-
-LanguageType ValueObject::GetObjectRuntimeLanguage() {
- return GetCompilerType().GetMinimumLanguage();
-}
-
void ValueObject::AddSyntheticChild(ConstString key,
ValueObject *valobj) {
m_synthetic_children[key] = valobj;
@@ -1622,27 +1563,6 @@ ValueObjectSP ValueObject::GetSyntheticChild(ConstString key) const {
return synthetic_child_sp;
}
-uint32_t
-ValueObject::GetTypeInfo(CompilerType *pointee_or_element_compiler_type) {
- return GetCompilerType().GetTypeInfo(pointee_or_element_compiler_type);
-}
-
-bool ValueObject::IsPointerType() { return GetCompilerType().IsPointerType(); }
-
-bool ValueObject::IsArrayType() {
- return GetCompilerType().IsArrayType(nullptr, nullptr, nullptr);
-}
-
-bool ValueObject::IsScalarType() { return GetCompilerType().IsScalarType(); }
-
-bool ValueObject::IsIntegerType(bool &is_signed) {
- return GetCompilerType().IsIntegerType(is_signed);
-}
-
-bool ValueObject::IsPointerOrReferenceType() {
- return GetCompilerType().IsPointerOrReferenceType();
-}
-
bool ValueObject::IsPossibleDynamicType() {
ExecutionContext exe_ctx(GetExecutionContextRef());
Process *process = exe_ctx.GetProcessPtr();
@@ -1657,7 +1577,7 @@ bool ValueObject::IsRuntimeSupportValue() {
if (!process)
return false;
- // We trust the the compiler did the right thing and marked runtime support
+ // We trust that the compiler did the right thing and marked runtime support
// values as artificial.
if (!GetVariable() || !GetVariable()->IsArtificial())
return false;
@@ -1712,7 +1632,7 @@ ValueObjectSP ValueObject::GetSyntheticArrayMember(size_t index,
AddSyntheticChild(index_const_str, synthetic_child);
synthetic_child_sp = synthetic_child->GetSP();
synthetic_child_sp->SetName(ConstString(index_str));
- synthetic_child_sp->m_is_array_item_for_pointer = true;
+ synthetic_child_sp->m_flags.m_is_array_item_for_pointer = true;
}
}
}
@@ -1746,7 +1666,7 @@ ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
AddSyntheticChild(index_const_str, synthetic_child);
synthetic_child_sp = synthetic_child->GetSP();
synthetic_child_sp->SetName(ConstString(index_str));
- synthetic_child_sp->m_is_bitfield_for_scalar = true;
+ synthetic_child_sp->m_flags.m_is_bitfield_for_scalar = true;
}
}
}
@@ -1785,7 +1705,7 @@ ValueObjectSP ValueObject::GetSyntheticChildAtOffset(
AddSyntheticChild(name_const_str, synthetic_child);
synthetic_child_sp = synthetic_child->GetSP();
synthetic_child_sp->SetName(name_const_str);
- synthetic_child_sp->m_is_child_at_offset = true;
+ synthetic_child_sp->m_flags.m_is_child_at_offset = true;
}
return synthetic_child_sp;
}
@@ -1922,10 +1842,6 @@ ValueObjectSP ValueObject::GetDynamicValue(DynamicValueType use_dynamic) {
return ValueObjectSP();
}
-ValueObjectSP ValueObject::GetStaticValue() { return GetSP(); }
-
-lldb::ValueObjectSP ValueObject::GetNonSyntheticValue() { return GetSP(); }
-
ValueObjectSP ValueObject::GetSyntheticValue() {
CalculateSyntheticValue();
@@ -1977,10 +1893,10 @@ void ValueObject::GetExpressionPath(Stream &s,
// sometimes they are consed up in ways that don't make sense from an
// underlying language/API standpoint. So, use a special code path here to
// return something that can hopefully be used in expression
- if (m_is_synthetic_children_generated) {
+ if (m_flags.m_is_synthetic_children_generated) {
UpdateValueIfNeeded();
- if (m_value.GetValueType() == Value::eValueTypeLoadAddress) {
+ if (m_value.GetValueType() == Value::ValueType::LoadAddress) {
if (IsPointerOrReferenceType()) {
s.Printf("((%s)0x%" PRIx64 ")", GetTypeName().AsCString("void"),
GetValueAsUnsigned(0));
@@ -2025,7 +1941,7 @@ void ValueObject::GetExpressionPath(Stream &s,
// if we are a deref_of_parent just because we are synthetic array members
// made up to allow ptr[%d] syntax to work in variable printing, then add our
// name ([%d]) to the expression path
- if (m_is_array_item_for_pointer &&
+ if (m_flags.m_is_array_item_for_pointer &&
epformat == eGetExpressionPathFormatHonorPointers)
s.PutCString(m_name.GetStringRef());
@@ -2640,21 +2556,6 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
}
}
-void ValueObject::LogValueObject(Log *log) {
- if (log)
- return LogValueObject(log, DumpValueObjectOptions(*this));
-}
-
-void ValueObject::LogValueObject(Log *log,
- const DumpValueObjectOptions &options) {
- if (log) {
- StreamString s;
- Dump(s, options);
- if (s.GetSize())
- log->PutCString(s.GetData());
- }
-}
-
void ValueObject::Dump(Stream &s) { Dump(s, DumpValueObjectOptions(*this)); }
void ValueObject::Dump(Stream &s, const DumpValueObjectOptions &options) {
@@ -2895,8 +2796,7 @@ ValueObjectSP ValueObject::CastPointerType(const char *name, TypeSP &type_sp) {
return valobj_sp;
}
-ValueObject::EvaluationPoint::EvaluationPoint()
- : m_mod_id(), m_exe_ctx_ref(), m_needs_update(true) {}
+ValueObject::EvaluationPoint::EvaluationPoint() : m_mod_id(), m_exe_ctx_ref() {}
ValueObject::EvaluationPoint::EvaluationPoint(ExecutionContextScope *exe_scope,
bool use_selected)
@@ -2939,7 +2839,7 @@ ValueObject::EvaluationPoint::EvaluationPoint(
const ValueObject::EvaluationPoint &rhs)
: m_mod_id(), m_exe_ctx_ref(rhs.m_exe_ctx_ref), m_needs_update(true) {}
-ValueObject::EvaluationPoint::~EvaluationPoint() {}
+ValueObject::EvaluationPoint::~EvaluationPoint() = default;
// This function checks the EvaluationPoint against the current process state.
// If the current state matches the evaluation point, or the evaluation point
@@ -3093,7 +2993,7 @@ lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress(
exe_ctx.GetAddressByteSize()));
if (ptr_result_valobj_sp) {
ptr_result_valobj_sp->GetValue().SetValueType(
- Value::eValueTypeLoadAddress);
+ Value::ValueType::LoadAddress);
Status err;
ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference(err);
if (ptr_result_valobj_sp && !name.empty())
@@ -3192,10 +3092,6 @@ lldb::LanguageType ValueObject::GetPreferredDisplayLanguage() {
return (m_preferred_display_language = type); // only compute it once
}
-void ValueObject::SetPreferredDisplayLanguage(lldb::LanguageType lt) {
- m_preferred_display_language = lt;
-}
-
void ValueObject::SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType lt) {
if (m_preferred_display_language == lldb::eLanguageTypeUnknown)
SetPreferredDisplayLanguage(lt);
@@ -3209,7 +3105,7 @@ bool ValueObject::CanProvideValue() {
return (!type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue));
}
-bool ValueObject::IsChecksumEmpty() { return m_value_checksum.empty(); }
+
ValueObjectSP ValueObject::Persist() {
if (!UpdateValueIfNeeded())
@@ -3238,109 +3134,3 @@ ValueObjectSP ValueObject::Persist() {
return persistent_var_sp->GetValueObject();
}
-
-bool ValueObject::IsSyntheticChildrenGenerated() {
- return m_is_synthetic_children_generated;
-}
-
-void ValueObject::SetSyntheticChildrenGenerated(bool b) {
- m_is_synthetic_children_generated = b;
-}
-
-uint64_t ValueObject::GetLanguageFlags() { return m_language_flags; }
-
-void ValueObject::SetLanguageFlags(uint64_t flags) { m_language_flags = flags; }
-
-ValueObjectManager::ValueObjectManager(lldb::ValueObjectSP in_valobj_sp,
- lldb::DynamicValueType use_dynamic,
- bool use_synthetic) : m_root_valobj_sp(),
- m_user_valobj_sp(), m_use_dynamic(use_dynamic), m_stop_id(UINT32_MAX),
- m_use_synthetic(use_synthetic) {
- if (!in_valobj_sp)
- return;
- // If the user passes in a value object that is dynamic or synthetic, then
- // water it down to the static type.
- m_root_valobj_sp = in_valobj_sp->GetQualifiedRepresentationIfAvailable(lldb::eNoDynamicValues, false);
-}
-
-bool ValueObjectManager::IsValid() const {
- if (!m_root_valobj_sp)
- return false;
- lldb::TargetSP target_sp = GetTargetSP();
- if (target_sp)
- return target_sp->IsValid();
- return false;
-}
-
-lldb::ValueObjectSP ValueObjectManager::GetSP() {
- lldb::ProcessSP process_sp = GetProcessSP();
- if (!process_sp)
- return lldb::ValueObjectSP();
-
- const uint32_t current_stop_id = process_sp->GetLastNaturalStopID();
- if (current_stop_id == m_stop_id)
- return m_user_valobj_sp;
-
- m_stop_id = current_stop_id;
-
- if (!m_root_valobj_sp) {
- m_user_valobj_sp.reset();
- return m_root_valobj_sp;
- }
-
- m_user_valobj_sp = m_root_valobj_sp;
-
- if (m_use_dynamic != lldb::eNoDynamicValues) {
- lldb::ValueObjectSP dynamic_sp = m_user_valobj_sp->GetDynamicValue(m_use_dynamic);
- if (dynamic_sp)
- m_user_valobj_sp = dynamic_sp;
- }
-
- if (m_use_synthetic) {
- lldb::ValueObjectSP synthetic_sp = m_user_valobj_sp->GetSyntheticValue();
- if (synthetic_sp)
- m_user_valobj_sp = synthetic_sp;
- }
-
- return m_user_valobj_sp;
-}
-
-void ValueObjectManager::SetUseDynamic(lldb::DynamicValueType use_dynamic) {
- if (use_dynamic != m_use_dynamic) {
- m_use_dynamic = use_dynamic;
- m_user_valobj_sp.reset();
- m_stop_id = UINT32_MAX;
- }
-}
-
-void ValueObjectManager::SetUseSynthetic(bool use_synthetic) {
- if (m_use_synthetic != use_synthetic) {
- m_use_synthetic = use_synthetic;
- m_user_valobj_sp.reset();
- m_stop_id = UINT32_MAX;
- }
-}
-
-lldb::TargetSP ValueObjectManager::GetTargetSP() const {
- if (!m_root_valobj_sp)
- return m_root_valobj_sp->GetTargetSP();
- return lldb::TargetSP();
-}
-
-lldb::ProcessSP ValueObjectManager::GetProcessSP() const {
- if (m_root_valobj_sp)
- return m_root_valobj_sp->GetProcessSP();
- return lldb::ProcessSP();
-}
-
-lldb::ThreadSP ValueObjectManager::GetThreadSP() const {
- if (m_root_valobj_sp)
- return m_root_valobj_sp->GetThreadSP();
- return lldb::ThreadSP();
-}
-
-lldb::StackFrameSP ValueObjectManager::GetFrameSP() const {
- if (m_root_valobj_sp)
- return m_root_valobj_sp->GetFrameSP();
- return lldb::StackFrameSP();
-}
diff --git a/lldb/source/Core/ValueObjectCast.cpp b/lldb/source/Core/ValueObjectCast.cpp
index 7b6d3591faf4..9f803912d0ca 100644
--- a/lldb/source/Core/ValueObjectCast.cpp
+++ b/lldb/source/Core/ValueObjectCast.cpp
@@ -36,7 +36,7 @@ ValueObjectCast::ValueObjectCast(ValueObject &parent, ConstString name,
m_value.SetCompilerType(cast_type);
}
-ValueObjectCast::~ValueObjectCast() {}
+ValueObjectCast::~ValueObjectCast() = default;
CompilerType ValueObjectCast::GetCompilerTypeImpl() { return m_cast_type; }
diff --git a/lldb/source/Core/ValueObjectChild.cpp b/lldb/source/Core/ValueObjectChild.cpp
index 34baa19f0a24..a2beeb0bcdeb 100644
--- a/lldb/source/Core/ValueObjectChild.cpp
+++ b/lldb/source/Core/ValueObjectChild.cpp
@@ -21,8 +21,8 @@
#include <memory>
#include <vector>
-#include <stdio.h>
-#include <string.h>
+#include <cstdio>
+#include <cstring>
using namespace lldb_private;
@@ -43,7 +43,7 @@ ValueObjectChild::ValueObjectChild(
SetLanguageFlags(language_flags);
}
-ValueObjectChild::~ValueObjectChild() {}
+ValueObjectChild::~ValueObjectChild() = default;
lldb::ValueType ValueObjectChild::GetValueType() const {
return m_parent->GetValueType();
@@ -125,28 +125,30 @@ bool ValueObjectChild::UpdateValue() {
case eAddressTypeFile: {
lldb::ProcessSP process_sp(GetProcessSP());
if (process_sp && process_sp->IsAlive())
- m_value.SetValueType(Value::eValueTypeLoadAddress);
+ m_value.SetValueType(Value::ValueType::LoadAddress);
else
- m_value.SetValueType(Value::eValueTypeFileAddress);
+ m_value.SetValueType(Value::ValueType::FileAddress);
} break;
case eAddressTypeLoad:
m_value.SetValueType(is_instance_ptr_base
- ? Value::eValueTypeScalar
- : Value::eValueTypeLoadAddress);
+ ? Value::ValueType::Scalar
+ : Value::ValueType::LoadAddress);
break;
case eAddressTypeHost:
- m_value.SetValueType(Value::eValueTypeHostAddress);
+ m_value.SetValueType(Value::ValueType::HostAddress);
break;
case eAddressTypeInvalid:
// TODO: does this make sense?
- m_value.SetValueType(Value::eValueTypeScalar);
+ m_value.SetValueType(Value::ValueType::Scalar);
break;
}
}
switch (m_value.GetValueType()) {
- case Value::eValueTypeLoadAddress:
- case Value::eValueTypeFileAddress:
- case Value::eValueTypeHostAddress: {
+ case Value::ValueType::Invalid:
+ break;
+ case Value::ValueType::LoadAddress:
+ case Value::ValueType::FileAddress:
+ case Value::ValueType::HostAddress: {
lldb::addr_t addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
if (addr == LLDB_INVALID_ADDRESS) {
m_error.SetErrorString("parent address is invalid.");
@@ -182,7 +184,7 @@ bool ValueObjectChild::UpdateValue() {
}
} break;
- case Value::eValueTypeScalar:
+ case Value::ValueType::Scalar:
// try to extract the child value from the parent's scalar value
{
Scalar scalar(m_value.GetScalar());
diff --git a/lldb/source/Core/ValueObjectConstResult.cpp b/lldb/source/Core/ValueObjectConstResult.cpp
index ceb4491f8666..174b9359d52d 100644
--- a/lldb/source/Core/ValueObjectConstResult.cpp
+++ b/lldb/source/Core/ValueObjectConstResult.cpp
@@ -73,7 +73,7 @@ ValueObjectConstResult::ValueObjectConstResult(
}
m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
- m_value.SetValueType(Value::eValueTypeHostAddress);
+ m_value.SetValueType(Value::ValueType::HostAddress);
m_value.SetCompilerType(compiler_type);
m_name = name;
SetIsConstant();
@@ -115,7 +115,7 @@ ValueObjectConstResult::ValueObjectConstResult(
m_data.SetAddressByteSize(data_addr_size);
m_data.SetData(data_sp);
m_value.GetScalar() = (uintptr_t)data_sp->GetBytes();
- m_value.SetValueType(Value::eValueTypeHostAddress);
+ m_value.SetValueType(Value::ValueType::HostAddress);
m_value.SetCompilerType(compiler_type);
m_name = name;
SetIsConstant();
@@ -145,19 +145,19 @@ ValueObjectConstResult::ValueObjectConstResult(
m_value.GetScalar() = address;
m_data.SetAddressByteSize(addr_byte_size);
m_value.GetScalar().GetData(m_data, addr_byte_size);
- // m_value.SetValueType(Value::eValueTypeHostAddress);
+ // m_value.SetValueType(Value::ValueType::HostAddress);
switch (address_type) {
case eAddressTypeInvalid:
- m_value.SetValueType(Value::eValueTypeScalar);
+ m_value.SetValueType(Value::ValueType::Scalar);
break;
case eAddressTypeFile:
- m_value.SetValueType(Value::eValueTypeFileAddress);
+ m_value.SetValueType(Value::ValueType::FileAddress);
break;
case eAddressTypeLoad:
- m_value.SetValueType(Value::eValueTypeLoadAddress);
+ m_value.SetValueType(Value::ValueType::LoadAddress);
break;
case eAddressTypeHost:
- m_value.SetValueType(Value::eValueTypeHostAddress);
+ m_value.SetValueType(Value::ValueType::HostAddress);
break;
}
m_value.SetCompilerType(compiler_type);
@@ -193,7 +193,7 @@ ValueObjectConstResult::ValueObjectConstResult(ExecutionContextScope *exe_scope,
m_error = m_value.GetValueAsData(&exe_ctx, m_data, module);
}
-ValueObjectConstResult::~ValueObjectConstResult() {}
+ValueObjectConstResult::~ValueObjectConstResult() = default;
CompilerType ValueObjectConstResult::GetCompilerTypeImpl() {
return m_value.GetCompilerType();
diff --git a/lldb/source/Core/ValueObjectConstResultCast.cpp b/lldb/source/Core/ValueObjectConstResultCast.cpp
index 53ec9db45540..e70d055ac57c 100644
--- a/lldb/source/Core/ValueObjectConstResultCast.cpp
+++ b/lldb/source/Core/ValueObjectConstResultCast.cpp
@@ -27,7 +27,7 @@ ValueObjectConstResultCast::ValueObjectConstResultCast(
m_name = name;
}
-ValueObjectConstResultCast::~ValueObjectConstResultCast() {}
+ValueObjectConstResultCast::~ValueObjectConstResultCast() = default;
lldb::ValueObjectSP ValueObjectConstResultCast::Dereference(Status &error) {
return m_impl.Dereference(error);
diff --git a/lldb/source/Core/ValueObjectConstResultChild.cpp b/lldb/source/Core/ValueObjectConstResultChild.cpp
index 13c8393d8081..0fd81410ae54 100644
--- a/lldb/source/Core/ValueObjectConstResultChild.cpp
+++ b/lldb/source/Core/ValueObjectConstResultChild.cpp
@@ -34,7 +34,7 @@ ValueObjectConstResultChild::ValueObjectConstResultChild(
m_name = name;
}
-ValueObjectConstResultChild::~ValueObjectConstResultChild() {}
+ValueObjectConstResultChild::~ValueObjectConstResultChild() = default;
lldb::ValueObjectSP ValueObjectConstResultChild::Dereference(Status &error) {
return m_impl.Dereference(error);
diff --git a/lldb/source/Core/ValueObjectConstResultImpl.cpp b/lldb/source/Core/ValueObjectConstResultImpl.cpp
index e4cbbec849ec..980cea049f6f 100644
--- a/lldb/source/Core/ValueObjectConstResultImpl.cpp
+++ b/lldb/source/Core/ValueObjectConstResultImpl.cpp
@@ -132,7 +132,7 @@ lldb::ValueObjectSP ValueObjectConstResultImpl::AddressOf(Status &error) {
ConstString(new_name.c_str()), buffer, endian::InlHostByteOrder(),
exe_ctx.GetAddressByteSize());
- m_address_of_backend->GetValue().SetValueType(Value::eValueTypeScalar);
+ m_address_of_backend->GetValue().SetValueType(Value::ValueType::Scalar);
m_address_of_backend->GetValue().GetScalar() = m_live_address;
return m_address_of_backend;
diff --git a/lldb/source/Core/ValueObjectDynamicValue.cpp b/lldb/source/Core/ValueObjectDynamicValue.cpp
index 1c25b8c85a05..d77509496509 100644
--- a/lldb/source/Core/ValueObjectDynamicValue.cpp
+++ b/lldb/source/Core/ValueObjectDynamicValue.cpp
@@ -22,7 +22,7 @@
#include "lldb/Utility/Status.h"
#include "lldb/lldb-types.h"
-#include <string.h>
+#include <cstring>
namespace lldb_private {
class Declaration;
}
diff --git a/lldb/source/Core/ValueObjectMemory.cpp b/lldb/source/Core/ValueObjectMemory.cpp
index abf7b38ed89a..af039ee4040b 100644
--- a/lldb/source/Core/ValueObjectMemory.cpp
+++ b/lldb/source/Core/ValueObjectMemory.cpp
@@ -18,7 +18,7 @@
#include "lldb/lldb-types.h"
#include "llvm/Support/ErrorHandling.h"
-#include <assert.h>
+#include <cassert>
#include <memory>
namespace lldb_private {
@@ -57,20 +57,20 @@ ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope,
// Do not attempt to construct one of these objects with no variable!
assert(m_type_sp.get() != nullptr);
SetName(ConstString(name));
- m_value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get());
+ m_value.SetContext(Value::ContextType::LLDBType, m_type_sp.get());
TargetSP target_sp(GetTargetSP());
lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
if (load_address != LLDB_INVALID_ADDRESS) {
- m_value.SetValueType(Value::eValueTypeLoadAddress);
+ m_value.SetValueType(Value::ValueType::LoadAddress);
m_value.GetScalar() = load_address;
} else {
lldb::addr_t file_address = m_address.GetFileAddress();
if (file_address != LLDB_INVALID_ADDRESS) {
- m_value.SetValueType(Value::eValueTypeFileAddress);
+ m_value.SetValueType(Value::ValueType::FileAddress);
m_value.GetScalar() = file_address;
} else {
m_value.GetScalar() = m_address.GetOffset();
- m_value.SetValueType(Value::eValueTypeScalar);
+ m_value.SetValueType(Value::ValueType::Scalar);
}
}
}
@@ -92,21 +92,21 @@ ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope,
m_value.SetCompilerType(m_compiler_type);
lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
if (load_address != LLDB_INVALID_ADDRESS) {
- m_value.SetValueType(Value::eValueTypeLoadAddress);
+ m_value.SetValueType(Value::ValueType::LoadAddress);
m_value.GetScalar() = load_address;
} else {
lldb::addr_t file_address = m_address.GetFileAddress();
if (file_address != LLDB_INVALID_ADDRESS) {
- m_value.SetValueType(Value::eValueTypeFileAddress);
+ m_value.SetValueType(Value::ValueType::FileAddress);
m_value.GetScalar() = file_address;
} else {
m_value.GetScalar() = m_address.GetOffset();
- m_value.SetValueType(Value::eValueTypeScalar);
+ m_value.SetValueType(Value::ValueType::Scalar);
}
}
}
-ValueObjectMemory::~ValueObjectMemory() {}
+ValueObjectMemory::~ValueObjectMemory() = default;
CompilerType ValueObjectMemory::GetCompilerTypeImpl() {
if (m_type_sp)
@@ -168,15 +168,18 @@ bool ValueObjectMemory::UpdateValue() {
Value::ValueType value_type = m_value.GetValueType();
switch (value_type) {
- case Value::eValueTypeScalar:
+ case Value::ValueType::Invalid:
+ m_error.SetErrorString("Invalid value");
+ return false;
+ case Value::ValueType::Scalar:
// The variable value is in the Scalar value inside the m_value. We can
// point our m_data right to it.
m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
break;
- case Value::eValueTypeFileAddress:
- case Value::eValueTypeLoadAddress:
- case Value::eValueTypeHostAddress:
+ case Value::ValueType::FileAddress:
+ case Value::ValueType::LoadAddress:
+ case Value::ValueType::HostAddress:
// The DWARF expression result was an address in the inferior process. If
// this variable is an aggregate type, we just need the address as the
// main value as all child variable objects will rely upon this location
@@ -185,11 +188,11 @@ bool ValueObjectMemory::UpdateValue() {
// sure this type has a value before we try and read it
// If we have a file address, convert it to a load address if we can.
- if (value_type == Value::eValueTypeFileAddress &&
+ if (value_type == Value::ValueType::FileAddress &&
exe_ctx.GetProcessPtr()) {
lldb::addr_t load_addr = m_address.GetLoadAddress(target);
if (load_addr != LLDB_INVALID_ADDRESS) {
- m_value.SetValueType(Value::eValueTypeLoadAddress);
+ m_value.SetValueType(Value::ValueType::LoadAddress);
m_value.GetScalar() = load_addr;
}
}
@@ -205,7 +208,7 @@ bool ValueObjectMemory::UpdateValue() {
// extract read its value into m_data appropriately
Value value(m_value);
if (m_type_sp)
- value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get());
+ value.SetContext(Value::ContextType::LLDBType, m_type_sp.get());
else {
value.SetCompilerType(m_compiler_type);
}
diff --git a/lldb/source/Core/ValueObjectRegister.cpp b/lldb/source/Core/ValueObjectRegister.cpp
index 27461e9cebc4..089fd7667080 100644
--- a/lldb/source/Core/ValueObjectRegister.cpp
+++ b/lldb/source/Core/ValueObjectRegister.cpp
@@ -25,7 +25,7 @@
#include "llvm/ADT/StringRef.h"
-#include <assert.h>
+#include <cassert>
#include <memory>
namespace lldb_private {
@@ -60,7 +60,7 @@ ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope,
}
}
-ValueObjectRegisterSet::~ValueObjectRegisterSet() {}
+ValueObjectRegisterSet::~ValueObjectRegisterSet() = default;
CompilerType ValueObjectRegisterSet::GetCompilerTypeImpl() {
return CompilerType();
@@ -193,7 +193,7 @@ ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,
ConstructObject(reg_num);
}
-ValueObjectRegister::~ValueObjectRegister() {}
+ValueObjectRegister::~ValueObjectRegister() = default;
CompilerType ValueObjectRegister::GetCompilerTypeImpl() {
if (!m_compiler_type.IsValid()) {
@@ -249,9 +249,9 @@ bool ValueObjectRegister::UpdateValue() {
Process *process = exe_ctx.GetProcessPtr();
if (process)
m_data.SetAddressByteSize(process->GetAddressByteSize());
- m_value.SetContext(Value::eContextTypeRegisterInfo,
+ m_value.SetContext(Value::ContextType::RegisterInfo,
(void *)&m_reg_info);
- m_value.SetValueType(Value::eValueTypeHostAddress);
+ m_value.SetValueType(Value::ValueType::HostAddress);
m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
SetValueIsValid(true);
SetValueDidChange(!(m_old_reg_value == m_reg_value));
diff --git a/lldb/source/Core/ValueObjectSyntheticFilter.cpp b/lldb/source/Core/ValueObjectSyntheticFilter.cpp
index cebf7abfe523..aa55e3965706 100644
--- a/lldb/source/Core/ValueObjectSyntheticFilter.cpp
+++ b/lldb/source/Core/ValueObjectSyntheticFilter.cpp
@@ -190,7 +190,7 @@ bool ValueObjectSynthetic::UpdateValue() {
// 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_flags.m_children_count_valid = false;
{
std::lock_guard<std::mutex> guard(m_child_mutex);
m_synthetic_children_cache.clear();
diff --git a/lldb/source/Core/ValueObjectUpdater.cpp b/lldb/source/Core/ValueObjectUpdater.cpp
new file mode 100644
index 000000000000..af7f976a6d27
--- /dev/null
+++ b/lldb/source/Core/ValueObjectUpdater.cpp
@@ -0,0 +1,56 @@
+//===-- ValueObjectUpdater.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 "lldb/Core/ValueObjectUpdater.h"
+
+using namespace lldb_private;
+
+ValueObjectUpdater::ValueObjectUpdater(lldb::ValueObjectSP in_valobj_sp) {
+ if (!in_valobj_sp)
+ return;
+ // If the user passes in a value object that is dynamic or synthetic, then
+ // water it down to the static type.
+ m_root_valobj_sp = in_valobj_sp->GetQualifiedRepresentationIfAvailable(
+ lldb::eNoDynamicValues, false);
+}
+
+lldb::ValueObjectSP ValueObjectUpdater::GetSP() {
+ lldb::ProcessSP process_sp = GetProcessSP();
+ if (!process_sp)
+ return lldb::ValueObjectSP();
+
+ const uint32_t current_stop_id = process_sp->GetLastNaturalStopID();
+ if (current_stop_id == m_stop_id)
+ return m_user_valobj_sp;
+
+ m_stop_id = current_stop_id;
+
+ if (!m_root_valobj_sp) {
+ m_user_valobj_sp.reset();
+ return m_root_valobj_sp;
+ }
+
+ m_user_valobj_sp = m_root_valobj_sp;
+
+ lldb::ValueObjectSP dynamic_sp =
+ m_user_valobj_sp->GetDynamicValue(lldb::eDynamicDontRunTarget);
+ if (dynamic_sp)
+ m_user_valobj_sp = dynamic_sp;
+
+ lldb::ValueObjectSP synthetic_sp = m_user_valobj_sp->GetSyntheticValue();
+ if (synthetic_sp)
+ m_user_valobj_sp = synthetic_sp;
+
+ return m_user_valobj_sp;
+}
+
+lldb::ProcessSP ValueObjectUpdater::GetProcessSP() const {
+ if (m_root_valobj_sp)
+ return m_root_valobj_sp->GetProcessSP();
+ return lldb::ProcessSP();
+}
diff --git a/lldb/source/Core/ValueObjectVariable.cpp b/lldb/source/Core/ValueObjectVariable.cpp
index 5acb23aaac5b..8e89503a8a76 100644
--- a/lldb/source/Core/ValueObjectVariable.cpp
+++ b/lldb/source/Core/ValueObjectVariable.cpp
@@ -10,10 +10,10 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/AddressRange.h"
+#include "lldb/Core/Declaration.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/DWARFExpression.h"
-#include "lldb/Symbol/Declaration.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -33,7 +33,7 @@
#include "llvm/ADT/StringRef.h"
-#include <assert.h>
+#include <cassert>
#include <memory>
namespace lldb_private {
@@ -63,7 +63,7 @@ ValueObjectVariable::ValueObjectVariable(ExecutionContextScope *exe_scope,
m_name = var_sp->GetName();
}
-ValueObjectVariable::~ValueObjectVariable() {}
+ValueObjectVariable::~ValueObjectVariable() = default;
CompilerType ValueObjectVariable::GetCompilerTypeImpl() {
Type *var_type = m_variable_sp->GetType();
@@ -135,12 +135,12 @@ bool ValueObjectVariable::UpdateValue() {
if (expr.GetExpressionData(m_data)) {
if (m_data.GetDataStart() && m_data.GetByteSize())
m_value.SetBytes(m_data.GetDataStart(), m_data.GetByteSize());
- m_value.SetContext(Value::eContextTypeVariable, variable);
+ m_value.SetContext(Value::ContextType::Variable, variable);
}
else
m_error.SetErrorString("empty constant data");
// constant bytes can't be edited - sorry
- m_resolved_value.SetContext(Value::eContextTypeInvalid, nullptr);
+ m_resolved_value.SetContext(Value::ContextType::Invalid, nullptr);
} else {
lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS;
ExecutionContext exe_ctx(GetExecutionContextRef());
@@ -163,7 +163,7 @@ bool ValueObjectVariable::UpdateValue() {
if (expr.Evaluate(&exe_ctx, nullptr, loclist_base_load_addr, nullptr,
nullptr, m_value, &m_error)) {
m_resolved_value = m_value;
- m_value.SetContext(Value::eContextTypeVariable, variable);
+ m_value.SetContext(Value::ContextType::Variable, variable);
CompilerType compiler_type = GetCompilerType();
if (compiler_type.IsValid())
@@ -183,7 +183,7 @@ bool ValueObjectVariable::UpdateValue() {
//
// FIXME: When we grow m_value, we should represent the added bits as
// undefined somehow instead of as 0's.
- if (value_type == Value::eValueTypeHostAddress &&
+ if (value_type == Value::ValueType::HostAddress &&
compiler_type.IsValid()) {
if (size_t value_buf_size = m_value.GetBuffer().GetByteSize()) {
size_t value_size = m_value.GetValueByteSize(&m_error, &exe_ctx);
@@ -196,16 +196,19 @@ bool ValueObjectVariable::UpdateValue() {
const bool process_is_alive = process && process->IsAlive();
switch (value_type) {
- case Value::eValueTypeScalar:
+ case Value::ValueType::Invalid:
+ m_error.SetErrorString("invalid value");
+ break;
+ case Value::ValueType::Scalar:
// The variable value is in the Scalar value inside the m_value. We can
// point our m_data right to it.
m_error =
m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
break;
- case Value::eValueTypeFileAddress:
- case Value::eValueTypeLoadAddress:
- case Value::eValueTypeHostAddress:
+ case Value::ValueType::FileAddress:
+ case Value::ValueType::LoadAddress:
+ case Value::ValueType::HostAddress:
// The DWARF expression result was an address in the inferior process.
// If this variable is an aggregate type, we just need the address as
// the main value as all child variable objects will rely upon this
@@ -214,7 +217,7 @@ bool ValueObjectVariable::UpdateValue() {
// m_data. Make sure this type has a value before we try and read it
// If we have a file address, convert it to a load address if we can.
- if (value_type == Value::eValueTypeFileAddress && process_is_alive)
+ if (value_type == Value::ValueType::FileAddress && process_is_alive)
m_value.ConvertToLoadAddress(GetModule().get(), target);
if (!CanProvideValue()) {
@@ -227,7 +230,7 @@ bool ValueObjectVariable::UpdateValue() {
// Copy the Value and set the context to use our Variable so it can
// extract read its value into m_data appropriately
Value value(m_value);
- value.SetContext(Value::eContextTypeVariable, variable);
+ value.SetContext(Value::ContextType::Variable, variable);
m_error =
value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
@@ -240,7 +243,7 @@ bool ValueObjectVariable::UpdateValue() {
SetValueIsValid(m_error.Success());
} else {
// could not find location, won't allow editing
- m_resolved_value.SetContext(Value::eContextTypeInvalid, nullptr);
+ m_resolved_value.SetContext(Value::ContextType::Invalid, nullptr);
}
}
@@ -257,7 +260,9 @@ void ValueObjectVariable::DoUpdateChildrenAddressType(ValueObject &valobj) {
(type_info & (lldb::eTypeIsPointer | lldb::eTypeIsReference)) != 0;
switch (value_type) {
- case Value::eValueTypeFileAddress:
+ case Value::ValueType::Invalid:
+ break;
+ case Value::ValueType::FileAddress:
// 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.
@@ -280,7 +285,7 @@ void ValueObjectVariable::DoUpdateChildrenAddressType(ValueObject &valobj) {
else
valobj.SetAddressTypeOfChildren(eAddressTypeFile);
break;
- case Value::eValueTypeHostAddress:
+ case Value::ValueType::HostAddress:
// 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
@@ -291,8 +296,8 @@ void ValueObjectVariable::DoUpdateChildrenAddressType(ValueObject &valobj) {
else
valobj.SetAddressTypeOfChildren(eAddressTypeHost);
break;
- case Value::eValueTypeLoadAddress:
- case Value::eValueTypeScalar:
+ case Value::ValueType::LoadAddress:
+ case Value::ValueType::Scalar:
valobj.SetAddressTypeOfChildren(eAddressTypeLoad);
break;
}
@@ -343,7 +348,7 @@ bool ValueObjectVariable::GetDeclaration(Declaration &decl) {
}
const char *ValueObjectVariable::GetLocationAsCString() {
- if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo)
+ if (m_resolved_value.GetContextType() == Value::ContextType::RegisterInfo)
return GetLocationAsCStringImpl(m_resolved_value, m_data);
else
return ValueObject::GetLocationAsCString();
@@ -356,7 +361,7 @@ bool ValueObjectVariable::SetValueFromCString(const char *value_str,
return false;
}
- if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo) {
+ if (m_resolved_value.GetContextType() == Value::ContextType::RegisterInfo) {
RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo();
ExecutionContext exe_ctx(GetExecutionContextRef());
RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
@@ -385,7 +390,7 @@ bool ValueObjectVariable::SetData(DataExtractor &data, Status &error) {
return false;
}
- if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo) {
+ if (m_resolved_value.GetContextType() == Value::ContextType::RegisterInfo) {
RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo();
ExecutionContext exe_ctx(GetExecutionContextRef());
RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
diff --git a/lldb/source/DataFormatters/StringPrinter.cpp b/lldb/source/DataFormatters/StringPrinter.cpp
index 139f1ec0554f..0c6438f7dd86 100644
--- a/lldb/source/DataFormatters/StringPrinter.cpp
+++ b/lldb/source/DataFormatters/StringPrinter.cpp
@@ -18,7 +18,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ConvertUTF.h"
-#include <ctype.h>
+#include <cctype>
#include <locale>
#include <memory>
diff --git a/lldb/source/DataFormatters/TypeFormat.cpp b/lldb/source/DataFormatters/TypeFormat.cpp
index b9a9447c5f3e..9c5046687013 100644
--- a/lldb/source/DataFormatters/TypeFormat.cpp
+++ b/lldb/source/DataFormatters/TypeFormat.cpp
@@ -27,16 +27,15 @@
using namespace lldb;
using namespace lldb_private;
-TypeFormatImpl::TypeFormatImpl(const Flags &flags)
- : m_flags(flags), m_my_revision(0) {}
+TypeFormatImpl::TypeFormatImpl(const Flags &flags) : m_flags(flags) {}
-TypeFormatImpl::~TypeFormatImpl() {}
+TypeFormatImpl::~TypeFormatImpl() = default;
TypeFormatImpl_Format::TypeFormatImpl_Format(lldb::Format f,
const TypeFormatImpl::Flags &flags)
: TypeFormatImpl(flags), m_format(f) {}
-TypeFormatImpl_Format::~TypeFormatImpl_Format() {}
+TypeFormatImpl_Format::~TypeFormatImpl_Format() = default;
bool TypeFormatImpl_Format::FormatObject(ValueObject *valobj,
std::string &dest) const {
@@ -48,7 +47,7 @@ bool TypeFormatImpl_Format::FormatObject(ValueObject *valobj,
ExecutionContext exe_ctx(valobj->GetExecutionContextRef());
DataExtractor data;
- if (context_type == Value::eContextTypeRegisterInfo) {
+ if (context_type == Value::ContextType::RegisterInfo) {
const RegisterInfo *reg_info = value.GetRegisterInfo();
if (reg_info) {
Status error;
@@ -135,7 +134,7 @@ TypeFormatImpl_EnumType::TypeFormatImpl_EnumType(
ConstString type_name, const TypeFormatImpl::Flags &flags)
: TypeFormatImpl(flags), m_enum_type(type_name), m_types() {}
-TypeFormatImpl_EnumType::~TypeFormatImpl_EnumType() {}
+TypeFormatImpl_EnumType::~TypeFormatImpl_EnumType() = default;
bool TypeFormatImpl_EnumType::FormatObject(ValueObject *valobj,
std::string &dest) const {
diff --git a/lldb/source/DataFormatters/TypeSummary.cpp b/lldb/source/DataFormatters/TypeSummary.cpp
index 5d4fe2e467f8..c09ed31d0338 100644
--- a/lldb/source/DataFormatters/TypeSummary.cpp
+++ b/lldb/source/DataFormatters/TypeSummary.cpp
@@ -26,8 +26,7 @@
using namespace lldb;
using namespace lldb_private;
-TypeSummaryOptions::TypeSummaryOptions()
- : m_lang(eLanguageTypeUnknown), m_capping(eTypeSummaryCapped) {}
+TypeSummaryOptions::TypeSummaryOptions() = default;
lldb::LanguageType TypeSummaryOptions::GetLanguage() const { return m_lang; }
diff --git a/lldb/source/DataFormatters/TypeSynthetic.cpp b/lldb/source/DataFormatters/TypeSynthetic.cpp
index 75388a93cc64..2cca5d65f470 100644
--- a/lldb/source/DataFormatters/TypeSynthetic.cpp
+++ b/lldb/source/DataFormatters/TypeSynthetic.cpp
@@ -128,7 +128,7 @@ ScriptedSyntheticChildren::FrontEnd::FrontEnd(std::string pclass,
ValueObject &backend)
: SyntheticChildrenFrontEnd(backend), m_python_class(pclass),
m_wrapper_sp(), m_interpreter(nullptr) {
- if (backend == LLDB_INVALID_UID)
+ if (backend.GetID() == LLDB_INVALID_UID)
return;
TargetSP target_sp = backend.GetTargetSP();
@@ -143,7 +143,7 @@ ScriptedSyntheticChildren::FrontEnd::FrontEnd(std::string pclass,
m_python_class.c_str(), backend.GetSP());
}
-ScriptedSyntheticChildren::FrontEnd::~FrontEnd() {}
+ScriptedSyntheticChildren::FrontEnd::~FrontEnd() = default;
lldb::ValueObjectSP
ScriptedSyntheticChildren::FrontEnd::GetChildAtIndex(size_t idx) {
diff --git a/lldb/source/DataFormatters/VectorType.cpp b/lldb/source/DataFormatters/VectorType.cpp
index cc24bb1de428..11371918830b 100644
--- a/lldb/source/DataFormatters/VectorType.cpp
+++ b/lldb/source/DataFormatters/VectorType.cpp
@@ -219,7 +219,7 @@ public:
m_parent_format = m_backend.GetFormat();
CompilerType parent_type(m_backend.GetCompilerType());
CompilerType element_type;
- parent_type.IsVectorType(&element_type, nullptr);
+ parent_type.IsVectorType(&element_type);
m_child_type = ::GetCompilerTypeForFormat(m_parent_format, element_type,
parent_type.GetTypeSystem());
m_num_children = ::CalculateNumChildren(parent_type, m_child_type);
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index c30fdf565cd5..a10546c1deae 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -8,7 +8,7 @@
#include "lldb/Expression/DWARFExpression.h"
-#include <inttypes.h>
+#include <cinttypes>
#include <vector>
@@ -55,9 +55,7 @@ ReadAddressFromDebugAddrSection(const DWARFUnit *dwarf_cu,
}
// DWARFExpression constructor
-DWARFExpression::DWARFExpression()
- : m_module_wp(), m_data(), m_dwarf_cu(nullptr),
- m_reg_kind(eRegisterKindDWARF) {}
+DWARFExpression::DWARFExpression() : m_module_wp(), m_data() {}
DWARFExpression::DWARFExpression(lldb::ModuleSP module_sp,
const DataExtractor &data,
@@ -69,7 +67,7 @@ DWARFExpression::DWARFExpression(lldb::ModuleSP module_sp,
}
// Destructor
-DWARFExpression::~DWARFExpression() {}
+DWARFExpression::~DWARFExpression() = default;
bool DWARFExpression::IsValid() const { return m_data.GetByteSize() > 0; }
@@ -174,8 +172,8 @@ static bool ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
RegisterValue reg_value;
if (reg_ctx->ReadRegister(reg_info, reg_value)) {
if (reg_value.GetScalarValue(value.GetScalar())) {
- value.SetValueType(Value::eValueTypeScalar);
- value.SetContext(Value::eContextTypeRegisterInfo,
+ value.SetValueType(Value::ValueType::Scalar);
+ value.SetContext(Value::ContextType::RegisterInfo,
const_cast<RegisterInfo *>(reg_info));
if (error_ptr)
error_ptr->Clear();
@@ -904,6 +902,52 @@ bool DWARFExpression::Evaluate(ExecutionContext *exe_ctx,
object_address_ptr, result, error_ptr);
}
+namespace {
+/// The location description kinds described by the DWARF v5
+/// specification. Composite locations are handled out-of-band and
+/// thus aren't part of the enum.
+enum LocationDescriptionKind {
+ Empty,
+ Memory,
+ Register,
+ Implicit
+ /* Composite*/
+};
+/// Adjust value's ValueType according to the kind of location description.
+void UpdateValueTypeFromLocationDescription(Log *log, const DWARFUnit *dwarf_cu,
+ LocationDescriptionKind kind,
+ Value *value = nullptr) {
+ // Note that this function is conflating DWARF expressions with
+ // DWARF location descriptions. Perhaps it would be better to define
+ // a wrapper for DWARFExpresssion::Eval() that deals with DWARF
+ // location descriptions (which consist of one or more DWARF
+ // expressions). But doing this would mean we'd also need factor the
+ // handling of DW_OP_(bit_)piece out of this function.
+ if (dwarf_cu && dwarf_cu->GetVersion() >= 4) {
+ const char *log_msg = "DWARF location description kind: %s";
+ switch (kind) {
+ case Empty:
+ LLDB_LOGF(log, log_msg, "Empty");
+ break;
+ case Memory:
+ LLDB_LOGF(log, log_msg, "Memory");
+ if (value->GetValueType() == Value::ValueType::Scalar)
+ value->SetValueType(Value::ValueType::LoadAddress);
+ break;
+ case Register:
+ LLDB_LOGF(log, log_msg, "Register");
+ value->SetValueType(Value::ValueType::Scalar);
+ break;
+ case Implicit:
+ LLDB_LOGF(log, log_msg, "Implicit");
+ if (value->GetValueType() == Value::ValueType::LoadAddress)
+ value->SetValueType(Value::ValueType::Scalar);
+ break;
+ }
+ }
+}
+} // namespace
+
bool DWARFExpression::Evaluate(
ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
lldb::ModuleSP module_sp, const DataExtractor &opcodes,
@@ -952,6 +996,11 @@ bool DWARFExpression::Evaluate(
!is_signed));
};
+ // The default kind is a memory location. This is updated by any
+ // operation that changes this, such as DW_OP_stack_value, and reset
+ // by composition operations like DW_OP_piece.
+ LocationDescriptionKind dwarf4_location_description_kind = Memory;
+
while (opcodes.ValidOffset(offset)) {
const lldb::offset_t op_offset = offset;
const uint8_t op = opcodes.GetU8(&offset);
@@ -975,7 +1024,7 @@ bool DWARFExpression::Evaluate(
// address and whose size is the size of an address on the target machine.
case DW_OP_addr:
stack.push_back(Scalar(opcodes.GetAddress(&offset)));
- stack.back().SetValueType(Value::eValueTypeFileAddress);
+ stack.back().SetValueType(Value::ValueType::FileAddress);
// Convert the file address to a load address, so subsequent
// DWARF operators can operate on it.
if (frame)
@@ -1034,14 +1083,14 @@ bool DWARFExpression::Evaluate(
}
Value::ValueType value_type = stack.back().GetValueType();
switch (value_type) {
- case Value::eValueTypeHostAddress: {
+ case Value::ValueType::HostAddress: {
void *src = (void *)stack.back().GetScalar().ULongLong();
intptr_t ptr;
::memcpy(&ptr, src, sizeof(void *));
stack.back().GetScalar() = ptr;
stack.back().ClearContext();
} break;
- case Value::eValueTypeFileAddress: {
+ case Value::ValueType::FileAddress: {
auto file_addr = stack.back().GetScalar().ULongLong(
LLDB_INVALID_ADDRESS);
if (!module_sp) {
@@ -1064,10 +1113,13 @@ bool DWARFExpression::Evaluate(
return false;
}
stack.back().GetScalar() = load_Addr;
- stack.back().SetValueType(Value::eValueTypeLoadAddress);
- // Fall through to load address code below...
+ // Fall through to load address promotion code below.
} LLVM_FALLTHROUGH;
- case Value::eValueTypeLoadAddress:
+ case Value::ValueType::Scalar:
+ // Promote Scalar to LoadAddress and fall through.
+ stack.back().SetValueType(Value::ValueType::LoadAddress);
+ LLVM_FALLTHROUGH;
+ case Value::ValueType::LoadAddress:
if (exe_ctx) {
if (process) {
lldb::addr_t pointer_addr =
@@ -1076,6 +1128,8 @@ bool DWARFExpression::Evaluate(
lldb::addr_t pointer_value =
process->ReadPointerFromMemory(pointer_addr, error);
if (pointer_value != LLDB_INVALID_ADDRESS) {
+ if (ABISP abi_sp = process->GetABI())
+ pointer_value = abi_sp->FixCodeAddress(pointer_value);
stack.back().GetScalar() = pointer_value;
stack.back().ClearContext();
} else {
@@ -1099,8 +1153,10 @@ bool DWARFExpression::Evaluate(
}
break;
- default:
- break;
+ case Value::ValueType::Invalid:
+ if (error_ptr)
+ error_ptr->SetErrorString("Invalid value type for DW_OP_deref.\n");
+ return false;
}
} break;
@@ -1127,7 +1183,7 @@ bool DWARFExpression::Evaluate(
uint8_t size = opcodes.GetU8(&offset);
Value::ValueType value_type = stack.back().GetValueType();
switch (value_type) {
- case Value::eValueTypeHostAddress: {
+ case Value::ValueType::HostAddress: {
void *src = (void *)stack.back().GetScalar().ULongLong();
intptr_t ptr;
::memcpy(&ptr, src, sizeof(void *));
@@ -1167,7 +1223,8 @@ bool DWARFExpression::Evaluate(
stack.back().GetScalar() = ptr;
stack.back().ClearContext();
} break;
- case Value::eValueTypeLoadAddress:
+ case Value::ValueType::Scalar:
+ case Value::ValueType::LoadAddress:
if (exe_ctx) {
if (process) {
lldb::addr_t pointer_addr =
@@ -1207,19 +1264,22 @@ bool DWARFExpression::Evaluate(
}
} else {
if (error_ptr)
- error_ptr->SetErrorString("NULL process for DW_OP_deref.\n");
+ error_ptr->SetErrorString("NULL process for DW_OP_deref_size.\n");
return false;
}
} else {
if (error_ptr)
error_ptr->SetErrorString(
- "NULL execution context for DW_OP_deref.\n");
+ "NULL execution context for DW_OP_deref_size.\n");
return false;
}
break;
- default:
- break;
+ case Value::ValueType::FileAddress:
+ case Value::ValueType::Invalid:
+ if (error_ptr)
+ error_ptr->SetErrorString("Invalid value for DW_OP_deref_size.\n");
+ return false;
}
} break;
@@ -1941,6 +2001,7 @@ bool DWARFExpression::Evaluate(
case DW_OP_reg29:
case DW_OP_reg30:
case DW_OP_reg31: {
+ dwarf4_location_description_kind = Register;
reg_num = op - DW_OP_reg0;
if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr, tmp))
@@ -1953,6 +2014,7 @@ bool DWARFExpression::Evaluate(
// ULEB128 literal operand that encodes the register.
// DESCRIPTION: Push the value in register on the top of the stack.
case DW_OP_regx: {
+ dwarf4_location_description_kind = Register;
reg_num = opcodes.GetULEB128(&offset);
if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr, tmp))
stack.push_back(tmp);
@@ -2005,7 +2067,7 @@ bool DWARFExpression::Evaluate(
tmp.ResolveValue(exe_ctx) += (uint64_t)breg_offset;
tmp.ClearContext();
stack.push_back(tmp);
- stack.back().SetValueType(Value::eValueTypeLoadAddress);
+ stack.back().SetValueType(Value::ValueType::LoadAddress);
} else
return false;
} break;
@@ -2024,7 +2086,7 @@ bool DWARFExpression::Evaluate(
tmp.ResolveValue(exe_ctx) += (uint64_t)breg_offset;
tmp.ClearContext();
stack.push_back(tmp);
- stack.back().SetValueType(Value::eValueTypeLoadAddress);
+ stack.back().SetValueType(Value::ValueType::LoadAddress);
} else
return false;
} break;
@@ -2037,7 +2099,7 @@ bool DWARFExpression::Evaluate(
int64_t fbreg_offset = opcodes.GetSLEB128(&offset);
value += fbreg_offset;
stack.push_back(value);
- stack.back().SetValueType(Value::eValueTypeLoadAddress);
+ stack.back().SetValueType(Value::ValueType::LoadAddress);
} else
return false;
} else {
@@ -2076,12 +2138,18 @@ bool DWARFExpression::Evaluate(
// provides a way of describing how large a part of a variable a particular
// DWARF expression refers to.
case DW_OP_piece: {
+ LocationDescriptionKind piece_locdesc = dwarf4_location_description_kind;
+ // Reset for the next piece.
+ dwarf4_location_description_kind = Memory;
+
const uint64_t piece_byte_size = opcodes.GetULEB128(&offset);
if (piece_byte_size > 0) {
Value curr_piece;
if (stack.empty()) {
+ UpdateValueTypeFromLocationDescription(
+ log, dwarf_cu, LocationDescriptionKind::Empty);
// In a multi-piece expression, this means that the current piece is
// not available. Fill with zeros for now by resizing the data and
// appending it
@@ -2097,11 +2165,15 @@ bool DWARFExpression::Evaluate(
// Extract the current piece into "curr_piece"
Value curr_piece_source_value(stack.back());
stack.pop_back();
+ UpdateValueTypeFromLocationDescription(log, dwarf_cu, piece_locdesc,
+ &curr_piece_source_value);
const Value::ValueType curr_piece_source_value_type =
curr_piece_source_value.GetValueType();
switch (curr_piece_source_value_type) {
- case Value::eValueTypeLoadAddress:
+ case Value::ValueType::Invalid:
+ return false;
+ case Value::ValueType::LoadAddress:
if (process) {
if (curr_piece.ResizeData(piece_byte_size) == piece_byte_size) {
lldb::addr_t load_addr =
@@ -2128,8 +2200,8 @@ bool DWARFExpression::Evaluate(
}
break;
- case Value::eValueTypeFileAddress:
- case Value::eValueTypeHostAddress:
+ case Value::ValueType::FileAddress:
+ case Value::ValueType::HostAddress:
if (error_ptr) {
lldb::addr_t addr = curr_piece_source_value.GetScalar().ULongLong(
LLDB_INVALID_ADDRESS);
@@ -2137,14 +2209,14 @@ bool DWARFExpression::Evaluate(
"failed to read memory DW_OP_piece(%" PRIu64
") from %s address 0x%" PRIx64,
piece_byte_size, curr_piece_source_value.GetValueType() ==
- Value::eValueTypeFileAddress
+ Value::ValueType::FileAddress
? "file"
: "host",
addr);
}
return false;
- case Value::eValueTypeScalar: {
+ case Value::ValueType::Scalar: {
uint32_t bit_size = piece_byte_size * 8;
uint32_t bit_offset = 0;
Scalar &scalar = curr_piece_source_value.GetScalar();
@@ -2205,15 +2277,25 @@ bool DWARFExpression::Evaluate(
case DW_OP_bit_piece: // 0x9d ULEB128 bit size, ULEB128 bit offset (DWARF3);
if (stack.size() < 1) {
+ UpdateValueTypeFromLocationDescription(log, dwarf_cu,
+ LocationDescriptionKind::Empty);
+ // Reset for the next piece.
+ dwarf4_location_description_kind = Memory;
if (error_ptr)
error_ptr->SetErrorString(
"Expression stack needs at least 1 item for DW_OP_bit_piece.");
return false;
} else {
+ UpdateValueTypeFromLocationDescription(
+ log, dwarf_cu, dwarf4_location_description_kind, &stack.back());
+ // Reset for the next piece.
+ dwarf4_location_description_kind = Memory;
const uint64_t piece_bit_size = opcodes.GetULEB128(&offset);
const uint64_t piece_bit_offset = opcodes.GetULEB128(&offset);
switch (stack.back().GetValueType()) {
- case Value::eValueTypeScalar: {
+ case Value::ValueType::Invalid:
+ return false;
+ case Value::ValueType::Scalar: {
if (!stack.back().GetScalar().ExtractBitfield(piece_bit_size,
piece_bit_offset)) {
if (error_ptr)
@@ -2226,9 +2308,9 @@ bool DWARFExpression::Evaluate(
}
} break;
- case Value::eValueTypeFileAddress:
- case Value::eValueTypeLoadAddress:
- case Value::eValueTypeHostAddress:
+ case Value::ValueType::FileAddress:
+ case Value::ValueType::LoadAddress:
+ case Value::ValueType::HostAddress:
if (error_ptr) {
error_ptr->SetErrorStringWithFormat(
"unable to extract DW_OP_bit_piece(bit_size = %" PRIu64
@@ -2248,6 +2330,8 @@ bool DWARFExpression::Evaluate(
// DESCRIPTION: Value is immediately stored in block in the debug info with
// the memory representation of the target.
case DW_OP_implicit_value: {
+ dwarf4_location_description_kind = Implicit;
+
const uint32_t len = opcodes.GetULEB128(&offset);
const void *data = opcodes.GetData(&offset, len);
@@ -2263,6 +2347,12 @@ bool DWARFExpression::Evaluate(
break;
}
+ case DW_OP_implicit_pointer: {
+ dwarf4_location_description_kind = Implicit;
+ LLDB_ERRORF(error_ptr, "Could not evaluate %s.", DW_OP_value_to_name(op));
+ return false;
+ }
+
// OPCODE: DW_OP_push_object_address
// OPERANDS: none
// DESCRIPTION: Pushes the address of the object currently being
@@ -2334,13 +2424,14 @@ bool DWARFExpression::Evaluate(
// rather is a constant value. The value from the top of the stack is the
// value to be used. This is the actual object value and not the location.
case DW_OP_stack_value:
+ dwarf4_location_description_kind = Implicit;
if (stack.empty()) {
if (error_ptr)
error_ptr->SetErrorString(
"Expression stack needs at least 1 item for DW_OP_stack_value.");
return false;
}
- stack.back().SetValueType(Value::eValueTypeScalar);
+ stack.back().SetValueType(Value::ValueType::Scalar);
break;
// OPCODE: DW_OP_convert
@@ -2428,7 +2519,7 @@ bool DWARFExpression::Evaluate(
addr_t cfa = id.GetCallFrameAddress();
if (cfa != LLDB_INVALID_ADDRESS) {
stack.push_back(Scalar(cfa));
- stack.back().SetValueType(Value::eValueTypeLoadAddress);
+ stack.back().SetValueType(Value::ValueType::LoadAddress);
} else if (error_ptr)
error_ptr->SetErrorString("Stack frame does not include a canonical "
"frame address for DW_OP_call_frame_cfa "
@@ -2488,7 +2579,7 @@ bool DWARFExpression::Evaluate(
}
stack.back().GetScalar() = tls_load_addr;
- stack.back().SetValueType(Value::eValueTypeLoadAddress);
+ stack.back().SetValueType(Value::ValueType::LoadAddress);
} break;
// OPCODE: DW_OP_addrx (DW_OP_GNU_addr_index is the legacy name.)
@@ -2508,7 +2599,7 @@ bool DWARFExpression::Evaluate(
uint64_t index = opcodes.GetULEB128(&offset);
lldb::addr_t value = ReadAddressFromDebugAddrSection(dwarf_cu, index);
stack.push_back(Scalar(value));
- stack.back().SetValueType(Value::eValueTypeFileAddress);
+ stack.back().SetValueType(Value::ValueType::FileAddress);
} break;
// OPCODE: DW_OP_GNU_const_index
@@ -2554,25 +2645,28 @@ bool DWARFExpression::Evaluate(
// or DW_OP_bit_piece opcodes
if (pieces.GetBuffer().GetByteSize()) {
result = pieces;
- } else {
- if (error_ptr)
- error_ptr->SetErrorString("Stack empty after evaluation.");
- return false;
+ return true;
}
- } else {
- if (log && log->GetVerbose()) {
- size_t count = stack.size();
- LLDB_LOGF(log, "Stack after operation has %" PRIu64 " values:",
- (uint64_t)count);
- for (size_t i = 0; i < count; ++i) {
- StreamString new_value;
- new_value.Printf("[%" PRIu64 "]", (uint64_t)i);
- stack[i].Dump(&new_value);
- LLDB_LOGF(log, " %s", new_value.GetData());
- }
+ if (error_ptr)
+ error_ptr->SetErrorString("Stack empty after evaluation.");
+ return false;
+ }
+
+ UpdateValueTypeFromLocationDescription(
+ log, dwarf_cu, dwarf4_location_description_kind, &stack.back());
+
+ if (log && log->GetVerbose()) {
+ size_t count = stack.size();
+ LLDB_LOGF(log,
+ "Stack after operation has %" PRIu64 " values:", (uint64_t)count);
+ for (size_t i = 0; i < count; ++i) {
+ StreamString new_value;
+ new_value.Printf("[%" PRIu64 "]", (uint64_t)i);
+ stack[i].Dump(&new_value);
+ LLDB_LOGF(log, " %s", new_value.GetData());
}
- result = stack.back();
}
+ result = stack.back();
return true; // Return true on success
}
diff --git a/lldb/source/Expression/ExpressionVariable.cpp b/lldb/source/Expression/ExpressionVariable.cpp
index 8b3dda7b2fe1..565a3d1a8161 100644
--- a/lldb/source/Expression/ExpressionVariable.cpp
+++ b/lldb/source/Expression/ExpressionVariable.cpp
@@ -13,7 +13,7 @@
using namespace lldb_private;
-ExpressionVariable::~ExpressionVariable() {}
+ExpressionVariable::~ExpressionVariable() = default;
uint8_t *ExpressionVariable::GetValueBytes() {
llvm::Optional<uint64_t> byte_size = m_frozen_sp->GetByteSize();
@@ -28,7 +28,7 @@ uint8_t *ExpressionVariable::GetValueBytes() {
return nullptr;
}
-PersistentExpressionState::~PersistentExpressionState() {}
+PersistentExpressionState::~PersistentExpressionState() = default;
lldb::addr_t PersistentExpressionState::LookupSymbol(ConstString name) {
SymbolMap::iterator si = m_symbol_map.find(name.GetCString());
diff --git a/lldb/source/Expression/FunctionCaller.cpp b/lldb/source/Expression/FunctionCaller.cpp
index 26ab4bfaff53..5f1eb24a905a 100644
--- a/lldb/source/Expression/FunctionCaller.cpp
+++ b/lldb/source/Expression/FunctionCaller.cpp
@@ -193,8 +193,8 @@ bool FunctionCaller::WriteFunctionArguments(
// Special case: if it's a pointer, don't do anything (the ABI supports
// passing cstrings)
- if (arg_value->GetValueType() == Value::eValueTypeHostAddress &&
- arg_value->GetContextType() == Value::eContextTypeInvalid &&
+ if (arg_value->GetValueType() == Value::ValueType::HostAddress &&
+ arg_value->GetContextType() == Value::ContextType::Invalid &&
arg_value->GetCompilerType().IsPointerType())
continue;
@@ -295,7 +295,7 @@ bool FunctionCaller::FetchFunctionResults(ExecutionContext &exe_ctx,
return false;
ret_value.SetCompilerType(m_function_return_type);
- ret_value.SetValueType(Value::eValueTypeScalar);
+ ret_value.SetValueType(Value::ValueType::Scalar);
return true;
}
@@ -317,12 +317,16 @@ lldb::ExpressionResults FunctionCaller::ExecuteFunction(
lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
// FunctionCaller::ExecuteFunction execution is always just to get the
- // result. Do make sure we ignore breakpoints, unwind on error, and don't try
- // to debug it.
+ // result. Unless explicitly asked for, ignore breakpoints and unwind on
+ // error.
+ const bool enable_debugging =
+ exe_ctx.GetTargetPtr() &&
+ exe_ctx.GetTargetPtr()->GetDebugUtilityExpression();
EvaluateExpressionOptions real_options = options;
- real_options.SetDebug(false);
- real_options.SetUnwindOnError(true);
- real_options.SetIgnoreBreakpoints(true);
+ real_options.SetDebug(false); // This halts the expression for debugging.
+ real_options.SetGenerateDebugInfo(enable_debugging);
+ real_options.SetUnwindOnError(!enable_debugging);
+ real_options.SetIgnoreBreakpoints(!enable_debugging);
lldb::addr_t args_addr;
diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp
index 538935da52ee..63184ba477a6 100644
--- a/lldb/source/Expression/IRExecutionUnit.cpp
+++ b/lldb/source/Expression/IRExecutionUnit.cpp
@@ -9,6 +9,8 @@
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DiagnosticHandler.h"
+#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/SourceMgr.h"
@@ -200,16 +202,26 @@ Status IRExecutionUnit::DisassembleFunction(Stream &stream,
return ret;
}
-static void ReportInlineAsmError(const llvm::SMDiagnostic &diagnostic,
- void *Context, unsigned LocCookie) {
- Status *err = static_cast<Status *>(Context);
+namespace {
+struct IRExecDiagnosticHandler : public llvm::DiagnosticHandler {
+ Status *err;
+ IRExecDiagnosticHandler(Status *err) : err(err) {}
+ bool handleDiagnostics(const llvm::DiagnosticInfo &DI) override {
+ if (DI.getKind() == llvm::DK_SrcMgr) {
+ const auto &DISM = llvm::cast<llvm::DiagnosticInfoSrcMgr>(DI);
+ if (err && err->Success()) {
+ err->SetErrorToGenericError();
+ err->SetErrorStringWithFormat(
+ "Inline assembly error: %s",
+ DISM.getSMDiag().getMessage().str().c_str());
+ }
+ return true;
+ }
- if (err && err->Success()) {
- err->SetErrorToGenericError();
- err->SetErrorStringWithFormat("Inline assembly error: %s",
- diagnostic.getMessage().str().c_str());
+ return false;
}
-}
+};
+} // namespace
void IRExecutionUnit::ReportSymbolLookupError(ConstString name) {
m_failed_lookups.push_back(name);
@@ -257,8 +269,8 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr,
LLDB_LOGF(log, "Module being sent to JIT: \n%s", s.c_str());
}
- m_module_up->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError,
- &error);
+ m_module_up->getContext().setDiagnosticHandler(
+ std::make_unique<IRExecDiagnosticHandler>(&error));
llvm::EngineBuilder builder(std::move(m_module_up));
llvm::Triple triple(m_module->getTargetTriple());
@@ -484,7 +496,7 @@ IRExecutionUnit::~IRExecutionUnit() {
IRExecutionUnit::MemoryManager::MemoryManager(IRExecutionUnit &parent)
: m_default_mm_up(new llvm::SectionMemoryManager()), m_parent(parent) {}
-IRExecutionUnit::MemoryManager::~MemoryManager() {}
+IRExecutionUnit::MemoryManager::~MemoryManager() = default;
lldb::SectionType IRExecutionUnit::GetSectionTypeFromSectionName(
const llvm::StringRef &name, IRExecutionUnit::AllocationKind alloc_kind) {
diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp
index b87a759aadc5..788520d1f32b 100644
--- a/lldb/source/Expression/IRInterpreter.cpp
+++ b/lldb/source/Expression/IRInterpreter.cpp
@@ -122,7 +122,7 @@ public:
m_stack_pointer = stack_frame_top;
}
- ~InterpreterStackFrame() {}
+ ~InterpreterStackFrame() = default;
void Jump(const BasicBlock *bb) {
m_prev_bb = m_bb;
@@ -1241,7 +1241,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
if (!write_error.Success()) {
LLDB_LOGF(log, "Couldn't write to a region on behalf of a LoadInst");
error.SetErrorToGenericError();
- error.SetErrorString(memory_read_error);
+ error.SetErrorString(memory_write_error);
return false;
}
diff --git a/lldb/source/Expression/IRMemoryMap.cpp b/lldb/source/Expression/IRMemoryMap.cpp
index 6b1e4c313a39..4ae2724d4dd8 100644
--- a/lldb/source/Expression/IRMemoryMap.cpp
+++ b/lldb/source/Expression/IRMemoryMap.cpp
@@ -639,7 +639,7 @@ void IRMemoryMap::ReadMemory(uint8_t *bytes, lldb::addr_t process_address,
if (target_sp) {
Address absolute_address(process_address);
- target_sp->ReadMemory(absolute_address, false, bytes, size, error);
+ target_sp->ReadMemory(absolute_address, bytes, size, error, true);
return;
}
diff --git a/lldb/source/Expression/LLVMUserExpression.cpp b/lldb/source/Expression/LLVMUserExpression.cpp
index 187b427e66aa..527dff8bf60f 100644
--- a/lldb/source/Expression/LLVMUserExpression.cpp
+++ b/lldb/source/Expression/LLVMUserExpression.cpp
@@ -188,9 +188,8 @@ LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager,
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)
+ if (user_expression_plan) {
+ if (auto real_stop_info_sp = user_expression_plan->GetRealStopInfo())
error_desc = real_stop_info_sp->GetDescription();
}
if (error_desc)
diff --git a/lldb/source/Expression/Materializer.cpp b/lldb/source/Expression/Materializer.cpp
index a93c127dd0d0..3945f3a70f75 100644
--- a/lldb/source/Expression/Materializer.cpp
+++ b/lldb/source/Expression/Materializer.cpp
@@ -794,13 +794,15 @@ public:
llvm::Optional<uint64_t> byte_size = m_type.GetByteSize(exe_scope);
if (!byte_size) {
- err.SetErrorString("can't get size of type");
+ err.SetErrorStringWithFormat("can't get size of type \"%s\"",
+ m_type.GetTypeName().AsCString());
return;
}
llvm::Optional<size_t> opt_bit_align = m_type.GetTypeBitAlign(exe_scope);
if (!opt_bit_align) {
- err.SetErrorString("can't get the type alignment");
+ err.SetErrorStringWithFormat("can't get the alignment of type \"%s\"",
+ m_type.GetTypeName().AsCString());
return;
}
diff --git a/lldb/source/Expression/UserExpression.cpp b/lldb/source/Expression/UserExpression.cpp
index 5beed4657b37..eac89c24bc1e 100644
--- a/lldb/source/Expression/UserExpression.cpp
+++ b/lldb/source/Expression/UserExpression.cpp
@@ -8,7 +8,7 @@
#include "lldb/Host/Config.h"
-#include <stdio.h>
+#include <cstdio>
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -57,7 +57,7 @@ UserExpression::UserExpression(ExecutionContextScope &exe_scope,
m_expr_prefix(std::string(prefix)), m_language(language),
m_desired_type(desired_type), m_options(options) {}
-UserExpression::~UserExpression() {}
+UserExpression::~UserExpression() = default;
void UserExpression::InstallContext(ExecutionContext &exe_ctx) {
m_jit_process_wp = exe_ctx.GetProcessSP();
@@ -187,7 +187,12 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx,
}
}
- if (process == nullptr || !process->CanJIT())
+ // Explicitly force the IR interpreter to evaluate the expression when the
+ // there is no process that supports running the expression for us. Don't
+ // change the execution policy if we have the special top-level policy that
+ // doesn't contain any expression and there is nothing to interpret.
+ if (execution_policy != eExecutionPolicyTopLevel &&
+ (process == nullptr || !process->CanJIT()))
execution_policy = eExecutionPolicyNever;
// We need to set the expression execution thread here, turns out parse can
@@ -297,19 +302,19 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx,
}
if (!parse_success) {
- if (!fixed_expression->empty() && target->GetEnableNotifyAboutFixIts()) {
- error.SetExpressionErrorWithFormat(
- execution_results,
- "expression failed to parse, fixed expression suggested:\n %s",
- fixed_expression->c_str());
- } else {
- if (!diagnostic_manager.Diagnostics().size())
- error.SetExpressionError(execution_results,
- "expression failed to parse, unknown error");
+ std::string msg;
+ {
+ llvm::raw_string_ostream os(msg);
+ os << "expression failed to parse:\n";
+ if (!diagnostic_manager.Diagnostics().empty())
+ os << diagnostic_manager.GetString();
else
- error.SetExpressionError(execution_results,
- diagnostic_manager.GetString().c_str());
+ os << "unknown error";
+ if (target->GetEnableNotifyAboutFixIts() && fixed_expression &&
+ !fixed_expression->empty())
+ os << "\nfixed expression suggested:\n " << *fixed_expression;
}
+ error.SetExpressionError(execution_results, msg.c_str());
}
}
@@ -362,7 +367,7 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx,
LLDB_LOG(log,
"== [UserExpression::Evaluate] Execution completed "
- "normally with result %s ==",
+ "normally with result {0} ==",
result_valobj_sp->GetValueAsCString());
} else {
LLDB_LOG(log, "== [UserExpression::Evaluate] Execution completed "
diff --git a/lldb/source/Expression/UtilityFunction.cpp b/lldb/source/Expression/UtilityFunction.cpp
index 128db0ccbc3e..d7a89a8e1446 100644
--- a/lldb/source/Expression/UtilityFunction.cpp
+++ b/lldb/source/Expression/UtilityFunction.cpp
@@ -8,7 +8,7 @@
#include "lldb/Host/Config.h"
-#include <stdio.h>
+#include <cstdio>
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -41,7 +41,8 @@ char UtilityFunction::ID;
/// \param[in] name
/// The name of the function, as used in the text.
UtilityFunction::UtilityFunction(ExecutionContextScope &exe_scope,
- std::string text, std::string name)
+ std::string text, std::string name,
+ bool enable_debugging)
: Expression(exe_scope), m_execution_unit_sp(), m_jit_module_wp(),
m_function_text(std::move(text)), m_function_name(std::move(name)) {}
diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp
index 026a05da45b2..a5598c387b8c 100644
--- a/lldb/source/Host/common/Editline.cpp
+++ b/lldb/source/Host/common/Editline.cpp
@@ -6,11 +6,12 @@
//
//===----------------------------------------------------------------------===//
+#include <climits>
#include <iomanip>
-#include <limits.h>
-#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Editline.h"
+
+#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Utility/CompletionRequest.h"
@@ -152,6 +153,11 @@ std::vector<EditLineStringType> SplitLines(const EditLineStringType &input) {
result.push_back(input.substr(start, end - start));
start = end + 1;
}
+ // Treat an empty history session as a single command of zero-length instead
+ // of returning an empty vector.
+ if (result.empty()) {
+ result.emplace_back();
+ }
return result;
}
@@ -641,8 +647,7 @@ unsigned char Editline::BreakLineCommand(int ch) {
lines.AppendString(new_line_fragment);
#endif
- int indent_correction = m_fix_indentation_callback(
- this, lines, 0, m_fix_indentation_callback_baton);
+ int indent_correction = m_fix_indentation_callback(this, lines, 0);
new_line_fragment = FixIndentation(new_line_fragment, indent_correction);
m_revert_cursor_index = GetIndentation(new_line_fragment);
}
@@ -677,8 +682,7 @@ unsigned char Editline::EndOrAddLineCommand(int ch) {
info->cursor == info->lastchar) {
if (m_is_input_complete_callback) {
auto lines = GetInputAsStringList();
- if (!m_is_input_complete_callback(this, lines,
- m_is_input_complete_callback_baton)) {
+ if (!m_is_input_complete_callback(this, lines)) {
return BreakLineCommand(ch);
}
@@ -811,8 +815,7 @@ unsigned char Editline::NextLineCommand(int ch) {
if (m_fix_indentation_callback) {
StringList lines = GetInputAsStringList();
lines.AppendString("");
- indentation = m_fix_indentation_callback(
- this, lines, 0, m_fix_indentation_callback_baton);
+ indentation = m_fix_indentation_callback(this, lines, 0);
}
m_input_lines.insert(
m_input_lines.end(),
@@ -857,8 +860,8 @@ unsigned char Editline::FixIndentationCommand(int ch) {
// Save the edits and determine the correct indentation level
SaveEditedLine();
StringList lines = GetInputAsStringList(m_current_line_index + 1);
- int indent_correction = m_fix_indentation_callback(
- this, lines, cursor_position, m_fix_indentation_callback_baton);
+ int indent_correction =
+ m_fix_indentation_callback(this, lines, cursor_position);
// If it is already correct no special work is needed
if (indent_correction == 0)
@@ -977,7 +980,7 @@ DisplayCompletions(::EditLine *editline, FILE *output_file,
}
unsigned char Editline::TabCommand(int ch) {
- if (m_completion_callback == nullptr)
+ if (!m_completion_callback)
return CC_ERROR;
const LineInfo *line_info = el_line(m_editline);
@@ -988,7 +991,7 @@ unsigned char Editline::TabCommand(int ch) {
CompletionResult result;
CompletionRequest request(line, cursor_index, result);
- m_completion_callback(request, m_completion_callback_baton);
+ m_completion_callback(request);
llvm::ArrayRef<CompletionResult::Completion> results = result.GetResults();
@@ -1047,12 +1050,15 @@ unsigned char Editline::TabCommand(int ch) {
}
unsigned char Editline::ApplyAutosuggestCommand(int ch) {
+ if (!m_suggestion_callback) {
+ return CC_REDISPLAY;
+ }
+
const LineInfo *line_info = el_line(m_editline);
llvm::StringRef line(line_info->buffer,
line_info->lastchar - line_info->buffer);
- if (llvm::Optional<std::string> to_add =
- m_suggestion_callback(line, m_suggestion_callback_baton))
+ if (llvm::Optional<std::string> to_add = m_suggestion_callback(line))
el_insertstr(m_editline, to_add->c_str());
return CC_REDISPLAY;
@@ -1061,12 +1067,16 @@ unsigned char Editline::ApplyAutosuggestCommand(int ch) {
unsigned char Editline::TypedCharacter(int ch) {
std::string typed = std::string(1, ch);
el_insertstr(m_editline, typed.c_str());
+
+ if (!m_suggestion_callback) {
+ return CC_REDISPLAY;
+ }
+
const LineInfo *line_info = el_line(m_editline);
llvm::StringRef line(line_info->buffer,
line_info->lastchar - line_info->buffer);
- if (llvm::Optional<std::string> to_add =
- m_suggestion_callback(line, m_suggestion_callback_baton)) {
+ if (llvm::Optional<std::string> to_add = m_suggestion_callback(line)) {
std::string to_add_color = ANSI_FAINT + to_add.getValue() + ANSI_UNFAINT;
fputs(typed.c_str(), m_output_file);
fputs(to_add_color.c_str(), m_output_file);
@@ -1092,6 +1102,21 @@ unsigned char Editline::TypedCharacter(int ch) {
return CC_REDISPLAY;
}
+void Editline::AddFunctionToEditLine(const EditLineCharType *command,
+ const EditLineCharType *helptext,
+ EditlineCommandCallbackType callbackFn) {
+ el_wset(m_editline, EL_ADDFN, command, helptext, callbackFn);
+}
+
+void Editline::SetEditLinePromptCallback(
+ EditlinePromptCallbackType callbackFn) {
+ el_set(m_editline, EL_PROMPT, callbackFn);
+}
+
+void Editline::SetGetCharacterFunction(EditlineGetCharCallbackType callbackFn) {
+ el_wset(m_editline, EL_GETCFN, callbackFn);
+}
+
void Editline::ConfigureEditor(bool multiline) {
if (m_editline && m_multiline_enabled == multiline)
return;
@@ -1118,74 +1143,83 @@ void Editline::ConfigureEditor(bool multiline) {
el_set(m_editline, EL_CLIENTDATA, this);
el_set(m_editline, EL_SIGNAL, 0);
el_set(m_editline, EL_EDITOR, "emacs");
- el_set(m_editline, EL_PROMPT,
- (EditlinePromptCallbackType)([](EditLine *editline) {
- return Editline::InstanceFor(editline)->Prompt();
- }));
- el_wset(m_editline, EL_GETCFN, (EditlineGetCharCallbackType)([](
- EditLine *editline, EditLineGetCharType *c) {
- return Editline::InstanceFor(editline)->GetCharacter(c);
- }));
+ SetGetCharacterFunction([](EditLine *editline, EditLineGetCharType *c) {
+ return Editline::InstanceFor(editline)->GetCharacter(c);
+ });
+
+ SetEditLinePromptCallback([](EditLine *editline) {
+ return Editline::InstanceFor(editline)->Prompt();
+ });
// Commands used for multiline support, registered whether or not they're
// used
- el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-break-line"),
- EditLineConstString("Insert a line break"),
- (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
- return Editline::InstanceFor(editline)->BreakLineCommand(ch);
- }));
- el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-end-or-add-line"),
- EditLineConstString("End editing or continue when incomplete"),
- (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
- return Editline::InstanceFor(editline)->EndOrAddLineCommand(ch);
- }));
- el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-delete-next-char"),
- EditLineConstString("Delete next character"),
- (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
- return Editline::InstanceFor(editline)->DeleteNextCharCommand(ch);
- }));
- el_wset(
- m_editline, EL_ADDFN, EditLineConstString("lldb-delete-previous-char"),
+ AddFunctionToEditLine(
+ EditLineConstString("lldb-break-line"),
+ EditLineConstString("Insert a line break"),
+ [](EditLine *editline, int ch) {
+ return Editline::InstanceFor(editline)->BreakLineCommand(ch);
+ });
+
+ AddFunctionToEditLine(
+ EditLineConstString("lldb-end-or-add-line"),
+ EditLineConstString("End editing or continue when incomplete"),
+ [](EditLine *editline, int ch) {
+ return Editline::InstanceFor(editline)->EndOrAddLineCommand(ch);
+ });
+ AddFunctionToEditLine(
+ EditLineConstString("lldb-delete-next-char"),
+ EditLineConstString("Delete next character"),
+ [](EditLine *editline, int ch) {
+ return Editline::InstanceFor(editline)->DeleteNextCharCommand(ch);
+ });
+ AddFunctionToEditLine(
+ EditLineConstString("lldb-delete-previous-char"),
EditLineConstString("Delete previous character"),
- (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
+ [](EditLine *editline, int ch) {
return Editline::InstanceFor(editline)->DeletePreviousCharCommand(ch);
- }));
- el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-previous-line"),
- EditLineConstString("Move to previous line"),
- (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
- return Editline::InstanceFor(editline)->PreviousLineCommand(ch);
- }));
- el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-next-line"),
- EditLineConstString("Move to next line"),
- (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
- return Editline::InstanceFor(editline)->NextLineCommand(ch);
- }));
- el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-previous-history"),
- EditLineConstString("Move to previous history"),
- (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
- return Editline::InstanceFor(editline)->PreviousHistoryCommand(ch);
- }));
- el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-next-history"),
- EditLineConstString("Move to next history"),
- (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
- return Editline::InstanceFor(editline)->NextHistoryCommand(ch);
- }));
- el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-start"),
- EditLineConstString("Move to start of buffer"),
- (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
- return Editline::InstanceFor(editline)->BufferStartCommand(ch);
- }));
- el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-end"),
- EditLineConstString("Move to end of buffer"),
- (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
- return Editline::InstanceFor(editline)->BufferEndCommand(ch);
- }));
- el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-fix-indentation"),
- EditLineConstString("Fix line indentation"),
- (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
- return Editline::InstanceFor(editline)->FixIndentationCommand(ch);
- }));
+ });
+ AddFunctionToEditLine(
+ EditLineConstString("lldb-previous-line"),
+ EditLineConstString("Move to previous line"),
+ [](EditLine *editline, int ch) {
+ return Editline::InstanceFor(editline)->PreviousLineCommand(ch);
+ });
+ AddFunctionToEditLine(
+ EditLineConstString("lldb-next-line"),
+ EditLineConstString("Move to next line"), [](EditLine *editline, int ch) {
+ return Editline::InstanceFor(editline)->NextLineCommand(ch);
+ });
+ AddFunctionToEditLine(
+ EditLineConstString("lldb-previous-history"),
+ EditLineConstString("Move to previous history"),
+ [](EditLine *editline, int ch) {
+ return Editline::InstanceFor(editline)->PreviousHistoryCommand(ch);
+ });
+ AddFunctionToEditLine(
+ EditLineConstString("lldb-next-history"),
+ EditLineConstString("Move to next history"),
+ [](EditLine *editline, int ch) {
+ return Editline::InstanceFor(editline)->NextHistoryCommand(ch);
+ });
+ AddFunctionToEditLine(
+ EditLineConstString("lldb-buffer-start"),
+ EditLineConstString("Move to start of buffer"),
+ [](EditLine *editline, int ch) {
+ return Editline::InstanceFor(editline)->BufferStartCommand(ch);
+ });
+ AddFunctionToEditLine(
+ EditLineConstString("lldb-buffer-end"),
+ EditLineConstString("Move to end of buffer"),
+ [](EditLine *editline, int ch) {
+ return Editline::InstanceFor(editline)->BufferEndCommand(ch);
+ });
+ AddFunctionToEditLine(
+ EditLineConstString("lldb-fix-indentation"),
+ EditLineConstString("Fix line indentation"),
+ [](EditLine *editline, int ch) {
+ return Editline::InstanceFor(editline)->FixIndentationCommand(ch);
+ });
// Register the complete callback under two names for compatibility with
// older clients using custom .editrc files (largely because libedit has a
@@ -1196,10 +1230,12 @@ void Editline::ConfigureEditor(bool multiline) {
int ch) {
return Editline::InstanceFor(editline)->TabCommand(ch);
};
- el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-complete"),
- EditLineConstString("Invoke completion"), complete_callback);
- el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb_complete"),
- EditLineConstString("Invoke completion"), complete_callback);
+ AddFunctionToEditLine(EditLineConstString("lldb-complete"),
+ EditLineConstString("Invoke completion"),
+ complete_callback);
+ AddFunctionToEditLine(EditLineConstString("lldb_complete"),
+ EditLineConstString("Invoke completion"),
+ complete_callback);
// General bindings we don't mind being overridden
if (!multiline) {
@@ -1207,21 +1243,22 @@ void Editline::ConfigureEditor(bool multiline) {
NULL); // Cycle through backwards search, entering string
if (m_suggestion_callback) {
- el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-apply-complete"),
- EditLineConstString("Adopt autocompletion"),
- (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
- return Editline::InstanceFor(editline)->ApplyAutosuggestCommand(
- ch);
- }));
+ AddFunctionToEditLine(
+ EditLineConstString("lldb-apply-complete"),
+ EditLineConstString("Adopt autocompletion"),
+ [](EditLine *editline, int ch) {
+ return Editline::InstanceFor(editline)->ApplyAutosuggestCommand(ch);
+ });
el_set(m_editline, EL_BIND, "^f", "lldb-apply-complete",
NULL); // Apply a part that is suggested automatically
- el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-typed-character"),
- EditLineConstString("Typed character"),
- (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
- return Editline::InstanceFor(editline)->TypedCharacter(ch);
- }));
+ AddFunctionToEditLine(
+ EditLineConstString("lldb-typed-character"),
+ EditLineConstString("Typed character"),
+ [](EditLine *editline, int ch) {
+ return Editline::InstanceFor(editline)->TypedCharacter(ch);
+ });
char bind_key[2] = {0, 0};
llvm::StringRef ascii_chars =
@@ -1256,11 +1293,12 @@ void Editline::ConfigureEditor(bool multiline) {
el_source(m_editline, nullptr);
// Register an internal binding that external developers shouldn't use
- el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-revert-line"),
- EditLineConstString("Revert line to saved state"),
- (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
- return Editline::InstanceFor(editline)->RevertLineCommand(ch);
- }));
+ AddFunctionToEditLine(
+ EditLineConstString("lldb-revert-line"),
+ EditLineConstString("Revert line to saved state"),
+ [](EditLine *editline, int ch) {
+ return Editline::InstanceFor(editline)->RevertLineCommand(ch);
+ });
// Register keys that perform auto-indent correction
if (m_fix_indentation_callback && m_fix_indentation_callback_chars) {
@@ -1447,33 +1485,6 @@ bool Editline::Cancel() {
return result;
}
-void Editline::SetSuggestionCallback(SuggestionCallbackType callback,
- void *baton) {
- m_suggestion_callback = callback;
- m_suggestion_callback_baton = baton;
-}
-
-void Editline::SetAutoCompleteCallback(CompleteCallbackType callback,
- void *baton) {
- m_completion_callback = callback;
- m_completion_callback_baton = baton;
-}
-
-void Editline::SetIsInputCompleteCallback(IsInputCompleteCallbackType callback,
- void *baton) {
- m_is_input_complete_callback = callback;
- m_is_input_complete_callback_baton = baton;
-}
-
-bool Editline::SetFixIndentationCallback(FixIndentationCallbackType callback,
- void *baton,
- const char *indent_chars) {
- m_fix_indentation_callback = callback;
- m_fix_indentation_callback_baton = baton;
- m_fix_indentation_callback_chars = indent_chars;
- return false;
-}
-
bool Editline::GetLine(std::string &line, bool &interrupted) {
ConfigureEditor(false);
m_input_lines = std::vector<EditLineStringType>();
diff --git a/lldb/source/Host/common/File.cpp b/lldb/source/Host/common/File.cpp
index a5b970907e64..e302e0a0de09 100644
--- a/lldb/source/Host/common/File.cpp
+++ b/lldb/source/Host/common/File.cpp
@@ -8,11 +8,11 @@
#include "lldb/Host/File.h"
-#include <errno.h>
+#include <cerrno>
+#include <climits>
+#include <cstdarg>
+#include <cstdio>
#include <fcntl.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdio.h>
#ifdef _WIN32
#include "lldb/Host/windows/windows.h"
diff --git a/lldb/source/Host/common/FileAction.cpp b/lldb/source/Host/common/FileAction.cpp
index 8b4e7f4c2208..e399c7ec47cd 100644
--- a/lldb/source/Host/common/FileAction.cpp
+++ b/lldb/source/Host/common/FileAction.cpp
@@ -16,8 +16,7 @@ using namespace lldb_private;
// FileAction member functions
-FileAction::FileAction()
- : m_action(eFileActionNone), m_fd(-1), m_arg(-1), m_file_spec() {}
+FileAction::FileAction() : m_file_spec() {}
void FileAction::Clear() {
m_action = eFileActionNone;
diff --git a/lldb/source/Host/common/FileSystem.cpp b/lldb/source/Host/common/FileSystem.cpp
index 9fa8854d950e..a2c3b3556a6c 100644
--- a/lldb/source/Host/common/FileSystem.cpp
+++ b/lldb/source/Host/common/FileSystem.cpp
@@ -19,11 +19,11 @@
#include "llvm/Support/Program.h"
#include "llvm/Support/Threading.h"
-#include <errno.h>
+#include <cerrno>
+#include <climits>
+#include <cstdarg>
+#include <cstdio>
#include <fcntl.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdio.h>
#ifdef _WIN32
#include "lldb/Host/windows/windows.h"
@@ -307,7 +307,7 @@ FileSystem::CreateDataBuffer(const llvm::Twine &path, uint64_t size,
std::unique_ptr<llvm::WritableMemoryBuffer> buffer;
if (size == 0) {
auto buffer_or_error =
- llvm::WritableMemoryBuffer::getFile(*external_path, -1, is_volatile);
+ llvm::WritableMemoryBuffer::getFile(*external_path, is_volatile);
if (!buffer_or_error)
return nullptr;
buffer = std::move(*buffer_or_error);
@@ -478,20 +478,18 @@ ErrorOr<std::string> FileSystem::GetExternalPath(const llvm::Twine &path) {
return path.str();
// If VFS mapped we know the underlying FS is a RedirectingFileSystem.
- ErrorOr<vfs::RedirectingFileSystem::Entry *> E =
+ ErrorOr<vfs::RedirectingFileSystem::LookupResult> Result =
static_cast<vfs::RedirectingFileSystem &>(*m_fs).lookupPath(path.str());
- if (!E) {
- if (E.getError() == llvm::errc::no_such_file_or_directory) {
+ if (!Result) {
+ if (Result.getError() == llvm::errc::no_such_file_or_directory) {
return path.str();
}
- return E.getError();
+ return Result.getError();
}
- auto *F = dyn_cast<vfs::RedirectingFileSystem::RedirectingFileEntry>(*E);
- if (!F)
- return make_error_code(llvm::errc::not_supported);
-
- return F->getExternalContentsPath().str();
+ if (Optional<StringRef> ExtRedirect = Result->getExternalRedirect())
+ return std::string(*ExtRedirect);
+ return make_error_code(llvm::errc::not_supported);
}
ErrorOr<std::string> FileSystem::GetExternalPath(const FileSpec &file_spec) {
diff --git a/lldb/source/Host/common/GetOptInc.cpp b/lldb/source/Host/common/GetOptInc.cpp
index 62ce7428e8cc..c2044b687322 100644
--- a/lldb/source/Host/common/GetOptInc.cpp
+++ b/lldb/source/Host/common/GetOptInc.cpp
@@ -12,9 +12,9 @@
defined(REPLACE_GETOPT_LONG_ONLY)
// getopt.cpp
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
+#include <cerrno>
+#include <cstdlib>
+#include <cstring>
#if defined(REPLACE_GETOPT)
int opterr = 1; /* if error message should be printed */
diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp
index 99316660908e..d14ebe99fd15 100644
--- a/lldb/source/Host/common/Host.cpp
+++ b/lldb/source/Host/common/Host.cpp
@@ -7,9 +7,9 @@
//===----------------------------------------------------------------------===//
// C includes
-#include <errno.h>
-#include <limits.h>
-#include <stdlib.h>
+#include <cerrno>
+#include <climits>
+#include <cstdlib>
#include <sys/types.h>
#ifndef _WIN32
#include <dlfcn.h>
@@ -442,14 +442,12 @@ bool Host::FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach) {
#endif
struct ShellInfo {
- ShellInfo()
- : process_reaped(false), pid(LLDB_INVALID_PROCESS_ID), signo(-1),
- status(-1) {}
+ ShellInfo() : process_reaped(false) {}
lldb_private::Predicate<bool> process_reaped;
- lldb::pid_t pid;
- int signo;
- int status;
+ lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+ int signo = -1;
+ int status = -1;
};
static bool
diff --git a/lldb/source/Host/common/HostInfoBase.cpp b/lldb/source/Host/common/HostInfoBase.cpp
index 333137a7fd25..a6239a3208bc 100644
--- a/lldb/source/Host/common/HostInfoBase.cpp
+++ b/lldb/source/Host/common/HostInfoBase.cpp
@@ -31,12 +31,7 @@ using namespace lldb;
using namespace lldb_private;
namespace {
-// The HostInfoBaseFields is a work around for windows not supporting static
-// variables correctly in a thread safe way. Really each of the variables in
-// HostInfoBaseFields should live in the functions in which they are used and
-// each one should be static, but the work around is in place to avoid this
-// restriction. Ick.
-
+/// Contains the state of the HostInfoBase plugin.
struct HostInfoBaseFields {
~HostInfoBaseFields() {
if (FileSystem::Instance().Exists(m_lldb_process_tmp_dir)) {
@@ -71,13 +66,18 @@ struct HostInfoBaseFields {
llvm::once_flag m_lldb_global_tmp_dir_once;
FileSpec m_lldb_global_tmp_dir;
};
+} // namespace
-HostInfoBaseFields *g_fields = nullptr;
-}
+static HostInfoBaseFields *g_fields = nullptr;
+static HostInfoBase::SharedLibraryDirectoryHelper *g_shlib_dir_helper = nullptr;
-void HostInfoBase::Initialize() { g_fields = new HostInfoBaseFields(); }
+void HostInfoBase::Initialize(SharedLibraryDirectoryHelper *helper) {
+ g_shlib_dir_helper = helper;
+ g_fields = new HostInfoBaseFields();
+}
void HostInfoBase::Terminate() {
+ g_shlib_dir_helper = nullptr;
delete g_fields;
g_fields = nullptr;
}
@@ -249,9 +249,8 @@ bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) {
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.
- FileSystem::Instance().ResolveSymbolicLink(lldb_file_spec, lldb_file_spec);
+ if (g_shlib_dir_helper)
+ g_shlib_dir_helper(lldb_file_spec);
// Remove the filename so that this FileSpec only represents the directory.
file_spec.GetDirectory() = lldb_file_spec.GetDirectory();
diff --git a/lldb/source/Host/common/HostNativeThreadBase.cpp b/lldb/source/Host/common/HostNativeThreadBase.cpp
index a79431f61d88..b15160b143ca 100644
--- a/lldb/source/Host/common/HostNativeThreadBase.cpp
+++ b/lldb/source/Host/common/HostNativeThreadBase.cpp
@@ -17,9 +17,6 @@
using namespace lldb;
using namespace lldb_private;
-HostNativeThreadBase::HostNativeThreadBase()
- : m_thread(LLDB_INVALID_HOST_THREAD), m_result(0) {}
-
HostNativeThreadBase::HostNativeThreadBase(thread_t thread)
: m_thread(thread), m_result(0) {}
diff --git a/lldb/source/Host/common/HostProcess.cpp b/lldb/source/Host/common/HostProcess.cpp
index 256a73bb6716..06dd192013ba 100644
--- a/lldb/source/Host/common/HostProcess.cpp
+++ b/lldb/source/Host/common/HostProcess.cpp
@@ -18,7 +18,7 @@ HostProcess::HostProcess() : m_native_process(new HostNativeProcess) {}
HostProcess::HostProcess(lldb::process_t process)
: m_native_process(new HostNativeProcess(process)) {}
-HostProcess::~HostProcess() {}
+HostProcess::~HostProcess() = default;
Status HostProcess::Terminate() { return m_native_process->Terminate(); }
diff --git a/lldb/source/Host/common/MainLoop.cpp b/lldb/source/Host/common/MainLoop.cpp
index 02cabbc93550..d36587ce2346 100644
--- a/lldb/source/Host/common/MainLoop.cpp
+++ b/lldb/source/Host/common/MainLoop.cpp
@@ -16,7 +16,7 @@
#include <cassert>
#include <cerrno>
#include <csignal>
-#include <time.h>
+#include <ctime>
#include <vector>
// Multiplexing is implemented using kqueue on systems that support it (BSD
@@ -302,13 +302,15 @@ MainLoop::RegisterSignal(int signo, const Callback &callback, Status &error) {
error.SetErrorString("Signal polling is not supported on this platform.");
return nullptr;
#else
- if (m_signals.find(signo) != m_signals.end()) {
- error.SetErrorStringWithFormat("Signal %d already monitored.", signo);
- return nullptr;
+ auto signal_it = m_signals.find(signo);
+ if (signal_it != m_signals.end()) {
+ auto callback_it = signal_it->second.callbacks.insert(
+ signal_it->second.callbacks.end(), callback);
+ return SignalHandleUP(new SignalHandle(*this, signo, callback_it));
}
SignalInfo info;
- info.callback = callback;
+ info.callbacks.push_back(callback);
struct sigaction new_action;
new_action.sa_sigaction = &SignalHandler;
new_action.sa_flags = SA_SIGINFO;
@@ -338,9 +340,10 @@ MainLoop::RegisterSignal(int signo, const Callback &callback, Status &error) {
&new_action.sa_mask, &old_set);
assert(ret == 0 && "pthread_sigmask failed");
info.was_blocked = sigismember(&old_set, signo);
- m_signals.insert({signo, info});
+ auto insert_ret = m_signals.insert({signo, info});
- return SignalHandleUP(new SignalHandle(*this, signo));
+ return SignalHandleUP(new SignalHandle(
+ *this, signo, insert_ret.first->second.callbacks.begin()));
#endif
}
@@ -350,13 +353,19 @@ void MainLoop::UnregisterReadObject(IOObject::WaitableHandle handle) {
assert(erased);
}
-void MainLoop::UnregisterSignal(int signo) {
+void MainLoop::UnregisterSignal(int signo,
+ std::list<Callback>::iterator callback_it) {
#if SIGNAL_POLLING_UNSUPPORTED
Status("Signal polling is not supported on this platform.");
#else
auto it = m_signals.find(signo);
assert(it != m_signals.end());
+ it->second.callbacks.erase(callback_it);
+ // Do not remove the signal handler unless all callbacks have been erased.
+ if (!it->second.callbacks.empty())
+ return;
+
sigaction(signo, &it->second.old_action, nullptr);
sigset_t set;
@@ -398,8 +407,14 @@ Status MainLoop::Run() {
void MainLoop::ProcessSignal(int signo) {
auto it = m_signals.find(signo);
- if (it != m_signals.end())
- it->second.callback(*this); // Do the work
+ if (it != m_signals.end()) {
+ // The callback may actually register/unregister signal handlers,
+ // so we need to create a copy first.
+ llvm::SmallVector<Callback, 4> callbacks_to_run{
+ it->second.callbacks.begin(), it->second.callbacks.end()};
+ for (auto &x : callbacks_to_run)
+ x(*this); // Do the work
+ }
}
void MainLoop::ProcessReadObject(IOObject::WaitableHandle handle) {
diff --git a/lldb/source/Host/common/NativeProcessProtocol.cpp b/lldb/source/Host/common/NativeProcessProtocol.cpp
index 493e14cb904b..ea80a05430f7 100644
--- a/lldb/source/Host/common/NativeProcessProtocol.cpp
+++ b/lldb/source/Host/common/NativeProcessProtocol.cpp
@@ -25,10 +25,8 @@ using namespace lldb_private;
NativeProcessProtocol::NativeProcessProtocol(lldb::pid_t pid, int terminal_fd,
NativeDelegate &delegate)
- : m_pid(pid), m_terminal_fd(terminal_fd) {
- bool registered = RegisterNativeDelegate(delegate);
- assert(registered);
- (void)registered;
+ : m_pid(pid), m_delegate(delegate), m_terminal_fd(terminal_fd) {
+ delegate.InitializeDelegate(this);
}
lldb_private::Status NativeProcessProtocol::Interrupt() {
@@ -54,6 +52,19 @@ NativeProcessProtocol::GetMemoryRegionInfo(lldb::addr_t load_addr,
return Status("not implemented");
}
+lldb_private::Status
+NativeProcessProtocol::ReadMemoryTags(int32_t type, lldb::addr_t addr,
+ size_t len, std::vector<uint8_t> &tags) {
+ return Status("not implemented");
+}
+
+lldb_private::Status
+NativeProcessProtocol::WriteMemoryTags(int32_t type, lldb::addr_t addr,
+ size_t len,
+ const std::vector<uint8_t> &tags) {
+ return Status("not implemented");
+}
+
llvm::Optional<WaitStatus> NativeProcessProtocol::GetExitStatus() {
if (m_state == lldb::eStateExited)
return m_exit_status;
@@ -295,64 +306,21 @@ Status NativeProcessProtocol::RemoveHardwareBreakpoint(lldb::addr_t addr) {
return error;
}
-bool NativeProcessProtocol::RegisterNativeDelegate(
- NativeDelegate &native_delegate) {
- std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex);
- if (llvm::is_contained(m_delegates, &native_delegate))
- return false;
-
- m_delegates.push_back(&native_delegate);
- native_delegate.InitializeDelegate(this);
- return true;
-}
-
-bool NativeProcessProtocol::UnregisterNativeDelegate(
- NativeDelegate &native_delegate) {
- std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex);
-
- const auto initial_size = m_delegates.size();
- m_delegates.erase(
- remove(m_delegates.begin(), m_delegates.end(), &native_delegate),
- m_delegates.end());
-
- // We removed the delegate if the count of delegates shrank after removing
- // all copies of the given native_delegate from the vector.
- return m_delegates.size() < initial_size;
-}
-
void NativeProcessProtocol::SynchronouslyNotifyProcessStateChanged(
lldb::StateType state) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex);
- for (auto native_delegate : m_delegates)
- native_delegate->ProcessStateChanged(this, state);
+ m_delegate.ProcessStateChanged(this, state);
- if (log) {
- if (!m_delegates.empty()) {
- LLDB_LOGF(log,
- "NativeProcessProtocol::%s: sent state notification [%s] "
- "from process %" PRIu64,
- __FUNCTION__, lldb_private::StateAsCString(state), GetID());
- } else {
- LLDB_LOGF(log,
- "NativeProcessProtocol::%s: would send state notification "
- "[%s] from process %" PRIu64 ", but no delegates",
- __FUNCTION__, lldb_private::StateAsCString(state), GetID());
- }
- }
+ LLDB_LOG(log, "sent state notification [{0}] from process {1}", state,
+ GetID());
}
void NativeProcessProtocol::NotifyDidExec() {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- LLDB_LOGF(log, "NativeProcessProtocol::%s - preparing to call delegates",
- __FUNCTION__);
+ LLDB_LOG(log, "process {0} exec()ed", GetID());
- {
- std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex);
- for (auto native_delegate : m_delegates)
- native_delegate->DidExec(this);
- }
+ m_delegate.DidExec(this);
}
Status NativeProcessProtocol::SetSoftwareBreakpoint(lldb::addr_t addr,
@@ -522,7 +490,8 @@ NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {
static const uint8_t g_mips64_opcode[] = {0x00, 0x00, 0x00, 0x0d};
static const uint8_t g_mips64el_opcode[] = {0x0d, 0x00, 0x00, 0x00};
static const uint8_t g_s390x_opcode[] = {0x00, 0x01};
- static const uint8_t g_ppc64le_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap
+ static const uint8_t g_ppc_opcode[] = {0x7f, 0xe0, 0x00, 0x08}; // trap
+ static const uint8_t g_ppcle_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap
switch (GetArchitecture().GetMachine()) {
case llvm::Triple::aarch64:
@@ -544,8 +513,12 @@ NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {
case llvm::Triple::systemz:
return llvm::makeArrayRef(g_s390x_opcode);
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ return llvm::makeArrayRef(g_ppc_opcode);
+
case llvm::Triple::ppc64le:
- return llvm::makeArrayRef(g_ppc64le_opcode);
+ return llvm::makeArrayRef(g_ppcle_opcode);
default:
return llvm::createStringError(llvm::inconvertibleErrorCode(),
@@ -568,6 +541,8 @@ size_t NativeProcessProtocol::GetSoftwareBreakpointPCOffset() {
case llvm::Triple::mips64el:
case llvm::Triple::mips:
case llvm::Triple::mipsel:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
// On these architectures the PC doesn't get updated for breakpoint hits.
return 0;
diff --git a/lldb/source/Host/common/NativeRegisterContext.cpp b/lldb/source/Host/common/NativeRegisterContext.cpp
index 9bb877fff878..04d10aba4e63 100644
--- a/lldb/source/Host/common/NativeRegisterContext.cpp
+++ b/lldb/source/Host/common/NativeRegisterContext.cpp
@@ -22,7 +22,7 @@ NativeRegisterContext::NativeRegisterContext(NativeThreadProtocol &thread)
: m_thread(thread) {}
// Destructor
-NativeRegisterContext::~NativeRegisterContext() {}
+NativeRegisterContext::~NativeRegisterContext() = default;
// FIXME revisit invalidation, process stop ids, etc. Right now we don't
// support caching in NativeRegisterContext. We can do this later by utilizing
@@ -60,8 +60,8 @@ NativeRegisterContext::GetRegisterInfoByName(llvm::StringRef reg_name,
for (uint32_t reg = start_idx; reg < num_registers; ++reg) {
const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
- if (reg_name.equals_lower(reg_info->name) ||
- reg_name.equals_lower(reg_info->alt_name))
+ if (reg_name.equals_insensitive(reg_info->name) ||
+ reg_name.equals_insensitive(reg_info->alt_name))
return reg_info;
}
return nullptr;
diff --git a/lldb/source/Host/common/ProcessLaunchInfo.cpp b/lldb/source/Host/common/ProcessLaunchInfo.cpp
index 1b4b2c6c3ac2..8d281b80e8f0 100644
--- a/lldb/source/Host/common/ProcessLaunchInfo.cpp
+++ b/lldb/source/Host/common/ProcessLaunchInfo.cpp
@@ -20,7 +20,7 @@
#include "llvm/Support/FileSystem.h"
#if !defined(_WIN32)
-#include <limits.h>
+#include <climits>
#endif
using namespace lldb;
@@ -30,9 +30,9 @@ using namespace lldb_private;
ProcessLaunchInfo::ProcessLaunchInfo()
: ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(0),
- m_file_actions(), m_pty(new PseudoTerminal), m_resume_count(0),
- m_monitor_callback(nullptr), m_monitor_callback_baton(nullptr),
- m_monitor_signals(false), m_listener_sp(), m_hijack_listener_sp() {}
+ m_file_actions(), m_pty(new PseudoTerminal), m_monitor_callback(nullptr),
+ m_listener_sp(), m_hijack_listener_sp(), m_scripted_process_class_name(),
+ m_scripted_process_dictionary_sp() {}
ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec,
const FileSpec &stdout_file_spec,
@@ -42,7 +42,8 @@ ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec,
: ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(launch_flags),
m_file_actions(), m_pty(new PseudoTerminal), m_resume_count(0),
m_monitor_callback(nullptr), m_monitor_callback_baton(nullptr),
- m_monitor_signals(false), m_listener_sp(), m_hijack_listener_sp() {
+ m_monitor_signals(false), m_listener_sp(), m_hijack_listener_sp(),
+ m_scripted_process_class_name(), m_scripted_process_dictionary_sp() {
if (stdin_file_spec) {
FileAction file_action;
const bool read = true;
@@ -171,6 +172,8 @@ void ProcessLaunchInfo::Clear() {
m_resume_count = 0;
m_listener_sp.reset();
m_hijack_listener_sp.reset();
+ m_scripted_process_class_name.clear();
+ m_scripted_process_dictionary_sp.reset();
}
void ProcessLaunchInfo::SetMonitorProcessCallback(
diff --git a/lldb/source/Host/common/ProcessRunLock.cpp b/lldb/source/Host/common/ProcessRunLock.cpp
index 3b6f033d33ab..aee15779d919 100644
--- a/lldb/source/Host/common/ProcessRunLock.cpp
+++ b/lldb/source/Host/common/ProcessRunLock.cpp
@@ -11,7 +11,7 @@
namespace lldb_private {
-ProcessRunLock::ProcessRunLock() : m_running(false) {
+ProcessRunLock::ProcessRunLock() {
int err = ::pthread_rwlock_init(&m_rwlock, nullptr);
(void)err;
}
diff --git a/lldb/source/Host/common/PseudoTerminal.cpp b/lldb/source/Host/common/PseudoTerminal.cpp
index de76e8ab4f68..dce4c5185c7b 100644
--- a/lldb/source/Host/common/PseudoTerminal.cpp
+++ b/lldb/source/Host/common/PseudoTerminal.cpp
@@ -11,11 +11,11 @@
#include "llvm/Support/Errc.h"
#include "llvm/Support/Errno.h"
#include <cassert>
-#include <limits.h>
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
#include <mutex>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#if defined(TIOCSCTTY)
#include <sys/ioctl.h>
#endif
@@ -29,8 +29,7 @@ int posix_openpt(int flags);
using namespace lldb_private;
// PseudoTerminal constructor
-PseudoTerminal::PseudoTerminal()
- : m_primary_fd(invalid_fd), m_secondary_fd(invalid_fd) {}
+PseudoTerminal::PseudoTerminal() = default;
// Destructor
//
diff --git a/lldb/source/Host/common/Socket.cpp b/lldb/source/Host/common/Socket.cpp
index 4bcf34a6b456..d1c327dcb790 100644
--- a/lldb/source/Host/common/Socket.cpp
+++ b/lldb/source/Host/common/Socket.cpp
@@ -41,9 +41,9 @@
#ifdef __ANDROID__
#include <arpa/inet.h>
#include <asm-generic/errno-base.h>
-#include <errno.h>
-#include <linux/tcp.h>
+#include <cerrno>
#include <fcntl.h>
+#include <linux/tcp.h>
#include <sys/syscall.h>
#include <unistd.h>
#endif // __ANDROID__
diff --git a/lldb/source/Host/common/SocketAddress.cpp b/lldb/source/Host/common/SocketAddress.cpp
index e98944d6cdc8..3f47d32d4652 100644
--- a/lldb/source/Host/common/SocketAddress.cpp
+++ b/lldb/source/Host/common/SocketAddress.cpp
@@ -17,15 +17,15 @@
#endif
#include "lldb/Host/SocketAddress.h"
-#include <stddef.h>
-#include <stdio.h>
+#include <cstddef>
+#include <cstdio>
#if !defined(_WIN32)
#include <arpa/inet.h>
#endif
-#include <assert.h>
-#include <string.h>
+#include <cassert>
+#include <cstring>
#include "lldb/Host/PosixApi.h"
@@ -93,7 +93,7 @@ SocketAddress::SocketAddress(const struct addrinfo *addr_info) {
}
// Destructor
-SocketAddress::~SocketAddress() {}
+SocketAddress::~SocketAddress() = default;
void SocketAddress::Clear() {
memset(&m_socket_addr, 0, sizeof(m_socket_addr));
diff --git a/lldb/source/Host/common/StringConvert.cpp b/lldb/source/Host/common/StringConvert.cpp
index e5f05e628c7c..b4eb92755367 100644
--- a/lldb/source/Host/common/StringConvert.cpp
+++ b/lldb/source/Host/common/StringConvert.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <stdlib.h>
+#include <cstdlib>
#include "lldb/Host/StringConvert.h"
diff --git a/lldb/source/Host/common/Terminal.cpp b/lldb/source/Host/common/Terminal.cpp
index 9990dbf74356..2301abe9afb1 100644
--- a/lldb/source/Host/common/Terminal.cpp
+++ b/lldb/source/Host/common/Terminal.cpp
@@ -12,8 +12,8 @@
#include "lldb/Host/PosixApi.h"
#include "llvm/ADT/STLExtras.h"
+#include <csignal>
#include <fcntl.h>
-#include <signal.h>
#if LLDB_ENABLE_TERMIOS
#include <termios.h>
@@ -83,15 +83,16 @@ bool Terminal::SetCanonical(bool enabled) {
// Default constructor
TerminalState::TerminalState()
- : m_tty(), m_tflags(-1),
+ : m_tty()
#if LLDB_ENABLE_TERMIOS
- m_termios_up(),
+ ,
+ m_termios_up()
#endif
- m_process_group(-1) {
+{
}
// Destructor
-TerminalState::~TerminalState() {}
+TerminalState::~TerminalState() = default;
void TerminalState::Clear() {
m_tty.Clear();
@@ -189,10 +190,10 @@ bool TerminalState::ProcessGroupIsValid() const {
}
// Constructor
-TerminalStateSwitcher::TerminalStateSwitcher() : m_currentState(UINT32_MAX) {}
+TerminalStateSwitcher::TerminalStateSwitcher() = default;
// Destructor
-TerminalStateSwitcher::~TerminalStateSwitcher() {}
+TerminalStateSwitcher::~TerminalStateSwitcher() = default;
// Returns the number of states that this switcher contains
uint32_t TerminalStateSwitcher::GetNumberOfStates() const {
diff --git a/lldb/source/Host/common/XML.cpp b/lldb/source/Host/common/XML.cpp
index 456c879b0148..c3225d3f4433 100644
--- a/lldb/source/Host/common/XML.cpp
+++ b/lldb/source/Host/common/XML.cpp
@@ -17,7 +17,7 @@ using namespace lldb_private;
#pragma mark-- XMLDocument
-XMLDocument::XMLDocument() : m_document(nullptr) {}
+XMLDocument::XMLDocument() = default;
XMLDocument::~XMLDocument() { Clear(); }
@@ -91,11 +91,11 @@ bool XMLDocument::XMLEnabled() {
#pragma mark-- XMLNode
-XMLNode::XMLNode() : m_node(nullptr) {}
+XMLNode::XMLNode() = default;
XMLNode::XMLNode(XMLNodeImpl node) : m_node(node) {}
-XMLNode::~XMLNode() {}
+XMLNode::~XMLNode() = default;
void XMLNode::Clear() { m_node = nullptr; }
@@ -398,7 +398,7 @@ ApplePropertyList::ApplePropertyList(const char *path)
ParseFile(path);
}
-ApplePropertyList::~ApplePropertyList() {}
+ApplePropertyList::~ApplePropertyList() = default;
llvm::StringRef ApplePropertyList::GetErrors() const {
return m_xml_doc.GetErrors();
diff --git a/lldb/source/Host/freebsd/Host.cpp b/lldb/source/Host/freebsd/Host.cpp
index c0cc74a5f6cc..f93581651273 100644
--- a/lldb/source/Host/freebsd/Host.cpp
+++ b/lldb/source/Host/freebsd/Host.cpp
@@ -16,9 +16,9 @@
#include <machine/elf.h>
+#include <cstdio>
#include <dlfcn.h>
#include <execinfo.h>
-#include <stdio.h>
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
diff --git a/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp b/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp
index 2db97dbcd74c..1b9e3ccaf181 100644
--- a/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp
+++ b/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp
@@ -8,8 +8,8 @@
#include "lldb/Host/freebsd/HostInfoFreeBSD.h"
-#include <stdio.h>
-#include <string.h>
+#include <cstdio>
+#include <cstring>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/utsname.h>
diff --git a/lldb/source/Host/netbsd/HostInfoNetBSD.cpp b/lldb/source/Host/netbsd/HostInfoNetBSD.cpp
index cc01ec35a5bc..bddd46cec3ee 100644
--- a/lldb/source/Host/netbsd/HostInfoNetBSD.cpp
+++ b/lldb/source/Host/netbsd/HostInfoNetBSD.cpp
@@ -8,11 +8,11 @@
#include "lldb/Host/netbsd/HostInfoNetBSD.h"
-#include <inttypes.h>
-#include <limits.h>
+#include <cinttypes>
+#include <climits>
+#include <cstdio>
+#include <cstring>
#include <pthread.h>
-#include <stdio.h>
-#include <string.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/utsname.h>
diff --git a/lldb/source/Host/netbsd/HostNetBSD.cpp b/lldb/source/Host/netbsd/HostNetBSD.cpp
index 1945f9f9052f..af31a11a20a0 100644
--- a/lldb/source/Host/netbsd/HostNetBSD.cpp
+++ b/lldb/source/Host/netbsd/HostNetBSD.cpp
@@ -6,14 +6,14 @@
//
//===----------------------------------------------------------------------===//
+#include <cstdio>
#include <dlfcn.h>
#include <execinfo.h>
-#include <stdio.h>
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/types.h>
-#include <limits.h>
+#include <climits>
#include <kvm.h>
#include <sys/exec.h>
diff --git a/lldb/source/Host/openbsd/Host.cpp b/lldb/source/Host/openbsd/Host.cpp
index 4ce549522908..799a61adbf26 100644
--- a/lldb/source/Host/openbsd/Host.cpp
+++ b/lldb/source/Host/openbsd/Host.cpp
@@ -15,7 +15,7 @@
#include <sys/sysctl.h>
#include <sys/user.h>
-#include <stdio.h>
+#include <cstdio>
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
diff --git a/lldb/source/Host/openbsd/HostInfoOpenBSD.cpp b/lldb/source/Host/openbsd/HostInfoOpenBSD.cpp
index 58836333b63c..9617375babe1 100644
--- a/lldb/source/Host/openbsd/HostInfoOpenBSD.cpp
+++ b/lldb/source/Host/openbsd/HostInfoOpenBSD.cpp
@@ -8,8 +8,8 @@
#include "lldb/Host/openbsd/HostInfoOpenBSD.h"
-#include <stdio.h>
-#include <string.h>
+#include <cstdio>
+#include <cstring>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/utsname.h>
diff --git a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
index 3a547ce128d8..2f4cc960f02d 100644
--- a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
+++ b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
@@ -20,10 +20,10 @@
#include "lldb/Utility/SelectHelper.h"
#include "lldb/Utility/Timeout.h"
-#include <errno.h>
+#include <cerrno>
+#include <cstdlib>
+#include <cstring>
#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
#include <sys/types.h>
#if LLDB_ENABLE_POSIX
@@ -76,7 +76,7 @@ llvm::Optional<llvm::StringRef> GetURLAddress(llvm::StringRef url,
ConnectionFileDescriptor::ConnectionFileDescriptor(bool child_processes_inherit)
: Connection(), m_pipe(), m_mutex(), m_shutting_down(false),
- m_waiting_for_accept(false),
+
m_child_processes_inherit(child_processes_inherit) {
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION |
LIBLLDB_LOG_OBJECT));
diff --git a/lldb/source/Host/posix/DomainSocket.cpp b/lldb/source/Host/posix/DomainSocket.cpp
index 5a396906fdf6..7322b15200b4 100644
--- a/lldb/source/Host/posix/DomainSocket.cpp
+++ b/lldb/source/Host/posix/DomainSocket.cpp
@@ -11,7 +11,7 @@
#include "llvm/Support/Errno.h"
#include "llvm/Support/FileSystem.h"
-#include <stddef.h>
+#include <cstddef>
#include <sys/socket.h>
#include <sys/un.h>
diff --git a/lldb/source/Host/posix/HostInfoPosix.cpp b/lldb/source/Host/posix/HostInfoPosix.cpp
index 7e110f07d7cf..b633acf6fec6 100644
--- a/lldb/source/Host/posix/HostInfoPosix.cpp
+++ b/lldb/source/Host/posix/HostInfoPosix.cpp
@@ -15,11 +15,11 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
+#include <climits>
+#include <cstdlib>
#include <grp.h>
-#include <limits.h>
#include <mutex>
#include <pwd.h>
-#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
diff --git a/lldb/source/Host/posix/HostProcessPosix.cpp b/lldb/source/Host/posix/HostProcessPosix.cpp
index 69a049bcf7a2..f0142ec946b7 100644
--- a/lldb/source/Host/posix/HostProcessPosix.cpp
+++ b/lldb/source/Host/posix/HostProcessPosix.cpp
@@ -12,8 +12,8 @@
#include "llvm/ADT/STLExtras.h"
+#include <climits>
#include <csignal>
-#include <limits.h>
#include <unistd.h>
using namespace lldb_private;
@@ -28,7 +28,7 @@ HostProcessPosix::HostProcessPosix()
HostProcessPosix::HostProcessPosix(lldb::process_t process)
: HostNativeProcessBase(process) {}
-HostProcessPosix::~HostProcessPosix() {}
+HostProcessPosix::~HostProcessPosix() = default;
Status HostProcessPosix::Signal(int signo) const {
if (m_process == kInvalidPosixProcess) {
diff --git a/lldb/source/Host/posix/HostThreadPosix.cpp b/lldb/source/Host/posix/HostThreadPosix.cpp
index 31c7c7f8e2f3..4250e07e51cc 100644
--- a/lldb/source/Host/posix/HostThreadPosix.cpp
+++ b/lldb/source/Host/posix/HostThreadPosix.cpp
@@ -9,18 +9,18 @@
#include "lldb/Host/posix/HostThreadPosix.h"
#include "lldb/Utility/Status.h"
-#include <errno.h>
+#include <cerrno>
#include <pthread.h>
using namespace lldb;
using namespace lldb_private;
-HostThreadPosix::HostThreadPosix() {}
+HostThreadPosix::HostThreadPosix() = default;
HostThreadPosix::HostThreadPosix(lldb::thread_t thread)
: HostNativeThreadBase(thread) {}
-HostThreadPosix::~HostThreadPosix() {}
+HostThreadPosix::~HostThreadPosix() = default;
Status HostThreadPosix::Join(lldb::thread_result_t *result) {
Status error;
diff --git a/lldb/source/Host/posix/PipePosix.cpp b/lldb/source/Host/posix/PipePosix.cpp
index 7cd05a1ad2eb..a8cce573f12a 100644
--- a/lldb/source/Host/posix/PipePosix.cpp
+++ b/lldb/source/Host/posix/PipePosix.cpp
@@ -12,19 +12,12 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Errno.h"
#include "llvm/Support/FileSystem.h"
-
-#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8))
-#ifndef _GLIBCXX_USE_NANOSLEEP
-#define _GLIBCXX_USE_NANOSLEEP
-#endif
-#endif
-
#include <functional>
#include <thread>
-#include <errno.h>
+#include <cerrno>
+#include <climits>
#include <fcntl.h>
-#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
diff --git a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp
index 35482341d3e6..25dcf1e592c5 100644
--- a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp
+++ b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp
@@ -15,7 +15,7 @@
#include "lldb/Utility/Log.h"
#include "llvm/Support/Errno.h"
-#include <limits.h>
+#include <climits>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <unistd.h>
diff --git a/lldb/source/Initialization/SystemInitializer.cpp b/lldb/source/Initialization/SystemInitializer.cpp
index fc460c32650d..823a905ebc4b 100644
--- a/lldb/source/Initialization/SystemInitializer.cpp
+++ b/lldb/source/Initialization/SystemInitializer.cpp
@@ -10,6 +10,6 @@
using namespace lldb_private;
-SystemInitializer::SystemInitializer() {}
+SystemInitializer::SystemInitializer() = default;
-SystemInitializer::~SystemInitializer() {}
+SystemInitializer::~SystemInitializer() = default;
diff --git a/lldb/source/Initialization/SystemInitializerCommon.cpp b/lldb/source/Initialization/SystemInitializerCommon.cpp
index d9f69f57703c..84c5a472332a 100644
--- a/lldb/source/Initialization/SystemInitializerCommon.cpp
+++ b/lldb/source/Initialization/SystemInitializerCommon.cpp
@@ -11,7 +11,6 @@
#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
-#include "lldb/Host/HostInfo.h"
#include "lldb/Host/Socket.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/ReproducerProvider.h"
@@ -35,9 +34,11 @@
using namespace lldb_private;
using namespace lldb_private::repro;
-SystemInitializerCommon::SystemInitializerCommon() {}
+SystemInitializerCommon::SystemInitializerCommon(
+ HostInfo::SharedLibraryDirectoryHelper *helper)
+ : m_shlib_dir_helper(helper) {}
-SystemInitializerCommon::~SystemInitializerCommon() {}
+SystemInitializerCommon::~SystemInitializerCommon() = default;
/// Initialize the FileSystem based on the current reproducer mode.
static llvm::Error InitializeFileSystem() {
@@ -95,7 +96,7 @@ llvm::Error SystemInitializerCommon::Initialize() {
#if defined(_WIN32)
const char *disable_crash_dialog_var = getenv("LLDB_DISABLE_CRASH_DIALOG");
if (disable_crash_dialog_var &&
- llvm::StringRef(disable_crash_dialog_var).equals_lower("true")) {
+ llvm::StringRef(disable_crash_dialog_var).equals_insensitive("true")) {
// This will prevent Windows from displaying a dialog box requiring user
// interaction when
// LLDB crashes. This is mostly useful when automating LLDB, for example
@@ -125,7 +126,7 @@ llvm::Error SystemInitializerCommon::Initialize() {
return e;
Log::Initialize();
- HostInfo::Initialize();
+ HostInfo::Initialize(m_shlib_dir_helper);
llvm::Error error = Socket::Initialize();
if (error)
diff --git a/lldb/source/Initialization/SystemLifetimeManager.cpp b/lldb/source/Initialization/SystemLifetimeManager.cpp
index 00ab3198c363..f9de41a67535 100644
--- a/lldb/source/Initialization/SystemLifetimeManager.cpp
+++ b/lldb/source/Initialization/SystemLifetimeManager.cpp
@@ -15,8 +15,7 @@
using namespace lldb_private;
-SystemLifetimeManager::SystemLifetimeManager()
- : m_mutex(), m_initialized(false) {}
+SystemLifetimeManager::SystemLifetimeManager() : m_mutex() {}
SystemLifetimeManager::~SystemLifetimeManager() {
assert(!m_initialized &&
diff --git a/lldb/source/Interpreter/CommandAlias.cpp b/lldb/source/Interpreter/CommandAlias.cpp
index a5e033937210..d55b3fdd44fa 100644
--- a/lldb/source/Interpreter/CommandAlias.cpp
+++ b/lldb/source/Interpreter/CommandAlias.cpp
@@ -47,7 +47,6 @@ static bool ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp,
if (!args_or) {
result.AppendError(toString(args_or.takeError()));
result.AppendError("Unable to create requested alias.\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
args = std::move(*args_or);
@@ -80,7 +79,7 @@ CommandAlias::CommandAlias(CommandInterpreter &interpreter,
llvm::StringRef help, llvm::StringRef syntax,
uint32_t flags)
: CommandObject(interpreter, name, help, syntax, flags),
- m_underlying_command_sp(), m_option_string(std::string(options_args)),
+ m_option_string(std::string(options_args)),
m_option_args_sp(new OptionArgVector),
m_is_dashdash_alias(eLazyBoolCalculate), m_did_set_help(false),
m_did_set_help_long(false) {
diff --git a/lldb/source/Interpreter/CommandHistory.cpp b/lldb/source/Interpreter/CommandHistory.cpp
index 9c7919ecc41f..8f399840b802 100644
--- a/lldb/source/Interpreter/CommandHistory.cpp
+++ b/lldb/source/Interpreter/CommandHistory.cpp
@@ -6,17 +6,13 @@
//
//===----------------------------------------------------------------------===//
-#include <inttypes.h>
+#include <cinttypes>
#include "lldb/Interpreter/CommandHistory.h"
using namespace lldb;
using namespace lldb_private;
-CommandHistory::CommandHistory() : m_mutex(), m_history() {}
-
-CommandHistory::~CommandHistory() {}
-
size_t CommandHistory::GetSize() const {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
return m_history.size();
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index fb503fe0afb0..00e9ccb762c3 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#include <cstdlib>
#include <limits>
#include <memory>
-#include <stdlib.h>
#include <string>
#include <vector>
@@ -76,6 +76,7 @@
#include "lldb/Target/UnixSignals.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/Path.h"
@@ -121,9 +122,8 @@ CommandInterpreter::CommandInterpreter(Debugger &debugger,
IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand),
m_debugger(debugger), m_synchronous_execution(true),
m_skip_lldbinit_files(false), m_skip_app_init_files(false),
- m_command_io_handler_sp(), m_comment_char('#'),
- m_batch_command_mode(false), m_truncation_warning(eNoTruncation),
- m_command_source_depth(0), m_result(), m_transcript_stream() {
+ m_comment_char('#'), m_batch_command_mode(false),
+ m_truncation_warning(eNoTruncation), m_command_source_depth(0) {
SetEventName(eBroadcastBitThreadShouldExit, "thread-should-exit");
SetEventName(eBroadcastBitResetPrompt, "reset-prompt");
SetEventName(eBroadcastBitQuitCommandReceived, "quit");
@@ -160,6 +160,16 @@ void CommandInterpreter::SetSaveSessionOnQuit(bool enable) {
m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, enable);
}
+FileSpec CommandInterpreter::GetSaveSessionDirectory() const {
+ const uint32_t idx = ePropertySaveSessionDirectory;
+ return m_collection_sp->GetPropertyAtIndexAsFileSpec(nullptr, idx);
+}
+
+void CommandInterpreter::SetSaveSessionDirectory(llvm::StringRef path) {
+ const uint32_t idx = ePropertySaveSessionDirectory;
+ m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, path);
+}
+
bool CommandInterpreter::GetEchoCommands() const {
const uint32_t idx = ePropertyEchoCommands;
return m_collection_sp->GetPropertyAtIndexAsBoolean(
@@ -223,6 +233,12 @@ bool CommandInterpreter::GetSpaceReplPrompts() const {
nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0);
}
+bool CommandInterpreter::GetRepeatPreviousCommand() const {
+ const uint32_t idx = ePropertyRepeatPreviousCommand;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0);
+}
+
void CommandInterpreter::Initialize() {
LLDB_SCOPED_TIMER();
@@ -416,17 +432,14 @@ void CommandInterpreter::Initialize() {
cmd_obj_sp = GetCommandSPExact("process launch");
if (cmd_obj_sp) {
alias_arguments_vector_sp = std::make_shared<OptionArgVector>();
-#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
+#if defined(__APPLE__)
+#if defined(TARGET_OS_IPHONE)
AddAlias("r", cmd_obj_sp, "--");
AddAlias("run", cmd_obj_sp, "--");
#else
-#if defined(__APPLE__)
- std::string shell_option;
- shell_option.append("--shell-expand-args");
- shell_option.append(" true");
- shell_option.append(" --");
AddAlias("r", cmd_obj_sp, "--shell-expand-args true --");
AddAlias("run", cmd_obj_sp, "--shell-expand-args true --");
+#endif
#else
StreamString defaultshell;
defaultshell.Printf("--shell=%s --",
@@ -434,7 +447,6 @@ void CommandInterpreter::Initialize() {
AddAlias("r", cmd_obj_sp, defaultshell.GetString());
AddAlias("run", cmd_obj_sp, defaultshell.GetString());
#endif
-#endif
}
cmd_obj_sp = GetCommandSPExact("target symbols add");
@@ -1463,7 +1475,6 @@ CommandObject *CommandInterpreter::BuildAliasResult(
"need at least %d arguments to use "
"this alias.\n",
index);
- result.SetStatus(eReturnStatusFailed);
return nullptr;
} else {
size_t strpos = raw_input_string.find(cmd_args.GetArgumentAtIndex(index));
@@ -1631,12 +1642,18 @@ Status CommandInterpreter::PreprocessCommand(std::string &command) {
bool CommandInterpreter::HandleCommand(const char *command_line,
LazyBool lazy_add_to_history,
- CommandReturnObject &result,
- ExecutionContext *override_context,
- bool repeat_on_empty_command,
- bool no_context_switching)
+ const ExecutionContext &override_context,
+ CommandReturnObject &result) {
+
+ OverrideExecutionContext(override_context);
+ bool status = HandleCommand(command_line, lazy_add_to_history, result);
+ RestoreExecutionContext();
+ return status;
+}
-{
+bool CommandInterpreter::HandleCommand(const char *command_line,
+ LazyBool lazy_add_to_history,
+ CommandReturnObject &result) {
std::string command_string(command_line);
std::string original_command_string(command_line);
@@ -1648,12 +1665,8 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
LLDB_LOGF(log, "Processing command: %s", command_line);
LLDB_SCOPED_TIMERF("Processing command: %s.", command_line);
- if (!no_context_switching)
- UpdateExecutionContext(override_context);
-
if (WasInterrupted()) {
result.AppendError("interrupted");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1689,33 +1702,31 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
} else {
result.AppendErrorWithFormat("Could not find entry: %s in history",
command_string.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
}
if (empty_command) {
- if (repeat_on_empty_command) {
- if (m_command_history.IsEmpty()) {
- result.AppendError("empty command");
- result.SetStatus(eReturnStatusFailed);
- return false;
- } else {
- command_line = m_repeat_command.c_str();
- command_string = command_line;
- original_command_string = command_line;
- if (m_repeat_command.empty()) {
- result.AppendError("No auto repeat.");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- }
- add_to_history = false;
- } else {
+ if (!GetRepeatPreviousCommand()) {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return true;
}
+
+ if (m_command_history.IsEmpty()) {
+ result.AppendError("empty command");
+ return false;
+ }
+
+ command_line = m_repeat_command.c_str();
+ command_string = command_line;
+ original_command_string = command_line;
+ if (m_repeat_command.empty()) {
+ result.AppendError("No auto repeat.");
+ return false;
+ }
+
+ add_to_history = false;
} else if (comment_command) {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return true;
@@ -1725,7 +1736,6 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
if (error.Fail()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1852,8 +1862,6 @@ void CommandInterpreter::HandleCompletionMatches(CompletionRequest &request) {
void CommandInterpreter::HandleCompletion(CompletionRequest &request) {
- UpdateExecutionContext(nullptr);
-
// Don't complete comments, and if the line we are completing is just the
// history repeat character, substitute the appropriate history line.
llvm::StringRef first_arg = request.GetParsedLine().GetArgumentAtIndex(0);
@@ -1885,8 +1893,6 @@ CommandInterpreter::GetAutoSuggestionForCommand(llvm::StringRef line) {
return llvm::None;
}
-CommandInterpreter::~CommandInterpreter() {}
-
void CommandInterpreter::UpdatePrompt(llvm::StringRef new_prompt) {
EventSP prompt_change_event_sp(
new Event(eBroadcastBitResetPrompt, new EventDataBytes(new_prompt)));
@@ -1997,7 +2003,6 @@ void CommandInterpreter::BuildAliasCommandArgs(CommandObject *alias_cmd_obj,
"need at least %d arguments to use "
"this alias.\n",
index);
- result.SetStatus(eReturnStatusFailed);
return;
} else {
// Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
@@ -2128,13 +2133,12 @@ void CommandInterpreter::SourceInitFile(FileSpec file,
// broadcasting of the commands back to any appropriate listener (see
// CommandObjectSource::Execute for more details).
const bool saved_batch = SetBatchCommandMode(true);
- ExecutionContext *ctx = nullptr;
CommandInterpreterRunOptions options;
options.SetSilent(true);
options.SetPrintErrors(true);
options.SetStopOnError(false);
options.SetStopOnContinue(true);
- HandleCommandsFromFile(file, ctx, options, result);
+ HandleCommandsFromFile(file, options, result);
SetBatchCommandMode(saved_batch);
}
@@ -2168,7 +2172,6 @@ void CommandInterpreter::SourceInitFileCwd(CommandReturnObject &result) {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
result.AppendError(InitFileWarning);
- result.SetStatus(eReturnStatusFailed);
}
}
}
@@ -2225,7 +2228,8 @@ PlatformSP CommandInterpreter::GetPlatform(bool prefer_target_platform) {
}
bool CommandInterpreter::DidProcessStopAbnormally() const {
- TargetSP target_sp = m_debugger.GetTargetList().GetSelectedTarget();
+ auto exe_ctx = GetExecutionContext();
+ TargetSP target_sp = exe_ctx.GetTargetSP();
if (!target_sp)
return false;
@@ -2242,7 +2246,9 @@ bool CommandInterpreter::DidProcessStopAbnormally() const {
return false;
const StopReason reason = stop_info->GetStopReason();
- if (reason == eStopReasonException || reason == eStopReasonInstrumentation)
+ if (reason == eStopReasonException ||
+ reason == eStopReasonInstrumentation ||
+ reason == eStopReasonProcessorTrace)
return true;
if (reason == eStopReasonSignal) {
@@ -2263,9 +2269,19 @@ bool CommandInterpreter::DidProcessStopAbnormally() const {
return false;
}
+void
+CommandInterpreter::HandleCommands(const StringList &commands,
+ const ExecutionContext &override_context,
+ const CommandInterpreterRunOptions &options,
+ CommandReturnObject &result) {
+
+ OverrideExecutionContext(override_context);
+ HandleCommands(commands, options, result);
+ RestoreExecutionContext();
+}
+
void CommandInterpreter::HandleCommands(const StringList &commands,
- ExecutionContext *override_context,
- CommandInterpreterRunOptions &options,
+ const CommandInterpreterRunOptions &options,
CommandReturnObject &result) {
size_t num_lines = commands.GetSize();
@@ -2275,13 +2291,6 @@ void CommandInterpreter::HandleCommands(const StringList &commands,
bool old_async_execution = m_debugger.GetAsyncExecution();
- // If we've been given an execution context, set it at the start, but don't
- // keep resetting it or we will cause series of commands that change the
- // context, then do an operation that relies on that context to fail.
-
- if (override_context != nullptr)
- UpdateExecutionContext(override_context);
-
if (!options.GetStopOnContinue()) {
m_debugger.SetAsyncExecution(false);
}
@@ -2299,20 +2308,14 @@ void CommandInterpreter::HandleCommands(const StringList &commands,
CommandReturnObject tmp_result(m_debugger.GetUseColor());
tmp_result.SetInteractive(result.GetInteractive());
-
- // If override_context is not NULL, pass no_context_switching = true for
- // HandleCommand() since we updated our context already.
+ tmp_result.SetSuppressImmediateOutput(true);
// We might call into a regex or alias command, in which case the
// add_to_history will get lost. This m_command_source_depth dingus is the
// way we turn off adding to the history in that case, so set it up here.
if (!options.GetAddToHistory())
m_command_source_depth++;
- bool success =
- HandleCommand(cmd, options.m_add_to_history, tmp_result,
- nullptr, /* override_context */
- true, /* repeat_on_empty_command */
- override_context != nullptr /* no_context_switching */);
+ bool success = HandleCommand(cmd, options.m_add_to_history, tmp_result);
if (!options.GetAddToHistory())
m_command_source_depth--;
@@ -2330,7 +2333,6 @@ void CommandInterpreter::HandleCommands(const StringList &commands,
"Aborting reading of commands after command #%" PRIu64
": '%s' failed with %s",
(uint64_t)idx, cmd, error_msg.str().c_str());
- result.SetStatus(eReturnStatusFailed);
m_debugger.SetAsyncExecution(old_async_execution);
return;
} else if (options.GetPrintResults()) {
@@ -2413,13 +2415,19 @@ enum {
};
void CommandInterpreter::HandleCommandsFromFile(
- FileSpec &cmd_file, ExecutionContext *context,
- CommandInterpreterRunOptions &options, CommandReturnObject &result) {
+ FileSpec &cmd_file, const ExecutionContext &context,
+ const CommandInterpreterRunOptions &options, CommandReturnObject &result) {
+ OverrideExecutionContext(context);
+ HandleCommandsFromFile(cmd_file, options, result);
+ RestoreExecutionContext();
+}
+
+void CommandInterpreter::HandleCommandsFromFile(FileSpec &cmd_file,
+ const CommandInterpreterRunOptions &options, CommandReturnObject &result) {
if (!FileSystem::Instance().Exists(cmd_file)) {
result.AppendErrorWithFormat(
"Error reading commands from file %s - file not found.\n",
cmd_file.GetFilename().AsCString("<Unknown>"));
- result.SetStatus(eReturnStatusFailed);
return;
}
@@ -2431,7 +2439,6 @@ void CommandInterpreter::HandleCommandsFromFile(
result.AppendErrorWithFormatv(
"error: an error occurred read file '{0}': {1}\n", cmd_file_path,
llvm::fmt_consume(input_file_up.takeError()));
- result.SetStatus(eReturnStatusFailed);
return;
}
FileSP input_file_sp = FileSP(std::move(input_file_up.get()));
@@ -2678,7 +2685,7 @@ void CommandInterpreter::FindCommandsForApropos(
const bool search_long_help = false;
const bool search_syntax = false;
const bool search_options = false;
- if (command_name.contains_lower(search_word) ||
+ if (command_name.contains_insensitive(search_word) ||
cmd_obj->HelpTextContainsWord(search_word, search_short_help,
search_long_help, search_syntax,
search_options)) {
@@ -2715,23 +2722,24 @@ void CommandInterpreter::FindCommandsForApropos(llvm::StringRef search_word,
m_alias_dict);
}
-void CommandInterpreter::UpdateExecutionContext(
- ExecutionContext *override_context) {
- if (override_context != nullptr) {
- m_exe_ctx_ref = *override_context;
- } else {
- const bool adopt_selected = true;
- m_exe_ctx_ref.SetTargetPtr(m_debugger.GetSelectedTarget().get(),
- adopt_selected);
- }
+ExecutionContext CommandInterpreter::GetExecutionContext() const {
+ return !m_overriden_exe_contexts.empty()
+ ? m_overriden_exe_contexts.top()
+ : m_debugger.GetSelectedExecutionContext();
}
-void CommandInterpreter::GetProcessOutput() {
- TargetSP target_sp(m_debugger.GetTargetList().GetSelectedTarget());
- if (!target_sp)
- return;
+void CommandInterpreter::OverrideExecutionContext(
+ const ExecutionContext &override_context) {
+ m_overriden_exe_contexts.push(override_context);
+}
+
+void CommandInterpreter::RestoreExecutionContext() {
+ if (!m_overriden_exe_contexts.empty())
+ m_overriden_exe_contexts.pop();
+}
- if (ProcessSP process_sp = target_sp->GetProcessSP())
+void CommandInterpreter::GetProcessOutput() {
+ if (ProcessSP process_sp = GetExecutionContext().GetProcessSP())
m_debugger.FlushProcessOutput(*process_sp, /*flush_stdout*/ true,
/*flush_stderr*/ true);
}
@@ -2831,6 +2839,11 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler,
StartHandlingCommand();
+ OverrideExecutionContext(m_debugger.GetSelectedExecutionContext());
+ auto finalize = llvm::make_scope_exit([this]() {
+ RestoreExecutionContext();
+ });
+
lldb_private::CommandReturnObject result(m_debugger.GetUseColor());
HandleCommand(line.c_str(), eLazyBoolCalculate, result);
@@ -2922,9 +2935,15 @@ bool CommandInterpreter::SaveTranscript(
std::string now = llvm::to_string(std::chrono::system_clock::now());
std::replace(now.begin(), now.end(), ' ', '_');
const std::string file_name = "lldb_session_" + now + ".log";
- FileSpec tmp = HostInfo::GetGlobalTempDir();
- tmp.AppendPathComponent(file_name);
- output_file = tmp.GetPath();
+
+ FileSpec save_location = GetSaveSessionDirectory();
+
+ if (!save_location)
+ save_location = HostInfo::GetGlobalTempDir();
+
+ FileSystem::Instance().Resolve(save_location);
+ save_location.AppendPathComponent(file_name);
+ output_file = save_location.GetPath();
}
auto error_out = [&](llvm::StringRef error_message, std::string description) {
@@ -2955,6 +2974,7 @@ bool CommandInterpreter::SaveTranscript(
return error_out("Unable to write to destination file",
"Bytes written do not match transcript size.");
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
result.AppendMessageWithFormat("Session's transcripts saved to %s\n",
output_file->c_str());
@@ -2973,9 +2993,9 @@ void CommandInterpreter::GetLLDBCommandsFromIOHandler(
IOHandlerSP io_handler_sp(
new IOHandlerEditline(debugger, IOHandler::Type::CommandList,
"lldb", // Name of input reader for history
- llvm::StringRef::withNullAsEmpty(prompt), // Prompt
- llvm::StringRef(), // Continuation prompt
- true, // Get multiple lines
+ llvm::StringRef(prompt), // Prompt
+ llvm::StringRef(), // Continuation prompt
+ true, // Get multiple lines
debugger.GetUseColor(),
0, // Don't show line numbers
delegate, // IOHandlerDelegate
@@ -2993,9 +3013,9 @@ void CommandInterpreter::GetPythonCommandsFromIOHandler(
IOHandlerSP io_handler_sp(
new IOHandlerEditline(debugger, IOHandler::Type::PythonCode,
"lldb-python", // Name of input reader for history
- llvm::StringRef::withNullAsEmpty(prompt), // Prompt
- llvm::StringRef(), // Continuation prompt
- true, // Get multiple lines
+ llvm::StringRef(prompt), // Prompt
+ llvm::StringRef(), // Continuation prompt
+ true, // Get multiple lines
debugger.GetUseColor(),
0, // Don't show line numbers
delegate, // IOHandlerDelegate
@@ -3088,7 +3108,6 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line,
CommandObject *cmd_obj = nullptr;
StreamString revised_command_line;
bool wants_raw_input = false;
- size_t actual_cmd_name_len = 0;
std::string next_word;
StringList matches;
bool done = false;
@@ -3110,12 +3129,10 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line,
revised_command_line.Printf("%s", alias_result.c_str());
if (cmd_obj) {
wants_raw_input = cmd_obj->WantsRawCommandString();
- actual_cmd_name_len = cmd_obj->GetCommandName().size();
}
} else {
if (cmd_obj) {
llvm::StringRef cmd_name = cmd_obj->GetCommandName();
- actual_cmd_name_len += cmd_name.size();
revised_command_line.Printf("%s", cmd_name.str().c_str());
wants_raw_input = cmd_obj->WantsRawCommandString();
} else {
@@ -3130,7 +3147,6 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line,
// The subcommand's name includes the parent command's name, so
// restart rather than append to the revised_command_line.
llvm::StringRef sub_cmd_name = sub_cmd_obj->GetCommandName();
- actual_cmd_name_len = sub_cmd_name.size() + 1;
revised_command_line.Clear();
revised_command_line.Printf("%s", sub_cmd_name.str().c_str());
cmd_obj = sub_cmd_obj;
@@ -3174,7 +3190,6 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line,
result.AppendErrorWithFormat("'%s' is not a valid command.\n",
next_word.c_str());
}
- result.SetStatus(eReturnStatusFailed);
return nullptr;
}
@@ -3186,7 +3201,6 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line,
cmd_obj->GetCommandName().str().c_str(),
next_word.empty() ? "" : next_word.c_str(),
next_word.empty() ? " -- " : " ", suffix.c_str());
- result.SetStatus(eReturnStatusFailed);
return nullptr;
}
} else {
@@ -3222,7 +3236,6 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line,
result.AppendErrorWithFormat(
"the '%s' command doesn't support the --gdb-format option\n",
cmd_obj->GetCommandName().str().c_str());
- result.SetStatus(eReturnStatusFailed);
return nullptr;
}
}
@@ -3231,7 +3244,6 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line,
default:
result.AppendErrorWithFormat(
"unknown command shorthand suffix: '%s'\n", suffix.c_str());
- result.SetStatus(eReturnStatusFailed);
return nullptr;
}
}
diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp
index 71adf8c39f1b..a7dcd5682701 100644
--- a/lldb/source/Interpreter/CommandObject.cpp
+++ b/lldb/source/Interpreter/CommandObject.cpp
@@ -12,8 +12,8 @@
#include <sstream>
#include <string>
-#include <ctype.h>
-#include <stdlib.h>
+#include <cctype>
+#include <cstdlib>
#include "lldb/Core/Address.h"
#include "lldb/Interpreter/Options.h"
@@ -42,15 +42,12 @@ CommandObject::CommandObject(CommandInterpreter &interpreter,
llvm::StringRef name, llvm::StringRef help,
llvm::StringRef syntax, uint32_t flags)
: m_interpreter(interpreter), m_cmd_name(std::string(name)),
- m_cmd_help_short(), m_cmd_help_long(), m_cmd_syntax(), m_flags(flags),
- m_arguments(), m_deprecated_command_override_callback(nullptr),
+ m_flags(flags), m_deprecated_command_override_callback(nullptr),
m_command_override_callback(nullptr), m_command_override_baton(nullptr) {
m_cmd_help_short = std::string(help);
m_cmd_syntax = std::string(syntax);
}
-CommandObject::~CommandObject() {}
-
Debugger &CommandObject::GetDebugger() { return m_interpreter.GetDebugger(); }
llvm::StringRef CommandObject::GetHelp() { return m_cmd_help_short; }
@@ -222,7 +219,6 @@ bool CommandObject::CheckRequirements(CommandReturnObject &result) {
// A process that is not running is considered paused.
if (GetFlags().Test(eCommandProcessMustBeLaunched)) {
result.AppendError("Process must exist.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else {
@@ -242,7 +238,6 @@ bool CommandObject::CheckRequirements(CommandReturnObject &result) {
case eStateUnloaded:
if (GetFlags().Test(eCommandProcessMustBeLaunched)) {
result.AppendError("Process must be launched.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
break;
@@ -252,7 +247,6 @@ bool CommandObject::CheckRequirements(CommandReturnObject &result) {
if (GetFlags().Test(eCommandProcessMustBePaused)) {
result.AppendError("Process is running. Use 'process interrupt' to "
"pause execution.");
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -262,7 +256,7 @@ bool CommandObject::CheckRequirements(CommandReturnObject &result) {
if (GetFlags().Test(eCommandProcessMustBeTraced)) {
Target *target = m_exe_ctx.GetTargetPtr();
if (target && !target->GetTrace()) {
- result.SetError("Process is not being traced.");
+ result.AppendError("Process is not being traced.");
return false;
}
}
@@ -322,11 +316,11 @@ bool CommandObject::HelpTextContainsWord(llvm::StringRef search_word,
llvm::StringRef long_help = GetHelpLong();
llvm::StringRef syntax_help = GetSyntax();
- if (search_short_help && short_help.contains_lower(search_word))
+ if (search_short_help && short_help.contains_insensitive(search_word))
found_word = true;
- else if (search_long_help && long_help.contains_lower(search_word))
+ else if (search_long_help && long_help.contains_insensitive(search_word))
found_word = true;
- else if (search_syntax && syntax_help.contains_lower(search_word))
+ else if (search_syntax && syntax_help.contains_insensitive(search_word))
found_word = true;
if (!found_word && search_options && GetOptions() != nullptr) {
@@ -336,7 +330,7 @@ bool CommandObject::HelpTextContainsWord(llvm::StringRef search_word,
GetCommandInterpreter().GetDebugger().GetTerminalWidth());
if (!usage_help.Empty()) {
llvm::StringRef usage_text = usage_help.GetString();
- if (usage_text.contains_lower(search_word))
+ if (usage_text.contains_insensitive(search_word))
found_word = true;
}
}
@@ -354,7 +348,6 @@ bool CommandObject::ParseOptionsAndNotify(Args &args,
Status error(group_options.NotifyOptionParsingFinished(&exe_ctx));
if (error.Fail()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
return true;
@@ -1129,7 +1122,8 @@ CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = {
{ eArgRawInput, "raw-input", CommandCompletions::eNoCompletion, { nullptr, false }, "Free-form text passed to a command without prior interpretation, allowing spaces without requiring quotes. To pass arguments and free form text put two dashes ' -- ' between the last argument and any raw input." },
{ eArgTypeCommand, "command", CommandCompletions::eNoCompletion, { nullptr, false }, "An LLDB Command line command." },
{ eArgTypeColumnNum, "column", CommandCompletions::eNoCompletion, { nullptr, false }, "Column number in a source file." },
- { eArgTypeModuleUUID, "module-uuid", CommandCompletions::eModuleUUIDCompletion, { nullptr, false }, "A module UUID value." }
+ { eArgTypeModuleUUID, "module-uuid", CommandCompletions::eModuleUUIDCompletion, { nullptr, false }, "A module UUID value." },
+ { eArgTypeSaveCoreStyle, "corefile-style", CommandCompletions::eNoCompletion, { nullptr, false }, "The type of corefile that lldb will try to create, dependant on this target's capabilities." }
// clang-format on
};
diff --git a/lldb/source/Interpreter/CommandReturnObject.cpp b/lldb/source/Interpreter/CommandReturnObject.cpp
index 6f3732e35078..506b0d6e7cde 100644
--- a/lldb/source/Interpreter/CommandReturnObject.cpp
+++ b/lldb/source/Interpreter/CommandReturnObject.cpp
@@ -41,13 +41,11 @@ static void DumpStringToStreamWithNewline(Stream &strm, const std::string &s) {
}
CommandReturnObject::CommandReturnObject(bool colors)
- : m_out_stream(colors), m_err_stream(colors),
- m_status(eReturnStatusStarted), m_did_change_process_state(false),
- m_interactive(true) {}
-
-CommandReturnObject::~CommandReturnObject() {}
+ : m_out_stream(colors), m_err_stream(colors) {}
void CommandReturnObject::AppendErrorWithFormat(const char *format, ...) {
+ SetStatus(eReturnStatusFailed);
+
if (!format)
return;
va_list args;
@@ -90,52 +88,33 @@ void CommandReturnObject::AppendWarningWithFormat(const char *format, ...) {
void CommandReturnObject::AppendMessage(llvm::StringRef in_string) {
if (in_string.empty())
return;
- GetOutputStream() << in_string << "\n";
+ GetOutputStream() << in_string.rtrim() << '\n';
}
void CommandReturnObject::AppendWarning(llvm::StringRef in_string) {
if (in_string.empty())
return;
- warning(GetErrorStream()) << in_string << '\n';
-}
-
-// Similar to AppendWarning, but do not prepend 'warning: ' to message, and
-// don't append "\n" to the end of it.
-
-void CommandReturnObject::AppendRawWarning(llvm::StringRef in_string) {
- if (in_string.empty())
- return;
- GetErrorStream() << in_string;
+ warning(GetErrorStream()) << in_string.rtrim() << '\n';
}
void CommandReturnObject::AppendError(llvm::StringRef in_string) {
+ SetStatus(eReturnStatusFailed);
if (in_string.empty())
return;
- error(GetErrorStream()) << in_string << '\n';
+ error(GetErrorStream()) << in_string.rtrim() << '\n';
}
void CommandReturnObject::SetError(const Status &error,
const char *fallback_error_cstr) {
- const char *error_cstr = error.AsCString();
- if (error_cstr == nullptr)
- error_cstr = fallback_error_cstr;
- SetError(error_cstr);
-}
-
-void CommandReturnObject::SetError(llvm::StringRef error_str) {
- if (error_str.empty())
- return;
-
- AppendError(error_str);
- SetStatus(eReturnStatusFailed);
+ AppendError(error.AsCString(fallback_error_cstr));
}
// Similar to AppendError, but do not prepend 'Status: ' to message, and don't
// append "\n" to the end of it.
void CommandReturnObject::AppendRawError(llvm::StringRef in_string) {
- if (in_string.empty())
- return;
+ SetStatus(eReturnStatusFailed);
+ assert(!in_string.empty() && "Expected a non-empty error message");
GetErrorStream() << in_string;
}
@@ -162,6 +141,7 @@ void CommandReturnObject::Clear() {
static_cast<StreamString *>(stream_sp.get())->Clear();
m_status = eReturnStatusStarted;
m_did_change_process_state = false;
+ m_suppress_immediate_output = false;
m_interactive = true;
}
@@ -176,3 +156,11 @@ void CommandReturnObject::SetDidChangeProcessState(bool b) {
bool CommandReturnObject::GetInteractive() const { return m_interactive; }
void CommandReturnObject::SetInteractive(bool b) { m_interactive = b; }
+
+bool CommandReturnObject::GetSuppressImmediateOutput() const {
+ return m_suppress_immediate_output;
+}
+
+void CommandReturnObject::SetSuppressImmediateOutput(bool b) {
+ m_suppress_immediate_output = b;
+}
diff --git a/lldb/source/Interpreter/InterpreterProperties.td b/lldb/source/Interpreter/InterpreterProperties.td
index e5346d14a6e1..1c6f0206c489 100644
--- a/lldb/source/Interpreter/InterpreterProperties.td
+++ b/lldb/source/Interpreter/InterpreterProperties.td
@@ -13,6 +13,9 @@ let Definition = "interpreter" in {
Global,
DefaultFalse,
Desc<"If true, LLDB will save the session's transcripts before quitting.">;
+ def SaveSessionDirectory: Property<"save-session-directory", "FileSpec">,
+ DefaultStringValue<"">,
+ Desc<"A path where LLDB will save the session's transcripts. This is particularly useful when you can't set the session file, for example when using `save-session-on-quit`.">;
def StopCmdSourceOnError: Property<"stop-command-source-on-error", "Boolean">,
Global,
DefaultTrue,
@@ -29,4 +32,8 @@ let Definition = "interpreter" in {
Global,
DefaultTrue,
Desc<"If true, commands will be echoed even if they are pure comment lines.">;
+ def RepeatPreviousCommand: Property<"repeat-previous-command", "Boolean">,
+ Global,
+ DefaultTrue,
+ Desc<"If true, LLDB will repeat the previous command if no command was passed to the interpreter. If false, LLDB won't repeat the previous command but only return a new prompt.">;
}
diff --git a/lldb/source/Interpreter/OptionArgParser.cpp b/lldb/source/Interpreter/OptionArgParser.cpp
index 3dcb30e846d9..93b01abde4bb 100644
--- a/lldb/source/Interpreter/OptionArgParser.cpp
+++ b/lldb/source/Interpreter/OptionArgParser.cpp
@@ -20,11 +20,11 @@ bool OptionArgParser::ToBoolean(llvm::StringRef ref, bool fail_value,
if (success_ptr)
*success_ptr = true;
ref = ref.trim();
- if (ref.equals_lower("false") || ref.equals_lower("off") ||
- ref.equals_lower("no") || ref.equals_lower("0")) {
+ if (ref.equals_insensitive("false") || ref.equals_insensitive("off") ||
+ ref.equals_insensitive("no") || ref.equals_insensitive("0")) {
return false;
- } else if (ref.equals_lower("true") || ref.equals_lower("on") ||
- ref.equals_lower("yes") || ref.equals_lower("1")) {
+ } else if (ref.equals_insensitive("true") || ref.equals_insensitive("on") ||
+ ref.equals_insensitive("yes") || ref.equals_insensitive("1")) {
return true;
}
if (success_ptr)
@@ -125,13 +125,13 @@ lldb::ScriptLanguage OptionArgParser::ToScriptLanguage(
if (success_ptr)
*success_ptr = true;
- if (s.equals_lower("python"))
+ if (s.equals_insensitive("python"))
return eScriptLanguagePython;
- if (s.equals_lower("lua"))
+ if (s.equals_insensitive("lua"))
return eScriptLanguageLua;
- if (s.equals_lower("default"))
+ if (s.equals_insensitive("default"))
return eScriptLanguageDefault;
- if (s.equals_lower("none"))
+ if (s.equals_insensitive("none"))
return eScriptLanguageNone;
if (success_ptr)
diff --git a/lldb/source/Interpreter/OptionGroupArchitecture.cpp b/lldb/source/Interpreter/OptionGroupArchitecture.cpp
index baca1c6e8068..00541b7198d2 100644
--- a/lldb/source/Interpreter/OptionGroupArchitecture.cpp
+++ b/lldb/source/Interpreter/OptionGroupArchitecture.cpp
@@ -13,10 +13,6 @@
using namespace lldb;
using namespace lldb_private;
-OptionGroupArchitecture::OptionGroupArchitecture() : m_arch_str() {}
-
-OptionGroupArchitecture::~OptionGroupArchitecture() {}
-
static constexpr OptionDefinition g_option_table[] = {
{LLDB_OPT_SET_1, false, "arch", 'a', OptionParser::eRequiredArgument,
nullptr, {}, 0, eArgTypeArchitecture,
diff --git a/lldb/source/Interpreter/OptionGroupBoolean.cpp b/lldb/source/Interpreter/OptionGroupBoolean.cpp
index 3482e784ca0c..3f73893fca96 100644
--- a/lldb/source/Interpreter/OptionGroupBoolean.cpp
+++ b/lldb/source/Interpreter/OptionGroupBoolean.cpp
@@ -33,8 +33,6 @@ OptionGroupBoolean::OptionGroupBoolean(uint32_t usage_mask, bool required,
m_option_definition.usage_text = usage_text;
}
-OptionGroupBoolean::~OptionGroupBoolean() {}
-
Status OptionGroupBoolean::SetOptionValue(uint32_t option_idx,
llvm::StringRef option_value,
ExecutionContext *execution_context) {
diff --git a/lldb/source/Interpreter/OptionGroupFile.cpp b/lldb/source/Interpreter/OptionGroupFile.cpp
index 9d9be5b6f178..12ade1855829 100644
--- a/lldb/source/Interpreter/OptionGroupFile.cpp
+++ b/lldb/source/Interpreter/OptionGroupFile.cpp
@@ -17,8 +17,7 @@ OptionGroupFile::OptionGroupFile(uint32_t usage_mask, bool required,
const char *long_option, int short_option,
uint32_t completion_type,
lldb::CommandArgumentType argument_type,
- const char *usage_text)
- : m_file() {
+ const char *usage_text) {
m_option_definition.usage_mask = usage_mask;
m_option_definition.required = required;
m_option_definition.long_option = long_option;
@@ -31,8 +30,6 @@ OptionGroupFile::OptionGroupFile(uint32_t usage_mask, bool required,
m_option_definition.usage_text = usage_text;
}
-OptionGroupFile::~OptionGroupFile() {}
-
Status OptionGroupFile::SetOptionValue(uint32_t option_idx,
llvm::StringRef option_arg,
ExecutionContext *execution_context) {
@@ -62,7 +59,7 @@ OptionGroupFileList::OptionGroupFileList(
m_option_definition.usage_text = usage_text;
}
-OptionGroupFileList::~OptionGroupFileList() {}
+OptionGroupFileList::~OptionGroupFileList() = default;
Status
OptionGroupFileList::SetOptionValue(uint32_t option_idx,
diff --git a/lldb/source/Interpreter/OptionGroupFormat.cpp b/lldb/source/Interpreter/OptionGroupFormat.cpp
index 0052f72b0550..1cc5e70282c1 100644
--- a/lldb/source/Interpreter/OptionGroupFormat.cpp
+++ b/lldb/source/Interpreter/OptionGroupFormat.cpp
@@ -24,8 +24,6 @@ OptionGroupFormat::OptionGroupFormat(lldb::Format default_format,
m_count(default_count, default_count), m_prev_gdb_format('x'),
m_prev_gdb_size('w') {}
-OptionGroupFormat::~OptionGroupFormat() {}
-
static constexpr OptionDefinition g_option_table[] = {
{LLDB_OPT_SET_1, false, "format", 'f', OptionParser::eRequiredArgument,
nullptr, {}, 0, eArgTypeFormat,
diff --git a/lldb/source/Interpreter/OptionGroupOutputFile.cpp b/lldb/source/Interpreter/OptionGroupOutputFile.cpp
index 65105c3e0180..6a626bd63014 100644
--- a/lldb/source/Interpreter/OptionGroupOutputFile.cpp
+++ b/lldb/source/Interpreter/OptionGroupOutputFile.cpp
@@ -13,10 +13,7 @@
using namespace lldb;
using namespace lldb_private;
-OptionGroupOutputFile::OptionGroupOutputFile()
- : m_file(), m_append(false, false) {}
-
-OptionGroupOutputFile::~OptionGroupOutputFile() {}
+OptionGroupOutputFile::OptionGroupOutputFile() : m_append(false, false) {}
static const uint32_t SHORT_OPTION_APND = 0x61706e64; // 'apnd'
diff --git a/lldb/source/Interpreter/OptionGroupPythonClassWithDict.cpp b/lldb/source/Interpreter/OptionGroupPythonClassWithDict.cpp
index 217dab2ef63b..a01c190266dd 100644
--- a/lldb/source/Interpreter/OptionGroupPythonClassWithDict.cpp
+++ b/lldb/source/Interpreter/OptionGroupPythonClassWithDict.cpp
@@ -13,12 +13,10 @@
using namespace lldb;
using namespace lldb_private;
-OptionGroupPythonClassWithDict::OptionGroupPythonClassWithDict
- (const char *class_use,
- bool is_class,
- int class_option,
- int key_option,
- int value_option) : OptionGroup(), m_is_class(is_class) {
+OptionGroupPythonClassWithDict::OptionGroupPythonClassWithDict(
+ const char *class_use, bool is_class, int class_option, int key_option,
+ int value_option, uint16_t required_options)
+ : m_is_class(is_class), m_required_options(required_options) {
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);
@@ -36,7 +34,7 @@ OptionGroupPythonClassWithDict::OptionGroupPythonClassWithDict
m_class_usage_text.append(".");
m_option_definition[0].usage_mask = LLDB_OPT_SET_1;
- m_option_definition[0].required = true;
+ m_option_definition[0].required = m_required_options.Test(eScriptClass);
m_option_definition[0].long_option = "script-class";
m_option_definition[0].short_option = class_option;
m_option_definition[0].validator = nullptr;
@@ -47,7 +45,7 @@ OptionGroupPythonClassWithDict::OptionGroupPythonClassWithDict
m_option_definition[0].usage_text = m_class_usage_text.data();
m_option_definition[1].usage_mask = LLDB_OPT_SET_2;
- m_option_definition[1].required = false;
+ m_option_definition[1].required = m_required_options.Test(eDictKey);
m_option_definition[1].long_option = "structured-data-key";
m_option_definition[1].short_option = key_option;
m_option_definition[1].validator = nullptr;
@@ -58,7 +56,7 @@ OptionGroupPythonClassWithDict::OptionGroupPythonClassWithDict
m_option_definition[1].usage_text = m_key_usage_text.data();
m_option_definition[2].usage_mask = LLDB_OPT_SET_2;
- m_option_definition[2].required = false;
+ m_option_definition[2].required = m_required_options.Test(eDictValue);
m_option_definition[2].long_option = "structured-data-value";
m_option_definition[2].short_option = value_option;
m_option_definition[2].validator = nullptr;
@@ -69,7 +67,7 @@ OptionGroupPythonClassWithDict::OptionGroupPythonClassWithDict
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].required = m_required_options.Test(ePythonFunction);
m_option_definition[3].long_option = "python-function";
m_option_definition[3].short_option = class_option;
m_option_definition[3].validator = nullptr;
@@ -78,11 +76,8 @@ OptionGroupPythonClassWithDict::OptionGroupPythonClassWithDict
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() {}
-
Status OptionGroupPythonClassWithDict::SetOptionValue(
uint32_t option_idx,
llvm::StringRef option_arg,
diff --git a/lldb/source/Interpreter/OptionGroupString.cpp b/lldb/source/Interpreter/OptionGroupString.cpp
index c9f78eb953f4..75faaac9f6dd 100644
--- a/lldb/source/Interpreter/OptionGroupString.cpp
+++ b/lldb/source/Interpreter/OptionGroupString.cpp
@@ -32,8 +32,6 @@ OptionGroupString::OptionGroupString(uint32_t usage_mask, bool required,
m_option_definition.usage_text = usage_text;
}
-OptionGroupString::~OptionGroupString() {}
-
Status OptionGroupString::SetOptionValue(uint32_t option_idx,
llvm::StringRef option_arg,
ExecutionContext *execution_context) {
diff --git a/lldb/source/Interpreter/OptionGroupUInt64.cpp b/lldb/source/Interpreter/OptionGroupUInt64.cpp
index 309855d4718c..486941a7555a 100644
--- a/lldb/source/Interpreter/OptionGroupUInt64.cpp
+++ b/lldb/source/Interpreter/OptionGroupUInt64.cpp
@@ -32,8 +32,6 @@ OptionGroupUInt64::OptionGroupUInt64(uint32_t usage_mask, bool required,
m_option_definition.usage_text = usage_text;
}
-OptionGroupUInt64::~OptionGroupUInt64() {}
-
Status OptionGroupUInt64::SetOptionValue(uint32_t option_idx,
llvm::StringRef option_arg,
ExecutionContext *execution_context) {
diff --git a/lldb/source/Interpreter/OptionGroupUUID.cpp b/lldb/source/Interpreter/OptionGroupUUID.cpp
index dc6f4139896f..5b4c24a0a32b 100644
--- a/lldb/source/Interpreter/OptionGroupUUID.cpp
+++ b/lldb/source/Interpreter/OptionGroupUUID.cpp
@@ -13,10 +13,6 @@
using namespace lldb;
using namespace lldb_private;
-OptionGroupUUID::OptionGroupUUID() : m_uuid() {}
-
-OptionGroupUUID::~OptionGroupUUID() {}
-
static constexpr OptionDefinition g_option_table[] = {
{LLDB_OPT_SET_1, false, "uuid", 'u', OptionParser::eRequiredArgument,
nullptr, {}, 0, eArgTypeModuleUUID, "A module UUID value."},
diff --git a/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
index e0401f8987ad..04861b539650 100644
--- a/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
+++ b/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
@@ -19,10 +19,6 @@
using namespace lldb;
using namespace lldb_private;
-OptionGroupValueObjectDisplay::OptionGroupValueObjectDisplay() {}
-
-OptionGroupValueObjectDisplay::~OptionGroupValueObjectDisplay() {}
-
static const OptionDefinition g_option_table[] = {
{LLDB_OPT_SET_1, false, "dynamic-type", 'd',
OptionParser::eRequiredArgument, nullptr, GetDynamicValueTypes(), 0,
diff --git a/lldb/source/Interpreter/OptionGroupVariable.cpp b/lldb/source/Interpreter/OptionGroupVariable.cpp
index 9f57dbbd073e..20a521b8e44f 100644
--- a/lldb/source/Interpreter/OptionGroupVariable.cpp
+++ b/lldb/source/Interpreter/OptionGroupVariable.cpp
@@ -67,10 +67,8 @@ static Status ValidateSummaryString(const char *str, void *) {
}
OptionGroupVariable::OptionGroupVariable(bool show_frame_options)
- : OptionGroup(), include_frame_options(show_frame_options),
- summary(ValidateNamedSummary), summary_string(ValidateSummaryString) {}
-
-OptionGroupVariable::~OptionGroupVariable() {}
+ : include_frame_options(show_frame_options), summary(ValidateNamedSummary),
+ summary_string(ValidateSummaryString) {}
Status
OptionGroupVariable::SetOptionValue(uint32_t option_idx,
diff --git a/lldb/source/Interpreter/OptionGroupWatchpoint.cpp b/lldb/source/Interpreter/OptionGroupWatchpoint.cpp
index 07013b5b78fe..eb9842add28c 100644
--- a/lldb/source/Interpreter/OptionGroupWatchpoint.cpp
+++ b/lldb/source/Interpreter/OptionGroupWatchpoint.cpp
@@ -74,10 +74,6 @@ bool OptionGroupWatchpoint::IsWatchSizeSupported(uint32_t watch_size) {
return false;
}
-OptionGroupWatchpoint::OptionGroupWatchpoint() : OptionGroup() {}
-
-OptionGroupWatchpoint::~OptionGroupWatchpoint() {}
-
Status
OptionGroupWatchpoint::SetOptionValue(uint32_t option_idx,
llvm::StringRef option_arg,
diff --git a/lldb/source/Interpreter/OptionValue.cpp b/lldb/source/Interpreter/OptionValue.cpp
index 0bd9a591af67..79bdf74b6fd9 100644
--- a/lldb/source/Interpreter/OptionValue.cpp
+++ b/lldb/source/Interpreter/OptionValue.cpp
@@ -543,8 +543,7 @@ lldb::OptionValueSP OptionValue::CreateValueFromCStringForTypeMask(
}
if (value_sp)
- error = value_sp->SetValueFromString(
- llvm::StringRef::withNullAsEmpty(value_cstr), eVarSetOperationAssign);
+ error = value_sp->SetValueFromString(value_cstr, eVarSetOperationAssign);
else
error.SetErrorString("unsupported type mask");
return value_sp;
@@ -568,6 +567,12 @@ bool OptionValue::DumpQualifiedName(Stream &strm) const {
return dumped_something;
}
+OptionValueSP OptionValue::DeepCopy(const OptionValueSP &new_parent) const {
+ auto clone = Clone();
+ clone->SetParent(new_parent);
+ return clone;
+}
+
void OptionValue::AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) {}
diff --git a/lldb/source/Interpreter/OptionValueArch.cpp b/lldb/source/Interpreter/OptionValueArch.cpp
index ac78ee64a9d7..4d1e2c7869f3 100644
--- a/lldb/source/Interpreter/OptionValueArch.cpp
+++ b/lldb/source/Interpreter/OptionValueArch.cpp
@@ -64,10 +64,6 @@ Status OptionValueArch::SetValueFromString(llvm::StringRef value,
return error;
}
-lldb::OptionValueSP OptionValueArch::DeepCopy() const {
- return OptionValueSP(new OptionValueArch(*this));
-}
-
void OptionValueArch::AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) {
CommandCompletions::InvokeCommonCompletionCallbacks(
diff --git a/lldb/source/Interpreter/OptionValueArgs.cpp b/lldb/source/Interpreter/OptionValueArgs.cpp
index 9e7774a231c7..bdb5f486835a 100644
--- a/lldb/source/Interpreter/OptionValueArgs.cpp
+++ b/lldb/source/Interpreter/OptionValueArgs.cpp
@@ -13,9 +13,9 @@
using namespace lldb;
using namespace lldb_private;
-size_t OptionValueArgs::GetArgs(Args &args) {
+size_t OptionValueArgs::GetArgs(Args &args) const {
args.Clear();
- for (auto value : m_values) {
+ for (const auto &value : m_values) {
llvm::StringRef string_value = value->GetStringValue();
if (!string_value.empty())
args.AppendArgument(string_value);
diff --git a/lldb/source/Interpreter/OptionValueArray.cpp b/lldb/source/Interpreter/OptionValueArray.cpp
index 0b293ccfc248..b1545bdebf10 100644
--- a/lldb/source/Interpreter/OptionValueArray.cpp
+++ b/lldb/source/Interpreter/OptionValueArray.cpp
@@ -303,15 +303,16 @@ Status OptionValueArray::SetArgs(const Args &args, VarSetOperationType op) {
return error;
}
-lldb::OptionValueSP OptionValueArray::DeepCopy() const {
- OptionValueArray *copied_array =
- new OptionValueArray(m_type_mask, m_raw_value_dump);
- lldb::OptionValueSP copied_value_sp(copied_array);
- *static_cast<OptionValue *>(copied_array) = *this;
- copied_array->m_callback = m_callback;
- const uint32_t size = m_values.size();
- for (uint32_t i = 0; i < size; ++i) {
- copied_array->AppendValue(m_values[i]->DeepCopy());
- }
- return copied_value_sp;
+OptionValueSP
+OptionValueArray::DeepCopy(const OptionValueSP &new_parent) const {
+ auto copy_sp = OptionValue::DeepCopy(new_parent);
+ // copy_sp->GetAsArray cannot be used here as it doesn't work for derived
+ // types that override GetType returning a different value.
+ auto *array_value_ptr = static_cast<OptionValueArray *>(copy_sp.get());
+ lldbassert(array_value_ptr);
+
+ for (auto &value : array_value_ptr->m_values)
+ value = value->DeepCopy(copy_sp);
+
+ return copy_sp;
}
diff --git a/lldb/source/Interpreter/OptionValueBoolean.cpp b/lldb/source/Interpreter/OptionValueBoolean.cpp
index 24ae3f673bf9..62845c14bd13 100644
--- a/lldb/source/Interpreter/OptionValueBoolean.cpp
+++ b/lldb/source/Interpreter/OptionValueBoolean.cpp
@@ -67,10 +67,6 @@ Status OptionValueBoolean::SetValueFromString(llvm::StringRef value_str,
return error;
}
-lldb::OptionValueSP OptionValueBoolean::DeepCopy() const {
- return OptionValueSP(new OptionValueBoolean(*this));
-}
-
void OptionValueBoolean::AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) {
llvm::StringRef autocomplete_entries[] = {"true", "false", "on", "off",
diff --git a/lldb/source/Interpreter/OptionValueChar.cpp b/lldb/source/Interpreter/OptionValueChar.cpp
index af9a371f46d4..7fe72c9aa221 100644
--- a/lldb/source/Interpreter/OptionValueChar.cpp
+++ b/lldb/source/Interpreter/OptionValueChar.cpp
@@ -57,7 +57,3 @@ Status OptionValueChar::SetValueFromString(llvm::StringRef value,
}
return error;
}
-
-lldb::OptionValueSP OptionValueChar::DeepCopy() const {
- return OptionValueSP(new OptionValueChar(*this));
-}
diff --git a/lldb/source/Interpreter/OptionValueDictionary.cpp b/lldb/source/Interpreter/OptionValueDictionary.cpp
index 79323f502d17..26fed4a987e1 100644
--- a/lldb/source/Interpreter/OptionValueDictionary.cpp
+++ b/lldb/source/Interpreter/OptionValueDictionary.cpp
@@ -311,15 +311,16 @@ bool OptionValueDictionary::DeleteValueForKey(ConstString key) {
return false;
}
-lldb::OptionValueSP OptionValueDictionary::DeepCopy() const {
- OptionValueDictionary *copied_dict =
- new OptionValueDictionary(m_type_mask, m_raw_value_dump);
- lldb::OptionValueSP copied_value_sp(copied_dict);
- collection::const_iterator pos, end = m_values.end();
- for (pos = m_values.begin(); pos != end; ++pos) {
- StreamString strm;
- strm.Printf("%s=", pos->first.GetCString());
- copied_dict->SetValueForKey(pos->first, pos->second->DeepCopy(), true);
- }
- return copied_value_sp;
+OptionValueSP
+OptionValueDictionary::DeepCopy(const OptionValueSP &new_parent) const {
+ auto copy_sp = OptionValue::DeepCopy(new_parent);
+ // copy_sp->GetAsDictionary cannot be used here as it doesn't work for derived
+ // types that override GetType returning a different value.
+ auto *dict_value_ptr = static_cast<OptionValueDictionary *>(copy_sp.get());
+ lldbassert(dict_value_ptr);
+
+ for (auto &value : dict_value_ptr->m_values)
+ value.second = value.second->DeepCopy(copy_sp);
+
+ return copy_sp;
}
diff --git a/lldb/source/Interpreter/OptionValueEnumeration.cpp b/lldb/source/Interpreter/OptionValueEnumeration.cpp
index 9a1e08d4fba0..f75519c577c5 100644
--- a/lldb/source/Interpreter/OptionValueEnumeration.cpp
+++ b/lldb/source/Interpreter/OptionValueEnumeration.cpp
@@ -15,13 +15,10 @@ using namespace lldb_private;
OptionValueEnumeration::OptionValueEnumeration(
const OptionEnumValues &enumerators, enum_type value)
- : OptionValue(), m_current_value(value), m_default_value(value),
- m_enumerations() {
+ : m_current_value(value), m_default_value(value) {
SetEnumerations(enumerators);
}
-OptionValueEnumeration::~OptionValueEnumeration() {}
-
void OptionValueEnumeration::DumpValue(const ExecutionContext *exe_ctx,
Stream &strm, uint32_t dump_mask) {
if (dump_mask & eDumpOptionType)
@@ -98,10 +95,6 @@ void OptionValueEnumeration::SetEnumerations(
m_enumerations.Sort();
}
-lldb::OptionValueSP OptionValueEnumeration::DeepCopy() const {
- return OptionValueSP(new OptionValueEnumeration(*this));
-}
-
void OptionValueEnumeration::AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) {
const uint32_t num_enumerators = m_enumerations.GetSize();
diff --git a/lldb/source/Interpreter/OptionValueFileColonLine.cpp b/lldb/source/Interpreter/OptionValueFileColonLine.cpp
index dac557c4248a..fb0b516c8616 100644
--- a/lldb/source/Interpreter/OptionValueFileColonLine.cpp
+++ b/lldb/source/Interpreter/OptionValueFileColonLine.cpp
@@ -21,13 +21,10 @@ using namespace lldb_private;
// I set the completer to "source file" which isn't quite right, but we can
// only usefully complete in the file name part of it so it should be good
// enough.
-OptionValueFileColonLine::OptionValueFileColonLine()
- : OptionValue(), m_file_spec(), m_line_number(LLDB_INVALID_LINE_NUMBER),
- m_column_number(LLDB_INVALID_COLUMN_NUMBER),
- m_completion_mask(CommandCompletions::eSourceFileCompletion) {}
+OptionValueFileColonLine::OptionValueFileColonLine() = default;
OptionValueFileColonLine::OptionValueFileColonLine(llvm::StringRef input)
- : OptionValue(), m_file_spec(), m_line_number(LLDB_INVALID_LINE_NUMBER),
+ : m_line_number(LLDB_INVALID_LINE_NUMBER),
m_column_number(LLDB_INVALID_COLUMN_NUMBER),
m_completion_mask(CommandCompletions::eSourceFileCompletion) {
SetValueFromString(input, eVarSetOperationAssign);
@@ -92,8 +89,8 @@ Status OptionValueFileColonLine::SetValueFromString(llvm::StringRef value,
llvm::StringRef middle_piece;
std::tie(file_name, middle_piece) = left_of_last_piece.rsplit(':');
- if (middle_piece.empty() || !llvm::to_integer(middle_piece,
- m_line_number)) {
+ if (middle_piece.empty() ||
+ !llvm::to_integer(middle_piece, m_line_number)) {
// The middle piece was empty or not an integer, so there were only two
// legit pieces; our original division was right. Reassign the file
// name and pull out the line number:
@@ -134,10 +131,6 @@ Status OptionValueFileColonLine::SetValueFromString(llvm::StringRef value,
return error;
}
-lldb::OptionValueSP OptionValueFileColonLine::DeepCopy() const {
- return OptionValueSP(new OptionValueFileColonLine(*this));
-}
-
void OptionValueFileColonLine::AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) {
CommandCompletions::InvokeCommonCompletionCallbacks(
diff --git a/lldb/source/Interpreter/OptionValueFileSpec.cpp b/lldb/source/Interpreter/OptionValueFileSpec.cpp
index a03fd55d0385..3987a36b1b65 100644
--- a/lldb/source/Interpreter/OptionValueFileSpec.cpp
+++ b/lldb/source/Interpreter/OptionValueFileSpec.cpp
@@ -18,23 +18,17 @@
using namespace lldb;
using namespace lldb_private;
-OptionValueFileSpec::OptionValueFileSpec(bool resolve)
- : OptionValue(), m_current_value(), m_default_value(), m_data_sp(),
- m_data_mod_time(),
- m_completion_mask(CommandCompletions::eDiskFileCompletion),
- m_resolve(resolve) {}
+OptionValueFileSpec::OptionValueFileSpec(bool resolve) : m_resolve(resolve) {}
OptionValueFileSpec::OptionValueFileSpec(const FileSpec &value, bool resolve)
- : OptionValue(), m_current_value(value), m_default_value(value),
- m_data_sp(), m_data_mod_time(),
+ : m_current_value(value), m_default_value(value),
m_completion_mask(CommandCompletions::eDiskFileCompletion),
m_resolve(resolve) {}
OptionValueFileSpec::OptionValueFileSpec(const FileSpec &current_value,
const FileSpec &default_value,
bool resolve)
- : OptionValue(), m_current_value(current_value),
- m_default_value(default_value), m_data_sp(), m_data_mod_time(),
+ : m_current_value(current_value), m_default_value(default_value),
m_completion_mask(CommandCompletions::eDiskFileCompletion),
m_resolve(resolve) {}
@@ -88,10 +82,6 @@ Status OptionValueFileSpec::SetValueFromString(llvm::StringRef value,
return error;
}
-lldb::OptionValueSP OptionValueFileSpec::DeepCopy() const {
- return OptionValueSP(new OptionValueFileSpec(*this));
-}
-
void OptionValueFileSpec::AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) {
CommandCompletions::InvokeCommonCompletionCallbacks(
diff --git a/lldb/source/Interpreter/OptionValueFileSpecList.cpp b/lldb/source/Interpreter/OptionValueFileSpecList.cpp
index f2367b1941c9..2160fd61d428 100644
--- a/lldb/source/Interpreter/OptionValueFileSpecList.cpp
+++ b/lldb/source/Interpreter/OptionValueFileSpecList.cpp
@@ -164,7 +164,7 @@ Status OptionValueFileSpecList::SetValueFromString(llvm::StringRef value,
return error;
}
-lldb::OptionValueSP OptionValueFileSpecList::DeepCopy() const {
+OptionValueSP OptionValueFileSpecList::Clone() const {
std::lock_guard<std::recursive_mutex> lock(m_mutex);
- return OptionValueSP(new OptionValueFileSpecList(m_current_value));
+ return Cloneable::Clone();
}
diff --git a/lldb/source/Interpreter/OptionValueFormat.cpp b/lldb/source/Interpreter/OptionValueFormat.cpp
index b676bed50e62..76a446d1c3bc 100644
--- a/lldb/source/Interpreter/OptionValueFormat.cpp
+++ b/lldb/source/Interpreter/OptionValueFormat.cpp
@@ -56,7 +56,3 @@ Status OptionValueFormat::SetValueFromString(llvm::StringRef value,
}
return error;
}
-
-lldb::OptionValueSP OptionValueFormat::DeepCopy() const {
- return OptionValueSP(new OptionValueFormat(*this));
-}
diff --git a/lldb/source/Interpreter/OptionValueFormatEntity.cpp b/lldb/source/Interpreter/OptionValueFormatEntity.cpp
index 509a21752e48..64fcaf2cbc85 100644
--- a/lldb/source/Interpreter/OptionValueFormatEntity.cpp
+++ b/lldb/source/Interpreter/OptionValueFormatEntity.cpp
@@ -15,9 +15,7 @@
using namespace lldb;
using namespace lldb_private;
-OptionValueFormatEntity::OptionValueFormatEntity(const char *default_format)
- : OptionValue(), m_current_format(), m_default_format(), m_current_entry(),
- m_default_entry() {
+OptionValueFormatEntity::OptionValueFormatEntity(const char *default_format) {
if (default_format && default_format[0]) {
llvm::StringRef default_format_str(default_format);
Status error = FormatEntity::Parse(default_format_str, m_default_entry);
@@ -111,10 +109,6 @@ Status OptionValueFormatEntity::SetValueFromString(llvm::StringRef value_str,
return error;
}
-lldb::OptionValueSP OptionValueFormatEntity::DeepCopy() const {
- return OptionValueSP(new OptionValueFormatEntity(*this));
-}
-
void OptionValueFormatEntity::AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) {
FormatEntity::AutoComplete(request);
diff --git a/lldb/source/Interpreter/OptionValueLanguage.cpp b/lldb/source/Interpreter/OptionValueLanguage.cpp
index 5b310782a1ba..d2fbe248300d 100644
--- a/lldb/source/Interpreter/OptionValueLanguage.cpp
+++ b/lldb/source/Interpreter/OptionValueLanguage.cpp
@@ -69,7 +69,3 @@ Status OptionValueLanguage::SetValueFromString(llvm::StringRef value,
}
return error;
}
-
-lldb::OptionValueSP OptionValueLanguage::DeepCopy() const {
- return OptionValueSP(new OptionValueLanguage(*this));
-}
diff --git a/lldb/source/Interpreter/OptionValuePathMappings.cpp b/lldb/source/Interpreter/OptionValuePathMappings.cpp
index 3b3f43d07293..4dceb5632716 100644
--- a/lldb/source/Interpreter/OptionValuePathMappings.cpp
+++ b/lldb/source/Interpreter/OptionValuePathMappings.cpp
@@ -196,7 +196,3 @@ Status OptionValuePathMappings::SetValueFromString(llvm::StringRef value,
}
return error;
}
-
-lldb::OptionValueSP OptionValuePathMappings::DeepCopy() const {
- return OptionValueSP(new OptionValuePathMappings(*this));
-}
diff --git a/lldb/source/Interpreter/OptionValueProperties.cpp b/lldb/source/Interpreter/OptionValueProperties.cpp
index 6c4e77f614f9..ae073798ca12 100644
--- a/lldb/source/Interpreter/OptionValueProperties.cpp
+++ b/lldb/source/Interpreter/OptionValueProperties.cpp
@@ -20,29 +20,7 @@
using namespace lldb;
using namespace lldb_private;
-OptionValueProperties::OptionValueProperties(ConstString name)
- : OptionValue(), m_name(name), m_properties(), m_name_to_index() {}
-
-OptionValueProperties::OptionValueProperties(
- const OptionValueProperties &global_properties)
- : OptionValue(global_properties),
- std::enable_shared_from_this<OptionValueProperties>(),
- m_name(global_properties.m_name),
- m_properties(global_properties.m_properties),
- m_name_to_index(global_properties.m_name_to_index) {
- // We now have an exact copy of "global_properties". We need to now find all
- // non-global settings and copy the property values so that all non-global
- // settings get new OptionValue instances created for them.
- const size_t num_properties = m_properties.size();
- for (size_t i = 0; i < num_properties; ++i) {
- // Duplicate any values that are not global when constructing properties
- // from a global copy
- if (!m_properties[i].IsGlobal()) {
- lldb::OptionValueSP new_value_sp(m_properties[i].GetValue()->DeepCopy());
- m_properties[i].SetOptionValue(new_value_sp);
- }
- }
-}
+OptionValueProperties::OptionValueProperties(ConstString name) : m_name(name) {}
size_t OptionValueProperties::GetNumProperties() const {
return m_properties.size();
@@ -250,38 +228,50 @@ OptionValueProperties::GetPropertyAtIndexAsOptionValueLanguage(
bool OptionValueProperties::GetPropertyAtIndexAsArgs(
const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const {
const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
- if (property) {
- OptionValue *value = property->GetValue().get();
- if (value) {
- const OptionValueArray *array = value->GetAsArray();
- if (array)
- return array->GetArgs(args);
- else {
- const OptionValueDictionary *dict = value->GetAsDictionary();
- if (dict)
- return dict->GetArgs(args);
- }
- }
- }
+ if (!property)
+ return false;
+
+ OptionValue *value = property->GetValue().get();
+ if (!value)
+ return false;
+
+ const OptionValueArgs *arguments = value->GetAsArgs();
+ if (arguments)
+ return arguments->GetArgs(args);
+
+ const OptionValueArray *array = value->GetAsArray();
+ if (array)
+ return array->GetArgs(args);
+
+ const OptionValueDictionary *dict = value->GetAsDictionary();
+ if (dict)
+ return dict->GetArgs(args);
+
return false;
}
bool OptionValueProperties::SetPropertyAtIndexFromArgs(
const ExecutionContext *exe_ctx, uint32_t idx, const Args &args) {
const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
- if (property) {
- OptionValue *value = property->GetValue().get();
- if (value) {
- OptionValueArray *array = value->GetAsArray();
- if (array)
- return array->SetArgs(args, eVarSetOperationAssign).Success();
- else {
- OptionValueDictionary *dict = value->GetAsDictionary();
- if (dict)
- return dict->SetArgs(args, eVarSetOperationAssign).Success();
- }
- }
- }
+ if (!property)
+ return false;
+
+ OptionValue *value = property->GetValue().get();
+ if (!value)
+ return false;
+
+ OptionValueArgs *arguments = value->GetAsArgs();
+ if (arguments)
+ return arguments->SetArgs(args, eVarSetOperationAssign).Success();
+
+ OptionValueArray *array = value->GetAsArray();
+ if (array)
+ return array->SetArgs(args, eVarSetOperationAssign).Success();
+
+ OptionValueDictionary *dict = value->GetAsDictionary();
+ if (dict)
+ return dict->SetArgs(args, eVarSetOperationAssign).Success();
+
return false;
}
@@ -552,8 +542,32 @@ Status OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx,
return error;
}
-lldb::OptionValueSP OptionValueProperties::DeepCopy() const {
- llvm_unreachable("this shouldn't happen");
+OptionValuePropertiesSP
+OptionValueProperties::CreateLocalCopy(const Properties &global_properties) {
+ auto global_props_sp = global_properties.GetValueProperties();
+ lldbassert(global_props_sp);
+
+ auto copy_sp = global_props_sp->DeepCopy(global_props_sp->GetParent());
+ return std::static_pointer_cast<OptionValueProperties>(copy_sp);
+}
+
+OptionValueSP
+OptionValueProperties::DeepCopy(const OptionValueSP &new_parent) const {
+ auto copy_sp = OptionValue::DeepCopy(new_parent);
+ // copy_sp->GetAsProperties cannot be used here as it doesn't work for derived
+ // types that override GetType returning a different value.
+ auto *props_value_ptr = static_cast<OptionValueProperties *>(copy_sp.get());
+ lldbassert(props_value_ptr);
+
+ for (auto &property : props_value_ptr->m_properties) {
+ // Duplicate any values that are not global when constructing properties
+ // from a global copy.
+ if (!property.IsGlobal()) {
+ auto value_sp = property.GetValue()->DeepCopy(copy_sp);
+ property.SetOptionValue(value_sp);
+ }
+ }
+ return copy_sp;
}
const Property *OptionValueProperties::GetPropertyAtPath(
@@ -616,11 +630,11 @@ void OptionValueProperties::Apropos(
} else {
bool match = false;
llvm::StringRef name = property->GetName();
- if (name.contains_lower(keyword))
+ if (name.contains_insensitive(keyword))
match = true;
else {
llvm::StringRef desc = property->GetDescription();
- if (desc.contains_lower(keyword))
+ if (desc.contains_insensitive(keyword))
match = true;
}
if (match) {
diff --git a/lldb/source/Interpreter/OptionValueRegex.cpp b/lldb/source/Interpreter/OptionValueRegex.cpp
index bec3942d9cb0..bbeca8da7714 100644
--- a/lldb/source/Interpreter/OptionValueRegex.cpp
+++ b/lldb/source/Interpreter/OptionValueRegex.cpp
@@ -59,7 +59,3 @@ Status OptionValueRegex::SetValueFromString(llvm::StringRef value,
}
return error;
}
-
-lldb::OptionValueSP OptionValueRegex::DeepCopy() const {
- return OptionValueSP(new OptionValueRegex(m_regex.GetText().str().c_str()));
-}
diff --git a/lldb/source/Interpreter/OptionValueSInt64.cpp b/lldb/source/Interpreter/OptionValueSInt64.cpp
index ada20b2139a3..b875ba8e3536 100644
--- a/lldb/source/Interpreter/OptionValueSInt64.cpp
+++ b/lldb/source/Interpreter/OptionValueSInt64.cpp
@@ -70,7 +70,3 @@ Status OptionValueSInt64::SetValueFromString(llvm::StringRef value_ref,
}
return error;
}
-
-lldb::OptionValueSP OptionValueSInt64::DeepCopy() const {
- return OptionValueSP(new OptionValueSInt64(*this));
-}
diff --git a/lldb/source/Interpreter/OptionValueString.cpp b/lldb/source/Interpreter/OptionValueString.cpp
index 22f5d08bf832..b4fec91bc33f 100644
--- a/lldb/source/Interpreter/OptionValueString.cpp
+++ b/lldb/source/Interpreter/OptionValueString.cpp
@@ -117,10 +117,6 @@ Status OptionValueString::SetValueFromString(llvm::StringRef value,
return error;
}
-lldb::OptionValueSP OptionValueString::DeepCopy() const {
- return OptionValueSP(new OptionValueString(*this));
-}
-
Status OptionValueString::SetCurrentValue(llvm::StringRef value) {
if (m_validator) {
Status error(m_validator(value.str().c_str(), m_validator_baton));
diff --git a/lldb/source/Interpreter/OptionValueUInt64.cpp b/lldb/source/Interpreter/OptionValueUInt64.cpp
index 98ef016e5f77..a2751a4d02eb 100644
--- a/lldb/source/Interpreter/OptionValueUInt64.cpp
+++ b/lldb/source/Interpreter/OptionValueUInt64.cpp
@@ -68,7 +68,3 @@ Status OptionValueUInt64::SetValueFromString(llvm::StringRef value_ref,
}
return error;
}
-
-lldb::OptionValueSP OptionValueUInt64::DeepCopy() const {
- return OptionValueSP(new OptionValueUInt64(*this));
-}
diff --git a/lldb/source/Interpreter/OptionValueUUID.cpp b/lldb/source/Interpreter/OptionValueUUID.cpp
index 2bd749773556..283f9c1b67b3 100644
--- a/lldb/source/Interpreter/OptionValueUUID.cpp
+++ b/lldb/source/Interpreter/OptionValueUUID.cpp
@@ -58,10 +58,6 @@ Status OptionValueUUID::SetValueFromString(llvm::StringRef value,
return error;
}
-lldb::OptionValueSP OptionValueUUID::DeepCopy() const {
- return OptionValueSP(new OptionValueUUID(*this));
-}
-
void OptionValueUUID::AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) {
ExecutionContext exe_ctx(interpreter.GetExecutionContext());
diff --git a/lldb/source/Interpreter/Options.cpp b/lldb/source/Interpreter/Options.cpp
index 9ecc9e229e0e..4aa298f0382b 100644
--- a/lldb/source/Interpreter/Options.cpp
+++ b/lldb/source/Interpreter/Options.cpp
@@ -25,9 +25,9 @@ using namespace lldb;
using namespace lldb_private;
// Options
-Options::Options() : m_getopt_table() { BuildValidOptionSets(); }
+Options::Options() { BuildValidOptionSets(); }
-Options::~Options() {}
+Options::~Options() = default;
void Options::NotifyOptionParsingStarting(ExecutionContext *execution_context) {
m_seen_options.clear();
@@ -137,7 +137,6 @@ bool Options::VerifyOptions(CommandReturnObject &result) {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
result.AppendError("invalid combination of options for the given command");
- result.SetStatus(eReturnStatusFailed);
}
return options_are_valid;
diff --git a/lldb/source/Interpreter/Property.cpp b/lldb/source/Interpreter/Property.cpp
index a02497662ff5..55400a2bc42d 100644
--- a/lldb/source/Interpreter/Property.cpp
+++ b/lldb/source/Interpreter/Property.cpp
@@ -22,7 +22,7 @@ using namespace lldb_private;
Property::Property(const PropertyDefinition &definition)
: m_name(definition.name), m_description(definition.description),
- m_value_sp(), m_is_global(definition.global) {
+ m_is_global(definition.global) {
switch (definition.type) {
case OptionValue::eTypeInvalid:
case OptionValue::eTypeProperties:
diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp
index 013ed6aecb80..f26474836a68 100644
--- a/lldb/source/Interpreter/ScriptInterpreter.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -18,37 +18,36 @@
#if defined(_WIN32)
#include "lldb/Host/windows/ConnectionGenericFileWindows.h"
#endif
+#include <cstdio>
+#include <cstdlib>
#include <memory>
-#include <stdio.h>
-#include <stdlib.h>
#include <string>
using namespace lldb;
using namespace lldb_private;
-ScriptInterpreter::ScriptInterpreter(Debugger &debugger,
- lldb::ScriptLanguage script_lang)
- : m_debugger(debugger), m_script_lang(script_lang) {}
-
-ScriptInterpreter::~ScriptInterpreter() {}
+ScriptInterpreter::ScriptInterpreter(
+ Debugger &debugger, lldb::ScriptLanguage script_lang,
+ lldb::ScriptedProcessInterfaceUP scripted_process_interface_up)
+ : m_debugger(debugger), m_script_lang(script_lang),
+ m_scripted_process_interface_up(
+ std::move(scripted_process_interface_up)) {}
void ScriptInterpreter::CollectDataForBreakpointCommandCallback(
- std::vector<BreakpointOptions *> &bp_options_vec,
+ std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
CommandReturnObject &result) {
- result.SetStatus(eReturnStatusFailed);
result.AppendError(
"This script interpreter does not support breakpoint callbacks.");
}
void ScriptInterpreter::CollectDataForWatchpointCommandCallback(
WatchpointOptions *bp_options, CommandReturnObject &result) {
- result.SetStatus(eReturnStatusFailed);
result.AppendError(
"This script interpreter does not support watchpoint callbacks.");
}
bool ScriptInterpreter::LoadScriptingModule(const char *filename,
- bool init_session,
+ const LoadScriptOptions &options,
lldb_private::Status &error,
StructuredData::ObjectSP *module_sp,
FileSpec extra_search_dir) {
@@ -71,22 +70,35 @@ std::string ScriptInterpreter::LanguageToString(lldb::ScriptLanguage language) {
llvm_unreachable("Unhandled ScriptInterpreter!");
}
+lldb::DataExtractorSP
+ScriptInterpreter::GetDataExtractorFromSBData(const lldb::SBData &data) const {
+ return data.m_opaque_sp;
+}
+
+Status
+ScriptInterpreter::GetStatusFromSBError(const lldb::SBError &error) const {
+ if (error.m_opaque_up)
+ return *error.m_opaque_up.get();
+
+ return Status();
+}
+
lldb::ScriptLanguage
ScriptInterpreter::StringToLanguage(const llvm::StringRef &language) {
- if (language.equals_lower(LanguageToString(eScriptLanguageNone)))
+ if (language.equals_insensitive(LanguageToString(eScriptLanguageNone)))
return eScriptLanguageNone;
- if (language.equals_lower(LanguageToString(eScriptLanguagePython)))
+ if (language.equals_insensitive(LanguageToString(eScriptLanguagePython)))
return eScriptLanguagePython;
- if (language.equals_lower(LanguageToString(eScriptLanguageLua)))
+ if (language.equals_insensitive(LanguageToString(eScriptLanguageLua)))
return eScriptLanguageLua;
return eScriptLanguageUnknown;
}
Status ScriptInterpreter::SetBreakpointCommandCallback(
- std::vector<BreakpointOptions *> &bp_options_vec,
+ std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
const char *callback_text) {
Status return_error;
- for (BreakpointOptions *bp_options : bp_options_vec) {
+ for (BreakpointOptions &bp_options : bp_options_vec) {
return_error = SetBreakpointCommandCallback(bp_options, callback_text);
if (return_error.Success())
break;
@@ -95,10 +107,10 @@ Status ScriptInterpreter::SetBreakpointCommandCallback(
}
Status ScriptInterpreter::SetBreakpointCommandCallbackFunction(
- std::vector<BreakpointOptions *> &bp_options_vec, const char *function_name,
- StructuredData::ObjectSP extra_args_sp) {
+ std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
+ const char *function_name, StructuredData::ObjectSP extra_args_sp) {
Status error;
- for (BreakpointOptions *bp_options : bp_options_vec) {
+ for (BreakpointOptions &bp_options : bp_options_vec) {
error = SetBreakpointCommandCallbackFunction(bp_options, function_name,
extra_args_sp);
if (!error.Success())
diff --git a/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp b/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp
index 7cae4cc42750..42d73ce39ed6 100644
--- a/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp
+++ b/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp
@@ -11,6 +11,7 @@
#include "ABISysV_arm64.h"
#include "Utility/ARM64_DWARF_Registers.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Target/Process.h"
LLDB_PLUGIN_DEFINE(ABIAArch64)
@@ -24,6 +25,18 @@ void ABIAArch64::Terminate() {
ABIMacOSX_arm64::Terminate();
}
+lldb::addr_t ABIAArch64::FixCodeAddress(lldb::addr_t pc) {
+ if (lldb::ProcessSP process_sp = GetProcessSP())
+ return FixAddress(pc, process_sp->GetCodeAddressMask());
+ return pc;
+}
+
+lldb::addr_t ABIAArch64::FixDataAddress(lldb::addr_t pc) {
+ if (lldb::ProcessSP process_sp = GetProcessSP())
+ return FixAddress(pc, process_sp->GetDataAddressMask());
+ return pc;
+}
+
std::pair<uint32_t, uint32_t>
ABIAArch64::GetEHAndDWARFNums(llvm::StringRef name) {
if (name == "pc")
diff --git a/lldb/source/Plugins/ABI/AArch64/ABIAArch64.h b/lldb/source/Plugins/ABI/AArch64/ABIAArch64.h
index bdff648f1b52..41bbf5cfdeb9 100644
--- a/lldb/source/Plugins/ABI/AArch64/ABIAArch64.h
+++ b/lldb/source/Plugins/ABI/AArch64/ABIAArch64.h
@@ -16,7 +16,14 @@ public:
static void Initialize();
static void Terminate();
+ virtual lldb::addr_t FixCodeAddress(lldb::addr_t pc) override;
+ virtual lldb::addr_t FixDataAddress(lldb::addr_t pc) override;
+
protected:
+ virtual lldb::addr_t FixAddress(lldb::addr_t pc, lldb::addr_t mask) {
+ return pc;
+ }
+
std::pair<uint32_t, uint32_t>
GetEHAndDWARFNums(llvm::StringRef name) override;
diff --git a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
index 09b319a84a08..348a081cfe17 100644
--- a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
+++ b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
@@ -66,7 +66,7 @@ bool ABIMacOSX_arm64::PrepareTrivialCall(
if (log) {
StreamString s;
- s.Printf("ABISysV_x86_64::PrepareTrivialCall (tid = 0x%" PRIx64
+ s.Printf("ABIMacOSX_arm64::PrepareTrivialCall (tid = 0x%" PRIx64
", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
", return_addr = 0x%" PRIx64,
thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
@@ -86,7 +86,7 @@ bool ABIMacOSX_arm64::PrepareTrivialCall(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
// x0 - x7 contain first 8 simple args
- if (args.size() > 8) // TODO handle more than 6 arguments
+ if (args.size() > 8) // TODO handle more than 8 arguments
return false;
for (size_t i = 0; i < args.size(); ++i) {
@@ -384,6 +384,7 @@ bool ABIMacOSX_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
row->SetOffset(0);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
@@ -654,7 +655,7 @@ ValueObjectSP ABIMacOSX_arm64::GetReturnValueObjectImpl(
const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr);
if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
bool success = false;
if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
@@ -814,6 +815,11 @@ ValueObjectSP ABIMacOSX_arm64::GetReturnValueObjectImpl(
return return_valobj_sp;
}
+lldb::addr_t ABIMacOSX_arm64::FixAddress(addr_t pc, addr_t mask) {
+ lldb::addr_t pac_sign_extension = 0x0080000000000000ULL;
+ return (pc & pac_sign_extension) ? pc | mask : pc & (~mask);
+}
+
void ABIMacOSX_arm64::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(), pluginDesc,
CreateInstance);
diff --git a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
index fc8ccee92e71..dc3ab35115fd 100644
--- a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
+++ b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
@@ -62,6 +62,8 @@ public:
return true;
}
+ lldb::addr_t FixAddress(lldb::addr_t pc, lldb::addr_t mask) override;
+
// Static Functions
static void Initialize();
diff --git a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp
index 1214195dcfc0..16fb38e107c3 100644
--- a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp
+++ b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp
@@ -356,6 +356,7 @@ bool ABISysV_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
row->SetOffset(0);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
@@ -622,7 +623,7 @@ ValueObjectSP ABISysV_arm64::GetReturnValueObjectImpl(
const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr);
if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
bool success = false;
if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
@@ -781,6 +782,61 @@ ValueObjectSP ABISysV_arm64::GetReturnValueObjectImpl(
return return_valobj_sp;
}
+lldb::addr_t ABISysV_arm64::FixAddress(addr_t pc, addr_t mask) {
+ lldb::addr_t pac_sign_extension = 0x0080000000000000ULL;
+ return (pc & pac_sign_extension) ? pc | mask : pc & (~mask);
+}
+
+// Reads code or data address mask for the current Linux process.
+static lldb::addr_t ReadLinuxProcessAddressMask(lldb::ProcessSP process_sp,
+ llvm::StringRef reg_name) {
+ // Linux configures user-space virtual addresses with top byte ignored.
+ // We set default value of mask such that top byte is masked out.
+ uint64_t address_mask = ~((1ULL << 56) - 1);
+ // If Pointer Authentication feature is enabled then Linux exposes
+ // PAC data and code mask register. Try reading relevant register
+ // below and merge it with default address mask calculated above.
+ lldb::ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread();
+ if (thread_sp) {
+ lldb::RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();
+ if (reg_ctx_sp) {
+ const RegisterInfo *reg_info =
+ reg_ctx_sp->GetRegisterInfoByName(reg_name, 0);
+ if (reg_info) {
+ lldb::addr_t mask_reg_val = reg_ctx_sp->ReadRegisterAsUnsigned(
+ reg_info->kinds[eRegisterKindLLDB], LLDB_INVALID_ADDRESS);
+ if (mask_reg_val != LLDB_INVALID_ADDRESS)
+ address_mask |= mask_reg_val;
+ }
+ }
+ }
+ return address_mask;
+}
+
+lldb::addr_t ABISysV_arm64::FixCodeAddress(lldb::addr_t pc) {
+ if (lldb::ProcessSP process_sp = GetProcessSP()) {
+ if (process_sp->GetTarget().GetArchitecture().GetTriple().isOSLinux() &&
+ !process_sp->GetCodeAddressMask())
+ process_sp->SetCodeAddressMask(
+ ReadLinuxProcessAddressMask(process_sp, "code_mask"));
+
+ return FixAddress(pc, process_sp->GetCodeAddressMask());
+ }
+ return pc;
+}
+
+lldb::addr_t ABISysV_arm64::FixDataAddress(lldb::addr_t pc) {
+ if (lldb::ProcessSP process_sp = GetProcessSP()) {
+ if (process_sp->GetTarget().GetArchitecture().GetTriple().isOSLinux() &&
+ !process_sp->GetDataAddressMask())
+ process_sp->SetDataAddressMask(
+ ReadLinuxProcessAddressMask(process_sp, "data_mask"));
+
+ return FixAddress(pc, process_sp->GetDataAddressMask());
+ }
+ return pc;
+}
+
void ABISysV_arm64::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
"SysV ABI for AArch64 targets", CreateInstance);
diff --git a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h
index aeb74acc38b5..3428a7ad9418 100644
--- a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h
+++ b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h
@@ -67,6 +67,8 @@ public:
bool GetPointerReturnRegister(const char *&name) override;
+ lldb::addr_t FixAddress(lldb::addr_t pc, lldb::addr_t mask) override;
+
// Static Functions
static void Initialize();
@@ -83,6 +85,9 @@ public:
uint32_t GetPluginVersion() override;
+ lldb::addr_t FixCodeAddress(lldb::addr_t pc) override;
+ lldb::addr_t FixDataAddress(lldb::addr_t pc) override;
+
protected:
lldb::ValueObjectSP
GetReturnValueObjectImpl(lldb_private::Thread &thread,
diff --git a/lldb/source/Plugins/ABI/ARC/ABISysV_arc.cpp b/lldb/source/Plugins/ABI/ARC/ABISysV_arc.cpp
index be8586722d8f..60cdbc534113 100644
--- a/lldb/source/Plugins/ABI/ARC/ABISysV_arc.cpp
+++ b/lldb/source/Plugins/ABI/ARC/ABISysV_arc.cpp
@@ -466,7 +466,7 @@ ABISysV_arc::GetReturnValueObjectSimple(Thread &thread,
if (!SetSizedInteger(value.GetScalar(), raw_value, byte_size, is_signed))
return ValueObjectSP();
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
}
// Pointer return type.
else if (type_flags & eTypeIsPointer) {
@@ -474,7 +474,7 @@ ABISysV_arc::GetReturnValueObjectSimple(Thread &thread,
LLDB_REGNUM_GENERIC_ARG1);
value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_r0, 0);
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
}
// Floating point return type.
else if (type_flags & eTypeIsFloat) {
@@ -537,7 +537,7 @@ ValueObjectSP ABISysV_arc::GetReturnValueObjectImpl(Thread &thread,
auto reg_info_r0 = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
LLDB_REGNUM_GENERIC_ARG1);
value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_r0, 0);
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
}
// Floating point return type.
else if (retType.isFloatingPointTy()) {
diff --git a/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp b/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp
index 06c4590b7740..e429f3ee0cc4 100644
--- a/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp
+++ b/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp
@@ -1824,6 +1824,7 @@ bool ABIMacOSX_arm::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
row->SetOffset(0);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp b/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp
index 26b3152bed16..3e544e0483a7 100644
--- a/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp
+++ b/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp
@@ -1617,7 +1617,7 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl(
thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) &
UINT32_MAX;
value.GetScalar() = ptr;
- } else if (compiler_type.IsVectorType(nullptr, nullptr)) {
+ } else if (compiler_type.IsVectorType()) {
if (IsArmHardFloat(thread) && (*byte_size == 8 || *byte_size == 16)) {
is_vfp_candidate = true;
vfp_byte_size = 8;
@@ -1704,7 +1704,7 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl(
if (homogeneous_count > 0 && homogeneous_count <= 4) {
llvm::Optional<uint64_t> base_byte_size =
base_type.GetByteSize(&thread);
- if (base_type.IsVectorType(nullptr, nullptr)) {
+ if (base_type.IsVectorType()) {
if (base_byte_size &&
(*base_byte_size == 8 || *base_byte_size == 16)) {
is_vfp_candidate = true;
@@ -1940,6 +1940,7 @@ bool ABISysV_arm::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
row->SetOffset(0);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp b/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp
index 47aaefd3b228..6794f7d07210 100644
--- a/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp
+++ b/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp
@@ -1225,6 +1225,7 @@ bool ABISysV_hexagon::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
UnwindPlan::RowSP row(new UnwindPlan::Row);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->GetCFAValue().SetIsRegisterPlusOffset(LLDB_REGNUM_GENERIC_FP, 8);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, -8, true);
diff --git a/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp b/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp
index d66e0926ad99..538ec06c3b0d 100644
--- a/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp
+++ b/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp
@@ -985,6 +985,7 @@ bool ABISysV_mips::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
UnwindPlan::RowSP row(new UnwindPlan::Row);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
diff --git a/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp b/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp
index 751555722dac..7220508c75ff 100644
--- a/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp
+++ b/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp
@@ -764,7 +764,7 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
bool success = false;
if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
@@ -1156,6 +1156,7 @@ bool ABISysV_mips64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
UnwindPlan::RowSP row(new UnwindPlan::Row);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
diff --git a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp
index 91d2e59ed632..98a14b50cbf3 100644
--- a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp
+++ b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp
@@ -520,7 +520,7 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectSimple(
const uint32_t type_flags = return_compiler_type.GetTypeInfo();
if (type_flags & eTypeIsScalar) {
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
bool success = false;
if (type_flags & eTypeIsInteger) {
@@ -603,7 +603,7 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectSimple(
reg_ctx->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB];
value.GetScalar() =
(uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0);
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
return_valobj_sp = ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
} else if (type_flags & eTypeIsVector) {
@@ -683,8 +683,6 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl(
r3_value.GetData(r3_data);
rdx_value.GetData(rdx_data);
- uint32_t fp_bytes =
- 0; // Tracks how much of the xmm registers we've consumed so far
uint32_t integer_bytes =
0; // Tracks how much of the r3/rds registers we've consumed so far
@@ -751,7 +749,6 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl(
break;
} else if (*field_bit_width == 64) {
copy_from_offset = 0;
- fp_bytes += field_byte_width;
} else if (*field_bit_width == 32) {
// This one is kind of complicated. If we are in an "eightbyte"
// with another float, we'll be stuffed into an xmm register with
@@ -815,8 +812,6 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl(
copy_from_offset = integer_bytes - 8;
integer_bytes += field_byte_width;
}
- } else {
- fp_bytes += field_byte_width;
}
}
}
@@ -900,6 +895,7 @@ bool ABISysV_ppc::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 4;
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->GetCFAValue().SetIsRegisterDereferenced(sp_reg_num);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 1, true);
diff --git a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp
index c7cb7736df9f..7cc9482e7c5d 100644
--- a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp
+++ b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp
@@ -577,7 +577,7 @@ private:
ValueSP NewScalarValue(CompilerType &type) {
ValueSP value_sp(new Value);
value_sp->SetCompilerType(type);
- value_sp->SetValueType(Value::eValueTypeScalar);
+ value_sp->SetValueType(Value::ValueType::Scalar);
return value_sp;
}
@@ -1003,6 +1003,7 @@ bool ABISysV_ppc64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 8;
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->GetCFAValue().SetIsRegisterDereferenced(sp_reg_num);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true);
diff --git a/lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.cpp b/lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.cpp
index 22a64170017b..88e85111d871 100644
--- a/lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.cpp
+++ b/lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.cpp
@@ -487,7 +487,7 @@ ValueObjectSP ABISysV_s390x::GetReturnValueObjectSimple(
const uint32_t type_flags = return_compiler_type.GetTypeInfo();
if (type_flags & eTypeIsScalar) {
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
bool success = false;
if (type_flags & eTypeIsInteger) {
@@ -571,7 +571,7 @@ ValueObjectSP ABISysV_s390x::GetReturnValueObjectSimple(
reg_ctx->GetRegisterInfoByName("r2", 0)->kinds[eRegisterKindLLDB];
value.GetScalar() =
(uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_id, 0);
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
return_valobj_sp = ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
}
diff --git a/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp b/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp
index 89112deb2c4a..461e4af599d3 100644
--- a/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp
+++ b/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp
@@ -389,6 +389,7 @@ bool ABIMacOSX_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
row->SetOffset(0);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp b/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp
index 2f47d3f462d2..7d2f0a64d679 100644
--- a/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp
+++ b/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp
@@ -378,14 +378,14 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
uint32_t ptr =
thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
0xffffffff;
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
value.GetScalar() = ptr;
return_valobj_sp = ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
} else if ((type_flags & eTypeIsScalar) ||
(type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
{
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
llvm::Optional<uint64_t> byte_size =
return_compiler_type.GetByteSize(&thread);
if (!byte_size)
@@ -453,7 +453,7 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
uint32_t enm =
thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
0xffffffff;
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
value.GetScalar() = enm;
return_valobj_sp = ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
@@ -652,6 +652,7 @@ bool ABISysV_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
row->SetOffset(0);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp b/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp
index 2aa2c02b2e87..196b45b3b6da 100644
--- a/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp
+++ b/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp
@@ -399,7 +399,7 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple(
const uint32_t type_flags = return_compiler_type.GetTypeInfo();
if (type_flags & eTypeIsScalar) {
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
bool success = false;
if (type_flags & eTypeIsInteger) {
@@ -487,7 +487,7 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple(
value.GetScalar() =
(uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id,
0);
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
return_valobj_sp = ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
} else if (type_flags & eTypeIsVector) {
@@ -887,6 +887,7 @@ bool ABISysV_x86_64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
const int32_t ptr_size = 8;
row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size);
row->SetOffset(0);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp b/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp
index 06e0ce40836d..6c473c652c5f 100644
--- a/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp
+++ b/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp
@@ -408,7 +408,7 @@ ValueObjectSP ABIWindows_x86_64::GetReturnValueObjectSimple(
const uint32_t type_flags = return_compiler_type.GetTypeInfo();
if (type_flags & eTypeIsScalar) {
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
bool success = false;
if (type_flags & eTypeIsInteger) {
@@ -494,7 +494,7 @@ ValueObjectSP ABIWindows_x86_64::GetReturnValueObjectSimple(
value.GetScalar() =
(uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id,
0);
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
return_valobj_sp = ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
} else if (type_flags & eTypeIsVector) {
@@ -767,6 +767,7 @@ bool ABIWindows_x86_64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
const int32_t ptr_size = 8;
row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size);
row->SetOffset(0);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.cpp b/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.cpp
new file mode 100644
index 000000000000..9994cc293d6a
--- /dev/null
+++ b/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.cpp
@@ -0,0 +1,45 @@
+//===-- ArchitectureAArch64.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 "Plugins/Architecture/AArch64/ArchitectureAArch64.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Utility/ArchSpec.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+LLDB_PLUGIN_DEFINE(ArchitectureAArch64)
+
+ConstString ArchitectureAArch64::GetPluginNameStatic() {
+ return ConstString("aarch64");
+}
+
+void ArchitectureAArch64::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ "AArch64-specific algorithms",
+ &ArchitectureAArch64::Create);
+}
+
+void ArchitectureAArch64::Terminate() {
+ PluginManager::UnregisterPlugin(&ArchitectureAArch64::Create);
+}
+
+std::unique_ptr<Architecture>
+ArchitectureAArch64::Create(const ArchSpec &arch) {
+ auto machine = arch.GetMachine();
+ if (machine != llvm::Triple::aarch64 && machine != llvm::Triple::aarch64_be &&
+ machine != llvm::Triple::aarch64_32) {
+ return nullptr;
+ }
+ return std::unique_ptr<Architecture>(new ArchitectureAArch64());
+}
+
+ConstString ArchitectureAArch64::GetPluginName() {
+ return GetPluginNameStatic();
+}
+uint32_t ArchitectureAArch64::GetPluginVersion() { return 1; }
diff --git a/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.h b/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.h
new file mode 100644
index 000000000000..775478cc9338
--- /dev/null
+++ b/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.h
@@ -0,0 +1,40 @@
+//===-- ArchitectureAArch64.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_SOURCE_PLUGINS_ARCHITECTURE_AARCH64_ARCHITECTUREAARCH64_H
+#define LLDB_SOURCE_PLUGINS_ARCHITECTURE_AARCH64_ARCHITECTUREAARCH64_H
+
+#include "Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h"
+#include "lldb/Core/Architecture.h"
+
+namespace lldb_private {
+
+class ArchitectureAArch64 : public Architecture {
+public:
+ static ConstString GetPluginNameStatic();
+ static void Initialize();
+ static void Terminate();
+
+ ConstString GetPluginName() override;
+ uint32_t GetPluginVersion() override;
+
+ void OverrideStopInfo(Thread &thread) const override{};
+
+ const MemoryTagManager *GetMemoryTagManager() const override {
+ return &m_memory_tag_manager;
+ }
+
+private:
+ static std::unique_ptr<Architecture> Create(const ArchSpec &arch);
+ ArchitectureAArch64() = default;
+ MemoryTagManagerAArch64MTE m_memory_tag_manager;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_ARCHITECTURE_AARCH64_ARCHITECTUREAARCH64_H
diff --git a/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp b/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp
index 22508969ceed..757c91570009 100644
--- a/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp
+++ b/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp
@@ -160,7 +160,6 @@ Instruction *ArchitectureMips::GetInstructionAtAddress(
InstructionList instruction_list;
InstructionSP prev_insn;
- bool prefer_file_cache = true; // Read from file
uint32_t inst_to_choose = 0;
Address addr = resolved_addr;
@@ -171,8 +170,7 @@ Instruction *ArchitectureMips::GetInstructionAtAddress(
uint32_t insn_size = 0;
disasm_sp->ParseInstructions(target, addr,
- {Disassembler::Limit::Bytes, i * 2}, nullptr,
- prefer_file_cache);
+ {Disassembler::Limit::Bytes, i * 2}, nullptr);
uint32_t num_insns = disasm_sp->GetInstructionList().GetSize();
if (num_insns) {
diff --git a/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp b/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp
index 8a2d3232a39a..7cd505d0ed29 100644
--- a/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp
+++ b/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp
@@ -905,7 +905,8 @@ DisassemblerLLVMC::MCDisasmInstance::Create(const char *triple, const char *cpu,
return Instance();
std::unique_ptr<llvm::MCContext> context_up(
- new llvm::MCContext(asm_info_up.get(), reg_info_up.get(), nullptr));
+ new llvm::MCContext(llvm::Triple(triple), asm_info_up.get(),
+ reg_info_up.get(), subtarget_info_up.get()));
if (!context_up)
return Instance();
diff --git a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h
index 5707f8858f6c..c34e02ed5678 100644
--- a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h
+++ b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h
@@ -35,15 +35,13 @@ class HexagonDYLDRendezvous {
// the layout of this struct is not binary compatible, it is simply large
// enough to hold the information on both 32 and 64 bit platforms.
struct Rendezvous {
- uint64_t version;
- lldb::addr_t map_addr;
- lldb::addr_t brk;
- uint64_t state;
- lldb::addr_t ldbase;
+ uint64_t version = 0;
+ lldb::addr_t map_addr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t brk = LLDB_INVALID_ADDRESS;
+ uint64_t state = 0;
+ lldb::addr_t ldbase = 0;
- Rendezvous()
- : version(0), map_addr(LLDB_INVALID_ADDRESS), brk(LLDB_INVALID_ADDRESS),
- state(0), ldbase(0) {}
+ Rendezvous() = default;
};
public:
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
index 3e88d88f407a..5775f5a730cd 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
@@ -38,13 +38,13 @@ class DYLDRendezvous {
// the layout of this struct is not binary compatible, it is simply large
// enough to hold the information on both 32 and 64 bit platforms.
struct Rendezvous {
- uint64_t version;
- lldb::addr_t map_addr;
- lldb::addr_t brk;
- uint64_t state;
- lldb::addr_t ldbase;
+ uint64_t version = 0;
+ lldb::addr_t map_addr = 0;
+ lldb::addr_t brk = 0;
+ uint64_t state = 0;
+ lldb::addr_t ldbase = 0;
- Rendezvous() : version(0), map_addr(0), brk(0), state(0), ldbase(0) {}
+ Rendezvous() = default;
};
public:
diff --git a/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp b/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
index c1fceeb1482c..8a5528f1e474 100644
--- a/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
+++ b/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
@@ -10,6 +10,7 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "DynamicLoaderStatic.h"
@@ -105,6 +106,15 @@ void DynamicLoaderStatic::LoadAllImagesAtFileAddresses() {
// the file...
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
if (section_sp) {
+ // If this section already has a load address set in the target,
+ // don't re-set it to the file address. Something may have
+ // set it to a more correct value already.
+ if (m_process->GetTarget()
+ .GetSectionLoadList()
+ .GetSectionLoadAddress(section_sp) !=
+ LLDB_INVALID_ADDRESS) {
+ continue;
+ }
if (m_process->GetTarget().SetSectionLoadAddress(
section_sp, section_sp->GetFileAddress()))
changed = true;
diff --git a/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
index 7f9504b9b3a9..54dfa3e9d6f2 100644
--- a/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
@@ -28,7 +28,7 @@ LLDB_PLUGIN_DEFINE(DynamicLoaderWindowsDYLD)
DynamicLoaderWindowsDYLD::DynamicLoaderWindowsDYLD(Process *process)
: DynamicLoader(process) {}
-DynamicLoaderWindowsDYLD::~DynamicLoaderWindowsDYLD() {}
+DynamicLoaderWindowsDYLD::~DynamicLoaderWindowsDYLD() = default;
void DynamicLoaderWindowsDYLD::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
@@ -193,7 +193,7 @@ DynamicLoaderWindowsDYLD::GetStepThroughTrampolinePlan(Thread &thread,
AddressRange range(pc, 2 * 15);
DisassemblerSP disassembler_sp = Disassembler::DisassembleRange(
- arch, nullptr, nullptr, m_process->GetTarget(), range, true);
+ arch, nullptr, nullptr, m_process->GetTarget(), range);
if (!disassembler_sp) {
return ThreadPlanSP();
}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
index 3edbc4ab98c0..85e2fcfc838c 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
@@ -15,7 +15,6 @@
#include "lldb/Target/Target.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
-#include "stdlib.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
@@ -27,6 +26,7 @@
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
+#include <cstdlib>
using namespace llvm;
using namespace clang;
@@ -43,7 +43,7 @@ ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough,
m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
}
-ASTResultSynthesizer::~ASTResultSynthesizer() {}
+ASTResultSynthesizer::~ASTResultSynthesizer() = default;
void ASTResultSynthesizer::Initialize(ASTContext &Context) {
m_ast_context = &Context;
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp
index 40f0de40da52..a2722db5d24a 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp
@@ -9,7 +9,6 @@
#include "ASTStructExtractor.h"
#include "lldb/Utility/Log.h"
-#include "stdlib.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
@@ -21,6 +20,7 @@
#include "clang/Sema/Sema.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
+#include <cstdlib>
using namespace llvm;
using namespace clang;
@@ -38,7 +38,7 @@ ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough,
m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
}
-ASTStructExtractor::~ASTStructExtractor() {}
+ASTStructExtractor::~ASTStructExtractor() = default;
void ASTStructExtractor::Initialize(ASTContext &Context) {
m_ast_context = &Context;
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp
index 1e438ed9d73e..a95fce1c5aa9 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp
@@ -8,17 +8,17 @@
#include "ASTUtils.h"
-lldb_private::ExternalASTSourceWrapper::~ExternalASTSourceWrapper() {}
+lldb_private::ExternalASTSourceWrapper::~ExternalASTSourceWrapper() = default;
void lldb_private::ExternalASTSourceWrapper::PrintStats() {
m_Source->PrintStats();
}
-lldb_private::ASTConsumerForwarder::~ASTConsumerForwarder() {}
+lldb_private::ASTConsumerForwarder::~ASTConsumerForwarder() = default;
void lldb_private::ASTConsumerForwarder::PrintStats() { m_c->PrintStats(); }
-lldb_private::SemaSourceWithPriorities::~SemaSourceWithPriorities() {}
+lldb_private::SemaSourceWithPriorities::~SemaSourceWithPriorities() = default;
void lldb_private::SemaSourceWithPriorities::PrintStats() {
for (size_t i = 0; i < Sources.size(); ++i)
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp
index e2601a059bb7..94647b0ef978 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp
@@ -184,7 +184,7 @@ private:
}
public:
- DeclContextOverride() {}
+ DeclContextOverride() = default;
void OverrideAllDeclsFromContainingFunction(clang::Decl *decl) {
for (DeclContext *decl_context = decl->getLexicalDeclContext();
@@ -359,9 +359,6 @@ bool ClangASTImporter::CanImport(const CompilerType &type) {
if (!ClangUtil::IsClangType(type))
return false;
- // TODO: remove external completion BOOL
- // CompleteAndFetchChildren should get the Decl out and check for the
-
clang::QualType qual_type(
ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type)));
@@ -435,8 +432,6 @@ bool ClangASTImporter::CanImport(const CompilerType &type) {
bool ClangASTImporter::Import(const CompilerType &type) {
if (!ClangUtil::IsClangType(type))
return false;
- // TODO: remove external completion BOOL
- // CompleteAndFetchChildren should get the Decl out and check for the
clang::QualType qual_type(
ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type)));
@@ -830,6 +825,10 @@ ClangASTImporter::ASTImporterDelegate::ImportImpl(Decl *From) {
// Check which ASTContext this declaration originally came from.
DeclOrigin origin = m_master.GetDeclOrigin(From);
+
+ // Prevent infinite recursion when the origin tracking contains a cycle.
+ assert(origin.decl != From && "Origin points to itself?");
+
// 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
@@ -889,6 +888,37 @@ ClangASTImporter::ASTImporterDelegate::ImportImpl(Decl *From) {
LLDB_LOG(log, "[ClangASTImporter] Complete definition not found");
}
+ // Disable the minimal import for fields that have record types. There is
+ // no point in minimally importing the record behind their type as Clang
+ // will anyway request their definition when the FieldDecl is added to the
+ // RecordDecl (as Clang will query the FieldDecl's type for things such
+ // as a deleted constexpr destructor).
+ // By importing the type ahead of time we avoid some corner cases where
+ // the FieldDecl's record is importing in the middle of Clang's
+ // `DeclContext::addDecl` logic.
+ if (clang::FieldDecl *fd = dyn_cast<FieldDecl>(From)) {
+ // This is only necessary because we do the 'minimal import'. Remove this
+ // once LLDB stopped using that mode.
+ assert(isMinimalImport() && "Only necessary for minimal import");
+ QualType field_type = fd->getType();
+ if (field_type->isRecordType()) {
+ // First get the underlying record and minimally import it.
+ clang::TagDecl *record_decl = field_type->getAsTagDecl();
+ llvm::Expected<Decl *> imported = Import(record_decl);
+ if (!imported)
+ return imported.takeError();
+ // Check how/if the import got redirected to a different AST. Now
+ // import the definition of what was actually imported. If there is no
+ // origin then that means the record was imported by just picking a
+ // compatible type in the target AST (in which case there is no more
+ // importing to do).
+ if (clang::Decl *origin = m_master.GetDeclOrigin(*imported).decl) {
+ if (llvm::Error def_err = ImportDefinition(record_decl))
+ return std::move(def_err);
+ }
+ }
+ }
+
return ASTImporter::ImportImpl(From);
}
@@ -904,16 +934,6 @@ void ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo(
MapImported(from, to);
ASTImporter::Imported(from, to);
- /*
- if (to_objc_interface)
- to_objc_interface->startDefinition();
-
- CXXRecordDecl *to_cxx_record = dyn_cast<CXXRecordDecl>(to);
-
- if (to_cxx_record)
- to_cxx_record->startDefinition();
- */
-
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
if (llvm::Error err = ImportDefinition(from)) {
@@ -1088,22 +1108,23 @@ void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from,
DeclOrigin origin = from_context_md->getOrigin(from);
if (origin.Valid()) {
- if (!to_context_md->hasOrigin(to) || user_id != LLDB_INVALID_UID)
- if (origin.ctx != &to->getASTContext())
+ if (origin.ctx != &to->getASTContext()) {
+ if (!to_context_md->hasOrigin(to) || user_id != LLDB_INVALID_UID)
to_context_md->setOrigin(to, origin);
- ImporterDelegateSP direct_completer =
- m_master.GetDelegate(&to->getASTContext(), origin.ctx);
+ ImporterDelegateSP direct_completer =
+ m_master.GetDelegate(&to->getASTContext(), origin.ctx);
- if (direct_completer.get() != this)
- direct_completer->ASTImporter::Imported(origin.decl, to);
+ if (direct_completer.get() != this)
+ direct_completer->ASTImporter::Imported(origin.decl, to);
- LLDB_LOG(log,
- " [ClangASTImporter] Propagated origin "
- "(Decl*){0}/(ASTContext*){1} from (ASTContext*){2} to "
- "(ASTContext*){3}",
- origin.decl, origin.ctx, &from->getASTContext(),
- &to->getASTContext());
+ LLDB_LOG(log,
+ " [ClangASTImporter] Propagated origin "
+ "(Decl*){0}/(ASTContext*){1} from (ASTContext*){2} to "
+ "(ASTContext*){3}",
+ origin.decl, origin.ctx, &from->getASTContext(),
+ &to->getASTContext());
+ }
} else {
if (m_new_decl_listener)
m_new_decl_listener->NewDeclImported(from, to);
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h
index bf4ad174cf9c..4f589d34aa48 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h
@@ -23,6 +23,7 @@
#include "lldb/Host/FileSystem.h"
#include "lldb/Symbol/CompilerDeclContext.h"
+#include "lldb/Utility/LLDBAssert.h"
#include "lldb/lldb-types.h"
#include "Plugins/ExpressionParser/Clang/CxxModuleHandler.h"
@@ -34,6 +35,32 @@ namespace lldb_private {
class ClangASTMetadata;
class TypeSystemClang;
+/// Manages and observes all Clang AST node importing in LLDB.
+///
+/// The ClangASTImporter takes care of two things:
+///
+/// 1. Keeps track of all ASTImporter instances in LLDB.
+///
+/// Clang's ASTImporter takes care of importing types from one ASTContext to
+/// another. This class expands this concept by allowing copying from several
+/// ASTContext instances to several other ASTContext instances. Instead of
+/// constructing a new ASTImporter manually to copy over a type/decl, this class
+/// can be asked to do this. It will construct a ASTImporter for the caller (and
+/// will cache the ASTImporter instance for later use) and then perform the
+/// import.
+///
+/// This mainly prevents that a caller might construct several ASTImporter
+/// instances for the same source/target ASTContext combination. As the
+/// ASTImporter has an internal state that keeps track of already imported
+/// declarations and so on, using only one ASTImporter instance is more
+/// efficient and less error-prone than using multiple.
+///
+/// 2. Keeps track of from where declarations were imported (origin-tracking).
+/// The ASTImporter instances in this class usually only performa a minimal
+/// import, i.e., only a shallow copy is made that is filled out on demand
+/// when more information is requested later on. This requires record-keeping
+/// of where any shallow clone originally came from so that the right original
+/// declaration can be found and used as the source of any missing information.
class ClangASTImporter {
public:
struct LayoutInfo {
@@ -52,12 +79,34 @@ public:
: m_file_manager(clang::FileSystemOptions(),
FileSystem::Instance().GetVirtualFileSystem()) {}
+ /// Copies the given type and the respective declarations to the destination
+ /// type system.
+ ///
+ /// This function does a shallow copy and requires that the target AST
+ /// has an ExternalASTSource which queries this ClangASTImporter instance
+ /// for any additional information that is maybe lacking in the shallow copy.
+ /// This also means that the type system of src_type can *not* be deleted
+ /// after this function has been called. If you need to delete the source
+ /// type system you either need to delete the destination type system first
+ /// or use \ref ClangASTImporter::DeportType.
+ ///
+ /// \see ClangASTImporter::DeportType
CompilerType CopyType(TypeSystemClang &dst, const CompilerType &src_type);
+ /// \see ClangASTImporter::CopyType
clang::Decl *CopyDecl(clang::ASTContext *dst_ctx, clang::Decl *decl);
+ /// Copies the given type and the respective declarations to the destination
+ /// type system.
+ ///
+ /// Unlike CopyType this function ensures that types/declarations which are
+ /// originally from the AST of src_type are fully copied over. The type
+ /// system of src_type can safely be deleted after calling this function.
+ /// \see ClangASTImporter::CopyType
CompilerType DeportType(TypeSystemClang &dst, const CompilerType &src_type);
+ /// Copies the given decl to the destination type system.
+ /// \see ClangASTImporter::DeportType
clang::Decl *DeportDecl(clang::ASTContext *dst_ctx, clang::Decl *decl);
/// Sets the layout for the given RecordDecl. The layout will later be
@@ -78,8 +127,22 @@ public:
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
&vbase_offsets);
+ /// Returns true iff the given type was copied from another TypeSystemClang
+ /// and the original type in this other TypeSystemClang might contain
+ /// additional information (e.g., the definition of a 'class' type) that could
+ /// be imported.
+ ///
+ /// \see ClangASTImporter::Import
bool CanImport(const CompilerType &type);
+ /// If the given type was copied from another TypeSystemClang then copy over
+ /// all missing information (e.g., the definition of a 'class' type).
+ ///
+ /// \return True iff an original type in another TypeSystemClang was found.
+ /// Note: Does *not* return false if an original type was found but
+ /// no information was imported over.
+ ///
+ /// \see ClangASTImporter::Import
bool Import(const CompilerType &type);
bool CompleteType(const CompilerType &compiler_type);
@@ -94,6 +157,14 @@ public:
bool RequireCompleteType(clang::QualType type);
+ /// Updates the internal origin-tracking information so that the given
+ /// 'original' decl is from now on used to import additional information
+ /// into the given decl.
+ ///
+ /// Usually the origin-tracking in the ClangASTImporter is automatically
+ /// updated when a declaration is imported, so the only valid reason to ever
+ /// call this is if there is a 'better' original decl and the target decl
+ /// is only a shallow clone that lacks any contents.
void SetDeclOrigin(const clang::Decl *decl, clang::Decl *original_decl);
ClangASTMetadata *GetDeclMetadata(const clang::Decl *decl);
@@ -145,10 +216,13 @@ public:
void ForgetSource(clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx);
struct DeclOrigin {
- DeclOrigin() : ctx(nullptr), decl(nullptr) {}
+ DeclOrigin() = default;
DeclOrigin(clang::ASTContext *_ctx, clang::Decl *_decl)
- : ctx(_ctx), decl(_decl) {}
+ : ctx(_ctx), decl(_decl) {
+ // The decl has to be in its associated ASTContext.
+ assert(_decl == nullptr || &_decl->getASTContext() == _ctx);
+ }
DeclOrigin(const DeclOrigin &rhs) {
ctx = rhs.ctx;
@@ -162,8 +236,8 @@ public:
bool Valid() const { return (ctx != nullptr || decl != nullptr); }
- clang::ASTContext *ctx;
- clang::Decl *decl;
+ clang::ASTContext *ctx = nullptr;
+ clang::Decl *decl = nullptr;
};
/// Listener interface used by the ASTImporterDelegate to inform other code
@@ -190,6 +264,16 @@ public:
: clang::ASTImporter(*target_ctx, master.m_file_manager, *source_ctx,
master.m_file_manager, true /*minimal*/),
m_master(master), m_source_ctx(source_ctx) {
+ // Target and source ASTContext shouldn't be identical. Importing AST
+ // nodes within the same AST doesn't make any sense as the whole idea
+ // is to import them to a different AST.
+ lldbassert(target_ctx != source_ctx && "Can't import into itself");
+ // This is always doing a minimal import of any declarations. This means
+ // that there has to be an ExternalASTSource in the target ASTContext
+ // (that should implement the callbacks that complete any declarations
+ // on demand). Without an ExternalASTSource, this ASTImporter will just
+ // do a minimal import and the imported declarations won't be completed.
+ assert(target_ctx->getExternalSource() && "Missing ExternalSource");
setODRHandling(clang::ASTImporter::ODRHandlingType::Liberal);
}
@@ -272,6 +356,13 @@ public:
/// Sets the DeclOrigin for the given Decl and overwrites any existing
/// DeclOrigin.
void setOrigin(const clang::Decl *decl, DeclOrigin origin) {
+ // Setting the origin of any decl to itself (or to a different decl
+ // in the same ASTContext) doesn't make any sense. It will also cause
+ // ASTImporterDelegate::ImportImpl to infinite recurse when trying to find
+ // the 'original' Decl when importing code.
+ assert(&decl->getASTContext() != origin.ctx &&
+ "Trying to set decl origin to its own ASTContext?");
+ assert(decl != origin.decl && "Trying to set decl origin to itself?");
m_origins[decl] = origin;
}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
index 0f34c48c7e82..b43423707ae1 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
@@ -479,10 +479,7 @@ void ClangASTSource::FindExternalLexicalDecls(
decl->getDeclKindName(), ast_dump);
}
- Decl *copied_decl = CopyDecl(decl);
-
- if (!copied_decl)
- continue;
+ CopyDecl(decl);
// FIXME: We should add the copied decl to the 'decls' list. This would
// add the copied Decl into the DeclContext and make sure that we
@@ -492,12 +489,6 @@ void ClangASTSource::FindExternalLexicalDecls(
// lookup issues later on.
// We can't just add them for now as the ASTImporter already added the
// decl into the DeclContext and this would add it twice.
-
- if (FieldDecl *copied_field = dyn_cast<FieldDecl>(copied_decl)) {
- QualType copied_field_type = copied_field->getType();
-
- m_ast_importer_sp->RequireCompleteType(copied_field_type);
- }
} else {
SkippedDecls = true;
}
@@ -850,8 +841,8 @@ void ClangASTSource::FindDeclInModules(NameSearchContext &context,
ConstString name) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- ClangModulesDeclVendor *modules_decl_vendor =
- m_target->GetClangModulesDeclVendor();
+ std::shared_ptr<ClangModulesDeclVendor> modules_decl_vendor =
+ GetClangModulesDeclVendor();
if (!modules_decl_vendor)
return;
@@ -1143,8 +1134,8 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) {
// Check the modules only if the debug information didn't have a complete
// interface.
- if (ClangModulesDeclVendor *modules_decl_vendor =
- m_target->GetClangModulesDeclVendor()) {
+ if (std::shared_ptr<ClangModulesDeclVendor> modules_decl_vendor =
+ GetClangModulesDeclVendor()) {
ConstString interface_name(interface_decl->getNameAsString().c_str());
bool append = false;
uint32_t max_matches = 1;
@@ -1313,8 +1304,8 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) {
// Check the modules only if the debug information didn't have a complete
// interface.
- ClangModulesDeclVendor *modules_decl_vendor =
- m_target->GetClangModulesDeclVendor();
+ std::shared_ptr<ClangModulesDeclVendor> modules_decl_vendor =
+ GetClangModulesDeclVendor();
if (!modules_decl_vendor)
break;
@@ -1570,10 +1561,10 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size,
if (log) {
LLDB_LOG(log, "LRT returned:");
- LLDB_LOG(log, "LRT Original = (RecordDecl*)%p",
+ LLDB_LOG(log, "LRT Original = (RecordDecl*){0}",
static_cast<const void *>(origin_record.decl));
- LLDB_LOG(log, "LRT Size = %" PRId64, size);
- LLDB_LOG(log, "LRT Alignment = %" PRId64, alignment);
+ LLDB_LOG(log, "LRT Size = {0}", size);
+ LLDB_LOG(log, "LRT Alignment = {0}", alignment);
LLDB_LOG(log, "LRT Fields:");
for (RecordDecl::field_iterator fi = record->field_begin(),
fe = record->field_end();
@@ -1750,3 +1741,10 @@ CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) {
return m_clang_ast_context->GetType(copied_qual_type);
}
+
+std::shared_ptr<ClangModulesDeclVendor>
+ClangASTSource::GetClangModulesDeclVendor() {
+ auto persistent_vars = llvm::cast<ClangPersistentVariables>(
+ m_target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
+ return persistent_vars->GetClangModulesDeclVendor();
+}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
index 14761fbeb26b..3afd1fd5f2d1 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
@@ -314,6 +314,8 @@ protected:
/// The imported type.
CompilerType GuardedCopyType(const CompilerType &src_type);
+ std::shared_ptr<ClangModulesDeclVendor> GetClangModulesDeclVendor();
+
public:
/// Returns true if a name should be ignored by name lookup.
///
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h
index bf52bec4b1fa..6313117c08d6 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h
@@ -22,7 +22,7 @@ class ClangDeclVendor : public DeclVendor {
public:
ClangDeclVendor(DeclVendorKind kind) : DeclVendor(kind) {}
- virtual ~ClangDeclVendor() {}
+ virtual ~ClangDeclVendor() = default;
using DeclVendor::FindDecls;
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
index 852ce3bbd3db..731b81c61a6f 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -350,7 +350,7 @@ bool ClangExpressionDeclMap::AddValueToStruct(const NamedDecl *decl,
if (!var)
return false;
- LLDB_LOG(log, "Adding value for (NamedDecl*)%p [%s - %s] to the structure",
+ LLDB_LOG(log, "Adding value for (NamedDecl*){0} [{1} - {2}] to the structure",
decl, name, var->GetName());
// We know entity->m_parser_vars is valid because we used a parser variable
@@ -752,7 +752,7 @@ void ClangExpressionDeclMap::SearchPersistenDecls(NameSearchContext &context,
MaybeRegisterFunctionBody(parser_function_decl);
}
- LLDB_LOG(log, " CEDM::FEVD Found persistent decl %s", name);
+ LLDB_LOG(log, " CEDM::FEVD Found persistent decl {0}", name);
context.AddNamedDecl(parser_named_decl);
}
@@ -1021,7 +1021,8 @@ void ClangExpressionDeclMap::LookupInModulesDeclVendor(
if (!m_target)
return;
- auto *modules_decl_vendor = m_target->GetClangModulesDeclVendor();
+ std::shared_ptr<ClangModulesDeclVendor> modules_decl_vendor =
+ GetClangModulesDeclVendor();
if (!modules_decl_vendor)
return;
@@ -1213,8 +1214,8 @@ void ClangExpressionDeclMap::LookupFunction(
std::vector<clang::NamedDecl *> decls_from_modules;
if (target) {
- if (ClangModulesDeclVendor *decl_vendor =
- target->GetClangModulesDeclVendor()) {
+ if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
+ GetClangModulesDeclVendor()) {
decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules);
}
}
@@ -1493,7 +1494,7 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var,
if (var_location_expr.GetExpressionData(const_value_extractor)) {
var_location = Value(const_value_extractor.GetDataStart(),
const_value_extractor.GetByteSize());
- var_location.SetValueType(Value::eValueTypeHostAddress);
+ var_location.SetValueType(Value::ValueType::HostAddress);
} else {
LLDB_LOG(log, "Error evaluating constant variable: {0}", err.AsCString());
return false;
@@ -1512,10 +1513,10 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var,
if (parser_type)
*parser_type = TypeFromParser(type_to_use);
- if (var_location.GetContextType() == Value::eContextTypeInvalid)
+ if (var_location.GetContextType() == Value::ContextType::Invalid)
var_location.SetCompilerType(type_to_use);
- if (var_location.GetValueType() == Value::eValueTypeFileAddress) {
+ if (var_location.GetValueType() == Value::ValueType::FileAddress) {
SymbolContext var_sc;
var->CalculateSymbolContext(&var_sc);
@@ -1529,7 +1530,7 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var,
if (load_addr != LLDB_INVALID_ADDRESS) {
var_location.GetScalar() = load_addr;
- var_location.SetValueType(Value::eValueTypeLoadAddress);
+ var_location.SetValueType(Value::ValueType::LoadAddress);
}
}
@@ -1665,11 +1666,11 @@ void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context,
const Address symbol_address = symbol.GetAddress();
lldb::addr_t symbol_load_addr = symbol_address.GetLoadAddress(target);
- // parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType,
+ // parser_vars->m_lldb_value.SetContext(Value::ContextType::ClangType,
// user_type.GetOpaqueQualType());
parser_vars->m_lldb_value.SetCompilerType(user_type);
parser_vars->m_lldb_value.GetScalar() = symbol_load_addr;
- parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress);
+ parser_vars->m_lldb_value.SetValueType(Value::ValueType::LoadAddress);
parser_vars->m_named_decl = var_decl;
parser_vars->m_llvm_value = nullptr;
@@ -1860,14 +1861,14 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
entity->GetParserVars(GetParserID());
if (load_addr != LLDB_INVALID_ADDRESS) {
- parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress);
+ parser_vars->m_lldb_value.SetValueType(Value::ValueType::LoadAddress);
parser_vars->m_lldb_value.GetScalar() = load_addr;
} else {
// We have to try finding a file address.
lldb::addr_t file_addr = fun_address.GetFileAddress();
- parser_vars->m_lldb_value.SetValueType(Value::eValueTypeFileAddress);
+ parser_vars->m_lldb_value.SetValueType(Value::ValueType::FileAddress);
parser_vars->m_lldb_value.GetScalar() = file_addr;
}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
index a9cd5d166b9d..e39dc587bc43 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
@@ -9,8 +9,8 @@
#ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONDECLMAP_H
#define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONDECLMAP_H
-#include <signal.h>
-#include <stdint.h>
+#include <csignal>
+#include <cstdint>
#include <vector>
@@ -248,10 +248,10 @@ public:
lldb::SymbolType symbol_type);
struct TargetInfo {
- lldb::ByteOrder byte_order;
- size_t address_byte_size;
+ lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
+ size_t address_byte_size = 0;
- TargetInfo() : byte_order(lldb::eByteOrderInvalid), address_byte_size(0) {}
+ TargetInfo() = default;
bool IsValid() {
return (byte_order != lldb::eByteOrderInvalid && address_byte_size != 0);
@@ -308,7 +308,7 @@ private:
/// The following values should not live beyond parsing
class ParserVars {
public:
- ParserVars() {}
+ ParserVars() = default;
Target *GetTarget() {
if (m_exe_ctx.GetTargetPtr())
@@ -353,16 +353,15 @@ private:
/// The following values contain layout information for the materialized
/// struct, but are not specific to a single materialization
struct StructVars {
- StructVars()
- : m_struct_alignment(0), m_struct_size(0), m_struct_laid_out(false),
- m_result_name(), m_object_pointer_type(nullptr, nullptr) {}
+ StructVars() : m_result_name(), m_object_pointer_type(nullptr, nullptr) {}
- lldb::offset_t
- m_struct_alignment; ///< The alignment of the struct in bytes.
- size_t m_struct_size; ///< The size of the struct in bytes.
- bool m_struct_laid_out; ///< True if the struct has been laid out and the
- ///layout is valid (that is, no new fields have been
- ///added since).
+ lldb::offset_t m_struct_alignment =
+ 0; ///< The alignment of the struct in bytes.
+ size_t m_struct_size = 0; ///< The size of the struct in bytes.
+ bool m_struct_laid_out =
+ false; ///< True if the struct has been laid out and the
+ /// layout is valid (that is, no new fields have been
+ /// added since).
ConstString
m_result_name; ///< The name of the result variable ($1, for example)
TypeFromUser m_object_pointer_type; ///< The type of the "this" variable, if
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h
index e33e5df22236..37bcaf000cfc 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h
@@ -38,7 +38,7 @@ public:
ExpressionTypeSystemHelper::LLVMCastKind::eKindClangHelper) {}
/// Destructor
- virtual ~ClangExpressionHelper() {}
+ virtual ~ClangExpressionHelper() = default;
/// Return the object that the parser should use when resolving external
/// values. May be NULL if everything should be self-contained.
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index 7644a5e1423e..0b5e1ab059d2 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -343,6 +343,7 @@ static void SetupDefaultClangDiagnostics(CompilerInstance &compiler) {
const std::vector<const char *> groupsToIgnore = {
"unused-value",
"odr",
+ "unused-getter-return-value",
};
for (const char *group : groupsToIgnore) {
compiler.getDiagnostics().setSeverityForGroup(
@@ -513,7 +514,7 @@ ClangExpressionParser::ClangExpressionParser(
LLDB_LOGF(log, "Using SIMD alignment: %d",
target_info->getSimdDefaultAlign());
LLDB_LOGF(log, "Target datalayout string: '%s'",
- target_info->getDataLayout().getStringRepresentation().c_str());
+ target_info->getDataLayoutString());
LLDB_LOGF(log, "Target ABI: '%s'", target_info->getABI().str().c_str());
LLDB_LOGF(log, "Target vector alignment: %d",
target_info->getMaxVectorAlign());
@@ -657,7 +658,8 @@ ClangExpressionParser::ClangExpressionParser(
//
// FIXME: We shouldn't need to do this, the target should be immutable once
// created. This complexity should be lifted elsewhere.
- m_compiler->getTarget().adjust(m_compiler->getLangOpts());
+ m_compiler->getTarget().adjust(m_compiler->getDiagnostics(),
+ m_compiler->getLangOpts());
// 6. Set up the diagnostic buffer for reporting errors
@@ -686,11 +688,11 @@ ClangExpressionParser::ClangExpressionParser(
break;
}
- if (ClangModulesDeclVendor *decl_vendor =
- target_sp->GetClangModulesDeclVendor()) {
- if (auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(
- target_sp->GetPersistentExpressionStateForLanguage(
- lldb::eLanguageTypeC))) {
+ if (auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(
+ target_sp->GetPersistentExpressionStateForLanguage(
+ lldb::eLanguageTypeC))) {
+ if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
+ clang_persistent_vars->GetClangModulesDeclVendor()) {
std::unique_ptr<PPCallbacks> pp_callbacks(
new LLDBPreprocessorCallbacks(*decl_vendor, *clang_persistent_vars,
m_compiler->getSourceManager()));
@@ -723,7 +725,7 @@ ClangExpressionParser::ClangExpressionParser(
m_compiler->getCodeGenOpts(), *m_llvm_context));
}
-ClangExpressionParser::~ClangExpressionParser() {}
+ClangExpressionParser::~ClangExpressionParser() = default;
namespace {
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
index 180e08b03c93..31707f81a270 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
@@ -31,6 +31,7 @@
using namespace lldb_private;
#define PREFIX_NAME "<lldb wrapper prefix>"
+#define SUFFIX_NAME "<lldb wrapper suffix>"
const llvm::StringRef ClangExpressionSourceCode::g_prefix_file_name = PREFIX_NAME;
@@ -73,6 +74,9 @@ extern "C"
}
)";
+const char *ClangExpressionSourceCode::g_expression_suffix =
+ "\n;\n#line 1 \"" SUFFIX_NAME "\"\n";
+
namespace {
class AddMacroState {
@@ -180,7 +184,7 @@ lldb_private::ClangExpressionSourceCode::ClangExpressionSourceCode(
// containing only the user expression. This will hide our wrapper code
// from the user when we render diagnostics with Clang.
m_start_marker = "#line 1 \"" + filename.str() + "\"\n";
- m_end_marker = "\n;\n#line 1 \"<lldb wrapper suffix>\"\n";
+ m_end_marker = g_expression_suffix;
}
namespace {
@@ -314,10 +318,11 @@ bool ClangExpressionSourceCode::GetText(
}
}
- ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor();
auto *persistent_vars = llvm::cast<ClangPersistentVariables>(
target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
- if (decl_vendor && persistent_vars) {
+ std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
+ persistent_vars->GetClangModulesDeclVendor();
+ if (decl_vendor) {
const ClangModulesDeclVendor::ModuleVector &hand_imported_modules =
persistent_vars->GetHandLoadedClangModules();
ClangModulesDeclVendor::ModuleVector modules_for_macros;
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
index 9a54f0e3ad8d..54ae837fb30f 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
@@ -27,6 +27,7 @@ public:
/// the user expression.
static const llvm::StringRef g_prefix_file_name;
static const char *g_expression_prefix;
+ static const char *g_expression_suffix;
/// The possible ways an expression can be wrapped.
enum class WrapKind {
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
index 58d589962abe..7bb68e78373f 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
@@ -9,9 +9,9 @@
#ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONVARIABLE_H
#define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONVARIABLE_H
-#include <signal.h>
-#include <stdint.h>
-#include <string.h>
+#include <csignal>
+#include <cstdint>
+#include <cstring>
#include <map>
#include <string>
@@ -116,19 +116,19 @@ public:
/// The following values should not live beyond parsing
class ParserVars {
public:
- ParserVars()
- : m_named_decl(nullptr), m_llvm_value(nullptr),
- m_lldb_value(), m_lldb_var(), m_lldb_sym(nullptr) {}
+ ParserVars() : m_lldb_value(), m_lldb_var() {}
- const clang::NamedDecl
- *m_named_decl; ///< The Decl corresponding to this variable
- llvm::Value *m_llvm_value; ///< The IR value corresponding to this variable;
- ///usually a GlobalValue
+ const clang::NamedDecl *m_named_decl =
+ nullptr; ///< The Decl corresponding to this variable
+ llvm::Value *m_llvm_value =
+ nullptr; ///< The IR value corresponding to this variable;
+ /// usually a GlobalValue
lldb_private::Value
m_lldb_value; ///< The value found in LLDB for this variable
lldb::VariableSP m_lldb_var; ///< The original variable for this variable
- const lldb_private::Symbol *m_lldb_sym; ///< The original symbol for this
- ///variable, if it was a symbol
+ const lldb_private::Symbol *m_lldb_sym =
+ nullptr; ///< The original symbol for this
+ /// variable, if it was a symbol
};
private:
@@ -157,13 +157,13 @@ public:
/// The following values are valid if the variable is used by JIT code
struct JITVars {
- JITVars() : m_alignment(0), m_size(0), m_offset(0) {}
+ JITVars() = default;
- lldb::offset_t
- m_alignment; ///< The required alignment of the variable, in bytes
- size_t m_size; ///< The space required for the variable, in bytes
- lldb::offset_t
- m_offset; ///< The offset of the variable in the struct, in bytes
+ lldb::offset_t m_alignment =
+ 0; ///< The required alignment of the variable, in bytes
+ size_t m_size = 0; ///< The space required for the variable, in bytes
+ lldb::offset_t m_offset =
+ 0; ///< The offset of the variable in the struct, in bytes
};
private:
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
index 0c9ad2021035..2cfa9a4c9ccf 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
@@ -59,7 +59,7 @@ ClangFunctionCaller::ClangFunctionCaller(ExecutionContextScope &exe_scope,
}
// Destructor
-ClangFunctionCaller::~ClangFunctionCaller() {}
+ClangFunctionCaller::~ClangFunctionCaller() = default;
unsigned
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
index c014ad504d37..336058a5abb9 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
@@ -42,9 +42,9 @@
using namespace lldb_private;
namespace {
-// Any Clang compiler requires a consumer for diagnostics. This one stores
-// them as strings so we can provide them to the user in case a module failed
-// to load.
+/// Any Clang compiler requires a consumer for diagnostics. This one stores
+/// them as strings so we can provide them to the user in case a module failed
+/// to load.
class StoringDiagnosticConsumer : public clang::DiagnosticConsumer {
public:
StoringDiagnosticConsumer();
@@ -74,8 +74,8 @@ private:
Log *m_log;
};
-// The private implementation of our ClangModulesDeclVendor. Contains all the
-// Clang state required to load modules.
+/// The private implementation of our ClangModulesDeclVendor. Contains all the
+/// Clang state required to load modules.
class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor {
public:
ClangModulesDeclVendorImpl(
@@ -100,9 +100,9 @@ public:
std::function<bool(llvm::StringRef, llvm::StringRef)> handler) override;
private:
- void
- ReportModuleExportsHelper(std::set<ClangModulesDeclVendor::ModuleID> &exports,
- clang::Module *module);
+ typedef llvm::DenseSet<ModuleID> ExportedModuleSet;
+ void ReportModuleExportsHelper(ExportedModuleSet &exports,
+ clang::Module *module);
void ReportModuleExports(ModuleVector &exports, clang::Module *module);
@@ -120,7 +120,7 @@ private:
typedef std::vector<ConstString> ImportedModule;
typedef std::map<ImportedModule, clang::Module *> ImportedModuleMap;
- typedef std::set<ModuleID> ImportedModuleSet;
+ typedef llvm::DenseSet<ModuleID> ImportedModuleSet;
ImportedModuleMap m_imported_modules;
ImportedModuleSet m_user_imported_modules;
// We assume that every ASTContext has an TypeSystemClang, so we also store
@@ -176,7 +176,7 @@ void StoringDiagnosticConsumer::EndSourceFile() {
ClangModulesDeclVendor::ClangModulesDeclVendor()
: ClangDeclVendor(eClangModuleDeclVendor) {}
-ClangModulesDeclVendor::~ClangModulesDeclVendor() {}
+ClangModulesDeclVendor::~ClangModulesDeclVendor() = default;
ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(
llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine,
@@ -195,8 +195,7 @@ ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(
}
void ClangModulesDeclVendorImpl::ReportModuleExportsHelper(
- std::set<ClangModulesDeclVendor::ModuleID> &exports,
- clang::Module *module) {
+ ExportedModuleSet &exports, clang::Module *module) {
if (exports.count(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module)))
return;
@@ -206,20 +205,18 @@ void ClangModulesDeclVendorImpl::ReportModuleExportsHelper(
module->getExportedModules(sub_exports);
- for (clang::Module *module : sub_exports) {
+ for (clang::Module *module : sub_exports)
ReportModuleExportsHelper(exports, module);
- }
}
void ClangModulesDeclVendorImpl::ReportModuleExports(
ClangModulesDeclVendor::ModuleVector &exports, clang::Module *module) {
- std::set<ClangModulesDeclVendor::ModuleID> exports_set;
+ ExportedModuleSet exports_set;
ReportModuleExportsHelper(exports_set, module);
- for (ModuleID module : exports_set) {
+ for (ModuleID module : exports_set)
exports.push_back(module);
- }
}
bool ClangModulesDeclVendorImpl::AddModule(const SourceModule &module,
@@ -237,17 +234,15 @@ bool ClangModulesDeclVendorImpl::AddModule(const SourceModule &module,
std::vector<ConstString> imported_module;
- for (ConstString path_component : module.path) {
+ for (ConstString path_component : module.path)
imported_module.push_back(path_component);
- }
{
ImportedModuleMap::iterator mi = m_imported_modules.find(imported_module);
if (mi != m_imported_modules.end()) {
- if (exported_modules) {
+ if (exported_modules)
ReportModuleExports(*exported_modules, mi->second);
- }
return true;
}
}
@@ -338,9 +333,8 @@ bool ClangModulesDeclVendorImpl::AddModule(const SourceModule &module,
clang::Module *requested_module = DoGetModule(clang_path, true);
if (requested_module != nullptr) {
- if (exported_modules) {
+ if (exported_modules)
ReportModuleExports(*exported_modules, requested_module);
- }
m_imported_modules[imported_module] = requested_module;
@@ -388,9 +382,8 @@ uint32_t
ClangModulesDeclVendorImpl::FindDecls(ConstString name, bool append,
uint32_t max_matches,
std::vector<CompilerDecl> &decls) {
- if (!m_enabled) {
+ if (!m_enabled)
return 0;
- }
if (!append)
decls.clear();
@@ -423,18 +416,16 @@ ClangModulesDeclVendorImpl::FindDecls(ConstString name, bool append,
void ClangModulesDeclVendorImpl::ForEachMacro(
const ClangModulesDeclVendor::ModuleVector &modules,
std::function<bool(llvm::StringRef, llvm::StringRef)> handler) {
- if (!m_enabled) {
+ if (!m_enabled)
return;
- }
typedef std::map<ModuleID, ssize_t> ModulePriorityMap;
ModulePriorityMap module_priorities;
ssize_t priority = 0;
- for (ModuleID module : modules) {
+ for (ModuleID module : modules)
module_priorities[module] = priority++;
- }
if (m_compiler_instance->getPreprocessor().getExternalSource()) {
m_compiler_instance->getPreprocessor()
@@ -455,9 +446,8 @@ void ClangModulesDeclVendorImpl::ForEachMacro(
.getExternalIdentifierLookup()) {
lookup->get(mi->first->getName());
}
- if (!ii) {
+ if (!ii)
ii = mi->first;
- }
}
ssize_t found_priority = -1;
@@ -504,24 +494,21 @@ void ClangModulesDeclVendorImpl::ForEachMacro(
for (auto pi = macro_info->param_begin(),
pe = macro_info->param_end();
pi != pe; ++pi) {
- if (!first_arg) {
+ if (!first_arg)
macro_expansion.append(", ");
- } else {
+ else
first_arg = false;
- }
macro_expansion.append((*pi)->getName().str());
}
if (macro_info->isC99Varargs()) {
- if (first_arg) {
+ if (first_arg)
macro_expansion.append("...");
- } else {
+ else
macro_expansion.append(", ...");
- }
- } else if (macro_info->isGNUVarargs()) {
+ } else if (macro_info->isGNUVarargs())
macro_expansion.append("...");
- }
macro_expansion.append(")");
}
@@ -533,11 +520,10 @@ void ClangModulesDeclVendorImpl::ForEachMacro(
for (clang::MacroInfo::tokens_iterator ti = macro_info->tokens_begin(),
te = macro_info->tokens_end();
ti != te; ++ti) {
- if (!first_token) {
+ if (!first_token)
macro_expansion.append(" ");
- } else {
+ else
first_token = false;
- }
if (ti->isLiteral()) {
if (const char *literal_data = ti->getLiteralData()) {
@@ -718,7 +704,7 @@ ClangModulesDeclVendor::Create(Target &target) {
if (!instance->hasTarget())
return nullptr;
- instance->getTarget().adjust(instance->getLangOpts());
+ instance->getTarget().adjust(*diagnostics_engine, instance->getLangOpts());
if (!action->BeginSourceFile(*instance,
instance->getFrontendOpts().Inputs[0]))
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
index 42afac9edb0d..13d6a37113b8 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
@@ -8,6 +8,7 @@
#include "ClangPersistentVariables.h"
#include "ClangASTImporter.h"
+#include "ClangModulesDeclVendor.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "lldb/Core/Value.h"
@@ -23,8 +24,10 @@
using namespace lldb;
using namespace lldb_private;
-ClangPersistentVariables::ClangPersistentVariables()
- : lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang) {}
+ClangPersistentVariables::ClangPersistentVariables(
+ std::shared_ptr<Target> target_sp)
+ : lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang),
+ m_target_sp(target_sp) {}
ExpressionVariableSP ClangPersistentVariables::CreatePersistentVariable(
const lldb::ValueObjectSP &valobj_sp) {
@@ -109,6 +112,15 @@ ClangPersistentVariables::GetClangASTImporter() {
return m_ast_importer_sp;
}
+std::shared_ptr<ClangModulesDeclVendor>
+ClangPersistentVariables::GetClangModulesDeclVendor() {
+ if (!m_modules_decl_vendor_sp) {
+ m_modules_decl_vendor_sp.reset(
+ ClangModulesDeclVendor::Create(*m_target_sp.get()));
+ }
+ return m_modules_decl_vendor_sp;
+}
+
ConstString
ClangPersistentVariables::GetNextPersistentVariableName(bool is_error) {
llvm::SmallString<64> name;
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
index f888b2d56e68..b8a359d05f75 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
@@ -19,6 +19,8 @@
namespace lldb_private {
class ClangASTImporter;
+class ClangModulesDeclVendor;
+class Target;
class TypeSystemClang;
/// \class ClangPersistentVariables ClangPersistentVariables.h
@@ -30,7 +32,7 @@ class TypeSystemClang;
/// 0-based counter for naming result variables.
class ClangPersistentVariables : public PersistentExpressionState {
public:
- ClangPersistentVariables();
+ ClangPersistentVariables(std::shared_ptr<Target> target_sp);
~ClangPersistentVariables() override = default;
@@ -40,6 +42,7 @@ public:
}
std::shared_ptr<ClangASTImporter> GetClangASTImporter();
+ std::shared_ptr<ClangModulesDeclVendor> GetClangModulesDeclVendor();
lldb::ExpressionVariableSP
CreatePersistentVariable(const lldb::ValueObjectSP &valobj_sp) override;
@@ -106,6 +109,8 @@ private:
///these are the highest-
///< priority source for macros.
std::shared_ptr<ClangASTImporter> m_ast_importer_sp;
+ std::shared_ptr<ClangModulesDeclVendor> m_modules_decl_vendor_sp;
+ std::shared_ptr<Target> m_target_sp;
};
} // namespace lldb_private
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
index 9be294750fa0..1b205b13113b 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -8,7 +8,7 @@
#include "lldb/Host/Config.h"
-#include <stdio.h>
+#include <cstdio>
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -90,7 +90,7 @@ ClangUserExpression::ClangUserExpression(
}
}
-ClangUserExpression::~ClangUserExpression() {}
+ClangUserExpression::~ClangUserExpression() = default;
void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
@@ -349,10 +349,6 @@ bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_man
static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target,
DiagnosticManager &diagnostic_manager) {
- ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor();
- if (!decl_vendor)
- return;
-
if (!target->GetEnableAutoImportClangModules())
return;
@@ -361,6 +357,11 @@ static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target,
if (!persistent_state)
return;
+ std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
+ persistent_state->GetClangModulesDeclVendor();
+ if (!decl_vendor)
+ return;
+
StackFrame *frame = exe_ctx.GetFramePtr();
if (!frame)
return;
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
index 9788a4e1c183..a78116352c2e 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
@@ -14,7 +14,7 @@
#include "ClangExpressionSourceCode.h"
#include "ClangPersistentVariables.h"
-#include <stdio.h>
+#include <cstdio>
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -34,21 +34,38 @@ using namespace lldb_private;
char ClangUtilityFunction::ID;
-/// Constructor
-///
-/// \param[in] text
-/// The text of the function. Must be a full translation unit.
-///
-/// \param[in] name
-/// The name of the function, as used in the text.
ClangUtilityFunction::ClangUtilityFunction(ExecutionContextScope &exe_scope,
- std::string text, std::string name)
+ std::string text, std::string name,
+ bool enable_debugging)
: UtilityFunction(
exe_scope,
- std::string(ClangExpressionSourceCode::g_expression_prefix) + text,
- std::move(name)) {}
+ std::string(ClangExpressionSourceCode::g_expression_prefix) + text +
+ std::string(ClangExpressionSourceCode::g_expression_suffix),
+ std::move(name), enable_debugging) {
+ // Write the source code to a file so that LLDB's source manager can display
+ // it when debugging the code.
+ if (enable_debugging) {
+ int temp_fd = -1;
+ llvm::SmallString<128> result_path;
+ llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path);
+ if (temp_fd != -1) {
+ lldb_private::NativeFile file(temp_fd, File::eOpenOptionWrite, true);
+ text = "#line 1 \"" + std::string(result_path) + "\"\n" + text;
+ size_t bytes_written = text.size();
+ file.Write(text.c_str(), bytes_written);
+ if (bytes_written == text.size()) {
+ // If we successfully wrote the source to a temporary file, replace the
+ // function text with the next text containing the line directive.
+ m_function_text =
+ std::string(ClangExpressionSourceCode::g_expression_prefix) + text +
+ std::string(ClangExpressionSourceCode::g_expression_suffix);
+ }
+ file.Close();
+ }
+ }
+}
-ClangUtilityFunction::~ClangUtilityFunction() {}
+ClangUtilityFunction::~ClangUtilityFunction() = default;
/// Install the utility function into a process
///
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
index 7914e1406cd0..b8a154b3baed 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
@@ -48,8 +48,11 @@ public:
///
/// \param[in] name
/// The name of the function, as used in the text.
+ ///
+ /// \param[in] enable_debugging
+ /// Enable debugging of this function.
ClangUtilityFunction(ExecutionContextScope &exe_scope, std::string text,
- std::string name);
+ std::string name, bool enable_debugging);
~ClangUtilityFunction() override;
@@ -71,9 +74,9 @@ public:
private:
class ClangUtilityFunctionHelper : public ClangExpressionHelper {
public:
- ClangUtilityFunctionHelper() {}
+ ClangUtilityFunctionHelper() = default;
- ~ClangUtilityFunctionHelper() override {}
+ ~ClangUtilityFunctionHelper() override = default;
/// Return the object that the parser should use when resolving external
/// values. May be NULL if everything should be self-contained.
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h b/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h
index b984db43fa6d..425106bba0a3 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h
@@ -59,7 +59,7 @@ public:
/// Creates a configuration by analyzing the given list of used source files.
explicit CppModuleConfiguration(const FileSpecList &support_files);
/// Creates an empty and invalid configuration.
- CppModuleConfiguration() {}
+ CppModuleConfiguration() = default;
/// Returns true iff this is a valid configuration that can be used to
/// load and compile modules.
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp b/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp
index f953e860969c..74dd04600b4b 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp
@@ -33,6 +33,9 @@ CxxModuleHandler::CxxModuleHandler(ASTImporter &importer, ASTContext *target)
"shared_ptr",
"unique_ptr",
"weak_ptr",
+ // iterator
+ "move_iterator",
+ "__wrap_iter",
// utility
"allocator",
"pair",
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
index b35bf07034bd..5655d548ee34 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
@@ -14,6 +14,7 @@
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Operator.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
@@ -41,14 +42,12 @@
using namespace llvm;
-static char ID;
-
typedef SmallVector<Instruction *, 2> InstrList;
IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker)
: m_maker(maker), m_values() {}
-IRForTarget::FunctionValueCache::~FunctionValueCache() {}
+IRForTarget::FunctionValueCache::~FunctionValueCache() = default;
llvm::Value *
IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) {
@@ -72,13 +71,9 @@ IRForTarget::IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map,
lldb_private::IRExecutionUnit &execution_unit,
lldb_private::Stream &error_stream,
const char *func_name)
- : ModulePass(ID), m_resolve_vars(resolve_vars), m_func_name(func_name),
- m_module(nullptr), m_decl_map(decl_map),
- m_CFStringCreateWithBytes(nullptr), m_sel_registerName(nullptr),
- m_objc_getClass(nullptr), m_intptr_ty(nullptr),
- m_error_stream(error_stream), m_execution_unit(execution_unit),
- m_result_store(nullptr), m_result_is_pointer(false),
- m_reloc_placeholder(nullptr),
+ : m_resolve_vars(resolve_vars), m_func_name(func_name),
+ m_decl_map(decl_map), m_error_stream(error_stream),
+ m_execution_unit(execution_unit),
m_entry_instruction_finder(FindEntryInstruction) {}
/* Handy utility functions used at several places in the code */
@@ -105,8 +100,6 @@ static std::string PrintType(const llvm::Type *type, bool truncate = false) {
return s;
}
-IRForTarget::~IRForTarget() {}
-
bool IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function) {
llvm_function.setLinkage(GlobalValue::ExternalLinkage);
@@ -1582,20 +1575,14 @@ bool IRForTarget::UnfoldConstant(Constant *old_constant,
FunctionValueCache get_element_pointer_maker(
[&value_maker, &entry_instruction_finder, old_constant,
constant_expr](llvm::Function *function) -> llvm::Value * {
- Value *ptr = constant_expr->getOperand(0);
+ auto *gep = cast<llvm::GEPOperator>(constant_expr);
+ Value *ptr = gep->getPointerOperand();
if (ptr == old_constant)
ptr = value_maker.GetValue(function);
std::vector<Value *> index_vector;
-
- unsigned operand_index;
- unsigned num_operands = constant_expr->getNumOperands();
-
- for (operand_index = 1; operand_index < num_operands;
- ++operand_index) {
- Value *operand = constant_expr->getOperand(operand_index);
-
+ for (Value *operand : gep->indices()) {
if (operand == old_constant)
operand = value_maker.GetValue(function);
@@ -1605,7 +1592,7 @@ bool IRForTarget::UnfoldConstant(Constant *old_constant,
ArrayRef<Value *> indices(index_vector);
return GetElementPtrInst::Create(
- nullptr, ptr, indices, "",
+ gep->getSourceElementType(), ptr, indices, "",
llvm::cast<Instruction>(
entry_instruction_finder.GetValue(function)));
});
@@ -1788,7 +1775,8 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) {
ConstantInt *offset_int(
ConstantInt::get(offset_type, offset, true));
GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(
- nullptr, argument, offset_int, "", entry_instruction);
+ argument->getType()->getPointerElementType(), argument,
+ offset_int, "", entry_instruction);
if (name == m_result_name && !m_result_is_pointer) {
BitCastInst *bit_cast = new BitCastInst(
@@ -2022,10 +2010,3 @@ bool IRForTarget::runOnModule(Module &llvm_module) {
return true;
}
-
-void IRForTarget::assignPassManager(PMStack &pass_mgr_stack,
- PassManagerType pass_mgr_type) {}
-
-PassManagerType IRForTarget::getPotentialPassManagerType() const {
- return PMT_ModulePassManager;
-}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
index ebfc0cae626c..5f212fa8f918 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
@@ -58,7 +58,7 @@ class IRMemoryMap;
/// transformations to the IR which make it relocatable. These
/// transformations are discussed in more detail next to their relevant
/// functions.
-class IRForTarget : public llvm::ModulePass {
+class IRForTarget {
public:
enum class LookupResult { Success, Fail, Ignore };
@@ -87,9 +87,6 @@ public:
lldb_private::Stream &error_stream,
const char *func_name = "$__lldb_expr");
- /// Destructor
- ~IRForTarget() override;
-
/// Run this IR transformer on a single module
///
/// Implementation of the llvm::ModulePass::runOnModule() function.
@@ -101,20 +98,7 @@ public:
///
/// \return
/// True on success; false otherwise
- bool runOnModule(llvm::Module &llvm_module) override;
-
- /// Interface stub
- ///
- /// Implementation of the llvm::ModulePass::assignPassManager() function.
- void assignPassManager(llvm::PMStack &pass_mgr_stack,
- llvm::PassManagerType pass_mgr_type =
- llvm::PMT_ModulePassManager) override;
-
- /// Returns PMT_ModulePassManager
- ///
- /// Implementation of the llvm::ModulePass::getPotentialPassManagerType()
- /// function.
- llvm::PassManagerType getPotentialPassManagerType() const override;
+ bool runOnModule(llvm::Module &llvm_module);
private:
/// Ensures that the current function's linkage is set to external.
@@ -419,51 +403,46 @@ private:
/// True on success; false otherwise
bool ReplaceVariables(llvm::Function &llvm_function);
- /// Flags
- bool m_resolve_vars; ///< True if external variable references and persistent
- ///variable references should be resolved
- lldb_private::ConstString
- m_func_name; ///< The name of the function to translate
- lldb_private::ConstString
- m_result_name; ///< The name of the result variable ($0, $1, ...)
- lldb_private::TypeFromParser
- m_result_type; ///< The type of the result variable.
- llvm::Module *m_module; ///< The module being processed, or NULL if that has
- ///not been determined yet.
- std::unique_ptr<llvm::DataLayout> m_target_data; ///< The target data for the
- ///module being processed, or
- ///NULL if there is no
- ///module.
- lldb_private::ClangExpressionDeclMap
- *m_decl_map; ///< The DeclMap containing the Decls
- llvm::FunctionCallee
- m_CFStringCreateWithBytes; ///< The address of the function
- /// CFStringCreateWithBytes, cast to the
- /// appropriate function pointer type
- llvm::FunctionCallee m_sel_registerName; ///< The address of the function
- /// sel_registerName, cast to the
- /// appropriate function pointer type
- llvm::FunctionCallee m_objc_getClass; ///< The address of the function
- /// objc_getClass, cast to the
- /// appropriate function pointer type
- llvm::IntegerType
- *m_intptr_ty; ///< The type of an integer large enough to hold a pointer.
- lldb_private::Stream
- &m_error_stream; ///< The stream on which errors should be printed
- lldb_private::IRExecutionUnit &
- m_execution_unit; ///< The execution unit containing the IR being created.
-
- llvm::StoreInst *m_result_store; ///< If non-NULL, the store instruction that
- ///writes to the result variable. If
- /// m_has_side_effects is true, this is
- /// NULL.
- bool m_result_is_pointer; ///< True if the function's result in the AST is a
- ///pointer (see comments in
- /// ASTResultSynthesizer::SynthesizeBodyResult)
-
+ /// True if external variable references and persistent variable references
+ /// should be resolved
+ bool m_resolve_vars;
+ /// The name of the function to translate
+ lldb_private::ConstString m_func_name;
+ /// The name of the result variable ($0, $1, ...)
+ lldb_private::ConstString m_result_name;
+ /// The type of the result variable.
+ lldb_private::TypeFromParser m_result_type;
+ /// The module being processed, or NULL if that has not been determined yet.
+ llvm::Module *m_module = nullptr;
+ /// The target data for the module being processed, or NULL if there is no
+ /// module.
+ std::unique_ptr<llvm::DataLayout> m_target_data;
+ /// The DeclMap containing the Decls
+ lldb_private::ClangExpressionDeclMap *m_decl_map;
+ /// The address of the function CFStringCreateWithBytes, cast to the
+ /// appropriate function pointer type
+ llvm::FunctionCallee m_CFStringCreateWithBytes;
+ /// The address of the function sel_registerName, cast to the appropriate
+ /// function pointer type.
+ llvm::FunctionCallee m_sel_registerName;
+ /// The address of the function objc_getClass, cast to the appropriate
+ /// function pointer type.
+ llvm::FunctionCallee m_objc_getClass;
+ /// The type of an integer large enough to hold a pointer.
+ llvm::IntegerType *m_intptr_ty = nullptr;
+ /// The stream on which errors should be printed.
+ lldb_private::Stream &m_error_stream;
+ /// The execution unit containing the IR being created.
+ lldb_private::IRExecutionUnit &m_execution_unit;
+ /// If non-NULL, the store instruction that writes to the result variable. If
+ /// m_has_side_effects is true, this is NULL.
+ llvm::StoreInst *m_result_store = nullptr;
+ /// True if the function's result in the AST is a pointer (see comments in
+ /// ASTResultSynthesizer::SynthesizeBodyResult)
+ bool m_result_is_pointer = false;
/// A placeholder that will be replaced by a pointer to the final location of
/// the static allocation.
- llvm::GlobalVariable *m_reloc_placeholder;
+ llvm::GlobalVariable *m_reloc_placeholder = nullptr;
class FunctionValueCache {
public:
diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index 555912780df9..bf0bbdab740f 100644
--- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <stdlib.h>
+#include <cstdlib>
#include "EmulateInstructionARM.h"
#include "EmulationStateARM.h"
diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
index d15d80c97e38..dfd7c926dabf 100644
--- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
+++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
@@ -19,8 +19,8 @@ namespace lldb_private {
// ITSession - Keep track of the IT Block progression.
class ITSession {
public:
- ITSession() : ITCounter(0), ITState(0) {}
- ~ITSession() {}
+ ITSession() = default;
+ ~ITSession() = default;
// InitIT - Initializes ITCounter/ITState.
bool InitIT(uint32_t bits7_0);
@@ -39,8 +39,8 @@ public:
uint32_t GetCond();
private:
- uint32_t ITCounter; // Possible values: 0, 1, 2, 3, 4.
- uint32_t ITState; // A2.5.2 Consists of IT[7:5] and IT[4:0] initially.
+ uint32_t ITCounter = 0; // Possible values: 0, 1, 2, 3, 4.
+ uint32_t ITState = 0; // A2.5.2 Consists of IT[7:5] and IT[4:0] initially.
};
class EmulateInstructionARM : public EmulateInstruction {
diff --git a/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp b/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp
index aef08baa8ae9..569482c7b23b 100644
--- a/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp
+++ b/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp
@@ -20,11 +20,11 @@
using namespace lldb;
using namespace lldb_private;
-EmulationStateARM::EmulationStateARM() : m_gpr(), m_vfp_regs(), m_memory() {
+EmulationStateARM::EmulationStateARM() : m_vfp_regs(), m_memory() {
ClearPseudoRegisters();
}
-EmulationStateARM::~EmulationStateARM() {}
+EmulationStateARM::~EmulationStateARM() = default;
bool EmulationStateARM::LoadPseudoRegistersFromFrame(StackFrame &frame) {
RegisterContext *reg_ctx = frame.GetRegisterContext().get();
diff --git a/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h b/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h
index 955c7c642058..28bc5d98649d 100644
--- a/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h
+++ b/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h
@@ -61,7 +61,7 @@ public:
const lldb_private::RegisterValue &reg_value);
private:
- uint32_t m_gpr[17];
+ uint32_t m_gpr[17] = {0};
struct _sd_regs {
uint32_t s_regs[32]; // sregs 0 - 31 & dregs 0 - 15
diff --git a/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
index d4cb726fc7e5..a1a93c0b5a5f 100644
--- a/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
+++ b/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
@@ -8,7 +8,7 @@
#include "EmulateInstructionMIPS.h"
-#include <stdlib.h>
+#include <cstdlib>
#include "lldb/Core/Address.h"
#include "lldb/Core/Opcode.h"
@@ -159,8 +159,8 @@ EmulateInstructionMIPS::EmulateInstructionMIPS(
target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
assert(m_asm_info.get() && m_subtype_info.get());
- m_context = std::make_unique<llvm::MCContext>(m_asm_info.get(),
- m_reg_info.get(), nullptr);
+ m_context = std::make_unique<llvm::MCContext>(
+ triple, m_asm_info.get(), m_reg_info.get(), m_subtype_info.get());
assert(m_context.get());
m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context));
@@ -1018,8 +1018,9 @@ bool EmulateInstructionMIPS::SetInstruction(const Opcode &insn_opcode,
const size_t bytes_read =
target->ReadMemory(next_addr, /* Address of next instruction */
- true, /* prefer_file_cache */
- buf, sizeof(uint32_t), error, &load_addr);
+ buf, sizeof(uint32_t), error,
+ false, /* force_live_memory */
+ &load_addr);
if (bytes_read == 0)
return true;
diff --git a/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
index 4ccaf0de0758..6044d00c0cbf 100644
--- a/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
+++ b/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
@@ -8,7 +8,7 @@
#include "EmulateInstructionMIPS64.h"
-#include <stdlib.h>
+#include <cstdlib>
#include "lldb/Core/Address.h"
#include "lldb/Core/Opcode.h"
@@ -163,8 +163,8 @@ EmulateInstructionMIPS64::EmulateInstructionMIPS64(
target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
assert(m_asm_info.get() && m_subtype_info.get());
- m_context = std::make_unique<llvm::MCContext>(m_asm_info.get(),
- m_reg_info.get(), nullptr);
+ m_context = std::make_unique<llvm::MCContext>(
+ triple, m_asm_info.get(), m_reg_info.get(), m_subtype_info.get());
assert(m_context.get());
m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context));
diff --git a/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp b/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp
index 5d97513c0be7..4e78c369c128 100644
--- a/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp
+++ b/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp
@@ -8,7 +8,7 @@
#include "EmulateInstructionPPC64.h"
-#include <stdlib.h>
+#include <cstdlib>
#include "lldb/Core/PluginManager.h"
#include "lldb/Symbol/UnwindPlan.h"
diff --git a/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp b/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp
index 99784bd3dbd1..9a88b343878c 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp
+++ b/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp
@@ -127,7 +127,7 @@ InstrumentationRuntimeMainThreadChecker::RetrieveReportData(
StackFrameSP responsible_frame;
for (unsigned I = 0; I < thread_sp->GetStackFrameCount(); ++I) {
StackFrameSP frame = thread_sp->GetStackFrameAtIndex(I);
- Address addr = frame->GetFrameCodeAddress();
+ Address addr = frame->GetFrameCodeAddressForSymbolication();
if (addr.GetModule() == runtime_module_sp) // Skip PCs from the runtime.
continue;
@@ -135,11 +135,6 @@ InstrumentationRuntimeMainThreadChecker::RetrieveReportData(
if (!responsible_frame)
responsible_frame = frame;
- // First frame in stacktrace should point to a real PC, not return address.
- if (I != 0 && trace->GetSize() == 0) {
- addr.Slide(-1);
- }
-
lldb::addr_t PC = addr.GetLoadAddress(&target);
trace->AddItem(StructuredData::ObjectSP(new StructuredData::Integer(PC)));
}
@@ -271,8 +266,11 @@ InstrumentationRuntimeMainThreadChecker::GetBacktracesFromExtendedStopInfo(
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);
+ // We gather symbolication addresses above, so no need for HistoryThread to
+ // try to infer the call addresses.
+ bool pcs_are_call_addresses = true;
+ ThreadSP new_thread_sp = std::make_shared<HistoryThread>(
+ *process_sp, tid, PCs, pcs_are_call_addresses);
// Save this in the Process' ExtendedThreadList so a strong pointer retains
// the object
diff --git a/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp b/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp
index b60eb53f3d4a..58bc38a551f0 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp
+++ b/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp
@@ -29,7 +29,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Stream.h"
-#include <ctype.h>
+#include <cctype>
#include <memory>
@@ -150,8 +150,8 @@ StructuredData::ObjectSP InstrumentationRuntimeUBSan::RetrieveReportData(
StructuredData::Array *trace = new StructuredData::Array();
auto trace_sp = StructuredData::ObjectSP(trace);
for (unsigned I = 0; I < thread_sp->GetStackFrameCount(); ++I) {
- const Address FCA =
- thread_sp->GetStackFrameAtIndex(I)->GetFrameCodeAddress();
+ const Address FCA = thread_sp->GetStackFrameAtIndex(I)
+ ->GetFrameCodeAddressForSymbolication();
if (FCA.GetModule() == runtime_module_sp) // Skip PCs from the runtime.
continue;
@@ -324,8 +324,11 @@ InstrumentationRuntimeUBSan::GetBacktracesFromExtendedStopInfo(
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);
+ // We gather symbolication addresses above, so no need for HistoryThread to
+ // try to infer the call addresses.
+ bool pcs_are_call_addresses = true;
+ ThreadSP new_thread_sp = std::make_shared<HistoryThread>(
+ *process_sp, tid, PCs, pcs_are_call_addresses);
std::string stop_reason_description = GetStopReasonDescription(info);
new_thread_sp->SetName(stop_reason_description.c_str());
diff --git a/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp b/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
index 35788a6445c2..1c498a2ddc11 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
@@ -74,14 +74,12 @@ public:
const CompilerType reserved_type =
clang_ast_context->GetBasicType(lldb::eBasicTypeInt);
const char *const FuncPtr_name("__FuncPtr");
- const CompilerType FuncPtr_type =
- clang_ast_importer->CopyType(*clang_ast_context, function_pointer_type);
m_block_struct_type = clang_ast_context->CreateStructForIdentifier(
ConstString(), {{isa_name, isa_type},
{flags_name, flags_type},
{reserved_name, reserved_type},
- {FuncPtr_name, FuncPtr_type}});
+ {FuncPtr_name, function_pointer_type}});
}
~BlockPointerSyntheticFrontEnd() override = default;
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index d844498fd8a3..895fd55f499c 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -59,6 +59,11 @@ lldb_private::ConstString CPlusPlusLanguage::GetPluginNameStatic() {
return g_name;
}
+bool CPlusPlusLanguage::SymbolNameFitsToLanguage(Mangled mangled) const {
+ const char *mangled_name = mangled.GetMangledName().GetCString();
+ return mangled_name && CPlusPlusLanguage::IsCPPMangledName(mangled_name);
+}
+
// PluginInterface protocol
lldb_private::ConstString CPlusPlusLanguage::GetPluginName() {
@@ -1054,7 +1059,7 @@ CPlusPlusLanguage::GetHardcodedSummaries() {
.SetSkipReferences(false),
lldb_private::formatters::VectorTypeSummaryProvider,
"vector_type pointer summary provider"));
- if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr)) {
+ if (valobj.GetCompilerType().IsVectorType()) {
if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
return formatter_sp;
}
@@ -1074,7 +1079,7 @@ CPlusPlusLanguage::GetHardcodedSummaries() {
.SetSkipReferences(false),
lldb_private::formatters::BlockPointerSummaryProvider,
"block pointer summary provider"));
- if (valobj.GetCompilerType().IsBlockPointerType(nullptr)) {
+ if (valobj.GetCompilerType().IsBlockPointerType()) {
return formatter_sp;
}
return nullptr;
@@ -1104,7 +1109,7 @@ CPlusPlusLanguage::GetHardcodedSynthetics() {
.SetNonCacheable(true),
"vector_type synthetic children",
lldb_private::formatters::VectorTypeSyntheticFrontEndCreator));
- if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr)) {
+ if (valobj.GetCompilerType().IsVectorType()) {
if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
return formatter_sp;
}
@@ -1123,7 +1128,7 @@ CPlusPlusLanguage::GetHardcodedSynthetics() {
.SetNonCacheable(true),
"block pointer synthetic children",
lldb_private::formatters::BlockPointerSyntheticFrontEndCreator));
- if (valobj.GetCompilerType().IsBlockPointerType(nullptr)) {
+ if (valobj.GetCompilerType().IsBlockPointerType()) {
return formatter_sp;
}
return nullptr;
@@ -1147,7 +1152,7 @@ bool CPlusPlusLanguage::IsSourceFile(llvm::StringRef file_path) const {
const auto suffixes = {".cpp", ".cxx", ".c++", ".cc", ".c",
".h", ".hh", ".hpp", ".hxx", ".h++"};
for (auto suffix : suffixes) {
- if (file_path.endswith_lower(suffix))
+ if (file_path.endswith_insensitive(suffix))
return true;
}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
index e2b5d2918753..9163be4807ec 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
@@ -28,8 +28,7 @@ public:
class MethodName {
public:
MethodName()
- : m_full(), m_basename(), m_context(), m_arguments(), m_qualifiers(),
- m_parsed(false), m_parse_error(false) {}
+ : m_full(), m_basename(), m_context(), m_arguments(), m_qualifiers() {}
MethodName(ConstString s)
: m_full(s), m_basename(), m_context(), m_arguments(), m_qualifiers(),
@@ -68,8 +67,8 @@ public:
llvm::StringRef m_context; // Decl context: "lldb::SBTarget"
llvm::StringRef m_arguments; // Arguments: "(unsigned int)"
llvm::StringRef m_qualifiers; // Qualifiers: "const"
- bool m_parsed;
- bool m_parse_error;
+ bool m_parsed = false;
+ bool m_parse_error = false;
};
CPlusPlusLanguage() = default;
@@ -105,6 +104,8 @@ public:
static lldb_private::ConstString GetPluginNameStatic();
+ bool SymbolNameFitsToLanguage(Mangled mangled) const override;
+
static bool IsCPPMangledName(llvm::StringRef name);
// Extract C++ context and identifier from a string using heuristic matching
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
index 6fe6b12725b0..426434c48608 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
@@ -69,7 +69,7 @@ private:
size_t begin_index = 0;
size_t end_index = 0;
- Range() {}
+ Range() = default;
Range(size_t begin, size_t end) : begin_index(begin), end_index(end) {
assert(end >= begin);
}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index 2b16ebe79daf..8eda422f3145 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -379,8 +379,7 @@ lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator(
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
- : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr), m_count_sp(),
- m_weak_count_sp(), m_ptr_size(0), m_byte_order(lldb::eByteOrderInvalid) {
+ : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr) {
if (valobj_sp)
Update();
}
@@ -403,42 +402,23 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
if (idx == 0)
return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true);
- if (idx > 2)
- return lldb::ValueObjectSP();
-
if (idx == 1) {
- if (!m_count_sp) {
- ValueObjectSP shared_owners_sp(m_cntrl->GetChildMemberWithName(
- ConstString("__shared_owners_"), true));
- if (!shared_owners_sp)
- return lldb::ValueObjectSP();
- uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0);
- DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
- m_count_sp = CreateValueObjectFromData(
- "count", data, valobj_sp->GetExecutionContextRef(),
- shared_owners_sp->GetCompilerType());
- }
- return m_count_sp;
- } else /* if (idx == 2) */
- {
- if (!m_weak_count_sp) {
- ValueObjectSP shared_weak_owners_sp(m_cntrl->GetChildMemberWithName(
- ConstString("__shared_weak_owners_"), true));
- if (!shared_weak_owners_sp)
- return lldb::ValueObjectSP();
- uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0);
- DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
- m_weak_count_sp = CreateValueObjectFromData(
- "count", data, valobj_sp->GetExecutionContextRef(),
- shared_weak_owners_sp->GetCompilerType());
+ if (auto ptr_sp =
+ valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true)) {
+ Status status;
+ auto value_sp = ptr_sp->Dereference(status);
+ if (status.Success()) {
+ auto value_type_sp =
+ valobj_sp->GetCompilerType().GetTypeTemplateArgument(0);
+ return value_sp->Cast(value_type_sp);
+ }
}
- return m_weak_count_sp;
}
+
+ return lldb::ValueObjectSP();
}
bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
- m_count_sp.reset();
- m_weak_count_sp.reset();
m_cntrl = nullptr;
ValueObjectSP valobj_sp = m_backend.GetSP();
@@ -449,9 +429,6 @@ bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
if (!target_sp)
return false;
- m_byte_order = target_sp->GetArchitecture().GetByteOrder();
- m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize();
-
lldb::ValueObjectSP cntrl_sp(
valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"), true));
@@ -469,10 +446,8 @@ size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
GetIndexOfChildWithName(ConstString name) {
if (name == "__ptr_")
return 0;
- if (name == "count")
+ if (name == "$$dereference$$")
return 1;
- if (name == "weak_count")
- return 2;
return UINT32_MAX;
}
@@ -488,7 +463,7 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator(
lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
LibcxxUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
- : SyntheticChildrenFrontEnd(*valobj_sp), m_compressed_pair_sp() {
+ : SyntheticChildrenFrontEnd(*valobj_sp) {
if (valobj_sp)
Update();
}
@@ -505,19 +480,27 @@ lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEndCreator(
size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
CalculateNumChildren() {
- return (m_compressed_pair_sp ? 1 : 0);
+ return (m_value_ptr_sp ? 1 : 0);
}
lldb::ValueObjectSP
lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::GetChildAtIndex(
size_t idx) {
- if (!m_compressed_pair_sp)
+ if (!m_value_ptr_sp)
return lldb::ValueObjectSP();
- if (idx != 0)
- return lldb::ValueObjectSP();
+ if (idx == 0)
+ return m_value_ptr_sp;
- return m_compressed_pair_sp;
+ if (idx == 1) {
+ Status status;
+ auto value_sp = m_value_ptr_sp->Dereference(status);
+ if (status.Success()) {
+ return value_sp;
+ }
+ }
+
+ return lldb::ValueObjectSP();
}
bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() {
@@ -530,7 +513,7 @@ bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() {
if (!ptr_sp)
return false;
- m_compressed_pair_sp = GetValueOfLibCXXCompressedPair(*ptr_sp);
+ m_value_ptr_sp = GetValueOfLibCXXCompressedPair(*ptr_sp);
return false;
}
@@ -544,6 +527,8 @@ size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
GetIndexOfChildWithName(ConstString name) {
if (name == "__value_")
return 0;
+ if (name == "$$dereference$$")
+ return 1;
return UINT32_MAX;
}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
index ea5a7c178178..99e206543197 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -105,10 +105,6 @@ public:
private:
ValueObject *m_cntrl;
- lldb::ValueObjectSP m_count_sp;
- lldb::ValueObjectSP m_weak_count_sp;
- uint8_t m_ptr_size;
- lldb::ByteOrder m_byte_order;
};
class LibcxxUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
@@ -128,7 +124,7 @@ public:
~LibcxxUniquePtrSyntheticFrontEnd() override;
private:
- lldb::ValueObjectSP m_compressed_pair_sp;
+ lldb::ValueObjectSP m_value_ptr_sp;
};
SyntheticChildrenFrontEnd *
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp
index 6de4637a6a4a..e5b868fc0fce 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp
@@ -85,7 +85,7 @@ ValueObjectSP BitsetFrontEnd::GetChildAtIndex(size_t idx) {
CompilerType type;
ValueObjectSP chunk;
// For small bitsets __first_ is not an array, but a plain size_t.
- if (m_first->GetCompilerType().IsArrayType(&type, nullptr, nullptr)) {
+ if (m_first->GetCompilerType().IsArrayType(&type)) {
llvm::Optional<uint64_t> bit_size =
type.GetBitSize(ctx.GetBestExecutionContextScope());
if (!bit_size || *bit_size == 0)
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
index 0d5ae16a0b29..47c6634ed65e 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
@@ -27,8 +27,7 @@ namespace {
class ListEntry {
public:
ListEntry() = default;
- ListEntry(ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
- ListEntry(const ListEntry &rhs) = default;
+ ListEntry(ValueObjectSP entry_sp) : m_entry_sp(std::move(entry_sp)) {}
ListEntry(ValueObject *entry)
: m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
@@ -73,9 +72,8 @@ private:
class ListIterator {
public:
ListIterator() = default;
- ListIterator(ListEntry entry) : m_entry(entry) {}
- ListIterator(ValueObjectSP entry) : m_entry(entry) {}
- ListIterator(const ListIterator &rhs) = default;
+ ListIterator(ListEntry entry) : m_entry(std::move(entry)) {}
+ ListIterator(ValueObjectSP entry) : m_entry(std::move(entry)) {}
ListIterator(ValueObject *entry) : m_entry(entry) {}
ValueObjectSP value() { return m_entry.GetEntry(); }
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
index 64a199e24e4a..25c2bfd9387b 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
@@ -26,7 +26,6 @@ class MapEntry {
public:
MapEntry() = default;
explicit MapEntry(ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
- MapEntry(const MapEntry &rhs) = default;
explicit MapEntry(ValueObject *entry)
: m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
@@ -86,9 +85,9 @@ class MapIterator {
public:
MapIterator() = default;
MapIterator(MapEntry entry, size_t depth = 0)
- : m_entry(entry), m_max_depth(depth), m_error(false) {}
+ : m_entry(std::move(entry)), m_max_depth(depth), m_error(false) {}
MapIterator(ValueObjectSP entry, size_t depth = 0)
- : m_entry(entry), m_max_depth(depth), m_error(false) {}
+ : m_entry(std::move(entry)), m_max_depth(depth), m_error(false) {}
MapIterator(const MapIterator &rhs)
: m_entry(rhs.m_entry), m_max_depth(rhs.m_max_depth), m_error(false) {}
MapIterator(ValueObject *entry, size_t depth = 0)
@@ -138,7 +137,7 @@ protected:
}
private:
- MapEntry tree_min(MapEntry &&x) {
+ MapEntry tree_min(MapEntry x) {
if (x.null())
return MapEntry();
MapEntry left(x.left());
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
index 0b34b4e2fc89..79e864a2cbd5 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
@@ -99,9 +99,17 @@ bool LibStdcppUniquePtrSyntheticFrontEnd::Update() {
if (ptr_obj)
m_ptr_obj = ptr_obj->Clone(ConstString("pointer")).get();
- ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1);
- if (del_obj)
- m_del_obj = del_obj->Clone(ConstString("deleter")).get();
+ // Add a 'deleter' child if there was a non-empty deleter type specified.
+ //
+ // The object might have size=1 in the TypeSystem but occupies no dedicated
+ // storage due to no_unique_address, so infer the actual size from the total
+ // size of the unique_ptr class. If sizeof(unique_ptr) == sizeof(void*) then
+ // the deleter is empty and should be hidden.
+ if (tuple_sp->GetByteSize() > ptr_obj->GetByteSize()) {
+ ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1);
+ if (del_obj)
+ m_del_obj = del_obj->Clone(ConstString("deleter")).get();
+ }
if (m_ptr_obj) {
Status error;
diff --git a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
index d871d3470e70..1479f4f0c151 100644
--- a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
+++ b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
@@ -351,7 +351,7 @@ static void NSNumber_FormatInt(ValueObject &valobj, Stream &stream, int value,
}
static void NSNumber_FormatLong(ValueObject &valobj, Stream &stream,
- uint64_t value, lldb::LanguageType lang) {
+ int64_t value, lldb::LanguageType lang) {
static ConstString g_TypeHint("NSNumber:long");
std::string prefix, suffix;
@@ -367,10 +367,10 @@ static void NSNumber_FormatLong(ValueObject &valobj, Stream &stream,
}
static void NSNumber_FormatInt128(ValueObject &valobj, Stream &stream,
- const llvm::APInt &value,
- lldb::LanguageType lang) {
+ const llvm::APInt &value,
+ lldb::LanguageType lang) {
static ConstString g_TypeHint("NSNumber:int128_t");
-
+
std::string prefix, suffix;
if (Language *language = Language::FindPlugin(lang)) {
if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix,
@@ -379,11 +379,11 @@ static void NSNumber_FormatInt128(ValueObject &valobj, Stream &stream,
suffix.clear();
}
}
-
+
stream.PutCString(prefix.c_str());
const int radix = 10;
const bool isSigned = true;
- std::string str = value.toString(radix, isSigned);
+ std::string str = llvm::toString(value, radix, isSigned);
stream.PutCString(str.c_str());
stream.PutCString(suffix.c_str());
}
@@ -426,6 +426,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
if (!process_sp)
return false;
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS);
ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
if (!runtime)
@@ -456,9 +457,18 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
return NSDecimalNumberSummaryProvider(valobj, stream, options);
if (class_name == "NSNumber" || class_name == "__NSCFNumber") {
- uint64_t value = 0;
+ int64_t value = 0;
uint64_t i_bits = 0;
- if (descriptor->GetTaggedPointerInfo(&i_bits, &value)) {
+ if (descriptor->GetTaggedPointerInfoSigned(&i_bits, &value)) {
+ // Check for "preserved" numbers. We still don't support them yet.
+ if (i_bits & 0x8) {
+ if (log)
+ log->Printf(
+ "Unsupported (preserved) NSNumber tagged pointer 0x%" PRIu64,
+ valobj_addr);
+ return false;
+ }
+
switch (i_bits) {
case 0:
NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage());
@@ -498,49 +508,66 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
f64 = 0x5,
sint128 = 0x6
};
-
+
uint64_t data_location = valobj_addr + 2 * ptr_size;
TypeCodes type_code;
-
+
if (new_format) {
- uint64_t cfinfoa =
- process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
- ptr_size, 0, error);
-
+ uint64_t cfinfoa = process_sp->ReadUnsignedIntegerFromMemory(
+ valobj_addr + ptr_size, ptr_size, 0, error);
+
if (error.Fail())
return false;
bool is_preserved_number = cfinfoa & 0x8;
if (is_preserved_number) {
- lldbassert(!static_cast<bool>("We should handle preserved numbers!"));
+ if (log)
+ log->Printf(
+ "Unsupported preserved NSNumber tagged pointer 0x%" PRIu64,
+ valobj_addr);
return false;
}
type_code = static_cast<TypeCodes>(cfinfoa & 0x7);
} else {
- uint8_t data_type =
- process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 1,
- 0, error) & 0x1F;
-
+ uint8_t data_type = process_sp->ReadUnsignedIntegerFromMemory(
+ valobj_addr + ptr_size, 1, 0, error) &
+ 0x1F;
+
if (error.Fail())
return false;
-
+
switch (data_type) {
- case 1: type_code = TypeCodes::sint8; break;
- case 2: type_code = TypeCodes::sint16; break;
- case 3: type_code = TypeCodes::sint32; break;
- case 17: data_location += 8; LLVM_FALLTHROUGH;
- case 4: type_code = TypeCodes::sint64; break;
- case 5: type_code = TypeCodes::f32; break;
- case 6: type_code = TypeCodes::f64; break;
- default: return false;
+ case 1:
+ type_code = TypeCodes::sint8;
+ break;
+ case 2:
+ type_code = TypeCodes::sint16;
+ break;
+ case 3:
+ type_code = TypeCodes::sint32;
+ break;
+ case 17:
+ data_location += 8;
+ LLVM_FALLTHROUGH;
+ case 4:
+ type_code = TypeCodes::sint64;
+ break;
+ case 5:
+ type_code = TypeCodes::f32;
+ break;
+ case 6:
+ type_code = TypeCodes::f64;
+ break;
+ default:
+ return false;
}
}
-
+
uint64_t value = 0;
bool success = false;
switch (type_code) {
- case TypeCodes::sint8:
+ case TypeCodes::sint8:
value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0,
error);
if (error.Fail())
@@ -548,7 +575,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage());
success = true;
break;
- case TypeCodes::sint16:
+ case TypeCodes::sint16:
value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0,
error);
if (error.Fail())
@@ -573,8 +600,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
NSNumber_FormatLong(valobj, stream, value, options.GetLanguage());
success = true;
break;
- case TypeCodes::f32:
- {
+ case TypeCodes::f32: {
uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(
data_location, 4, 0, error);
if (error.Fail())
@@ -585,8 +611,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
success = true;
break;
}
- case TypeCodes::f64:
- {
+ case TypeCodes::f64: {
uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(
data_location, 8, 0, error);
if (error.Fail())
@@ -600,16 +625,17 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
case TypeCodes::sint128: // internally, this is the same
{
uint64_t words[2];
- words[1] = process_sp->ReadUnsignedIntegerFromMemory(
- data_location, 8, 0, error);
+ words[1] = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8,
+ 0, error);
if (error.Fail())
return false;
- words[0] = process_sp->ReadUnsignedIntegerFromMemory(
- data_location + 8, 8, 0, error);
+ words[0] = process_sp->ReadUnsignedIntegerFromMemory(data_location + 8,
+ 8, 0, error);
if (error.Fail())
return false;
llvm::APInt i128_value(128, words);
- NSNumber_FormatInt128(valobj, stream, i128_value, options.GetLanguage());
+ NSNumber_FormatInt128(valobj, stream, i128_value,
+ options.GetLanguage());
success = true;
break;
}
diff --git a/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp b/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp
index efc80cc75557..a862da551813 100644
--- a/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp
+++ b/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp
@@ -13,7 +13,7 @@
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/Target.h"
-#include <inttypes.h>
+#include <cinttypes>
using namespace lldb;
using namespace lldb_private;
diff --git a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
index afb9c6951f55..326f47a10660 100644
--- a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
@@ -410,6 +410,7 @@ bool lldb_private::formatters::NSDictionarySummaryProvider(
static const ConstString g_DictionaryM("__NSDictionaryM");
static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
static const ConstString g_DictionaryMImmutable("__NSDictionaryM_Immutable");
+ static const ConstString g_DictionaryMFrozen("__NSFrozenDictionaryM");
static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
static const ConstString g_Dictionary0("__NSDictionary0");
static const ConstString g_DictionaryCF("__CFDictionary");
@@ -427,7 +428,8 @@ bool lldb_private::formatters::NSDictionarySummaryProvider(
return false;
value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
- } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy) {
+ } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy
+ || class_name == g_DictionaryMFrozen) {
AppleObjCRuntime *apple_runtime =
llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
Status error;
@@ -509,6 +511,7 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator(
static const ConstString g_DictionaryM("__NSDictionaryM");
static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
static const ConstString g_DictionaryImmutable("__NSDictionaryM_Immutable");
+ static const ConstString g_DictionaryMFrozen("__NSFrozenDictionaryM");
static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
static const ConstString g_Dictionary0("__NSDictionary0");
static const ConstString g_DictionaryCF("__CFDictionary");
@@ -520,7 +523,7 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator(
if (class_name == g_DictionaryI) {
return (new NSDictionaryISyntheticFrontEnd(valobj_sp));
- } else if (class_name == g_DictionaryM) {
+ } else if (class_name == g_DictionaryM || class_name == g_DictionaryMFrozen) {
if (runtime->GetFoundationVersion() >= 1437) {
return (new Foundation1437::NSDictionaryMSyntheticFrontEnd(valobj_sp));
} else if (runtime->GetFoundationVersion() >= 1428) {
diff --git a/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp b/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
index a15b0f64954a..068bca9e7b94 100644
--- a/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
@@ -209,14 +209,13 @@ protected:
m_process = nullptr;
}
- InlinedIndexes()
- : m_indexes(0), m_count(0), m_ptr_size(0), m_process(nullptr) {}
+ InlinedIndexes() {}
private:
- uint64_t m_indexes;
- size_t m_count;
- uint32_t m_ptr_size;
- Process *m_process;
+ uint64_t m_indexes = 0;
+ size_t m_count = 0;
+ uint32_t m_ptr_size = 0;
+ Process *m_process = nullptr;
// cfr. Foundation for the details of this code
size_t _lengthForInlinePayload(uint32_t ptr_size) {
@@ -271,10 +270,10 @@ protected:
m_count = 0;
}
- OutsourcedIndexes() : m_indexes(nullptr), m_count(0) {}
+ OutsourcedIndexes() {}
- ValueObject *m_indexes;
- size_t m_count;
+ ValueObject *m_indexes = nullptr;
+ size_t m_count = 0;
};
union {
@@ -288,9 +287,9 @@ protected:
m_outsourced.Clear();
}
- Impl() : m_mode(Mode::Invalid) {}
+ Impl() {}
- Mode m_mode;
+ Mode m_mode = Mode::Invalid;
} m_impl;
uint32_t m_ptr_size;
diff --git a/lldb/source/Plugins/Language/ObjC/NSSet.cpp b/lldb/source/Plugins/Language/ObjC/NSSet.cpp
index 4dbbe6fbddff..43ef7b694bbe 100644
--- a/lldb/source/Plugins/Language/ObjC/NSSet.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSSet.cpp
@@ -444,18 +444,12 @@ bool lldb_private::formatters::NSSetISyntheticFrontEnd::Update() {
if (!valobj_sp)
return false;
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
- Status error;
- if (valobj_sp->IsPointerType()) {
- valobj_sp = valobj_sp->Dereference(error);
- if (error.Fail() || !valobj_sp)
- return false;
- }
- error.Clear();
lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
if (!process_sp)
return false;
m_ptr_size = process_sp->GetAddressByteSize();
- uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
+ uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
+ Status error;
if (m_ptr_size == 4) {
m_data_32 = new DataDescriptor_32();
process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),
@@ -728,18 +722,12 @@ lldb_private::formatters::
if (!valobj_sp)
return false;
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
- Status error;
- if (valobj_sp->IsPointerType()) {
- valobj_sp = valobj_sp->Dereference(error);
- if (error.Fail() || !valobj_sp)
- return false;
- }
- error.Clear();
lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
if (!process_sp)
return false;
m_ptr_size = process_sp->GetAddressByteSize();
- uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
+ uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
+ Status error;
if (m_ptr_size == 4) {
m_data_32 = new D32();
process_sp->ReadMemory(data_location, m_data_32, sizeof(D32),
diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
index 29391daaab93..379c53432b7b 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -225,14 +225,17 @@ ConstString ObjCLanguage::MethodName::GetFullNameWithoutCategory(
return ConstString();
}
-std::vector<ConstString>
+std::vector<Language::MethodNameVariant>
ObjCLanguage::GetMethodNameVariants(ConstString method_name) const {
- std::vector<ConstString> variant_names;
+ std::vector<Language::MethodNameVariant> variant_names;
ObjCLanguage::MethodName objc_method(method_name.GetCString(), false);
if (!objc_method.IsValid(false)) {
return variant_names;
}
+ variant_names.emplace_back(objc_method.GetSelector(),
+ lldb::eFunctionNameTypeSelector);
+
const bool is_class_method =
objc_method.GetType() == MethodName::eTypeClassMethod;
const bool is_instance_method =
@@ -242,31 +245,43 @@ ObjCLanguage::GetMethodNameVariants(ConstString method_name) const {
if (is_class_method || is_instance_method) {
if (name_sans_category)
- variant_names.emplace_back(name_sans_category);
+ variant_names.emplace_back(name_sans_category,
+ lldb::eFunctionNameTypeFull);
} else {
StreamString strm;
strm.Printf("+%s", objc_method.GetFullName().GetCString());
- variant_names.emplace_back(strm.GetString());
+ variant_names.emplace_back(ConstString(strm.GetString()),
+ lldb::eFunctionNameTypeFull);
strm.Clear();
strm.Printf("-%s", objc_method.GetFullName().GetCString());
- variant_names.emplace_back(strm.GetString());
+ variant_names.emplace_back(ConstString(strm.GetString()),
+ lldb::eFunctionNameTypeFull);
strm.Clear();
if (name_sans_category) {
strm.Printf("+%s", name_sans_category.GetCString());
- variant_names.emplace_back(strm.GetString());
+ variant_names.emplace_back(ConstString(strm.GetString()),
+ lldb::eFunctionNameTypeFull);
strm.Clear();
strm.Printf("-%s", name_sans_category.GetCString());
- variant_names.emplace_back(strm.GetString());
+ variant_names.emplace_back(ConstString(strm.GetString()),
+ lldb::eFunctionNameTypeFull);
}
}
return variant_names;
}
+bool ObjCLanguage::SymbolNameFitsToLanguage(Mangled mangled) const {
+ ConstString demangled_name = mangled.GetDemangledName();
+ if (!demangled_name)
+ return false;
+ return ObjCLanguage::IsPossibleObjCMethodName(demangled_name.GetCString());
+}
+
static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
if (!objc_category_sp)
return;
@@ -990,8 +1005,11 @@ std::unique_ptr<Language::TypeScavenger> ObjCLanguage::GetTypeScavenger() {
bool result = false;
if (auto *target = exe_scope->CalculateTarget().get()) {
- if (auto *clang_modules_decl_vendor =
- target->GetClangModulesDeclVendor()) {
+ auto *persistent_vars = llvm::cast<ClangPersistentVariables>(
+ target->GetPersistentExpressionStateForLanguage(
+ lldb::eLanguageTypeC));
+ if (std::shared_ptr<ClangModulesDeclVendor> clang_modules_decl_vendor =
+ persistent_vars->GetClangModulesDeclVendor()) {
ConstString key_cs(key);
auto types = clang_modules_decl_vendor->FindTypes(
key_cs, /*max_matches*/ UINT32_MAX);
@@ -1116,7 +1134,7 @@ bool ObjCLanguage::IsNilReference(ValueObject &valobj) {
bool ObjCLanguage::IsSourceFile(llvm::StringRef file_path) const {
const auto suffixes = {".h", ".m", ".M"};
for (auto suffix : suffixes) {
- if (file_path.endswith_lower(suffix))
+ if (file_path.endswith_insensitive(suffix))
return true;
}
return false;
diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
index 02c15e86046b..691c51883c8a 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
@@ -27,9 +27,7 @@ public:
public:
enum Type { eTypeUnspecified, eTypeClassMethod, eTypeInstanceMethod };
- MethodName()
- : m_full(), m_class(), m_category(), m_selector(),
- m_type(eTypeUnspecified), m_category_is_valid(false) {}
+ MethodName() : m_full(), m_class(), m_category(), m_selector() {}
MethodName(const char *name, bool strict)
: m_full(), m_class(), m_category(), m_selector(),
@@ -81,8 +79,8 @@ public:
m_class_category; // Class with category: "NSString(my_additions)"
ConstString m_category; // Category: "my_additions"
ConstString m_selector; // Selector: "myStringWithCString:"
- Type m_type;
- bool m_category_is_valid;
+ Type m_type = eTypeUnspecified;
+ bool m_category_is_valid = false;
};
ObjCLanguage() = default;
@@ -102,9 +100,12 @@ public:
// variant_names[1] => "-[NSString(my_additions) myStringWithCString:]"
// variant_names[2] => "+[NSString myStringWithCString:]"
// variant_names[3] => "-[NSString myStringWithCString:]"
- std::vector<ConstString>
+ // Also returns the FunctionNameType of each possible name.
+ std::vector<Language::MethodNameVariant>
GetMethodNameVariants(ConstString method_name) const override;
+ bool SymbolNameFitsToLanguage(Mangled mangled) const override;
+
lldb::TypeCategoryImplSP GetFormatters() override;
std::vector<ConstString>
diff --git a/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
index 0a4017eda434..359978553210 100644
--- a/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
@@ -19,7 +19,7 @@ LLDB_PLUGIN_DEFINE(ObjCPlusPlusLanguage)
bool ObjCPlusPlusLanguage::IsSourceFile(llvm::StringRef file_path) const {
const auto suffixes = {".h", ".mm"};
for (auto suffix : suffixes) {
- if (file_path.endswith_lower(suffix))
+ if (file_path.endswith_insensitive(suffix))
return true;
}
return false;
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
index 24ab9cc5f238..bed2a98067e6 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <string.h>
+#include <cstring>
#include <memory>
@@ -322,6 +322,9 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
}
}
+ if (symbol == nullptr)
+ return optional_info;
+
// Case 1 or 3
if (scl.GetSize() >= 1) {
optional_info = line_entry_helper(target, scl[0], symbol,
@@ -397,8 +400,8 @@ CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread,
// We create a ThreadPlan to keep stepping through using the address range
// of the current function.
ret_plan_sp = std::make_shared<ThreadPlanStepInRange>(
- thread, range_of_curr_func, sc, eOnlyThisThread, eLazyBoolYes,
- eLazyBoolYes);
+ thread, range_of_curr_func, sc, nullptr, eOnlyThisThread,
+ eLazyBoolYes, eLazyBoolYes);
return ret_plan_sp;
}
}
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index 6ea9751f563a..f5b587c51960 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -196,7 +196,7 @@ bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress(
//
class_type_or_name.Clear();
- value_type = Value::ValueType::eValueTypeScalar;
+ value_type = Value::ValueType::Scalar;
// Only a pointer or reference type can have a different dynamic and static
// type:
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
index bdd5c29db848..405b8a6f16b7 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
@@ -252,6 +252,7 @@ bool ClassDescriptorV2::method_list_t::Read(Process *process,
}
bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr,
+ lldb::addr_t relative_selector_base_addr,
bool is_small, bool has_direct_sel) {
size_t ptr_size = process->GetAddressByteSize();
size_t size = GetSize(process, is_small);
@@ -281,6 +282,8 @@ bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr,
0, error);
if (!error.Success())
return false;
+ } else if (relative_selector_base_addr != LLDB_INVALID_ADDRESS) {
+ m_name_ptr = relative_selector_base_addr + nameref_offset;
}
m_types_ptr = addr + 4 + types_offset;
m_imp_ptr = addr + 8 + imp_offset;
@@ -389,14 +392,14 @@ bool ClassDescriptorV2::Describe(
if (base_method_list->m_entsize != method_t::GetSize(process, is_small))
return false;
- std::unique_ptr<method_t> method;
- method = std::make_unique<method_t>();
-
+ std::unique_ptr<method_t> method = std::make_unique<method_t>();
+ lldb::addr_t relative_selector_base_addr =
+ m_runtime.GetRelativeSelectorBaseAddr();
for (uint32_t i = 0, e = base_method_list->m_count; i < e; ++i) {
method->Read(process,
base_method_list->m_first_ptr +
(i * base_method_list->m_entsize),
- is_small, has_direct_selector);
+ relative_selector_base_addr, is_small, has_direct_selector);
if (instance_method_func(method->m_name.c_str(), method->m_types.c_str()))
break;
@@ -514,8 +517,7 @@ uint64_t ClassDescriptorV2::GetInstanceSize() {
return 0;
}
-ClassDescriptorV2::iVarsStorage::iVarsStorage()
- : m_filled(false), m_ivars(), m_mutex() {}
+ClassDescriptorV2::iVarsStorage::iVarsStorage() : m_ivars(), m_mutex() {}
size_t ClassDescriptorV2::iVarsStorage::size() { return m_ivars.size(); }
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
index 9ef21c6e7208..7ba957940ae7 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
@@ -41,6 +41,12 @@ public:
return false;
}
+ bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr,
+ int64_t *value_bits = nullptr,
+ uint64_t *payload = nullptr) override {
+ return false;
+ }
+
uint64_t GetInstanceSize() override;
ObjCLanguageRuntime::ObjCISA GetISA() override { return m_objc_class_ptr; }
@@ -71,16 +77,14 @@ private:
static const uint32_t RW_REALIZED = (1 << 31);
struct objc_class_t {
- ObjCLanguageRuntime::ObjCISA m_isa; // The class's metaclass.
- ObjCLanguageRuntime::ObjCISA m_superclass;
- lldb::addr_t m_cache_ptr;
- lldb::addr_t m_vtable_ptr;
- lldb::addr_t m_data_ptr;
- uint8_t m_flags;
+ ObjCLanguageRuntime::ObjCISA m_isa = 0; // The class's metaclass.
+ ObjCLanguageRuntime::ObjCISA m_superclass = 0;
+ lldb::addr_t m_cache_ptr = 0;
+ lldb::addr_t m_vtable_ptr = 0;
+ lldb::addr_t m_data_ptr = 0;
+ uint8_t m_flags = 0;
- objc_class_t()
- : m_isa(0), m_superclass(0), m_cache_ptr(0), m_vtable_ptr(0),
- m_data_ptr(0), m_flags(0) {}
+ objc_class_t() = default;
void Clear() {
m_isa = 0;
@@ -162,7 +166,8 @@ private:
+ field_size; // IMP imp;
}
- bool Read(Process *process, lldb::addr_t addr, bool, bool);
+ bool Read(Process *process, lldb::addr_t addr,
+ lldb::addr_t relative_method_lists_base_addr, bool, bool);
};
struct ivar_list_t {
@@ -207,7 +212,7 @@ private:
void fill(AppleObjCRuntimeV2 &runtime, ClassDescriptorV2 &descriptor);
private:
- bool m_filled;
+ bool m_filled = false;
std::vector<iVarDescriptor> m_ivars;
std::recursive_mutex m_mutex;
};
@@ -253,7 +258,7 @@ public:
ClassDescriptorV2Tagged(
ObjCLanguageRuntime::ClassDescriptorSP actual_class_sp,
- uint64_t payload) {
+ uint64_t u_payload, int64_t s_payload) {
if (!actual_class_sp) {
m_valid = false;
return;
@@ -264,9 +269,10 @@ public:
return;
}
m_valid = true;
- m_payload = payload;
+ m_payload = u_payload;
m_info_bits = (m_payload & 0x0FULL);
m_value_bits = (m_payload & ~0x0FULL) >> 4;
+ m_value_bits_signed = (s_payload & ~0x0FLL) >> 4;
}
~ClassDescriptorV2Tagged() override = default;
@@ -308,6 +314,18 @@ public:
return true;
}
+ bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr,
+ int64_t *value_bits = nullptr,
+ uint64_t *payload = nullptr) override {
+ if (info_bits)
+ *info_bits = GetInfoBits();
+ if (value_bits)
+ *value_bits = GetValueBitsSigned();
+ if (payload)
+ *payload = GetPayload();
+ return true;
+ }
+
uint64_t GetInstanceSize() override {
return (IsValid() ? m_pointer_size : 0);
}
@@ -319,6 +337,10 @@ public:
// these calls are not part of any formal tagged pointers specification
virtual uint64_t GetValueBits() { return (IsValid() ? m_value_bits : 0); }
+ virtual int64_t GetValueBitsSigned() {
+ return (IsValid() ? m_value_bits_signed : 0);
+ }
+
virtual uint64_t GetInfoBits() { return (IsValid() ? m_info_bits : 0); }
virtual uint64_t GetPayload() { return (IsValid() ? m_payload : 0); }
@@ -329,6 +351,7 @@ private:
bool m_valid;
uint64_t m_info_bits;
uint64_t m_value_bits;
+ int64_t m_value_bits_signed;
uint64_t m_payload;
};
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
index 7b331307c0f7..9bc40c16e5d0 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
@@ -59,7 +59,7 @@ public:
clang::DeclContext::lookup_result result =
non_const_interface_decl->lookup(name);
- return (result.size() != 0);
+ return (!result.empty());
} while (false);
SetNoExternalVisibleDeclsForName(decl_ctx, name);
@@ -555,7 +555,7 @@ uint32_t AppleObjCDeclVendor::FindDecls(ConstString name, bool append,
if (!lookup_result.empty()) {
if (clang::ObjCInterfaceDecl *result_iface_decl =
- llvm::dyn_cast<clang::ObjCInterfaceDecl>(lookup_result[0])) {
+ llvm::dyn_cast<clang::ObjCInterfaceDecl>(*lookup_result.begin())) {
if (log) {
clang::QualType result_iface_type =
ast_ctx.getObjCInterfaceType(result_iface_decl);
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
index 973a5570c06e..88e86c51fe44 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
@@ -48,7 +48,7 @@ LLDB_PLUGIN_DEFINE(AppleObjCRuntime)
char AppleObjCRuntime::ID = 0;
-AppleObjCRuntime::~AppleObjCRuntime() {}
+AppleObjCRuntime::~AppleObjCRuntime() = default;
AppleObjCRuntime::AppleObjCRuntime(Process *process)
: ObjCLanguageRuntime(process), m_read_objc_library(false),
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
index b37e5a9a7bf9..98d0e9cf991b 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
@@ -49,7 +49,7 @@ bool AppleObjCRuntimeV1::GetDynamicTypeAndAddress(
TypeAndOrName &class_type_or_name, Address &address,
Value::ValueType &value_type) {
class_type_or_name.Clear();
- value_type = Value::ValueType::eValueTypeScalar;
+ value_type = Value::ValueType::Scalar;
if (CouldHaveDynamicValue(in_value)) {
auto class_descriptor(GetClassDescriptor(in_value));
if (class_descriptor && class_descriptor->IsValid() &&
@@ -339,8 +339,6 @@ void AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded() {
if (!objc_module_sp)
return;
- uint32_t isa_count = 0;
-
lldb::addr_t hash_table_ptr = GetISAHashTablePointer();
if (hash_table_ptr != LLDB_INVALID_ADDRESS) {
// Read the NXHashTable struct:
@@ -383,8 +381,6 @@ void AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded() {
if (bucket_isa_count == 0)
continue;
- isa_count += bucket_isa_count;
-
ObjCISA isa;
if (bucket_isa_count == 1) {
// When we only have one entry in the bucket, the bucket data
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
index 4eb7d979394b..12ee2cc53639 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
@@ -64,6 +64,12 @@ public:
return false;
}
+ bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr,
+ int64_t *value_bits = nullptr,
+ uint64_t *payload = nullptr) override {
+ return false;
+ }
+
uint64_t GetInstanceSize() override { return m_instance_size; }
ObjCISA GetISA() override { return m_isa; }
@@ -120,8 +126,7 @@ protected:
class HashTableSignature {
public:
- HashTableSignature()
- : m_count(0), m_num_buckets(0), m_buckets_ptr(LLDB_INVALID_ADDRESS) {}
+ HashTableSignature() = default;
bool NeedsUpdate(uint32_t count, uint32_t num_buckets,
lldb::addr_t buckets_ptr) {
@@ -137,9 +142,9 @@ protected:
}
protected:
- uint32_t m_count;
- uint32_t m_num_buckets;
- lldb::addr_t m_buckets_ptr;
+ uint32_t m_count = 0;
+ uint32_t m_num_buckets = 0;
+ lldb::addr_t m_buckets_ptr = LLDB_INVALID_ADDRESS;
};
lldb::addr_t GetISAHashTablePointer();
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index ee84ccd869fc..10512a97ad69 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <stdint.h>
+#include <cstdint>
#include <memory>
#include <string>
@@ -39,6 +39,7 @@
#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ABI.h"
+#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
@@ -75,8 +76,7 @@ char AppleObjCRuntimeV2::ID = 0;
static const char *g_get_dynamic_class_info_name =
"__lldb_apple_objc_v2_get_dynamic_class_info";
-// Testing using the new C++11 raw string literals. If this breaks GCC then we
-// will need to revert to the code above...
+
static const char *g_get_dynamic_class_info_body = R"(
extern "C"
@@ -121,14 +121,20 @@ __lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr
if (grc)
{
const unsigned num_classes = grc->num_classes;
+ DEBUG_PRINTF ("num_classes = %u\n", grc->num_classes);
if (class_infos_ptr)
{
+ const unsigned num_buckets_minus_one = grc->num_buckets_minus_one;
+ DEBUG_PRINTF ("num_buckets_minus_one = %u\n", num_buckets_minus_one);
+
const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
+ DEBUG_PRINTF ("max_class_infos = %u\n", max_class_infos);
+
ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
BucketInfo *buckets = (BucketInfo *)grc->buckets;
-
+
uint32_t idx = 0;
- for (unsigned i=0; i<=grc->num_buckets_minus_one; ++i)
+ for (unsigned i=0; i<=num_buckets_minus_one; ++i)
{
if (buckets[i].name_ptr != NX_MAPNOTAKEY)
{
@@ -140,6 +146,7 @@ __lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr
h = ((h << 5) + h) + c;
class_infos[idx].hash = h;
class_infos[idx].isa = buckets[i].isa;
+ DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, buckets[i].name_ptr);
}
++idx;
}
@@ -157,6 +164,75 @@ __lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr
)";
+static const char *g_get_dynamic_class_info2_name =
+ "__lldb_apple_objc_v2_get_dynamic_class_info2";
+
+static const char *g_get_dynamic_class_info2_body = R"(
+
+extern "C" {
+ int printf(const char * format, ...);
+ void free(void *ptr);
+ Class* objc_copyRealizedClassList_nolock(unsigned int *outCount);
+ const char* objc_debug_class_getNameRaw(Class cls);
+}
+
+#define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__)
+
+struct ClassInfo
+{
+ Class isa;
+ uint32_t hash;
+} __attribute__((__packed__));
+
+uint32_t
+__lldb_apple_objc_v2_get_dynamic_class_info2(void *gdb_objc_realized_classes_ptr,
+ void *class_infos_ptr,
+ uint32_t class_infos_byte_size,
+ uint32_t should_log)
+{
+ DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
+ DEBUG_PRINTF ("class_infos_byte_size = %u\n", class_infos_byte_size);
+
+ const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
+ DEBUG_PRINTF ("max_class_infos = %u\n", max_class_infos);
+
+ ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
+
+ uint32_t count = 0;
+ Class* realized_class_list = objc_copyRealizedClassList_nolock(&count);
+ DEBUG_PRINTF ("count = %u\n", count);
+
+ uint32_t idx = 0;
+ for (uint32_t i=0; i<=count; ++i)
+ {
+ if (idx < max_class_infos)
+ {
+ Class isa = realized_class_list[i];
+ const char *name_ptr = objc_debug_class_getNameRaw(isa);
+ if (name_ptr == NULL)
+ continue;
+ const char *s = name_ptr;
+ uint32_t h = 5381;
+ for (unsigned char c = *s; c; c = *++s)
+ h = ((h << 5) + h) + c;
+ class_infos[idx].hash = h;
+ class_infos[idx].isa = isa;
+ DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name_ptr);
+ }
+ idx++;
+ }
+
+ if (idx < max_class_infos)
+ {
+ class_infos[idx].isa = NULL;
+ class_infos[idx].hash = 0;
+ }
+
+ free(realized_class_list);
+ return count;
+}
+)";
+
// We'll substitute in class_getName or class_getNameRaw depending
// on which is present.
static const char *g_shared_cache_class_name_funcptr = R"(
@@ -169,8 +245,7 @@ extern "C"
static const char *g_get_shared_cache_class_info_name =
"__lldb_apple_objc_v2_get_shared_cache_class_info";
-// Testing using the new C++11 raw string literals. If this breaks GCC then we
-// will need to revert to the code above...
+
static const char *g_get_shared_cache_class_info_body = R"(
extern "C"
@@ -188,6 +263,12 @@ struct objc_classheader_t {
int32_t hiOffset;
};
+struct objc_classheader_v16_t {
+ uint64_t isDuplicate : 1,
+ objectCacheOffset : 47, // Offset from the shared cache base
+ dylibObjCIndex : 16;
+};
+
struct objc_clsopt_t {
uint32_t capacity;
uint32_t occupied;
@@ -205,6 +286,22 @@ struct objc_clsopt_t {
// objc_classheader_t duplicateOffsets[duplicateCount];
};
+struct objc_clsopt_v16_t {
+ uint32_t version;
+ uint32_t capacity;
+ uint32_t occupied;
+ uint32_t shift;
+ uint32_t mask;
+ uint64_t salt;
+ uint32_t scramble[256];
+ uint8_t tab[0]; // tab[mask+1]
+ // uint8_t checkbytes[capacity];
+ // int32_t offset[capacity];
+ // objc_classheader_t clsOffsets[capacity];
+ // uint32_t duplicateCount;
+ // objc_classheader_t duplicateOffsets[duplicateCount];
+};
+
struct objc_opt_t {
uint32_t version;
int32_t selopt_offset;
@@ -220,6 +317,20 @@ struct objc_opt_v14_t {
int32_t clsopt_offset;
};
+struct objc_opt_v16_t {
+ uint32_t version;
+ uint32_t flags;
+ int32_t selopt_offset;
+ int32_t headeropt_ro_offset;
+ int32_t unused_clsopt_offset;
+ int32_t unused_protocolopt_offset;
+ int32_t headeropt_rw_offset;
+ int32_t unused_protocolopt2_offset;
+ int32_t largeSharedCachesClassOffset;
+ int32_t largeSharedCachesProtocolOffset;
+ uint64_t relativeMethodSelectorBaseAddressCacheOffset;
+};
+
struct ClassInfo
{
Class isa;
@@ -228,20 +339,33 @@ struct ClassInfo
uint32_t
__lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
+ void *shared_cache_base_ptr,
void *class_infos_ptr,
+ uint64_t *relative_selector_offset,
uint32_t class_infos_byte_size,
uint32_t should_log)
{
+ *relative_selector_offset = 0;
uint32_t idx = 0;
DEBUG_PRINTF ("objc_opt_ro_ptr = %p\n", objc_opt_ro_ptr);
+ DEBUG_PRINTF ("shared_cache_base_ptr = %p\n", shared_cache_base_ptr);
DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
DEBUG_PRINTF ("class_infos_byte_size = %u (%llu class infos)\n", class_infos_byte_size, (uint64_t)(class_infos_byte_size/sizeof(ClassInfo)));
if (objc_opt_ro_ptr)
{
const objc_opt_t *objc_opt = (objc_opt_t *)objc_opt_ro_ptr;
const objc_opt_v14_t* objc_opt_v14 = (objc_opt_v14_t*)objc_opt_ro_ptr;
- const bool is_v14_format = objc_opt->version >= 14;
- if (is_v14_format)
+ const objc_opt_v16_t* objc_opt_v16 = (objc_opt_v16_t*)objc_opt_ro_ptr;
+ if (objc_opt->version >= 16)
+ {
+ *relative_selector_offset = objc_opt_v16->relativeMethodSelectorBaseAddressCacheOffset;
+ DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt_v16->version);
+ DEBUG_PRINTF ("objc_opt->flags = %u\n", objc_opt_v16->flags);
+ DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt_v16->selopt_offset);
+ DEBUG_PRINTF ("objc_opt->headeropt_ro_offset = %d\n", objc_opt_v16->headeropt_ro_offset);
+ DEBUG_PRINTF ("objc_opt->relativeMethodSelectorBaseAddressCacheOffset = %d\n", *relative_selector_offset);
+ }
+ else if (objc_opt->version >= 14)
{
DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt_v14->version);
DEBUG_PRINTF ("objc_opt->flags = %u\n", objc_opt_v14->flags);
@@ -256,10 +380,126 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt->headeropt_offset);
DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt->clsopt_offset);
}
- if (objc_opt->version == 12 || objc_opt->version == 13 || objc_opt->version == 14 || objc_opt->version == 15)
+
+ if (objc_opt->version == 16)
+ {
+ const objc_clsopt_v16_t* clsopt = (const objc_clsopt_v16_t*)((uint8_t *)objc_opt + objc_opt_v16->largeSharedCachesClassOffset);
+ const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
+
+ DEBUG_PRINTF("max_class_infos = %llu\n", (uint64_t)max_class_infos);
+
+ ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
+
+ const uint8_t *checkbytes = &clsopt->tab[clsopt->mask+1];
+ const int32_t *offsets = (const int32_t *)(checkbytes + clsopt->capacity);
+ const objc_classheader_v16_t *classOffsets = (const objc_classheader_v16_t *)(offsets + clsopt->capacity);
+
+ DEBUG_PRINTF ("clsopt->capacity = %u\n", clsopt->capacity);
+ DEBUG_PRINTF ("clsopt->mask = 0x%8.8x\n", clsopt->mask);
+ DEBUG_PRINTF ("classOffsets = %p\n", classOffsets);
+
+ for (uint32_t i=0; i<clsopt->capacity; ++i)
+ {
+ const uint64_t objectCacheOffset = classOffsets[i].objectCacheOffset;
+ DEBUG_PRINTF("objectCacheOffset[%u] = %u\n", i, objectCacheOffset);
+
+ if (classOffsets[i].isDuplicate) {
+ DEBUG_PRINTF("isDuplicate = true\n");
+ continue; // duplicate
+ }
+
+ if (objectCacheOffset == 0) {
+ DEBUG_PRINTF("objectCacheOffset == invalidEntryOffset\n");
+ continue; // invalid offset
+ }
+
+ if (class_infos && idx < max_class_infos)
+ {
+ class_infos[idx].isa = (Class)((uint8_t *)shared_cache_base_ptr + objectCacheOffset);
+
+ // Lookup the class name.
+ const char *name = class_name_lookup_func(class_infos[idx].isa);
+ DEBUG_PRINTF("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
+
+ // Hash the class name so we don't have to read it.
+ const char *s = name;
+ uint32_t h = 5381;
+ for (unsigned char c = *s; c; c = *++s)
+ {
+ // class_getName demangles swift names and the hash must
+ // be calculated on the mangled name. hash==0 means lldb
+ // will fetch the mangled name and compute the hash in
+ // ParseClassInfoArray.
+ if (c == '.')
+ {
+ h = 0;
+ break;
+ }
+ h = ((h << 5) + h) + c;
+ }
+ class_infos[idx].hash = h;
+ }
+ else
+ {
+ DEBUG_PRINTF("not(class_infos && idx < max_class_infos)\n");
+ }
+ ++idx;
+ }
+
+ const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity];
+ const uint32_t duplicate_count = *duplicate_count_ptr;
+ const objc_classheader_v16_t *duplicateClassOffsets = (const objc_classheader_v16_t *)(&duplicate_count_ptr[1]);
+
+ DEBUG_PRINTF ("duplicate_count = %u\n", duplicate_count);
+ DEBUG_PRINTF ("duplicateClassOffsets = %p\n", duplicateClassOffsets);
+
+ for (uint32_t i=0; i<duplicate_count; ++i)
+ {
+ const uint64_t objectCacheOffset = classOffsets[i].objectCacheOffset;
+ DEBUG_PRINTF("objectCacheOffset[%u] = %u\n", i, objectCacheOffset);
+
+ if (classOffsets[i].isDuplicate) {
+ DEBUG_PRINTF("isDuplicate = true\n");
+ continue; // duplicate
+ }
+
+ if (objectCacheOffset == 0) {
+ DEBUG_PRINTF("objectCacheOffset == invalidEntryOffset\n");
+ continue; // invalid offset
+ }
+
+ if (class_infos && idx < max_class_infos)
+ {
+ class_infos[idx].isa = (Class)((uint8_t *)shared_cache_base_ptr + objectCacheOffset);
+
+ // Lookup the class name.
+ const char *name = class_name_lookup_func(class_infos[idx].isa);
+ DEBUG_PRINTF("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
+
+ // Hash the class name so we don't have to read it.
+ const char *s = name;
+ uint32_t h = 5381;
+ for (unsigned char c = *s; c; c = *++s)
+ {
+ // class_getName demangles swift names and the hash must
+ // be calculated on the mangled name. hash==0 means lldb
+ // will fetch the mangled name and compute the hash in
+ // ParseClassInfoArray.
+ if (c == '.')
+ {
+ h = 0;
+ break;
+ }
+ h = ((h << 5) + h) + c;
+ }
+ class_infos[idx].hash = h;
+ }
+ }
+ }
+ else if (objc_opt->version >= 12 && objc_opt->version <= 15)
{
const objc_clsopt_t* clsopt = NULL;
- if (is_v14_format)
+ if (objc_opt->version >= 14)
clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt_v14 + objc_opt_v14->clsopt_offset);
else
clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt + objc_opt->clsopt_offset);
@@ -291,7 +531,7 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
DEBUG_PRINTF("clsOffset == invalidEntryOffset\n");
continue; // invalid offset
}
-
+
if (class_infos && idx < max_class_infos)
{
class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
@@ -321,7 +561,7 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
}
++idx;
}
-
+
const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity];
const uint32_t duplicate_count = *duplicate_count_ptr;
const objc_classheader_t *duplicateClassOffsets = (const objc_classheader_t *)(&duplicate_count_ptr[1]);
@@ -334,7 +574,7 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
continue; // duplicate
else if (clsOffset == invalidEntryOffset)
continue; // invalid offset
-
+
if (class_infos && idx < max_class_infos)
{
class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
@@ -353,7 +593,7 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
{
h = 0;
break;
- }
+ }
h = ((h << 5) + h) + c;
}
class_infos[idx].hash = h;
@@ -380,55 +620,57 @@ ExtractRuntimeGlobalSymbol(Process *process, ConstString name,
error.SetErrorString("no process");
return default_value;
}
+
if (!module_sp) {
error.SetErrorString("no module");
return default_value;
}
+
if (!byte_size)
byte_size = process->GetAddressByteSize();
const Symbol *symbol =
module_sp->FindFirstSymbolWithNameAndType(name, lldb::eSymbolTypeData);
- if (symbol && symbol->ValueIsAddress()) {
- lldb::addr_t symbol_load_addr =
- symbol->GetAddressRef().GetLoadAddress(&process->GetTarget());
- if (symbol_load_addr != LLDB_INVALID_ADDRESS) {
- if (read_value)
- return process->ReadUnsignedIntegerFromMemory(
- symbol_load_addr, byte_size, default_value, error);
- else
- return symbol_load_addr;
- } else {
- error.SetErrorString("symbol address invalid");
- return default_value;
- }
- } else {
+
+ if (!symbol || !symbol->ValueIsAddress()) {
error.SetErrorString("no symbol");
return default_value;
}
+
+ lldb::addr_t symbol_load_addr =
+ symbol->GetAddressRef().GetLoadAddress(&process->GetTarget());
+ if (symbol_load_addr == LLDB_INVALID_ADDRESS) {
+ error.SetErrorString("symbol address invalid");
+ return default_value;
+ }
+
+ if (read_value)
+ return process->ReadUnsignedIntegerFromMemory(symbol_load_addr, byte_size,
+ default_value, error);
+ return symbol_load_addr;
}
static void RegisterObjCExceptionRecognizer(Process *process);
AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process,
const ModuleSP &objc_module_sp)
- : AppleObjCRuntime(process), m_get_class_info_code(),
- m_get_class_info_args(LLDB_INVALID_ADDRESS),
- m_get_class_info_args_mutex(), m_get_shared_cache_class_info_code(),
- m_get_shared_cache_class_info_args(LLDB_INVALID_ADDRESS),
- m_get_shared_cache_class_info_args_mutex(), m_decl_vendor_up(),
+ : AppleObjCRuntime(process), m_objc_module_sp(objc_module_sp),
+ m_dynamic_class_info_extractor(*this),
+ m_shared_cache_class_info_extractor(*this), m_decl_vendor_up(),
m_tagged_pointer_obfuscator(LLDB_INVALID_ADDRESS),
- m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS), m_hash_signature(),
- m_has_object_getClass(false), m_loaded_objc_opt(false),
- m_non_pointer_isa_cache_up(
- NonPointerISACache::CreateInstance(*this, objc_module_sp)),
+ m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS),
+ m_relative_selector_base(LLDB_INVALID_ADDRESS), m_hash_signature(),
+ m_has_object_getClass(false), m_has_objc_copyRealizedClassList(false),
+ m_loaded_objc_opt(false), m_non_pointer_isa_cache_up(),
m_tagged_pointer_vendor_up(
TaggedPointerVendorV2::CreateInstance(*this, objc_module_sp)),
m_encoding_to_type_sp(), m_noclasses_warning_emitted(false),
- m_CFBoolean_values() {
+ m_CFBoolean_values(), m_realized_class_generation_count(0) {
static const ConstString g_gdb_object_getClass("gdb_object_getClass");
- m_has_object_getClass =
- (objc_module_sp->FindFirstSymbolWithNameAndType(
- g_gdb_object_getClass, eSymbolTypeCode) != nullptr);
+ m_has_object_getClass = HasSymbol(g_gdb_object_getClass);
+ static const ConstString g_objc_copyRealizedClassList(
+ "_ZL33objc_copyRealizedClassList_nolockPj");
+ m_has_objc_copyRealizedClassList = HasSymbol(g_objc_copyRealizedClassList);
+
RegisterObjCExceptionRecognizer(process);
}
@@ -451,7 +693,7 @@ bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress(
assert(in_value.GetTargetSP().get() == m_process->CalculateTarget().get());
class_type_or_name.Clear();
- value_type = Value::ValueType::eValueTypeScalar;
+ value_type = Value::ValueType::Scalar;
// Make sure we can have a dynamic value before starting...
if (CouldHaveDynamicValue(in_value)) {
@@ -498,15 +740,21 @@ LanguageRuntime *AppleObjCRuntimeV2::CreateInstance(Process *process,
if (AppleObjCRuntime::GetObjCVersion(process, objc_module_sp) ==
ObjCRuntimeVersions::eAppleObjC_V2)
return new AppleObjCRuntimeV2(process, objc_module_sp);
- else
- return nullptr;
- } else
return nullptr;
+ }
+ return nullptr;
}
static constexpr OptionDefinition g_objc_classtable_dump_options[] = {
- {LLDB_OPT_SET_ALL, false, "verbose", 'v', OptionParser::eNoArgument,
- nullptr, {}, 0, eArgTypeNone,
+ {LLDB_OPT_SET_ALL,
+ false,
+ "verbose",
+ 'v',
+ OptionParser::eNoArgument,
+ nullptr,
+ {},
+ 0,
+ eArgTypeNone,
"Print ivar and method information in detail"}};
class CommandObjectObjC_ClassTable_Dump : public CommandObjectParsed {
@@ -548,12 +796,13 @@ public:
};
CommandObjectObjC_ClassTable_Dump(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "dump", "Dump information on Objective-C classes "
- "known to the current process.",
- "language objc class-table dump",
- eCommandRequiresProcess | eCommandProcessMustBeLaunched |
- eCommandProcessMustBePaused),
+ : CommandObjectParsed(interpreter, "dump",
+ "Dump information on Objective-C classes "
+ "known to the current process.",
+ "language objc class-table dump",
+ eCommandRequiresProcess |
+ eCommandProcessMustBeLaunched |
+ eCommandProcessMustBePaused),
m_options() {
CommandArgumentEntry arg;
CommandArgumentData index_arg;
@@ -581,8 +830,8 @@ protected:
case 0:
break;
case 1: {
- regex_up = std::make_unique<RegularExpression>(
- llvm::StringRef::withNullAsEmpty(command.GetArgumentAtIndex(0)));
+ regex_up =
+ std::make_unique<RegularExpression>(command.GetArgumentAtIndex(0));
if (!regex_up->IsValid()) {
result.AppendError(
"invalid argument - please provide a valid regular expression");
@@ -632,6 +881,7 @@ protected:
ivar.m_type.GetDisplayTypeName().AsCString("<unknown>"),
ivar.m_size, ivar.m_offset);
}
+
iterator->second->Describe(
nullptr,
[&std_out](const char *name, const char *type) -> bool {
@@ -655,11 +905,10 @@ protected:
}
result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
return true;
- } else {
- result.AppendError("current process has no Objective-C runtime loaded");
- result.SetStatus(lldb::eReturnStatusFailed);
- return false;
}
+ result.AppendError("current process has no Objective-C runtime loaded");
+ result.SetStatus(lldb::eReturnStatusFailed);
+ return false;
}
CommandOptions m_options;
@@ -741,11 +990,10 @@ protected:
}
result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
return true;
- } else {
- result.AppendError("current process has no Objective-C runtime loaded");
- result.SetStatus(lldb::eReturnStatusFailed);
- return false;
}
+ result.AppendError("current process has no Objective-C runtime loaded");
+ result.SetStatus(lldb::eReturnStatusFailed);
+ return false;
}
};
@@ -951,11 +1199,7 @@ bool AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr) {
class RemoteNXMapTable {
public:
- RemoteNXMapTable()
- : m_count(0), m_num_buckets_minus_one(0),
- m_buckets_ptr(LLDB_INVALID_ADDRESS), m_process(nullptr),
- m_end_iterator(*this, -1), m_load_addr(LLDB_INVALID_ADDRESS),
- m_map_pair_size(0), m_invalid_key(0) {}
+ RemoteNXMapTable() : m_end_iterator(*this, -1) {}
void Dump() {
printf("RemoteNXMapTable.m_load_addr = 0x%" PRIx64 "\n", m_load_addr);
@@ -1129,18 +1373,17 @@ public:
private:
// contents of _NXMapTable struct
- uint32_t m_count;
- uint32_t m_num_buckets_minus_one;
- lldb::addr_t m_buckets_ptr;
- lldb_private::Process *m_process;
+ uint32_t m_count = 0;
+ uint32_t m_num_buckets_minus_one = 0;
+ lldb::addr_t m_buckets_ptr = LLDB_INVALID_ADDRESS;
+ lldb_private::Process *m_process = nullptr;
const_iterator m_end_iterator;
- lldb::addr_t m_load_addr;
- size_t m_map_pair_size;
- lldb::addr_t m_invalid_key;
+ lldb::addr_t m_load_addr = LLDB_INVALID_ADDRESS;
+ size_t m_map_pair_size = 0;
+ lldb::addr_t m_invalid_key = 0;
};
-AppleObjCRuntimeV2::HashTableSignature::HashTableSignature()
- : m_count(0), m_num_buckets(0), m_buckets_ptr(0) {}
+AppleObjCRuntimeV2::HashTableSignature::HashTableSignature() = default;
void AppleObjCRuntimeV2::HashTableSignature::UpdateSignature(
const RemoteNXMapTable &hash_table) {
@@ -1171,8 +1414,8 @@ bool AppleObjCRuntimeV2::HashTableSignature::NeedsUpdate(
ObjCLanguageRuntime::ClassDescriptorSP
AppleObjCRuntimeV2::GetClassDescriptorFromISA(ObjCISA isa) {
ObjCLanguageRuntime::ClassDescriptorSP class_descriptor_sp;
- if (m_non_pointer_isa_cache_up)
- class_descriptor_sp = m_non_pointer_isa_cache_up->GetClassDescriptor(isa);
+ if (auto *non_pointer_isa_cache = GetNonPointerIsaCache())
+ class_descriptor_sp = non_pointer_isa_cache->GetClassDescriptor(isa);
if (!class_descriptor_sp)
class_descriptor_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA(isa);
return class_descriptor_sp;
@@ -1214,11 +1457,9 @@ AppleObjCRuntimeV2::GetClassDescriptor(ValueObject &valobj) {
objc_class_sp = GetClassDescriptorFromISA(isa);
if (isa && !objc_class_sp) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_TYPES));
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
LLDB_LOGF(log,
- "0x%" PRIx64
- ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was "
+ "0x%" PRIx64 ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was "
"not in class descriptor cache 0x%" PRIx64,
isa_pointer, isa);
}
@@ -1229,28 +1470,29 @@ lldb::addr_t AppleObjCRuntimeV2::GetTaggedPointerObfuscator() {
if (m_tagged_pointer_obfuscator != LLDB_INVALID_ADDRESS)
return m_tagged_pointer_obfuscator;
-
Process *process = GetProcess();
ModuleSP objc_module_sp(GetObjCModule());
if (!objc_module_sp)
return LLDB_INVALID_ADDRESS;
- static ConstString g_gdb_objc_obfuscator("objc_debug_taggedpointer_obfuscator");
+ static ConstString g_gdb_objc_obfuscator(
+ "objc_debug_taggedpointer_obfuscator");
const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(
- g_gdb_objc_obfuscator, lldb::eSymbolTypeAny);
+ g_gdb_objc_obfuscator, lldb::eSymbolTypeAny);
if (symbol) {
lldb::addr_t g_gdb_obj_obfuscator_ptr =
- symbol->GetLoadAddress(&process->GetTarget());
+ symbol->GetLoadAddress(&process->GetTarget());
if (g_gdb_obj_obfuscator_ptr != LLDB_INVALID_ADDRESS) {
Status error;
- m_tagged_pointer_obfuscator = process->ReadPointerFromMemory(
- g_gdb_obj_obfuscator_ptr, error);
+ m_tagged_pointer_obfuscator =
+ process->ReadPointerFromMemory(g_gdb_obj_obfuscator_ptr, error);
}
}
- // If we don't have a correct value at this point, there must be no obfuscation.
+ // If we don't have a correct value at this point, there must be no
+ // obfuscation.
if (m_tagged_pointer_obfuscator == LLDB_INVALID_ADDRESS)
m_tagged_pointer_obfuscator = 0;
@@ -1284,11 +1526,212 @@ lldb::addr_t AppleObjCRuntimeV2::GetISAHashTablePointer() {
return m_isa_hash_table_ptr;
}
+std::unique_ptr<UtilityFunction>
+AppleObjCRuntimeV2::DynamicClassInfoExtractor::GetClassInfoUtilityFunctionImpl(
+ ExecutionContext &exe_ctx, std::string code, std::string name) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
+
+ LLDB_LOG(log, "Creating utility function {0}", name);
+
+ TypeSystemClang *ast =
+ ScratchTypeSystemClang::GetForTarget(exe_ctx.GetTargetRef());
+ if (!ast)
+ return {};
+
+ auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction(
+ std::move(code), std::move(name), eLanguageTypeC, exe_ctx);
+ if (!utility_fn_or_error) {
+ LLDB_LOG_ERROR(
+ log, utility_fn_or_error.takeError(),
+ "Failed to get utility function for implementation lookup: {0}");
+ return {};
+ }
+
+ // Make some types for our arguments.
+ CompilerType clang_uint32_t_type =
+ ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
+ CompilerType clang_void_pointer_type =
+ ast->GetBasicType(eBasicTypeVoid).GetPointerType();
+
+ // Make the runner function for our implementation utility function.
+ ValueList arguments;
+ Value value;
+ value.SetValueType(Value::ValueType::Scalar);
+ value.SetCompilerType(clang_void_pointer_type);
+ arguments.PushValue(value);
+ arguments.PushValue(value);
+ value.SetValueType(Value::ValueType::Scalar);
+ value.SetCompilerType(clang_uint32_t_type);
+ arguments.PushValue(value);
+ arguments.PushValue(value);
+
+ std::unique_ptr<UtilityFunction> utility_fn = std::move(*utility_fn_or_error);
+
+ Status error;
+ utility_fn->MakeFunctionCaller(clang_uint32_t_type, arguments,
+ exe_ctx.GetThreadSP(), error);
+
+ if (error.Fail()) {
+ LLDB_LOG(log,
+ "Failed to make function caller for implementation lookup: {0}.",
+ error.AsCString());
+ return {};
+ }
+
+ return utility_fn;
+}
+
+UtilityFunction *
+AppleObjCRuntimeV2::DynamicClassInfoExtractor::GetClassInfoUtilityFunction(
+ ExecutionContext &exe_ctx, Helper helper) {
+ switch (helper) {
+ case gdb_objc_realized_classes: {
+ if (!m_gdb_objc_realized_classes_helper.utility_function)
+ m_gdb_objc_realized_classes_helper.utility_function =
+ GetClassInfoUtilityFunctionImpl(exe_ctx,
+ g_get_dynamic_class_info_body,
+ g_get_dynamic_class_info_name);
+ return m_gdb_objc_realized_classes_helper.utility_function.get();
+ }
+ case objc_copyRealizedClassList: {
+ if (!m_objc_copyRealizedClassList_helper.utility_function)
+ m_objc_copyRealizedClassList_helper.utility_function =
+ GetClassInfoUtilityFunctionImpl(exe_ctx,
+ g_get_dynamic_class_info2_body,
+ g_get_dynamic_class_info2_name);
+ return m_objc_copyRealizedClassList_helper.utility_function.get();
+ }
+ }
+ llvm_unreachable("Unexpected helper");
+}
+
+lldb::addr_t &
+AppleObjCRuntimeV2::DynamicClassInfoExtractor::GetClassInfoArgs(Helper helper) {
+ switch (helper) {
+ case gdb_objc_realized_classes:
+ return m_gdb_objc_realized_classes_helper.args;
+ case objc_copyRealizedClassList:
+ return m_objc_copyRealizedClassList_helper.args;
+ }
+ llvm_unreachable("Unexpected helper");
+}
+
+AppleObjCRuntimeV2::DynamicClassInfoExtractor::Helper
+AppleObjCRuntimeV2::DynamicClassInfoExtractor::ComputeHelper() const {
+ if (!m_runtime.m_has_objc_copyRealizedClassList)
+ return DynamicClassInfoExtractor::gdb_objc_realized_classes;
+
+ if (Process *process = m_runtime.GetProcess()) {
+ if (DynamicLoader *loader = process->GetDynamicLoader()) {
+ if (loader->IsFullyInitialized())
+ return DynamicClassInfoExtractor::objc_copyRealizedClassList;
+ }
+ }
+
+ return DynamicClassInfoExtractor::gdb_objc_realized_classes;
+}
+
+std::unique_ptr<UtilityFunction>
+AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::
+ GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
+
+ LLDB_LOG(log, "Creating utility function {0}",
+ g_get_shared_cache_class_info_name);
+
+ TypeSystemClang *ast =
+ ScratchTypeSystemClang::GetForTarget(exe_ctx.GetTargetRef());
+ if (!ast)
+ return {};
+
+ // If the inferior objc.dylib has the class_getNameRaw function, use that in
+ // our jitted expression. Else fall back to the old class_getName.
+ static ConstString g_class_getName_symbol_name("class_getName");
+ static ConstString g_class_getNameRaw_symbol_name(
+ "objc_debug_class_getNameRaw");
+
+ ConstString class_name_getter_function_name =
+ m_runtime.HasSymbol(g_class_getNameRaw_symbol_name)
+ ? g_class_getNameRaw_symbol_name
+ : g_class_getName_symbol_name;
+
+ // 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.
+ 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());
+
+ shared_class_expression += g_get_shared_cache_class_info_body;
+
+ auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction(
+ std::move(shared_class_expression), g_get_shared_cache_class_info_name,
+ eLanguageTypeC, exe_ctx);
+
+ if (!utility_fn_or_error) {
+ LLDB_LOG_ERROR(
+ log, utility_fn_or_error.takeError(),
+ "Failed to get utility function for implementation lookup: {0}");
+ return nullptr;
+ }
+
+ // Make some types for our arguments.
+ CompilerType clang_uint32_t_type =
+ ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
+ CompilerType clang_void_pointer_type =
+ ast->GetBasicType(eBasicTypeVoid).GetPointerType();
+ CompilerType clang_uint64_t_pointer_type =
+ ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 64)
+ .GetPointerType();
+
+ // Next make the function caller for our implementation utility function.
+ ValueList arguments;
+ Value value;
+ value.SetValueType(Value::ValueType::Scalar);
+ value.SetCompilerType(clang_void_pointer_type);
+ arguments.PushValue(value);
+ arguments.PushValue(value);
+ arguments.PushValue(value);
+
+ value.SetValueType(Value::ValueType::Scalar);
+ value.SetCompilerType(clang_uint64_t_pointer_type);
+ arguments.PushValue(value);
+
+ value.SetValueType(Value::ValueType::Scalar);
+ value.SetCompilerType(clang_uint32_t_type);
+ arguments.PushValue(value);
+ arguments.PushValue(value);
+
+ std::unique_ptr<UtilityFunction> utility_fn = std::move(*utility_fn_or_error);
+
+ Status error;
+ utility_fn->MakeFunctionCaller(clang_uint32_t_type, arguments,
+ exe_ctx.GetThreadSP(), error);
+
+ if (error.Fail()) {
+ LLDB_LOG(log,
+ "Failed to make function caller for implementation lookup: {0}.",
+ error.AsCString());
+ return {};
+ }
+
+ return utility_fn;
+}
+
+UtilityFunction *
+AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::GetClassInfoUtilityFunction(
+ ExecutionContext &exe_ctx) {
+ if (!m_utility_function)
+ m_utility_function = GetClassInfoUtilityFunctionImpl(exe_ctx);
+ return m_utility_function.get();
+}
+
AppleObjCRuntimeV2::DescriptorMapUpdateResult
-AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
+AppleObjCRuntimeV2::DynamicClassInfoExtractor::UpdateISAToDescriptorMap(
RemoteNXMapTable &hash_table) {
- Process *process = GetProcess();
-
+ Process *process = m_runtime.GetProcess();
if (process == nullptr)
return DescriptorMapUpdateResult::Fail();
@@ -1316,65 +1759,36 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
Status err;
+ // Compute which helper we're going to use for this update.
+ const DynamicClassInfoExtractor::Helper helper = ComputeHelper();
+
// Read the total number of classes from the hash table
- const uint32_t num_classes = hash_table.GetCount();
+ const uint32_t num_classes =
+ helper == DynamicClassInfoExtractor::gdb_objc_realized_classes
+ ? hash_table.GetCount()
+ : m_runtime.m_realized_class_generation_count;
if (num_classes == 0) {
- LLDB_LOGF(log, "No dynamic classes found in gdb_objc_realized_classes.");
+ LLDB_LOGF(log, "No dynamic classes found.");
return DescriptorMapUpdateResult::Success(0);
}
- // Make some types for our arguments
- CompilerType clang_uint32_t_type =
- ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
- CompilerType clang_void_pointer_type =
- ast->GetBasicType(eBasicTypeVoid).GetPointerType();
-
- ValueList arguments;
- FunctionCaller *get_class_info_function = nullptr;
-
- if (!m_get_class_info_code) {
- auto utility_fn_or_error = GetTargetRef().CreateUtilityFunction(
- g_get_dynamic_class_info_body, g_get_dynamic_class_info_name,
- eLanguageTypeC, exe_ctx);
- if (!utility_fn_or_error) {
- LLDB_LOG_ERROR(
- log, utility_fn_or_error.takeError(),
- "Failed to get utility function for implementation lookup: {0}");
- return DescriptorMapUpdateResult::Fail();
- }
- m_get_class_info_code = std::move(*utility_fn_or_error);
-
- // Next make the runner function for our implementation utility function.
- Value value;
- value.SetValueType(Value::eValueTypeScalar);
- value.SetCompilerType(clang_void_pointer_type);
- arguments.PushValue(value);
- arguments.PushValue(value);
-
- value.SetValueType(Value::eValueTypeScalar);
- value.SetCompilerType(clang_uint32_t_type);
- arguments.PushValue(value);
- arguments.PushValue(value);
+ UtilityFunction *get_class_info_code =
+ GetClassInfoUtilityFunction(exe_ctx, helper);
+ if (!get_class_info_code) {
+ // The callee will have already logged a useful error message.
+ return DescriptorMapUpdateResult::Fail();
+ }
- Status error;
- get_class_info_function = m_get_class_info_code->MakeFunctionCaller(
- clang_uint32_t_type, arguments, thread_sp, error);
+ FunctionCaller *get_class_info_function =
+ get_class_info_code->GetFunctionCaller();
- if (error.Fail()) {
- LLDB_LOGF(log,
- "Failed to make function caller for implementation lookup: %s.",
- error.AsCString());
- return DescriptorMapUpdateResult::Fail();
- }
- } else {
- get_class_info_function = m_get_class_info_code->GetFunctionCaller();
- if (!get_class_info_function) {
- LLDB_LOGF(log, "Failed to get implementation lookup function caller.");
- return DescriptorMapUpdateResult::Fail();
- }
- arguments = get_class_info_function->GetArgumentValues();
+ if (!get_class_info_function) {
+ LLDB_LOGF(log, "Failed to get implementation lookup function caller.");
+ return DescriptorMapUpdateResult::Fail();
}
+ ValueList arguments = get_class_info_function->GetArgumentValues();
+
DiagnosticManager diagnostics;
const uint32_t class_info_byte_size = addr_size + 4;
@@ -1390,18 +1804,18 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
return DescriptorMapUpdateResult::Fail();
}
- std::lock_guard<std::mutex> guard(m_get_class_info_args_mutex);
+ std::lock_guard<std::mutex> guard(m_mutex);
// Fill in our function argument values
arguments.GetValueAtIndex(0)->GetScalar() = hash_table.GetTableLoadAddress();
arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
-
+
// Only dump the runtime classes from the expression evaluation if the log is
// verbose:
Log *type_log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES);
bool dump_log = type_log && type_log->GetVerbose();
-
+
arguments.GetValueAtIndex(3)->GetScalar() = dump_log ? 1 : 0;
bool success = false;
@@ -1410,7 +1824,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
// Write our function arguments into the process so we can run our function
if (get_class_info_function->WriteFunctionArguments(
- exe_ctx, m_get_class_info_args, arguments, diagnostics)) {
+ exe_ctx, GetClassInfoArgs(helper), arguments, diagnostics)) {
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
options.SetTryAllThreads(false);
@@ -1419,8 +1833,11 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
options.SetTimeout(process->GetUtilityExpressionTimeout());
options.SetIsForUtilityExpr(true);
+ CompilerType clang_uint32_t_type =
+ ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
+
Value return_value;
- return_value.SetValueType(Value::eValueTypeScalar);
+ return_value.SetValueType(Value::ValueType::Scalar);
return_value.SetCompilerType(clang_uint32_t_type);
return_value.GetScalar() = 0;
@@ -1428,12 +1845,12 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
// Run the function
ExpressionResults results = get_class_info_function->ExecuteFunction(
- exe_ctx, &m_get_class_info_args, options, diagnostics, return_value);
+ exe_ctx, &GetClassInfoArgs(helper), options, diagnostics, return_value);
if (results == eExpressionCompleted) {
// The result is the number of ClassInfo structures that were filled in
num_class_infos = return_value.GetScalar().ULong();
- LLDB_LOGF(log, "Discovered %u ObjC classes\n", num_class_infos);
+ LLDB_LOG(log, "Discovered {0} Objective-C classes", num_class_infos);
if (num_class_infos > 0) {
// Read the ClassInfo structures
DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0);
@@ -1443,7 +1860,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
DataExtractor class_infos_data(buffer.GetBytes(),
buffer.GetByteSize(),
process->GetByteOrder(), addr_size);
- ParseClassInfoArray(class_infos_data, num_class_infos);
+ m_runtime.ParseClassInfoArray(class_infos_data, num_class_infos);
}
}
success = true;
@@ -1507,15 +1924,16 @@ uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data,
ClassDescriptorSP descriptor_sp(
new ClassDescriptorV2(*this, isa, nullptr));
- // The code in g_get_shared_cache_class_info_body sets the value of the hash
- // to 0 to signal a demangled symbol. We use class_getName() in that code to
- // find the class name, but this returns a demangled name for Swift symbols.
- // For those symbols, recompute the hash here by reading their name from the
- // runtime.
+ // The code in g_get_shared_cache_class_info_body sets the value of the
+ // hash to 0 to signal a demangled symbol. We use class_getName() in that
+ // code to find the class name, but this returns a demangled name for
+ // Swift symbols. For those symbols, recompute the hash here by reading
+ // their name from the runtime.
if (name_hash)
AddClass(isa, descriptor_sp, name_hash);
else
- AddClass(isa, descriptor_sp, descriptor_sp->GetClassName().AsCString(nullptr));
+ AddClass(isa, descriptor_sp,
+ descriptor_sp->GetClassName().AsCString(nullptr));
num_parsed++;
if (should_log)
LLDB_LOGF(log,
@@ -1531,10 +1949,20 @@ uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data,
return num_parsed;
}
-AppleObjCRuntimeV2::DescriptorMapUpdateResult
-AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
- Process *process = GetProcess();
+bool AppleObjCRuntimeV2::HasSymbol(ConstString Name) {
+ if (!m_objc_module_sp)
+ return false;
+ if (const Symbol *symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType(
+ Name, lldb::eSymbolTypeCode)) {
+ if (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())
+ return true;
+ }
+ return false;
+}
+AppleObjCRuntimeV2::DescriptorMapUpdateResult
+AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::UpdateISAToDescriptorMap() {
+ Process *process = m_runtime.GetProcess();
if (process == nullptr)
return DescriptorMapUpdateResult::Fail();
@@ -1562,103 +1990,38 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
uint32_t num_class_infos = 0;
- const lldb::addr_t objc_opt_ptr = GetSharedCacheReadOnlyAddress();
+ const lldb::addr_t objc_opt_ptr = m_runtime.GetSharedCacheReadOnlyAddress();
+ const lldb::addr_t shared_cache_base_addr =
+ m_runtime.GetSharedCacheBaseAddress();
- if (objc_opt_ptr == LLDB_INVALID_ADDRESS)
+ if (objc_opt_ptr == LLDB_INVALID_ADDRESS ||
+ shared_cache_base_addr == LLDB_INVALID_ADDRESS)
return DescriptorMapUpdateResult::Fail();
const uint32_t num_classes = 128 * 1024;
- // Make some types for our arguments
- CompilerType clang_uint32_t_type =
- ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
- CompilerType clang_void_pointer_type =
- ast->GetBasicType(eBasicTypeVoid).GetPointerType();
-
- ValueList arguments;
- FunctionCaller *get_shared_cache_class_info_function = nullptr;
-
- if (!m_get_shared_cache_class_info_code) {
- Status error;
-
- // If the inferior objc.dylib has the class_getNameRaw function,
- // use that in our jitted expression. Else fall back to the old
- // class_getName.
- static ConstString g_class_getName_symbol_name("class_getName");
- static ConstString g_class_getNameRaw_symbol_name("objc_debug_class_getNameRaw");
- ConstString class_name_getter_function_name = g_class_getName_symbol_name;
-
- ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process);
- if (objc_runtime) {
- for (lldb::ModuleSP mod_sp : process->GetTarget().GetImages().Modules()) {
- if (objc_runtime->IsModuleObjCLibrary(mod_sp)) {
- const Symbol *symbol =
- mod_sp->FindFirstSymbolWithNameAndType(g_class_getNameRaw_symbol_name,
- lldb::eSymbolTypeCode);
- if (symbol &&
- (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())) {
- class_name_getter_function_name = g_class_getNameRaw_symbol_name;
- }
- }
- }
- }
-
- // 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.
- 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());
-
- shared_class_expression += g_get_shared_cache_class_info_body;
-
- auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction(
- std::move(shared_class_expression), g_get_shared_cache_class_info_name,
- eLanguageTypeC, exe_ctx);
- if (!utility_fn_or_error) {
- LLDB_LOG_ERROR(
- log, utility_fn_or_error.takeError(),
- "Failed to get utility function for implementation lookup: {0}");
- return DescriptorMapUpdateResult::Fail();
- }
-
- m_get_shared_cache_class_info_code = std::move(*utility_fn_or_error);
-
- // Next make the function caller for our implementation utility function.
- Value value;
- value.SetValueType(Value::eValueTypeScalar);
- value.SetCompilerType(clang_void_pointer_type);
- arguments.PushValue(value);
- arguments.PushValue(value);
-
- value.SetValueType(Value::eValueTypeScalar);
- value.SetCompilerType(clang_uint32_t_type);
- arguments.PushValue(value);
- arguments.PushValue(value);
-
- get_shared_cache_class_info_function =
- m_get_shared_cache_class_info_code->MakeFunctionCaller(
- clang_uint32_t_type, arguments, thread_sp, error);
+ UtilityFunction *get_class_info_code = GetClassInfoUtilityFunction(exe_ctx);
+ FunctionCaller *get_shared_cache_class_info_function =
+ get_class_info_code->GetFunctionCaller();
- if (get_shared_cache_class_info_function == nullptr)
- return DescriptorMapUpdateResult::Fail();
-
- } else {
- get_shared_cache_class_info_function =
- m_get_shared_cache_class_info_code->GetFunctionCaller();
- if (get_shared_cache_class_info_function == nullptr)
- return DescriptorMapUpdateResult::Fail();
- arguments = get_shared_cache_class_info_function->GetArgumentValues();
+ if (!get_shared_cache_class_info_function) {
+ LLDB_LOGF(log, "Failed to get implementation lookup function caller.");
+ return DescriptorMapUpdateResult::Fail();
}
+ ValueList arguments =
+ get_shared_cache_class_info_function->GetArgumentValues();
+
DiagnosticManager diagnostics;
const uint32_t class_info_byte_size = addr_size + 4;
const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
lldb::addr_t class_infos_addr = process->AllocateMemory(
class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err);
+ const uint32_t relative_selector_offset_addr_size = 64;
+ lldb::addr_t relative_selector_offset_addr =
+ process->AllocateMemory(relative_selector_offset_addr_size,
+ ePermissionsReadable | ePermissionsWritable, err);
if (class_infos_addr == LLDB_INVALID_ADDRESS) {
LLDB_LOGF(log,
@@ -1668,18 +2031,20 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
return DescriptorMapUpdateResult::Fail();
}
- std::lock_guard<std::mutex> guard(m_get_shared_cache_class_info_args_mutex);
+ std::lock_guard<std::mutex> guard(m_mutex);
// Fill in our function argument values
arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr;
- arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
- arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
+ arguments.GetValueAtIndex(1)->GetScalar() = shared_cache_base_addr;
+ arguments.GetValueAtIndex(2)->GetScalar() = class_infos_addr;
+ arguments.GetValueAtIndex(3)->GetScalar() = relative_selector_offset_addr;
+ arguments.GetValueAtIndex(4)->GetScalar() = class_infos_byte_size;
// Only dump the runtime classes from the expression evaluation if the log is
// verbose:
Log *type_log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES);
bool dump_log = type_log && type_log->GetVerbose();
-
- arguments.GetValueAtIndex(3)->GetScalar() = dump_log ? 1 : 0;
+
+ arguments.GetValueAtIndex(5)->GetScalar() = dump_log ? 1 : 0;
bool success = false;
@@ -1687,8 +2052,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
// Write our function arguments into the process so we can run our function
if (get_shared_cache_class_info_function->WriteFunctionArguments(
- exe_ctx, m_get_shared_cache_class_info_args, arguments,
- diagnostics)) {
+ exe_ctx, m_args, arguments, diagnostics)) {
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
options.SetTryAllThreads(false);
@@ -1697,8 +2061,11 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
options.SetTimeout(process->GetUtilityExpressionTimeout());
options.SetIsForUtilityExpr(true);
+ CompilerType clang_uint32_t_type =
+ ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
+
Value return_value;
- return_value.SetValueType(Value::eValueTypeScalar);
+ return_value.SetValueType(Value::ValueType::Scalar);
return_value.SetCompilerType(clang_uint32_t_type);
return_value.GetScalar() = 0;
@@ -1707,14 +2074,13 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
// Run the function
ExpressionResults results =
get_shared_cache_class_info_function->ExecuteFunction(
- exe_ctx, &m_get_shared_cache_class_info_args, options, diagnostics,
- return_value);
+ exe_ctx, &m_args, options, diagnostics, return_value);
if (results == eExpressionCompleted) {
// The result is the number of ClassInfo structures that were filled in
num_class_infos = return_value.GetScalar().ULong();
- LLDB_LOGF(log, "Discovered %u ObjC classes in shared cache\n",
- num_class_infos);
+ LLDB_LOG(log, "Discovered {0} Objective-C classes in the shared cache",
+ num_class_infos);
assert(num_class_infos <= num_classes);
if (num_class_infos > 0) {
if (num_class_infos > num_classes) {
@@ -1725,16 +2091,38 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
success = true;
}
+ // Read the relative selector offset.
+ DataBufferHeap relative_selector_offset_buffer(64, 0);
+ if (process->ReadMemory(relative_selector_offset_addr,
+ relative_selector_offset_buffer.GetBytes(),
+ relative_selector_offset_buffer.GetByteSize(),
+ err) ==
+ relative_selector_offset_buffer.GetByteSize()) {
+ DataExtractor relative_selector_offset_data(
+ relative_selector_offset_buffer.GetBytes(),
+ relative_selector_offset_buffer.GetByteSize(),
+ process->GetByteOrder(), addr_size);
+ lldb::offset_t offset = 0;
+ uint64_t relative_selector_offset =
+ relative_selector_offset_data.GetU64(&offset);
+ if (relative_selector_offset > 0) {
+ // The offset is relative to the objc_opt struct.
+ m_runtime.SetRelativeSelectorBaseAddr(objc_opt_ptr +
+ relative_selector_offset);
+ }
+ }
+
// Read the ClassInfo structures
- DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0);
- if (process->ReadMemory(class_infos_addr, buffer.GetBytes(),
- buffer.GetByteSize(),
- err) == buffer.GetByteSize()) {
- DataExtractor class_infos_data(buffer.GetBytes(),
- buffer.GetByteSize(),
+ DataBufferHeap class_infos_buffer(
+ num_class_infos * class_info_byte_size, 0);
+ if (process->ReadMemory(class_infos_addr, class_infos_buffer.GetBytes(),
+ class_infos_buffer.GetByteSize(),
+ err) == class_infos_buffer.GetByteSize()) {
+ DataExtractor class_infos_data(class_infos_buffer.GetBytes(),
+ class_infos_buffer.GetByteSize(),
process->GetByteOrder(), addr_size);
- ParseClassInfoArray(class_infos_data, num_class_infos);
+ m_runtime.ParseClassInfoArray(class_infos_data, num_class_infos);
}
} else {
success = true;
@@ -1758,42 +2146,6 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
return DescriptorMapUpdateResult(success, num_class_infos);
}
-bool AppleObjCRuntimeV2::UpdateISAToDescriptorMapFromMemory(
- RemoteNXMapTable &hash_table) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
-
- Process *process = GetProcess();
-
- if (process == nullptr)
- return false;
-
- uint32_t num_map_table_isas = 0;
-
- ModuleSP objc_module_sp(GetObjCModule());
-
- if (objc_module_sp) {
- for (RemoteNXMapTable::element elt : hash_table) {
- ++num_map_table_isas;
-
- if (ISAIsCached(elt.second))
- continue;
-
- ClassDescriptorSP descriptor_sp = ClassDescriptorSP(
- new ClassDescriptorV2(*this, elt.second, elt.first.AsCString()));
-
- if (log && log->GetVerbose())
- LLDB_LOGF(log,
- "AppleObjCRuntimeV2 added (ObjCISA)0x%" PRIx64
- " (%s) from dynamic table to isa->descriptor cache",
- elt.second, elt.first.AsCString());
-
- AddClass(elt.second, descriptor_sp, elt.first.AsCString());
- }
- }
-
- return num_map_table_isas > 0;
-}
-
lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress() {
Process *process = GetProcess();
@@ -1827,6 +2179,19 @@ lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress() {
return LLDB_INVALID_ADDRESS;
}
+lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheBaseAddress() {
+ StructuredData::ObjectSP info = m_process->GetSharedCacheInfo();
+ if (!info)
+ return LLDB_INVALID_ADDRESS;
+
+ StructuredData::Dictionary *info_dict = info->GetAsDictionary();
+ if (!info_dict)
+ return LLDB_INVALID_ADDRESS;
+
+ return info_dict->GetValueForKey("shared_cache_base_address")
+ ->GetIntegerValue(LLDB_INVALID_ADDRESS);
+}
+
void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() {
LLDB_SCOPED_TIMER();
@@ -1842,14 +2207,19 @@ void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() {
// map, whether it was successful or not.
m_isa_to_descriptor_stop_id = process->GetStopID();
- if (!m_hash_signature.NeedsUpdate(process, this, hash_table))
+ // Ask the runtime is the realized class generation count changed. Unlike
+ // the hash table, this accounts for lazily named classes.
+ const bool class_count_changed = RealizedClassGenerationCountChanged();
+
+ if (!m_hash_signature.NeedsUpdate(process, this, hash_table) &&
+ !class_count_changed)
return;
m_hash_signature.UpdateSignature(hash_table);
- // Grab the dynamically loaded objc classes from the hash table in memory
+ // Grab the dynamically loaded Objective-C classes from memory.
DescriptorMapUpdateResult dynamic_update_result =
- UpdateISAToDescriptorMapDynamic(hash_table);
+ m_dynamic_class_info_extractor.UpdateISAToDescriptorMap(hash_table);
// Now get the objc classes that are baked into the Objective-C runtime in
// the shared cache, but only once per process as this data never changes
@@ -1865,7 +2235,7 @@ void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() {
const uint32_t num_classes_to_warn_at = 500;
DescriptorMapUpdateResult shared_cache_update_result =
- UpdateISAToDescriptorMapSharedCache();
+ m_shared_cache_class_info_extractor.UpdateISAToDescriptorMap();
LLDB_LOGF(log,
"attempted to read objc class data - results: "
@@ -1895,6 +2265,35 @@ void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() {
}
}
+bool AppleObjCRuntimeV2::RealizedClassGenerationCountChanged() {
+ Process *process = GetProcess();
+ if (!process)
+ return false;
+
+ Status error;
+ uint64_t objc_debug_realized_class_generation_count =
+ ExtractRuntimeGlobalSymbol(
+ process, ConstString("objc_debug_realized_class_generation_count"),
+ GetObjCModule(), error);
+ if (error.Fail())
+ return false;
+
+ if (m_realized_class_generation_count ==
+ objc_debug_realized_class_generation_count)
+ return false;
+
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
+ LLDB_LOG(log,
+ "objc_debug_realized_class_generation_count changed from {0} to {1}",
+ m_realized_class_generation_count,
+ objc_debug_realized_class_generation_count);
+
+ m_realized_class_generation_count =
+ objc_debug_realized_class_generation_count;
+
+ return true;
+}
+
static bool DoesProcessHaveSharedCache(Process &process) {
PlatformSP platform_sp = process.GetTarget().GetPlatform();
if (!platform_sp)
@@ -1975,9 +2374,10 @@ lldb::addr_t AppleObjCRuntimeV2::LookupRuntimeSymbol(ConstString name) {
const ConstString ivar_name_cs(class_and_ivar.second);
const char *ivar_name_cstr = ivar_name_cs.AsCString();
- auto ivar_func = [&ret, ivar_name_cstr](
- const char *name, const char *type, lldb::addr_t offset_addr,
- uint64_t size) -> lldb::addr_t {
+ auto ivar_func = [&ret,
+ ivar_name_cstr](const char *name, const char *type,
+ lldb::addr_t offset_addr,
+ uint64_t size) -> lldb::addr_t {
if (!strcmp(name, ivar_name_cstr)) {
ret = offset_addr;
return true;
@@ -2279,7 +2679,6 @@ ObjCLanguageRuntime::ClassDescriptorSP
AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(
lldb::addr_t ptr) {
ClassDescriptorSP actual_class_descriptor_sp;
- uint64_t data_payload;
uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator();
if (!IsPossibleTaggedPointer(unobfuscated))
@@ -2307,12 +2706,15 @@ AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(
m_cache[slot] = actual_class_descriptor_sp;
}
- data_payload =
+ uint64_t data_payload =
(((uint64_t)unobfuscated << m_objc_debug_taggedpointer_payload_lshift) >>
m_objc_debug_taggedpointer_payload_rshift);
-
- return ClassDescriptorSP(
- new ClassDescriptorV2Tagged(actual_class_descriptor_sp, data_payload));
+ int64_t data_payload_signed =
+ ((int64_t)((int64_t)unobfuscated
+ << m_objc_debug_taggedpointer_payload_lshift) >>
+ m_objc_debug_taggedpointer_payload_rshift);
+ return ClassDescriptorSP(new ClassDescriptorV2Tagged(
+ actual_class_descriptor_sp, data_payload, data_payload_signed));
}
AppleObjCRuntimeV2::TaggedPointerVendorExtended::TaggedPointerVendorExtended(
@@ -2364,7 +2766,6 @@ ObjCLanguageRuntime::ClassDescriptorSP
AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor(
lldb::addr_t ptr) {
ClassDescriptorSP actual_class_descriptor_sp;
- uint64_t data_payload;
uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator();
if (!IsPossibleTaggedPointer(unobfuscated))
@@ -2395,12 +2796,16 @@ AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor(
m_ext_cache[slot] = actual_class_descriptor_sp;
}
- data_payload =
- (((uint64_t)unobfuscated << m_objc_debug_taggedpointer_ext_payload_lshift) >>
+ uint64_t data_payload = (((uint64_t)unobfuscated
+ << m_objc_debug_taggedpointer_ext_payload_lshift) >>
+ m_objc_debug_taggedpointer_ext_payload_rshift);
+ int64_t data_payload_signed =
+ ((int64_t)((int64_t)unobfuscated
+ << m_objc_debug_taggedpointer_ext_payload_lshift) >>
m_objc_debug_taggedpointer_ext_payload_rshift);
- return ClassDescriptorSP(
- new ClassDescriptorV2Tagged(actual_class_descriptor_sp, data_payload));
+ return ClassDescriptorSP(new ClassDescriptorV2Tagged(
+ actual_class_descriptor_sp, data_payload, data_payload_signed));
}
AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache(
@@ -2552,8 +2957,8 @@ lldb_private::AppleObjCRuntime::ObjCISA
AppleObjCRuntimeV2::GetPointerISA(ObjCISA isa) {
ObjCISA ret = isa;
- if (m_non_pointer_isa_cache_up)
- m_non_pointer_isa_cache_up->EvaluateNonPointerISA(isa, ret);
+ if (auto *non_pointer_isa_cache = GetNonPointerIsaCache())
+ non_pointer_isa_cache->EvaluateNonPointerISA(isa, ret);
return ret;
}
@@ -2598,13 +3003,14 @@ void AppleObjCRuntimeV2::GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,
#pragma mark Frame recognizers
class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame {
- public:
+public:
ObjCExceptionRecognizedStackFrame(StackFrameSP frame_sp) {
ThreadSP thread_sp = frame_sp->GetThread();
ProcessSP process_sp = thread_sp->GetProcess();
const lldb::ABISP &abi = process_sp->GetABI();
- if (!abi) return;
+ if (!abi)
+ return;
TypeSystemClang *clang_ast_context =
ScratchTypeSystemClang::GetForTarget(process_sp->GetTarget());
@@ -2618,7 +3024,8 @@ class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame {
input_value.SetCompilerType(voidstar);
args.PushValue(input_value);
- if (!abi->GetArgumentValues(*thread_sp, args)) return;
+ if (!abi->GetArgumentValues(*thread_sp, args))
+ return;
addr_t exception_addr = args.GetValueAtIndex(0)->GetScalar().ULongLong();
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
index c6fb6ea26b98..d0caa2969115 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
@@ -26,7 +26,6 @@ class AppleObjCRuntimeV2 : public AppleObjCRuntime {
public:
~AppleObjCRuntimeV2() override = default;
- // Static Functions
static void Initialize();
static void Terminate();
@@ -46,7 +45,6 @@ public:
return runtime->isA(&ID);
}
- // These are generic runtime functions:
bool GetDynamicTypeAndAddress(ValueObject &in_value,
lldb::DynamicValueType use_dynamic,
TypeAndOrName &class_type_or_name,
@@ -56,7 +54,6 @@ public:
llvm::Expected<std::unique_ptr<UtilityFunction>>
CreateObjectChecker(std::string name, ExecutionContext &exe_ctx) override;
- // PluginInterface protocol
ConstString GetPluginName() override;
uint32_t GetPluginVersion() override;
@@ -88,6 +85,15 @@ public:
lldb::addr_t GetTaggedPointerObfuscator();
+ /// Returns the base address for relative method list selector strings.
+ lldb::addr_t GetRelativeSelectorBaseAddr() {
+ return m_relative_selector_base;
+ }
+
+ void SetRelativeSelectorBaseAddr(lldb::addr_t relative_selector_base) {
+ m_relative_selector_base = relative_selector_base;
+ }
+
void GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,
lldb::addr_t &cf_false) override;
@@ -105,8 +111,8 @@ public:
protected:
lldb::BreakpointResolverSP
- CreateExceptionResolver(const lldb::BreakpointSP &bkpt,
- bool catch_bp, bool throw_bp) override;
+ CreateExceptionResolver(const lldb::BreakpointSP &bkpt, bool catch_bp,
+ bool throw_bp) override;
private:
class HashTableSignature {
@@ -119,9 +125,9 @@ private:
void UpdateSignature(const RemoteNXMapTable &hash_table);
protected:
- uint32_t m_count;
- uint32_t m_num_buckets;
- lldb::addr_t m_buckets_ptr;
+ uint32_t m_count = 0;
+ uint32_t m_num_buckets = 0;
+ lldb::addr_t m_buckets_ptr = 0;
};
class NonPointerISACache {
@@ -296,22 +302,99 @@ private:
}
};
+ /// Abstraction to read the Objective-C class info.
+ class ClassInfoExtractor {
+ public:
+ ClassInfoExtractor(AppleObjCRuntimeV2 &runtime) : m_runtime(runtime) {}
+ std::mutex &GetMutex() { return m_mutex; }
+
+ protected:
+ /// The lifetime of this object is tied to that of the runtime.
+ AppleObjCRuntimeV2 &m_runtime;
+ std::mutex m_mutex;
+ };
+
+ /// We can read the class info from the Objective-C runtime using
+ /// gdb_objc_realized_classes or objc_copyRealizedClassList. The latter is
+ /// preferred because it includes lazily named classes, but it's not always
+ /// available or safe to call.
+ ///
+ /// We potentially need both for the same process, because we may need to use
+ /// gdb_objc_realized_classes until dyld is initialized and then switch over
+ /// to objc_copyRealizedClassList for lazily named classes.
+ class DynamicClassInfoExtractor : public ClassInfoExtractor {
+ public:
+ DynamicClassInfoExtractor(AppleObjCRuntimeV2 &runtime)
+ : ClassInfoExtractor(runtime) {}
+
+ DescriptorMapUpdateResult
+ UpdateISAToDescriptorMap(RemoteNXMapTable &hash_table);
+
+ private:
+ enum Helper { gdb_objc_realized_classes, objc_copyRealizedClassList };
+
+ /// Compute which helper to use. Prefer objc_copyRealizedClassList if it's
+ /// available and it's safe to call (i.e. dyld is fully initialized). Use
+ /// gdb_objc_realized_classes otherwise.
+ Helper ComputeHelper() const;
+
+ UtilityFunction *GetClassInfoUtilityFunction(ExecutionContext &exe_ctx,
+ Helper helper);
+ lldb::addr_t &GetClassInfoArgs(Helper helper);
+
+ std::unique_ptr<UtilityFunction>
+ GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx, std::string code,
+ std::string name);
+
+ /// Helper to read class info using the gdb_objc_realized_classes.
+ struct gdb_objc_realized_classes_helper {
+ std::unique_ptr<UtilityFunction> utility_function;
+ lldb::addr_t args = LLDB_INVALID_ADDRESS;
+ };
+
+ /// Helper to read class info using objc_copyRealizedClassList.
+ struct objc_copyRealizedClassList_helper {
+ std::unique_ptr<UtilityFunction> utility_function;
+ lldb::addr_t args = LLDB_INVALID_ADDRESS;
+ };
+
+ gdb_objc_realized_classes_helper m_gdb_objc_realized_classes_helper;
+ objc_copyRealizedClassList_helper m_objc_copyRealizedClassList_helper;
+ };
+
+ /// Abstraction to read the Objective-C class info from the shared cache.
+ class SharedCacheClassInfoExtractor : public ClassInfoExtractor {
+ public:
+ SharedCacheClassInfoExtractor(AppleObjCRuntimeV2 &runtime)
+ : ClassInfoExtractor(runtime) {}
+
+ DescriptorMapUpdateResult UpdateISAToDescriptorMap();
+
+ private:
+ UtilityFunction *GetClassInfoUtilityFunction(ExecutionContext &exe_ctx);
+
+ std::unique_ptr<UtilityFunction>
+ GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx);
+
+ std::unique_ptr<UtilityFunction> m_utility_function;
+ lldb::addr_t m_args = LLDB_INVALID_ADDRESS;
+ };
+
AppleObjCRuntimeV2(Process *process, const lldb::ModuleSP &objc_module_sp);
ObjCISA GetPointerISA(ObjCISA isa);
lldb::addr_t GetISAHashTablePointer();
- bool UpdateISAToDescriptorMapFromMemory(RemoteNXMapTable &hash_table);
-
- DescriptorMapUpdateResult
- UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table);
+ /// Update the generation count of realized classes. This is not an exact
+ /// count but rather a value that is incremented when new classes are realized
+ /// or destroyed. Unlike the count in gdb_objc_realized_classes, it will
+ /// change when lazily named classes get realized.
+ bool RealizedClassGenerationCountChanged();
uint32_t ParseClassInfoArray(const lldb_private::DataExtractor &data,
uint32_t num_class_infos);
- DescriptorMapUpdateResult UpdateISAToDescriptorMapSharedCache();
-
enum class SharedCacheWarningReason {
eExpressionExecutionFailure,
eNotEnoughClassesRead
@@ -320,30 +403,40 @@ private:
void WarnIfNoClassesCached(SharedCacheWarningReason reason);
lldb::addr_t GetSharedCacheReadOnlyAddress();
+ lldb::addr_t GetSharedCacheBaseAddress();
bool GetCFBooleanValuesIfNeeded();
+ bool HasSymbol(ConstString Name);
+
+ NonPointerISACache *GetNonPointerIsaCache() {
+ if (!m_non_pointer_isa_cache_up)
+ m_non_pointer_isa_cache_up.reset(
+ NonPointerISACache::CreateInstance(*this, m_objc_module_sp));
+ return m_non_pointer_isa_cache_up.get();
+ }
+
friend class ClassDescriptorV2;
- std::unique_ptr<UtilityFunction> m_get_class_info_code;
- lldb::addr_t m_get_class_info_args;
- std::mutex m_get_class_info_args_mutex;
+ lldb::ModuleSP m_objc_module_sp;
- std::unique_ptr<UtilityFunction> m_get_shared_cache_class_info_code;
- lldb::addr_t m_get_shared_cache_class_info_args;
- std::mutex m_get_shared_cache_class_info_args_mutex;
+ DynamicClassInfoExtractor m_dynamic_class_info_extractor;
+ SharedCacheClassInfoExtractor m_shared_cache_class_info_extractor;
std::unique_ptr<DeclVendor> m_decl_vendor_up;
lldb::addr_t m_tagged_pointer_obfuscator;
lldb::addr_t m_isa_hash_table_ptr;
+ lldb::addr_t m_relative_selector_base;
HashTableSignature m_hash_signature;
bool m_has_object_getClass;
+ bool m_has_objc_copyRealizedClassList;
bool m_loaded_objc_opt;
std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_up;
std::unique_ptr<TaggedPointerVendor> m_tagged_pointer_vendor_up;
EncodingToTypeSP m_encoding_to_type_sp;
bool m_noclasses_warning_emitted;
llvm::Optional<std::pair<lldb::addr_t, lldb::addr_t>> m_CFBoolean_values;
+ uint64_t m_realized_class_generation_count;
};
} // namespace lldb_private
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
index bcc1f6fd339f..aa6306bef8b9 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
@@ -285,7 +285,7 @@ AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::VTableRegion(
SetUpRegion();
}
-AppleObjCTrampolineHandler::~AppleObjCTrampolineHandler() {}
+AppleObjCTrampolineHandler::~AppleObjCTrampolineHandler() = default;
void AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::SetUpRegion() {
// The header looks like:
@@ -526,7 +526,7 @@ bool AppleObjCTrampolineHandler::AppleObjCVTables::RefreshTrampolines(
CompilerType clang_void_ptr_type =
clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
- input_value.SetValueType(Value::eValueTypeScalar);
+ input_value.SetValueType(Value::ValueType::Scalar);
// input_value.SetContext (Value::eContextTypeClangType,
// clang_void_ptr_type);
input_value.SetCompilerType(clang_void_ptr_type);
@@ -936,7 +936,7 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
Value void_ptr_value;
CompilerType clang_void_ptr_type =
clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
- void_ptr_value.SetValueType(Value::eValueTypeScalar);
+ void_ptr_value.SetValueType(Value::ValueType::Scalar);
// void_ptr_value.SetContext (Value::eContextTypeClangType,
// clang_void_ptr_type);
void_ptr_value.SetCompilerType(clang_void_ptr_type);
@@ -1048,7 +1048,7 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
Value isa_value(*(argument_values.GetValueAtIndex(obj_index)));
- isa_value.SetValueType(Value::eValueTypeLoadAddress);
+ isa_value.SetValueType(Value::ValueType::LoadAddress);
isa_value.ResolveValue(&exe_ctx);
if (isa_value.GetScalar().IsValid()) {
isa_addr = isa_value.GetScalar().ULongLong();
@@ -1110,7 +1110,7 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
CompilerType clang_int_type =
clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(
lldb::eEncodingSint, 32);
- flag_value.SetValueType(Value::eValueTypeScalar);
+ flag_value.SetValueType(Value::ValueType::Scalar);
// flag_value.SetContext (Value::eContextTypeClangType, clang_int_type);
flag_value.SetCompilerType(clang_int_type);
@@ -1157,13 +1157,8 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
flag_value.GetScalar() = 0; // FIXME - Set to 0 when debugging is done.
dispatch_values.PushValue(flag_value);
- // The step through code might have to fill in the cache, so it
- // is not safe to run only one thread. So we override the
- // stop_others value passed in to us here:
- const bool trampoline_stop_others = false;
ret_plan_sp = std::make_shared<AppleThreadPlanStepThroughObjCTrampoline>(
- thread, *this, dispatch_values, isa_addr, sel_addr,
- trampoline_stop_others);
+ thread, *this, dispatch_values, isa_addr, sel_addr);
if (log) {
StreamString s;
ret_plan_sp->GetDescription(&s, eDescriptionLevelFull);
@@ -1182,13 +1177,9 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
MsgsendMap::iterator pos;
pos = m_opt_dispatch_map.find(curr_pc);
if (pos != m_opt_dispatch_map.end()) {
-
const char *opt_name = g_opt_dispatch_names[(*pos).second];
-
- bool trampoline_stop_others = false;
- LazyBool step_in_should_stop = eLazyBoolCalculate;
- ret_plan_sp = std::make_shared<AppleThreadPlanStepThroughDirectDispatch> (
- thread, *this, opt_name, trampoline_stop_others, step_in_should_stop);
+ ret_plan_sp = std::make_shared<AppleThreadPlanStepThroughDirectDispatch>(
+ thread, *this, opt_name);
}
}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
index 27aebd8594df..546b500b4529 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
@@ -76,10 +76,7 @@ private:
class VTableRegion {
public:
- VTableRegion()
- : m_valid(false), m_owner(nullptr),
- m_header_addr(LLDB_INVALID_ADDRESS), m_code_start_addr(0),
- m_code_end_addr(0), m_next_region(0) {}
+ VTableRegion() = default;
VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr);
@@ -99,13 +96,13 @@ private:
void Dump(Stream &s);
- bool m_valid;
- AppleObjCVTables *m_owner;
- lldb::addr_t m_header_addr;
- lldb::addr_t m_code_start_addr;
- lldb::addr_t m_code_end_addr;
+ bool m_valid = false;
+ AppleObjCVTables *m_owner = nullptr;
+ lldb::addr_t m_header_addr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t m_code_start_addr = 0;
+ lldb::addr_t m_code_end_addr = 0;
std::vector<VTableDescriptor> m_descriptors;
- lldb::addr_t m_next_region;
+ lldb::addr_t m_next_region = 0;
};
public:
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
index b19d3d90d4b7..7b0121503bc4 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
@@ -59,7 +59,7 @@ uint32_t AppleObjCTypeEncodingParser::ReadNumber(StringLexer &type) {
// "{CGRect=\"origin\"{CGPoint=\"x\"d\"y\"d}\"size\"{CGSize=\"width\"d\"height\"d}}"
AppleObjCTypeEncodingParser::StructElement::StructElement()
- : name(""), type(clang::QualType()), bitfield(0) {}
+ : name(""), type(clang::QualType()) {}
AppleObjCTypeEncodingParser::StructElement
AppleObjCTypeEncodingParser::ReadStructElement(TypeSystemClang &ast_ctx,
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
index 9a108967e1ab..6e533b591eca 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
@@ -29,7 +29,7 @@ private:
struct StructElement {
std::string name;
clang::QualType type;
- uint32_t bitfield;
+ uint32_t bitfield = 0;
StructElement();
~StructElement() = default;
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
index 653e007c7b5f..1dc8034c537a 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
@@ -30,19 +30,17 @@ using namespace lldb_private;
AppleThreadPlanStepThroughObjCTrampoline::
AppleThreadPlanStepThroughObjCTrampoline(
Thread &thread, AppleObjCTrampolineHandler &trampoline_handler,
- ValueList &input_values, lldb::addr_t isa_addr, lldb::addr_t sel_addr,
- bool stop_others)
+ ValueList &input_values, lldb::addr_t isa_addr, lldb::addr_t sel_addr)
: ThreadPlan(ThreadPlan::eKindGeneric,
"MacOSX Step through ObjC Trampoline", thread, eVoteNoOpinion,
eVoteNoOpinion),
m_trampoline_handler(trampoline_handler),
m_args_addr(LLDB_INVALID_ADDRESS), m_input_values(input_values),
- m_isa_addr(isa_addr), m_sel_addr(sel_addr), m_impl_function(nullptr),
- m_stop_others(stop_others) {}
+ m_isa_addr(isa_addr), m_sel_addr(sel_addr), m_impl_function(nullptr) {}
// Destructor
AppleThreadPlanStepThroughObjCTrampoline::
- ~AppleThreadPlanStepThroughObjCTrampoline() {}
+ ~AppleThreadPlanStepThroughObjCTrampoline() = default;
void AppleThreadPlanStepThroughObjCTrampoline::DidPush() {
// Setting up the memory space for the called function text might require
@@ -66,7 +64,7 @@ bool AppleThreadPlanStepThroughObjCTrampoline::InitializeFunctionCaller() {
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
options.SetIgnoreBreakpoints(true);
- options.SetStopOthers(m_stop_others);
+ options.SetStopOthers(false);
GetThread().CalculateExecutionContext(exc_ctx);
m_func_sp = m_impl_function->GetThreadPlanToCallFunction(
exc_ctx, m_args_addr, options, diagnostics);
@@ -157,7 +155,7 @@ bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) {
const bool first_insn = true;
const uint32_t frame_idx = 0;
m_run_to_sp = GetThread().QueueThreadPlanForStepOutNoShouldStop(
- abort_other_plans, &sc, first_insn, m_stop_others, eVoteNoOpinion,
+ abort_other_plans, &sc, first_insn, false, eVoteNoOpinion,
eVoteNoOpinion, frame_idx, status);
if (m_run_to_sp && status.Success())
m_run_to_sp->SetPrivate(true);
@@ -179,7 +177,7 @@ bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) {
// Extract the target address from the value:
m_run_to_sp = std::make_shared<ThreadPlanRunToAddress>(
- GetThread(), target_so_addr, m_stop_others);
+ GetThread(), target_so_addr, false);
PushPlan(m_run_to_sp);
return false;
} else if (GetThread().IsThreadPlanDone(m_run_to_sp.get())) {
@@ -222,10 +220,9 @@ bool AppleThreadPlanStepThroughObjCTrampoline::WillStop() { return true; }
AppleThreadPlanStepThroughDirectDispatch ::
AppleThreadPlanStepThroughDirectDispatch(
Thread &thread, AppleObjCTrampolineHandler &handler,
- llvm::StringRef dispatch_func_name, bool stop_others,
- LazyBool step_in_avoids_code_without_debug_info)
- : ThreadPlanStepOut(thread, nullptr, true /* first instruction */,
- stop_others, eVoteNoOpinion, eVoteNoOpinion,
+ llvm::StringRef dispatch_func_name)
+ : ThreadPlanStepOut(thread, nullptr, true /* first instruction */, false,
+ eVoteNoOpinion, eVoteNoOpinion,
0 /* Step out of zeroth frame */,
eLazyBoolNo /* Our parent plan will decide this
when we are done */
@@ -234,7 +231,7 @@ AppleThreadPlanStepThroughDirectDispatch ::
false /* Don't gather the return value */),
m_trampoline_handler(handler),
m_dispatch_func_name(std::string(dispatch_func_name)),
- m_at_msg_send(false), m_stop_others(stop_others) {
+ m_at_msg_send(false) {
// Set breakpoints on the dispatch functions:
auto bkpt_callback = [&] (lldb::addr_t addr,
const AppleObjCTrampolineHandler
@@ -249,20 +246,7 @@ AppleThreadPlanStepThroughDirectDispatch ::
// We'll set the step-out plan in the DidPush so it gets queued in the right
// order.
- bool avoid_nodebug = true;
-
- switch (step_in_avoids_code_without_debug_info) {
- case eLazyBoolYes:
- avoid_nodebug = true;
- break;
- case eLazyBoolNo:
- avoid_nodebug = false;
- break;
- case eLazyBoolCalculate:
- avoid_nodebug = GetThread().GetStepInAvoidsNoDebug();
- break;
- }
- if (avoid_nodebug)
+ if (GetThread().GetStepInAvoidsNoDebug())
GetFlags().Set(ThreadPlanShouldStopHere::eStepInAvoidNoDebug);
else
GetFlags().Clear(ThreadPlanShouldStopHere::eStepInAvoidNoDebug);
@@ -398,8 +382,8 @@ bool AppleThreadPlanStepThroughDirectDispatch::ShouldStop(Event *event_ptr) {
// There's no way we could have gotten here without an ObjC language
// runtime.
assert(objc_runtime);
- m_objc_step_through_sp
- = objc_runtime->GetStepThroughTrampolinePlan(GetThread(), m_stop_others);
+ m_objc_step_through_sp =
+ objc_runtime->GetStepThroughTrampolinePlan(GetThread(), false);
// If we failed to find the target for this dispatch, just keep going and
// let the step out complete.
if (!m_objc_step_through_sp) {
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
index 89aed89f1ab1..b5b45079094c 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
@@ -24,8 +24,7 @@ class AppleThreadPlanStepThroughObjCTrampoline : public ThreadPlan {
public:
AppleThreadPlanStepThroughObjCTrampoline(
Thread &thread, AppleObjCTrampolineHandler &trampoline_handler,
- ValueList &values, lldb::addr_t isa_addr, lldb::addr_t sel_addr,
- bool stop_others);
+ ValueList &values, lldb::addr_t isa_addr, lldb::addr_t sel_addr);
~AppleThreadPlanStepThroughObjCTrampoline() override;
@@ -39,7 +38,9 @@ public:
bool ShouldStop(Event *event_ptr) override;
- bool StopOthers() override { return m_stop_others; }
+ // The step through code might have to fill in the cache, so it is not safe
+ // to run only one thread.
+ bool StopOthers() override { return false; }
// The base class MischiefManaged does some cleanup - so you have to call it
// in your MischiefManaged derived class.
@@ -69,15 +70,13 @@ private:
FunctionCaller *m_impl_function; /// This is a pointer to a impl function that
/// is owned by the client that pushes this
/// plan.
- bool m_stop_others; /// Whether we should stop other threads.
};
class AppleThreadPlanStepThroughDirectDispatch: public ThreadPlanStepOut {
public:
- AppleThreadPlanStepThroughDirectDispatch(
- Thread &thread, AppleObjCTrampolineHandler &handler,
- llvm::StringRef dispatch_func_name, bool stop_others,
- LazyBool step_in_avoids_code_without_debug_info);
+ AppleThreadPlanStepThroughDirectDispatch(Thread &thread,
+ AppleObjCTrampolineHandler &handler,
+ llvm::StringRef dispatch_func_name);
~AppleThreadPlanStepThroughDirectDispatch() override;
@@ -85,7 +84,7 @@ public:
bool ShouldStop(Event *event_ptr) override;
- bool StopOthers() override { return m_stop_others; }
+ bool StopOthers() override { return false; }
bool MischiefManaged() override;
@@ -107,7 +106,6 @@ protected:
std::vector<lldb::BreakpointSP> m_msgSend_bkpts; /// Breakpoints on the objc
/// dispatch functions.
bool m_at_msg_send; /// Are we currently handling an msg_send
- bool m_stop_others; /// Whether we should stop other threads.
};
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp
index 2ccf9b33f9d8..65bf3e6af626 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp
@@ -32,7 +32,7 @@ using namespace lldb_private;
char ObjCLanguageRuntime::ID = 0;
// Destructor
-ObjCLanguageRuntime::~ObjCLanguageRuntime() {}
+ObjCLanguageRuntime::~ObjCLanguageRuntime() = default;
ObjCLanguageRuntime::ObjCLanguageRuntime(Process *process)
: LanguageRuntime(process), m_impl_cache(),
@@ -305,7 +305,7 @@ ObjCLanguageRuntime::EncodingToType::RealizeType(const char *name,
return CompilerType();
}
-ObjCLanguageRuntime::EncodingToType::~EncodingToType() {}
+ObjCLanguageRuntime::EncodingToType::~EncodingToType() = default;
ObjCLanguageRuntime::EncodingToTypeSP ObjCLanguageRuntime::GetEncodingToType() {
return nullptr;
@@ -363,7 +363,8 @@ void ObjCLanguageRuntime::ObjCExceptionPrecondition::AddClassName(
m_class_names.insert(class_name);
}
-ObjCLanguageRuntime::ObjCExceptionPrecondition::ObjCExceptionPrecondition() {}
+ObjCLanguageRuntime::ObjCExceptionPrecondition::ObjCExceptionPrecondition() =
+ default;
bool ObjCLanguageRuntime::ObjCExceptionPrecondition::EvaluatePrecondition(
StoppointCallbackContext &context) {
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h
index 683eff777728..15fce04ea465 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h
@@ -49,9 +49,7 @@ public:
// implementations of the runtime, and more might come
class ClassDescriptor {
public:
- ClassDescriptor()
- : m_is_kvo(eLazyBoolCalculate), m_is_cf(eLazyBoolCalculate),
- m_type_wp() {}
+ ClassDescriptor() : m_type_wp() {}
virtual ~ClassDescriptor() = default;
@@ -87,10 +85,20 @@ public:
virtual bool IsValid() = 0;
+ /// There are two routines in the ObjC runtime that tagged pointer clients
+ /// can call to get the value from their tagged pointer, one that retrieves
+ /// it as an unsigned value and one a signed value. These two
+ /// GetTaggedPointerInfo methods mirror those two ObjC runtime calls.
+ /// @{
virtual bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr,
uint64_t *value_bits = nullptr,
uint64_t *payload = nullptr) = 0;
+ virtual bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr,
+ int64_t *value_bits = nullptr,
+ uint64_t *payload = nullptr) = 0;
+ /// @}
+
virtual uint64_t GetInstanceSize() = 0;
// use to implement version-specific additional constraints on pointers
@@ -135,8 +143,8 @@ public:
bool check_version_specific = false) const;
private:
- LazyBool m_is_kvo;
- LazyBool m_is_cf;
+ LazyBool m_is_kvo = eLazyBoolCalculate;
+ LazyBool m_is_cf = eLazyBoolCalculate;
lldb::TypeWP m_type_wp;
};
diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
index 6858c7134d33..08a752eaa888 100644
--- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
@@ -185,7 +185,7 @@ RSIRPasses::RSIRPasses(Process *process) {
EarlyPasses->add(new RenderScriptRuntimeModulePass(process));
}
-RSIRPasses::~RSIRPasses() {}
+RSIRPasses::~RSIRPasses() = default;
} // namespace lldb_renderscript
} // namespace lldb_private
diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
index dd9312234d8b..10ff5aa72b52 100644
--- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
@@ -61,7 +61,7 @@ namespace {
template <typename type_t> class empirical_type {
public:
// Ctor. Contents is invalid when constructed.
- empirical_type() : valid(false) {}
+ empirical_type() = default;
// Return true and copy contents to out if valid, else return false.
bool get(type_t &out) const {
@@ -99,7 +99,7 @@ public:
}
protected:
- bool valid;
+ bool valid = false;
type_t data;
};
@@ -2228,7 +2228,7 @@ bool RenderScriptRuntime::RefreshAllocation(AllocationDetails *alloc,
return JITAllocationSize(alloc, frame_ptr);
}
-// Function attempts to set the type_name member of the paramaterised Element
+// Function attempts to set the type_name member of the parameterised Element
// object. This string should be the name of the struct type the Element
// represents. We need this string for pretty printing the Element to users.
void RenderScriptRuntime::FindStructTypeName(Element &elem,
@@ -4087,9 +4087,7 @@ public:
class CommandOptions : public Options {
public:
- CommandOptions()
- : Options(),
- m_kernel_types(RSReduceBreakpointResolver::eKernelTypeAll) {}
+ CommandOptions() : Options() {}
~CommandOptions() override = default;
@@ -4175,7 +4173,7 @@ public:
return true;
}
- int m_kernel_types;
+ int m_kernel_types = RSReduceBreakpointResolver::eKernelTypeAll;
llvm::StringRef m_reduce_name;
RSCoordinate m_coord;
bool m_have_coord;
@@ -4189,7 +4187,6 @@ public:
result.AppendErrorWithFormat("'%s' takes 1 argument of reduction name, "
"and an optional kernel type list",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4203,7 +4200,6 @@ public:
auto coord = m_options.m_have_coord ? &m_options.m_coord : nullptr;
if (!runtime->PlaceBreakpointOnReduction(target, outstream, name, coord,
m_options.m_kernel_types)) {
- result.SetStatus(eReturnStatusFailed);
result.AppendError("Error: unable to place breakpoint on reduction");
return false;
}
@@ -4291,7 +4287,6 @@ public:
result.AppendErrorWithFormat(
"'%s' takes 1 argument of kernel name, and an optional coordinate.",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4304,7 +4299,6 @@ public:
auto name = command.GetArgumentAtIndex(0);
auto coord = m_options.m_have_coord ? &m_options.m_coord : nullptr;
if (!runtime->PlaceBreakpointOnKernel(target, outstream, name, coord)) {
- result.SetStatus(eReturnStatusFailed);
result.AppendErrorWithFormat(
"Error: unable to set breakpoint on kernel '%s'", name);
return false;
@@ -4342,7 +4336,6 @@ public:
if (argc != 1) {
result.AppendErrorWithFormat(
"'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4361,7 +4354,6 @@ public:
} else {
result.AppendErrorWithFormat(
"Argument must be either 'enable' or 'disable'");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4568,7 +4560,6 @@ public:
result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. "
"As well as an optional -f argument",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4583,7 +4574,6 @@ public:
if (!success) {
result.AppendErrorWithFormat("invalid allocation id argument '%s'",
id_cstr);
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4608,7 +4598,6 @@ public:
std::string error = llvm::toString(file.takeError());
result.AppendErrorWithFormat("Couldn't open file '%s': %s",
path.c_str(), error.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else
@@ -4653,7 +4642,7 @@ public:
class CommandOptions : public Options {
public:
- CommandOptions() : Options(), m_id(0) {}
+ CommandOptions() : Options() {}
~CommandOptions() override = default;
@@ -4681,7 +4670,7 @@ public:
return llvm::makeArrayRef(g_renderscript_runtime_alloc_list_options);
}
- uint32_t m_id;
+ uint32_t m_id = 0;
};
bool DoExecute(Args &command, CommandReturnObject &result) override {
@@ -4717,7 +4706,6 @@ public:
result.AppendErrorWithFormat(
"'%s' takes 2 arguments, an allocation ID and filename to read from.",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4732,7 +4720,6 @@ public:
if (!success) {
result.AppendErrorWithFormat("invalid allocation id argument '%s'",
id_cstr);
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4768,7 +4755,6 @@ public:
result.AppendErrorWithFormat(
"'%s' takes 2 arguments, an allocation ID and filename to read from.",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4783,7 +4769,6 @@ public:
if (!success) {
result.AppendErrorWithFormat("invalid allocation id argument '%s'",
id_cstr);
- result.SetStatus(eReturnStatusFailed);
return false;
}
diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
index 5e3726548369..2785c3b08125 100644
--- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
@@ -44,9 +44,9 @@ typedef std::shared_ptr<RSKernelDescriptor> RSKernelDescriptorSP;
typedef std::shared_ptr<RSScriptGroupDescriptor> RSScriptGroupDescriptorSP;
struct RSCoordinate {
- uint32_t x, y, z;
+ uint32_t x = 0, y = 0, z = 0;
- RSCoordinate() : x(), y(), z(){};
+ RSCoordinate() = default;
bool operator==(const lldb_renderscript::RSCoordinate &rhs) {
return x == rhs.x && y == rhs.y && z == rhs.z;
diff --git a/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
index 211eb9ce0d3a..7ff917518b64 100644
--- a/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
+++ b/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
@@ -42,9 +42,7 @@ using namespace lldb_private;
LLDB_PLUGIN_DEFINE(ObjectContainerBSDArchive)
-ObjectContainerBSDArchive::Object::Object()
- : ar_name(), modification_time(0), uid(0), gid(0), mode(0), size(0),
- file_offset(0), file_size(0) {}
+ObjectContainerBSDArchive::Object::Object() : ar_name() {}
void ObjectContainerBSDArchive::Object::Clear() {
ar_name.Clear();
@@ -142,7 +140,7 @@ ObjectContainerBSDArchive::Archive::Archive(const lldb_private::ArchSpec &arch,
: m_arch(arch), m_modification_time(time), m_file_offset(file_offset),
m_objects(), m_data(data) {}
-ObjectContainerBSDArchive::Archive::~Archive() {}
+ObjectContainerBSDArchive::Archive::~Archive() = default;
size_t ObjectContainerBSDArchive::Archive::ParseObjects() {
DataExtractor &data = m_data;
@@ -375,7 +373,7 @@ void ObjectContainerBSDArchive::SetArchive(Archive::shared_ptr &archive_sp) {
m_archive_sp = archive_sp;
}
-ObjectContainerBSDArchive::~ObjectContainerBSDArchive() {}
+ObjectContainerBSDArchive::~ObjectContainerBSDArchive() = default;
bool ObjectContainerBSDArchive::ParseHeader() {
if (m_archive_sp.get() == nullptr) {
diff --git a/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h b/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
index f6862afff8a0..9830e9b5d1b2 100644
--- a/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
+++ b/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
@@ -84,25 +84,25 @@ protected:
lldb_private::ConstString ar_name;
/// Object modification time in the archive.
- uint32_t modification_time;
+ uint32_t modification_time = 0;
/// Object user id in the archive.
- uint16_t uid;
+ uint16_t uid = 0;
/// Object group id in the archive.
- uint16_t gid;
+ uint16_t gid = 0;
/// Object octal file permissions in the archive.
- uint16_t mode;
+ uint16_t mode = 0;
/// Object size in bytes in the archive.
- uint32_t size;
+ uint32_t size = 0;
/// File offset in bytes from the beginning of the file of the object data.
- lldb::offset_t file_offset;
+ lldb::offset_t file_offset = 0;
/// Length of the object data.
- lldb::offset_t file_size;
+ lldb::offset_t file_size = 0;
};
class Archive {
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index cad9ce218b10..a5e86f0c2c1b 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -16,6 +16,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Progress.h"
#include "lldb/Core/Section.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/LZMA.h"
@@ -37,6 +38,7 @@
#include "llvm/Object/Decompressor.h"
#include "llvm/Support/ARMBuildAttributes.h"
#include "llvm/Support/CRC.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/MipsABIFlags.h"
@@ -857,8 +859,7 @@ Address ObjectFileELF::GetImageInfoAddress(Target *target) {
if (symbol.d_tag == DT_MIPS_RLD_MAP) {
// DT_MIPS_RLD_MAP tag stores an absolute address of the debug pointer.
Address addr;
- if (target->ReadPointerFromMemory(dyn_base + offset, false, error,
- addr))
+ if (target->ReadPointerFromMemory(dyn_base + offset, error, addr, true))
return addr;
}
if (symbol.d_tag == DT_MIPS_RLD_MAP_REL) {
@@ -866,7 +867,7 @@ Address ObjectFileELF::GetImageInfoAddress(Target *target) {
// relative to the address of the tag.
uint64_t rel_offset;
rel_offset = target->ReadUnsignedIntegerFromMemory(
- dyn_base + offset, false, GetAddressByteSize(), UINT64_MAX, error);
+ dyn_base + offset, GetAddressByteSize(), UINT64_MAX, error, true);
if (error.Success() && rel_offset != UINT64_MAX) {
Address addr;
addr_t debug_ptr_address =
@@ -1861,7 +1862,7 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
// unified section list.
if (GetType() != eTypeDebugInfo)
unified_section_list = *m_sections_up;
-
+
// If there's a .gnu_debugdata section, we'll try to read the .symtab that's
// embedded in there and replace the one in the original object file (if any).
// If there's none in the orignal object file, we add it to it.
@@ -1879,7 +1880,7 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
unified_section_list.AddSection(symtab_section_sp);
}
}
- }
+ }
}
std::shared_ptr<ObjectFileELF> ObjectFileELF::GetGnuDebugDataObjectFile() {
@@ -1923,7 +1924,7 @@ std::shared_ptr<ObjectFileELF> ObjectFileELF::GetGnuDebugDataObjectFile() {
ArchSpec spec = m_gnu_debug_data_object_file->GetArchitecture();
if (spec && m_gnu_debug_data_object_file->SetModulesArchitecture(spec))
return m_gnu_debug_data_object_file;
-
+
return nullptr;
}
@@ -2707,6 +2708,9 @@ Symtab *ObjectFileELF::GetSymtab() {
if (!module_sp)
return nullptr;
+ Progress progress(llvm::formatv("Parsing symbol table for {0}",
+ m_file.GetFilename().AsCString("<Unknown>")));
+
// We always want to use the main object file so we (hopefully) only have one
// cached copy of our symtab, dynamic sections, etc.
ObjectFile *module_obj_file = module_sp->GetObjectFile();
@@ -2770,14 +2774,14 @@ Symtab *ObjectFileELF::GetSymtab() {
user_id_t reloc_id = reloc_section->GetID();
const ELFSectionHeaderInfo *reloc_header =
GetSectionHeaderByIndex(reloc_id);
- assert(reloc_header);
-
- if (m_symtab_up == nullptr)
- m_symtab_up =
- std::make_unique<Symtab>(reloc_section->GetObjectFile());
+ if (reloc_header) {
+ if (m_symtab_up == nullptr)
+ m_symtab_up =
+ std::make_unique<Symtab>(reloc_section->GetObjectFile());
- ParseTrampolineSymbols(m_symtab_up.get(), symbol_id, reloc_header,
- reloc_id);
+ ParseTrampolineSymbols(m_symtab_up.get(), symbol_id, reloc_header,
+ reloc_id);
+ }
}
}
@@ -2809,31 +2813,37 @@ Symtab *ObjectFileELF::GetSymtab() {
if (is_valid_entry_point && !m_symtab_up->FindSymbolContainingFileAddress(
entry_point_file_addr)) {
uint64_t symbol_id = m_symtab_up->GetNumSymbols();
- Symbol symbol(symbol_id,
- GetNextSyntheticSymbolName().GetCString(), // Symbol name.
- eSymbolTypeCode, // Type of this symbol.
- true, // Is this globally visible?
- false, // Is this symbol debug info?
- false, // Is this symbol a trampoline?
- true, // Is this symbol artificial?
- entry_point_addr.GetSection(), // Section where this
- // symbol is defined.
- 0, // Offset in section or symbol value.
- 0, // Size.
- false, // Size is valid.
- false, // Contains linker annotations?
- 0); // Symbol flags.
- m_symtab_up->AddSymbol(symbol);
+ // Don't set the name for any synthetic symbols, the Symbol
+ // object will generate one if needed when the name is accessed
+ // via accessors.
+ SectionSP section_sp = entry_point_addr.GetSection();
+ Symbol symbol(
+ /*symID=*/symbol_id,
+ /*name=*/llvm::StringRef(), // Name will be auto generated.
+ /*type=*/eSymbolTypeCode,
+ /*external=*/true,
+ /*is_debug=*/false,
+ /*is_trampoline=*/false,
+ /*is_artificial=*/true,
+ /*section_sp=*/section_sp,
+ /*offset=*/0,
+ /*size=*/0, // FDE can span multiple symbols so don't use its size.
+ /*size_is_valid=*/false,
+ /*contains_linker_annotations=*/false,
+ /*flags=*/0);
// When the entry point is arm thumb we need to explicitly set its
// class address to reflect that. This is important because expression
// evaluation relies on correctly setting a breakpoint at this
// address.
if (arch.GetMachine() == llvm::Triple::arm &&
- (entry_point_file_addr & 1))
+ (entry_point_file_addr & 1)) {
+ symbol.GetAddressRef().SetOffset(entry_point_addr.GetOffset() ^ 1);
m_address_class_map[entry_point_file_addr ^ 1] =
AddressClass::eCodeAlternateISA;
- else
+ } else {
m_address_class_map[entry_point_file_addr] = AddressClass::eCode;
+ }
+ m_symtab_up->AddSymbol(symbol);
}
}
@@ -2897,8 +2907,11 @@ void ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table,
// recalculate the index first.
std::vector<Symbol> new_symbols;
- eh_frame->ForEachFDEEntries([this, symbol_table, section_list, &new_symbols](
- lldb::addr_t file_addr, uint32_t size, dw_offset_t) {
+ size_t num_symbols = symbol_table->GetNumSymbols();
+ uint64_t last_symbol_id =
+ num_symbols ? symbol_table->SymbolAtIndex(num_symbols - 1)->GetID() : 0;
+ eh_frame->ForEachFDEEntries([&](lldb::addr_t file_addr, uint32_t size,
+ dw_offset_t) {
Symbol *symbol = symbol_table->FindSymbolAtFileAddress(file_addr);
if (symbol) {
if (!symbol->GetByteSizeIsValid()) {
@@ -2910,22 +2923,24 @@ void ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table,
section_list->FindSectionContainingFileAddress(file_addr);
if (section_sp) {
addr_t offset = file_addr - section_sp->GetFileAddress();
- const char *symbol_name = GetNextSyntheticSymbolName().GetCString();
- uint64_t symbol_id = symbol_table->GetNumSymbols();
+ uint64_t symbol_id = ++last_symbol_id;
+ // Don't set the name for any synthetic symbols, the Symbol
+ // object will generate one if needed when the name is accessed
+ // via accessors.
Symbol eh_symbol(
- symbol_id, // Symbol table index.
- symbol_name, // Symbol name.
- eSymbolTypeCode, // Type of this symbol.
- true, // Is this globally visible?
- false, // Is this symbol debug info?
- false, // Is this symbol a trampoline?
- true, // Is this symbol artificial?
- section_sp, // Section in which this symbol is defined or null.
- offset, // Offset in section or symbol value.
- 0, // Size: Don't specify the size as an FDE can
- false, // Size is valid: cover multiple symbols.
- false, // Contains linker annotations?
- 0); // Symbol flags.
+ /*symID=*/symbol_id,
+ /*name=*/llvm::StringRef(), // Name will be auto generated.
+ /*type=*/eSymbolTypeCode,
+ /*external=*/true,
+ /*is_debug=*/false,
+ /*is_trampoline=*/false,
+ /*is_artificial=*/true,
+ /*section_sp=*/section_sp,
+ /*offset=*/offset,
+ /*size=*/0, // FDE can span multiple symbols so don't use its size.
+ /*size_is_valid=*/false,
+ /*contains_linker_annotations=*/false,
+ /*flags=*/0);
new_symbols.push_back(eh_symbol);
}
}
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 062271f1caf0..e678c2f5f011 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -9,7 +9,7 @@
#ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H
#define LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H
-#include <stdint.h>
+#include <cstdint>
#include <vector>
@@ -22,13 +22,13 @@
#include "ELFHeader.h"
struct ELFNote {
- elf::elf_word n_namesz;
- elf::elf_word n_descsz;
- elf::elf_word n_type;
+ elf::elf_word n_namesz = 0;
+ elf::elf_word n_descsz = 0;
+ elf::elf_word n_type = 0;
std::string n_name;
- ELFNote() : n_namesz(0), n_descsz(0), n_type(0) {}
+ ELFNote() = default;
/// Parse an ELFNote entry from the given DataExtractor starting at position
/// \p offset.
diff --git a/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp b/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
index 93c2c9f945fe..f93ac9261afd 100644
--- a/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
+++ b/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
@@ -100,7 +100,7 @@ ObjectFileJIT::ObjectFileJIT(const lldb::ModuleSP &module_sp,
}
}
-ObjectFileJIT::~ObjectFileJIT() {}
+ObjectFileJIT::~ObjectFileJIT() = default;
bool ObjectFileJIT::ParseHeader() {
// JIT code is never in a file, nor is it required to have any header
diff --git a/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
index 35a823e9a28f..cb7bbeeca054 100644
--- a/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
+++ b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
@@ -173,7 +173,7 @@ ObjectFilePDB::loadPDBFile(std::string PdbPath,
if (ec || magic != llvm::file_magic::pdb)
return nullptr;
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ErrorOrBuffer =
- llvm::MemoryBuffer::getFile(PdbPath, /*FileSize=*/-1,
+ llvm::MemoryBuffer::getFile(PdbPath, /*IsText=*/false,
/*RequiresNullTerminator=*/false);
if (!ErrorOrBuffer)
return nullptr;
diff --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
index 6c29c2326212..5272da9ab33a 100644
--- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
+++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
@@ -196,7 +196,7 @@ bool ObjectFileWasm::DecodeNextSection(lldb::offset_t *offset_ptr) {
m_sect_infos.push_back(section_info{*offset_ptr + c.tell(), section_length,
section_id, *sect_name});
*offset_ptr += (c.tell() + section_length);
- } else if (section_id <= llvm::wasm::WASM_SEC_EVENT) {
+ } else if (section_id <= llvm::wasm::WASM_SEC_TAG) {
m_sect_infos.push_back(section_info{*offset_ptr + c.tell(),
static_cast<uint32_t>(payload_len),
section_id, ConstString()});
diff --git a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index 4350010f0296..730c88f96e13 100644
--- a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -91,13 +91,13 @@ OperatingSystemPython::OperatingSystemPython(lldb_private::Process *process,
std::string os_plugin_class_name(
python_module_path.GetFilename().AsCString(""));
if (!os_plugin_class_name.empty()) {
- const bool init_session = false;
+ LoadScriptOptions options;
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,
- init_session, error)) {
+ if (m_interpreter->LoadScriptingModule(python_module_path_cstr, options,
+ 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)
@@ -115,7 +115,7 @@ OperatingSystemPython::OperatingSystemPython(lldb_private::Process *process,
}
}
-OperatingSystemPython::~OperatingSystemPython() {}
+OperatingSystemPython::~OperatingSystemPython() = default;
DynamicRegisterInfo *OperatingSystemPython::GetDynamicRegisterInfo() {
if (m_register_info_up == nullptr) {
diff --git a/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
index f4d44eb7e745..7b3d8a375bf6 100644
--- a/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
+++ b/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
@@ -9,7 +9,7 @@
#include "PlatformFreeBSD.h"
#include "lldb/Host/Config.h"
-#include <stdio.h>
+#include <cstdio>
#if LLDB_ENABLE_POSIX
#include <sys/utsname.h>
#endif
@@ -214,55 +214,9 @@ void PlatformFreeBSD::GetStatus(Stream &strm) {
#endif
}
-size_t
-PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode(Target &target,
- BreakpointSite *bp_site) {
- switch (target.GetArchitecture().GetMachine()) {
- case llvm::Triple::arm: {
- lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0));
- AddressClass addr_class = AddressClass::eUnknown;
-
- if (bp_loc_sp) {
- addr_class = bp_loc_sp->GetAddress().GetAddressClass();
- if (addr_class == AddressClass::eUnknown &&
- (bp_loc_sp->GetAddress().GetFileAddress() & 1))
- addr_class = AddressClass::eCodeAlternateISA;
- }
-
- if (addr_class == AddressClass::eCodeAlternateISA) {
- // TODO: Enable when FreeBSD supports thumb breakpoints.
- // FreeBSD kernel as of 10.x, does not support thumb breakpoints
- return 0;
- }
-
- static const uint8_t g_arm_breakpoint_opcode[] = {0xFE, 0xDE, 0xFF, 0xE7};
- size_t trap_opcode_size = sizeof(g_arm_breakpoint_opcode);
- assert(bp_site);
- if (bp_site->SetTrapOpcode(g_arm_breakpoint_opcode, trap_opcode_size))
- return trap_opcode_size;
- }
- LLVM_FALLTHROUGH;
- default:
- return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site);
- }
-}
-
bool PlatformFreeBSD::CanDebugProcess() {
if (IsHost()) {
- llvm::Triple host_triple{llvm::sys::getProcessTriple()};
- bool use_legacy_plugin;
-
- switch (host_triple.getArch()) {
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- // FreeBSDRemote plugin supports x86 only at the moment
- use_legacy_plugin = !!getenv("FREEBSD_LEGACY_PLUGIN");
- break;
- default:
- use_legacy_plugin = true;
- }
-
- return !use_legacy_plugin;
+ return true;
} else {
// If we're connected, we can debug.
return IsConnected();
diff --git a/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h b/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
index c198ea18638d..4fd10fb1be73 100644
--- a/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
+++ b/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
@@ -44,9 +44,6 @@ public:
bool CanDebugProcess() override;
- size_t GetSoftwareBreakpointTrapOpcode(Target &target,
- BreakpointSite *bp_site) override;
-
void CalculateTrapHandlerSymbolNames() override;
MmapArgList GetMmapArgumentList(const ArchSpec &arch, lldb::addr_t addr,
diff --git a/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
index a5d73c942830..e3682b44e141 100644
--- a/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
+++ b/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
@@ -9,7 +9,7 @@
#include "PlatformNetBSD.h"
#include "lldb/Host/Config.h"
-#include <stdio.h>
+#include <cstdio>
#if LLDB_ENABLE_POSIX
#include <sys/utsname.h>
#endif
diff --git a/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp b/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
index 2cd024f56ec9..012b688231a0 100644
--- a/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
+++ b/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
@@ -9,7 +9,7 @@
#include "PlatformOpenBSD.h"
#include "lldb/Host/Config.h"
-#include <stdio.h>
+#include <cstdio>
#if LLDB_ENABLE_POSIX
#include <sys/utsname.h>
#endif
diff --git a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index 3628b0a2ce5e..7353132cd96f 100644
--- a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -46,7 +46,7 @@ PlatformPOSIX::PlatformPOSIX(bool is_host)
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
-PlatformPOSIX::~PlatformPOSIX() {}
+PlatformPOSIX::~PlatformPOSIX() = default;
lldb_private::OptionGroupOptions *PlatformPOSIX::GetConnectionOptions(
lldb_private::CommandInterpreter &interpreter) {
@@ -578,7 +578,19 @@ PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx,
// __lldb_dlopen_result for consistency. The wrapper returns a void * but
// doesn't use it because UtilityFunctions don't work with void returns at
// present.
+ //
+ // Use lazy binding so as to not make dlopen()'s success conditional on
+ // forcing every symbol in the library.
+ //
+ // In general, the debugger should allow programs to load & run with
+ // libraries as far as they can, instead of defaulting to being super-picky
+ // about unavailable symbols.
+ //
+ // The value "1" appears to imply lazy binding (RTLD_LAZY) on both Darwin
+ // and other POSIX OSes.
static const char *dlopen_wrapper_code = R"(
+ const int RTLD_LAZY = 1;
+
struct __lldb_dlopen_result {
void *image_ptr;
const char *error_str;
@@ -595,7 +607,7 @@ PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx,
{
// This is the case where the name is the full path:
if (!path_strings) {
- result_ptr->image_ptr = dlopen(name, 2);
+ result_ptr->image_ptr = dlopen(name, RTLD_LAZY);
if (result_ptr->image_ptr)
result_ptr->error_str = nullptr;
return nullptr;
@@ -609,7 +621,7 @@ PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx,
buffer[path_len] = '/';
char *target_ptr = buffer+path_len+1;
memcpy((void *) target_ptr, (void *) name, name_len + 1);
- result_ptr->image_ptr = dlopen(buffer, 2);
+ result_ptr->image_ptr = dlopen(buffer, RTLD_LAZY);
if (result_ptr->image_ptr) {
result_ptr->error_str = nullptr;
break;
@@ -659,7 +671,7 @@ PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx,
// We are passing four arguments, the basename, the list of places to look,
// a buffer big enough for all the path + name combos, and
// a pointer to the storage we've made for the result:
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
value.SetCompilerType(clang_void_pointer_type);
arguments.PushValue(value);
value.SetCompilerType(clang_char_pointer_type);
@@ -994,13 +1006,6 @@ PlatformPOSIX::GetLibdlFunctionDeclarations(lldb_private::Process *process) {
)";
}
-size_t PlatformPOSIX::ConnectToWaitingProcesses(Debugger &debugger,
- Status &error) {
- if (m_remote_platform_sp)
- return m_remote_platform_sp->ConnectToWaitingProcesses(debugger, error);
- return Platform::ConnectToWaitingProcesses(debugger, error);
-}
-
ConstString PlatformPOSIX::GetFullNameForDylib(ConstString basename) {
if (basename.IsEmpty())
return basename;
diff --git a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h
index 72c54f4147c2..1cba4c5eb2e9 100644
--- a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h
+++ b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h
@@ -71,9 +71,6 @@ public:
lldb_private::Status UnloadImage(lldb_private::Process *process,
uint32_t image_token) override;
- size_t ConnectToWaitingProcesses(lldb_private::Debugger &debugger,
- lldb_private::Status &error) override;
-
lldb_private::ConstString GetFullNameForDylib(lldb_private::ConstString basename) override;
protected:
diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 6a4275d249f6..528208665a4e 100644
--- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -30,6 +30,7 @@
#include "lldb/Utility/UriParser.h"
#include "Plugins/Process/Utility/GDBRemoteSignals.h"
+#include "Plugins/Process/gdb-remote/ProcessGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
@@ -202,13 +203,16 @@ Status PlatformRemoteGDBServer::GetFileWithUUID(const FileSpec &platform_file,
/// Default Constructor
PlatformRemoteGDBServer::PlatformRemoteGDBServer()
: Platform(false), // This is a remote platform
- m_gdb_client() {}
+ m_gdb_client() {
+ m_gdb_client.SetPacketTimeout(
+ process_gdb_remote::ProcessGDBRemote::GetPacketTimeout());
+}
/// Destructor.
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
-PlatformRemoteGDBServer::~PlatformRemoteGDBServer() {}
+PlatformRemoteGDBServer::~PlatformRemoteGDBServer() = default;
bool PlatformRemoteGDBServer::GetSupportedArchitectureAtIndex(uint32_t idx,
ArchSpec &arch) {
@@ -736,8 +740,8 @@ const UnixSignalsSP &PlatformRemoteGDBServer::GetRemoteUnixSignals() {
m_remote_signals_sp = UnixSignals::Create(GetRemoteSystemArchitecture());
StringExtractorGDBRemote response;
- auto result = m_gdb_client.SendPacketAndWaitForResponse("jSignalsInfo",
- response, false);
+ auto result =
+ m_gdb_client.SendPacketAndWaitForResponse("jSignalsInfo", response);
if (result != decltype(result)::Success ||
response.GetResponseType() != response.eResponse)
@@ -839,7 +843,7 @@ size_t PlatformRemoteGDBServer::ConnectToWaitingProcesses(Debugger &debugger,
GetPendingGdbServerList(connection_urls);
for (size_t i = 0; i < connection_urls.size(); ++i) {
- ConnectProcess(connection_urls[i].c_str(), "", debugger, nullptr, error);
+ ConnectProcess(connection_urls[i].c_str(), "gdb-remote", debugger, nullptr, error);
if (error.Fail())
return i; // We already connected to i process succsessfully
}
diff --git a/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
deleted file mode 100644
index 3accc9cef6ed..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
+++ /dev/null
@@ -1,616 +0,0 @@
-//===-- FreeBSDThread.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 <errno.h>
-#include <pthread.h>
-#include <pthread_np.h>
-#include <stdlib.h>
-#include <sys/sysctl.h>
-#include <sys/types.h>
-#include <sys/user.h>
-
-#include "FreeBSDThread.h"
-#include "POSIXStopInfo.h"
-#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
-#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
-#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
-#include "ProcessFreeBSD.h"
-#include "ProcessMonitor.h"
-#include "RegisterContextPOSIXProcessMonitor_arm.h"
-#include "RegisterContextPOSIXProcessMonitor_arm64.h"
-#include "RegisterContextPOSIXProcessMonitor_mips64.h"
-#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
-#include "RegisterContextPOSIXProcessMonitor_x86.h"
-#include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Breakpoint/Watchpoint.h"
-#include "lldb/Core/Debugger.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Host/HostInfo.h"
-#include "lldb/Host/HostNativeThread.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/StopInfo.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Target/ThreadSpec.h"
-#include "lldb/Target/UnixSignals.h"
-#include "lldb/Target/Unwind.h"
-#include "lldb/Utility/State.h"
-#include "llvm/ADT/SmallString.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-FreeBSDThread::FreeBSDThread(Process &process, lldb::tid_t tid)
- : Thread(process, tid), m_frame_up(), m_breakpoint(),
- m_thread_name_valid(false), m_thread_name(), m_posix_thread(nullptr) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
- LLDB_LOGV(log, "tid = {0}", tid);
-
- // Set the current watchpoints for this thread.
- Target &target = GetProcess()->GetTarget();
- const WatchpointList &wp_list = target.GetWatchpointList();
- size_t wp_size = wp_list.GetSize();
-
- for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++) {
- lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx);
- if (wp.get() && wp->IsEnabled()) {
- // This watchpoint as been enabled; obviously this "new" thread has been
- // created since that watchpoint was enabled. Since the
- // POSIXBreakpointProtocol has yet to be initialized, its
- // m_watchpoints_initialized member will be FALSE. Attempting to read
- // the debug status register to determine if a watchpoint has been hit
- // would result in the zeroing of that register. Since the active debug
- // registers would have been cloned when this thread was created, simply
- // force the m_watchpoints_initized member to TRUE and avoid resetting
- // dr6 and dr7.
- GetPOSIXBreakpointProtocol()->ForceWatchpointsInitialized();
- }
- }
-}
-
-FreeBSDThread::~FreeBSDThread() { DestroyThread(); }
-
-ProcessMonitor &FreeBSDThread::GetMonitor() {
- ProcessSP base = GetProcess();
- ProcessFreeBSD &process = static_cast<ProcessFreeBSD &>(*base);
- return process.GetMonitor();
-}
-
-void FreeBSDThread::RefreshStateAfterStop() {
- // Invalidate all registers in our register context. We don't set "force" to
- // true because the stop reply packet might have had some register values
- // that were expedited and these will already be copied into the register
- // context by the time this function gets called. The KDPRegisterContext
- // class has been made smart enough to detect when it needs to invalidate
- // which registers are valid by putting hooks in the register read and
- // register supply functions where they check the process stop ID and do the
- // right thing. if (StateIsStoppedState(GetState())
- {
- const bool force = false;
- GetRegisterContext()->InvalidateIfNeeded(force);
- }
-}
-
-const char *FreeBSDThread::GetInfo() { return nullptr; }
-
-void FreeBSDThread::SetName(const char *name) {
- m_thread_name_valid = (name && name[0]);
- if (m_thread_name_valid)
- m_thread_name.assign(name);
- else
- m_thread_name.clear();
-}
-
-const char *FreeBSDThread::GetName() {
- if (!m_thread_name_valid) {
- m_thread_name.clear();
- int pid = GetProcess()->GetID();
-
- struct kinfo_proc *kp = nullptr, *nkp;
- size_t len = 0;
- int error;
- int ctl[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD,
- pid};
-
- while (1) {
- error = sysctl(ctl, 4, kp, &len, nullptr, 0);
- if (kp == nullptr || (error != 0 && errno == ENOMEM)) {
- // Add extra space in case threads are added before next call.
- len += sizeof(*kp) + len / 10;
- nkp = (struct kinfo_proc *)realloc(kp, len);
- if (nkp == nullptr) {
- free(kp);
- return nullptr;
- }
- kp = nkp;
- continue;
- }
- if (error != 0)
- len = 0;
- break;
- }
-
- for (size_t i = 0; i < len / sizeof(*kp); i++) {
- if (kp[i].ki_tid == (lwpid_t)GetID()) {
- m_thread_name.append(kp[i].ki_tdname,
- kp[i].ki_tdname + strlen(kp[i].ki_tdname));
- break;
- }
- }
- free(kp);
- m_thread_name_valid = true;
- }
-
- if (m_thread_name.empty())
- return nullptr;
- return m_thread_name.c_str();
-}
-
-lldb::RegisterContextSP FreeBSDThread::GetRegisterContext() {
- if (!m_reg_context_sp) {
- m_posix_thread = nullptr;
-
- RegisterInfoInterface *reg_interface = nullptr;
- const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture();
-
- assert(target_arch.GetTriple().getOS() == llvm::Triple::FreeBSD);
- switch (target_arch.GetMachine()) {
- case llvm::Triple::aarch64:
- case llvm::Triple::arm:
- break;
- case llvm::Triple::ppc:
-#ifndef __powerpc64__
- reg_interface = new RegisterContextFreeBSD_powerpc32(target_arch);
- break;
-#endif
- case llvm::Triple::ppc64:
- reg_interface = new RegisterContextFreeBSD_powerpc64(target_arch);
- break;
- case llvm::Triple::mips64:
- reg_interface = new RegisterContextFreeBSD_mips64(target_arch);
- break;
- case llvm::Triple::x86:
- reg_interface = new RegisterContextFreeBSD_i386(target_arch);
- break;
- case llvm::Triple::x86_64:
- reg_interface = new RegisterContextFreeBSD_x86_64(target_arch);
- break;
- default:
- llvm_unreachable("CPU not supported");
- }
-
- switch (target_arch.GetMachine()) {
- case llvm::Triple::aarch64: {
- RegisterContextPOSIXProcessMonitor_arm64 *reg_ctx =
- new RegisterContextPOSIXProcessMonitor_arm64(
- *this, std::make_unique<RegisterInfoPOSIX_arm64>(target_arch));
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- case llvm::Triple::arm: {
- RegisterContextPOSIXProcessMonitor_arm *reg_ctx =
- new RegisterContextPOSIXProcessMonitor_arm(
- *this, std::make_unique<RegisterInfoPOSIX_arm>(target_arch));
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- case llvm::Triple::mips64: {
- RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx =
- new RegisterContextPOSIXProcessMonitor_mips64(*this, 0,
- reg_interface);
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64: {
- RegisterContextPOSIXProcessMonitor_powerpc *reg_ctx =
- new RegisterContextPOSIXProcessMonitor_powerpc(*this, 0,
- reg_interface);
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- case llvm::Triple::x86:
- case llvm::Triple::x86_64: {
- RegisterContextPOSIXProcessMonitor_x86_64 *reg_ctx =
- new RegisterContextPOSIXProcessMonitor_x86_64(*this, 0,
- reg_interface);
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- default:
- break;
- }
- }
- return m_reg_context_sp;
-}
-
-lldb::RegisterContextSP
-FreeBSDThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) {
- lldb::RegisterContextSP reg_ctx_sp;
- uint32_t concrete_frame_idx = 0;
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
- LLDB_LOGV(log, "called");
-
- if (frame)
- concrete_frame_idx = frame->GetConcreteFrameIndex();
-
- if (concrete_frame_idx == 0)
- reg_ctx_sp = GetRegisterContext();
- else {
- reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);
- }
-
- return reg_ctx_sp;
-}
-
-lldb::addr_t FreeBSDThread::GetThreadPointer() {
- ProcessMonitor &monitor = GetMonitor();
- addr_t addr;
- if (monitor.ReadThreadPointer(GetID(), addr))
- return addr;
- else
- return LLDB_INVALID_ADDRESS;
-}
-
-bool FreeBSDThread::CalculateStopInfo() {
- SetStopInfo(m_stop_info_sp);
- return true;
-}
-
-void FreeBSDThread::DidStop() {
- // Don't set the thread state to stopped unless we really stopped.
-}
-
-void FreeBSDThread::WillResume(lldb::StateType resume_state) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
- LLDB_LOGF(log, "tid %lu resume_state = %s", GetID(),
- lldb_private::StateAsCString(resume_state));
- ProcessSP process_sp(GetProcess());
- ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(process_sp.get());
- int signo = GetResumeSignal();
- bool signo_valid = process->GetUnixSignals()->SignalIsValid(signo);
-
- switch (resume_state) {
- case eStateSuspended:
- case eStateStopped:
- process->m_suspend_tids.push_back(GetID());
- break;
- case eStateRunning:
- process->m_run_tids.push_back(GetID());
- if (signo_valid)
- process->m_resume_signo = signo;
- break;
- case eStateStepping:
- process->m_step_tids.push_back(GetID());
- if (signo_valid)
- process->m_resume_signo = signo;
- break;
- default:
- break;
- }
-}
-
-bool FreeBSDThread::Resume() {
- lldb::StateType resume_state = GetResumeState();
- ProcessMonitor &monitor = GetMonitor();
- bool status;
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
- LLDB_LOGF(log, "FreeBSDThread::%s (), resume_state = %s", __FUNCTION__,
- StateAsCString(resume_state));
-
- switch (resume_state) {
- default:
- assert(false && "Unexpected state for resume!");
- status = false;
- break;
-
- case lldb::eStateRunning:
- SetState(resume_state);
- status = monitor.Resume(GetID(), GetResumeSignal());
- break;
-
- case lldb::eStateStepping:
- SetState(resume_state);
- status = monitor.SingleStep(GetID(), GetResumeSignal());
- break;
- case lldb::eStateStopped:
- case lldb::eStateSuspended:
- status = true;
- break;
- }
-
- return status;
-}
-
-void FreeBSDThread::Notify(const ProcessMessage &message) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
- LLDB_LOGF(log, "FreeBSDThread::%s () message kind = '%s' for tid %" PRIu64,
- __FUNCTION__, message.PrintKind(), GetID());
-
- switch (message.GetKind()) {
- default:
- assert(false && "Unexpected message kind!");
- break;
-
- case ProcessMessage::eExitMessage:
- // Nothing to be done.
- break;
-
- case ProcessMessage::eLimboMessage:
- LimboNotify(message);
- break;
-
- case ProcessMessage::eCrashMessage:
- case ProcessMessage::eSignalMessage:
- SignalNotify(message);
- break;
-
- case ProcessMessage::eSignalDeliveredMessage:
- SignalDeliveredNotify(message);
- break;
-
- case ProcessMessage::eTraceMessage:
- TraceNotify(message);
- break;
-
- case ProcessMessage::eBreakpointMessage:
- BreakNotify(message);
- break;
-
- case ProcessMessage::eWatchpointMessage:
- WatchNotify(message);
- break;
-
- case ProcessMessage::eExecMessage:
- ExecNotify(message);
- break;
- }
-}
-
-bool FreeBSDThread::EnableHardwareWatchpoint(Watchpoint *wp) {
- bool wp_set = false;
- if (wp) {
- addr_t wp_addr = wp->GetLoadAddress();
- size_t wp_size = wp->GetByteSize();
- bool wp_read = wp->WatchpointRead();
- bool wp_write = wp->WatchpointWrite();
- uint32_t wp_hw_index = wp->GetHardwareIndex();
- POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol();
- if (reg_ctx)
- wp_set = reg_ctx->SetHardwareWatchpointWithIndex(
- wp_addr, wp_size, wp_read, wp_write, wp_hw_index);
- }
- return wp_set;
-}
-
-bool FreeBSDThread::DisableHardwareWatchpoint(Watchpoint *wp) {
- bool result = false;
- if (wp) {
- lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
- if (reg_ctx_sp.get())
- result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex());
- }
- return result;
-}
-
-uint32_t FreeBSDThread::NumSupportedHardwareWatchpoints() {
- lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
- if (reg_ctx_sp.get())
- return reg_ctx_sp->NumSupportedHardwareWatchpoints();
- return 0;
-}
-
-uint32_t FreeBSDThread::FindVacantWatchpointIndex() {
- uint32_t hw_index = LLDB_INVALID_INDEX32;
- uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
- uint32_t wp_idx;
- POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol();
- if (reg_ctx) {
- for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) {
- if (reg_ctx->IsWatchpointVacant(wp_idx)) {
- hw_index = wp_idx;
- break;
- }
- }
- }
- return hw_index;
-}
-
-void FreeBSDThread::BreakNotify(const ProcessMessage &message) {
- bool status;
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
-
- assert(GetRegisterContext());
- status = GetPOSIXBreakpointProtocol()->UpdateAfterBreakpoint();
- assert(status && "Breakpoint update failed!");
-
- // With our register state restored, resolve the breakpoint object
- // corresponding to our current PC.
- assert(GetRegisterContext());
- lldb::addr_t pc = GetRegisterContext()->GetPC();
- LLDB_LOGF(log, "FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc);
- lldb::BreakpointSiteSP bp_site(
- GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
-
- // If the breakpoint is for this thread, then we'll report the hit, but if it
- // is for another thread, we create a stop reason with should_stop=false. If
- // there is no breakpoint location, then report an invalid stop reason. We
- // don't need to worry about stepping over the breakpoint here, that will be
- // taken care of when the thread resumes and notices that there's a
- // breakpoint under the pc.
- if (bp_site) {
- lldb::break_id_t bp_id = bp_site->GetID();
- // If we have an operating system plug-in, we might have set a thread
- // specific breakpoint using the operating system thread ID, so we can't
- // make any assumptions about the thread ID so we must always report the
- // breakpoint regardless of the thread.
- if (bp_site->ValidForThisThread(this) ||
- GetProcess()->GetOperatingSystem() != nullptr)
- SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id));
- else {
- const bool should_stop = false;
- SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id,
- should_stop));
- }
- } else
- SetStopInfo(StopInfoSP());
-}
-
-void FreeBSDThread::WatchNotify(const ProcessMessage &message) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
-
- lldb::addr_t halt_addr = message.GetHWAddress();
- LLDB_LOGF(log,
- "FreeBSDThread::%s () Hardware Watchpoint Address = 0x%8.8" PRIx64,
- __FUNCTION__, halt_addr);
-
- POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol();
- if (reg_ctx) {
- uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
- uint32_t wp_idx;
- for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) {
- if (reg_ctx->IsWatchpointHit(wp_idx)) {
- // Clear the watchpoint hit here
- reg_ctx->ClearWatchpointHits();
- break;
- }
- }
-
- if (wp_idx == num_hw_wps)
- return;
-
- Target &target = GetProcess()->GetTarget();
- lldb::addr_t wp_monitor_addr = reg_ctx->GetWatchpointAddress(wp_idx);
- const WatchpointList &wp_list = target.GetWatchpointList();
- lldb::WatchpointSP wp_sp = wp_list.FindByAddress(wp_monitor_addr);
-
- assert(wp_sp.get() && "No watchpoint found");
- SetStopInfo(
- StopInfo::CreateStopReasonWithWatchpointID(*this, wp_sp->GetID()));
- }
-}
-
-void FreeBSDThread::TraceNotify(const ProcessMessage &message) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
-
- // Try to resolve the breakpoint object corresponding to the current PC.
- assert(GetRegisterContext());
- lldb::addr_t pc = GetRegisterContext()->GetPC();
- LLDB_LOGF(log, "FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc);
- lldb::BreakpointSiteSP bp_site(
- GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
-
- // If the current pc is a breakpoint site then set the StopInfo to
- // Breakpoint. Otherwise, set the StopInfo to Watchpoint or Trace. If we have
- // an operating system plug-in, we might have set a thread specific
- // breakpoint using the operating system thread ID, so we can't make any
- // assumptions about the thread ID so we must always report the breakpoint
- // regardless of the thread.
- if (bp_site && (bp_site->ValidForThisThread(this) ||
- GetProcess()->GetOperatingSystem() != nullptr))
- SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(
- *this, bp_site->GetID()));
- else {
- POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol();
- if (reg_ctx) {
- uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
- uint32_t wp_idx;
- for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) {
- if (reg_ctx->IsWatchpointHit(wp_idx)) {
- WatchNotify(message);
- return;
- }
- }
- }
- SetStopInfo(StopInfo::CreateStopReasonToTrace(*this));
- }
-}
-
-void FreeBSDThread::LimboNotify(const ProcessMessage &message) {
- SetStopInfo(lldb::StopInfoSP(new POSIXLimboStopInfo(*this)));
-}
-
-void FreeBSDThread::SignalNotify(const ProcessMessage &message) {
- int signo = message.GetSignal();
- if (message.GetKind() == ProcessMessage::eCrashMessage) {
- std::string stop_description = GetCrashReasonString(
- message.GetCrashReason(), message.GetFaultAddress());
- SetStopInfo(StopInfo::CreateStopReasonWithSignal(
- *this, signo, stop_description.c_str()));
- } else {
- SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, signo));
- }
-}
-
-void FreeBSDThread::SignalDeliveredNotify(const ProcessMessage &message) {
- int signo = message.GetSignal();
- SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, signo));
-}
-
-unsigned FreeBSDThread::GetRegisterIndexFromOffset(unsigned offset) {
- unsigned reg = LLDB_INVALID_REGNUM;
- ArchSpec arch = HostInfo::GetArchitecture();
-
- switch (arch.GetMachine()) {
- default:
- llvm_unreachable("CPU type not supported!");
- break;
-
- case llvm::Triple::aarch64:
- case llvm::Triple::arm:
- case llvm::Triple::mips64:
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- case llvm::Triple::x86:
- case llvm::Triple::x86_64: {
- POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol();
- reg = reg_ctx->GetRegisterIndexFromOffset(offset);
- } break;
- }
- return reg;
-}
-
-void FreeBSDThread::ExecNotify(const ProcessMessage &message) {
- SetStopInfo(StopInfo::CreateStopReasonWithExec(*this));
-}
-
-const char *FreeBSDThread::GetRegisterName(unsigned reg) {
- const char *name = nullptr;
- ArchSpec arch = HostInfo::GetArchitecture();
-
- switch (arch.GetMachine()) {
- default:
- assert(false && "CPU type not supported!");
- break;
-
- case llvm::Triple::aarch64:
- case llvm::Triple::arm:
- case llvm::Triple::mips64:
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- name = GetRegisterContext()->GetRegisterName(reg);
- break;
- }
- return name;
-}
-
-const char *FreeBSDThread::GetRegisterNameFromOffset(unsigned offset) {
- return GetRegisterName(GetRegisterIndexFromOffset(offset));
-}
diff --git a/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h b/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h
deleted file mode 100644
index 774ffb511bc6..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h
+++ /dev/null
@@ -1,111 +0,0 @@
-//===-- FreeBSDThread.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_FreeBSDThread_H_
-#define liblldb_FreeBSDThread_H_
-
-#include <memory>
-#include <string>
-
-#include "RegisterContextPOSIX.h"
-#include "lldb/Target/Thread.h"
-
-class ProcessMessage;
-class ProcessMonitor;
-class POSIXBreakpointProtocol;
-
-// @class FreeBSDThread
-// Abstraction of a FreeBSD thread.
-class FreeBSDThread : public lldb_private::Thread {
-public:
- // Constructors and destructors
- FreeBSDThread(lldb_private::Process &process, lldb::tid_t tid);
-
- virtual ~FreeBSDThread();
-
- // POSIXThread
- void RefreshStateAfterStop() override;
-
- // This notifies the thread when a private stop occurs.
- void DidStop() override;
-
- const char *GetInfo() override;
-
- void SetName(const char *name) override;
-
- const char *GetName() override;
-
- lldb::RegisterContextSP GetRegisterContext() override;
-
- lldb::RegisterContextSP
- CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
-
- lldb::addr_t GetThreadPointer() override;
-
- // These functions provide a mapping from the register offset
- // back to the register index or name for use in debugging or log
- // output.
-
- unsigned GetRegisterIndexFromOffset(unsigned offset);
-
- const char *GetRegisterName(unsigned reg);
-
- const char *GetRegisterNameFromOffset(unsigned offset);
-
- // These methods form a specialized interface to POSIX threads.
- //
- bool Resume();
-
- void Notify(const ProcessMessage &message);
-
- // These methods provide an interface to watchpoints
- //
- bool EnableHardwareWatchpoint(lldb_private::Watchpoint *wp);
-
- bool DisableHardwareWatchpoint(lldb_private::Watchpoint *wp);
-
- uint32_t NumSupportedHardwareWatchpoints();
-
- uint32_t FindVacantWatchpointIndex();
-
-protected:
- POSIXBreakpointProtocol *GetPOSIXBreakpointProtocol() {
- if (!m_reg_context_sp)
- m_reg_context_sp = GetRegisterContext();
- return m_posix_thread;
- }
-
- std::unique_ptr<lldb_private::StackFrame> m_frame_up;
-
- lldb::BreakpointSiteSP m_breakpoint;
-
- bool m_thread_name_valid;
- std::string m_thread_name;
- POSIXBreakpointProtocol *m_posix_thread;
-
- ProcessMonitor &GetMonitor();
-
- bool CalculateStopInfo() override;
-
- void BreakNotify(const ProcessMessage &message);
- void WatchNotify(const ProcessMessage &message);
- virtual void TraceNotify(const ProcessMessage &message);
- void LimboNotify(const ProcessMessage &message);
- void SignalNotify(const ProcessMessage &message);
- void SignalDeliveredNotify(const ProcessMessage &message);
- void CrashNotify(const ProcessMessage &message);
- void ExitNotify(const ProcessMessage &message);
- void ExecNotify(const ProcessMessage &message);
-
- // FreeBSDThread internal API.
-
- // POSIXThread override
- virtual void WillResume(lldb::StateType resume_state) override;
-};
-
-#endif // #ifndef liblldb_FreeBSDThread_H_
diff --git a/lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp
index 163093c2ab1f..d6426b3d2367 100644
--- a/lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp
@@ -128,13 +128,20 @@ NativeProcessFreeBSD::Factory::Attach(
return std::move(process_up);
}
+NativeProcessFreeBSD::Extension
+NativeProcessFreeBSD::Factory::GetSupportedExtensions() const {
+ return Extension::multiprocess | Extension::fork | Extension::vfork |
+ Extension::pass_signals | Extension::auxv | Extension::libraries_svr4;
+}
+
// Public Instance Methods
NativeProcessFreeBSD::NativeProcessFreeBSD(::pid_t pid, int terminal_fd,
NativeDelegate &delegate,
const ArchSpec &arch,
MainLoop &mainloop)
- : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch) {
+ : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch),
+ m_main_loop(mainloop) {
if (m_terminal_fd != -1) {
Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
assert(status.Success());
@@ -213,8 +220,9 @@ void NativeProcessFreeBSD::MonitorSIGTRAP(lldb::pid_t pid) {
llvm::Error error = t.CopyWatchpointsFrom(
static_cast<NativeThreadFreeBSD &>(*GetCurrentThread()));
if (error) {
- LLDB_LOG(log, "failed to copy watchpoints to new thread {0}: {1}",
- info.pl_lwpid, llvm::toString(std::move(error)));
+ LLDB_LOG_ERROR(log, std::move(error),
+ "failed to copy watchpoints to new thread {1}: {0}",
+ info.pl_lwpid);
SetState(StateType::eStateInvalid);
return;
}
@@ -257,6 +265,26 @@ void NativeProcessFreeBSD::MonitorSIGTRAP(lldb::pid_t pid) {
info.pl_lwpid);
}
+ if (info.pl_flags & PL_FLAG_FORKED) {
+ assert(thread);
+ MonitorClone(info.pl_child_pid, info.pl_flags & PL_FLAG_VFORKED, *thread);
+ return;
+ }
+
+ if (info.pl_flags & PL_FLAG_VFORK_DONE) {
+ assert(thread);
+ if ((m_enabled_extensions & Extension::vfork) == Extension::vfork) {
+ thread->SetStoppedByVForkDone();
+ SetState(StateType::eStateStopped, true);
+ } else {
+ Status error =
+ PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void *>(1), 0);
+ if (error.Fail())
+ SetState(StateType::eStateInvalid);
+ }
+ return;
+ }
+
if (info.pl_flags & PL_FLAG_SI) {
assert(info.pl_siginfo.si_signo == SIGTRAP);
LLDB_LOG(log, "SIGTRAP siginfo: si_code = {0}, pid = {1}",
@@ -264,19 +292,35 @@ void NativeProcessFreeBSD::MonitorSIGTRAP(lldb::pid_t pid) {
switch (info.pl_siginfo.si_code) {
case TRAP_BRKPT:
+ LLDB_LOG(log, "SIGTRAP/TRAP_BRKPT: si_addr: {0}",
+ info.pl_siginfo.si_addr);
+
if (thread) {
- thread->SetStoppedByBreakpoint();
+ auto thread_info =
+ m_threads_stepping_with_breakpoint.find(thread->GetID());
+ if (thread_info != m_threads_stepping_with_breakpoint.end()) {
+ thread->SetStoppedByTrace();
+ Status brkpt_error = RemoveBreakpoint(thread_info->second);
+ if (brkpt_error.Fail())
+ LLDB_LOG(log, "pid = {0} remove stepping breakpoint: {1}",
+ thread_info->first, brkpt_error);
+ m_threads_stepping_with_breakpoint.erase(thread_info);
+ } else
+ thread->SetStoppedByBreakpoint();
FixupBreakpointPCAsNeeded(*thread);
}
SetState(StateType::eStateStopped, true);
return;
case TRAP_TRACE:
+ LLDB_LOG(log, "SIGTRAP/TRAP_TRACE: si_addr: {0}",
+ info.pl_siginfo.si_addr);
+
if (thread) {
auto &regctx = static_cast<NativeRegisterContextFreeBSD &>(
thread->GetRegisterContext());
uint32_t wp_index = LLDB_INVALID_INDEX32;
- Status error =
- regctx.GetWatchpointHitIndex(wp_index, LLDB_INVALID_ADDRESS);
+ Status error = regctx.GetWatchpointHitIndex(
+ wp_index, reinterpret_cast<uintptr_t>(info.pl_siginfo.si_addr));
if (error.Fail())
LLDB_LOG(log,
"received error while checking for watchpoint hits, pid = "
@@ -354,6 +398,27 @@ Status NativeProcessFreeBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
return error;
}
+llvm::Expected<llvm::ArrayRef<uint8_t>>
+NativeProcessFreeBSD::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {
+ static const uint8_t g_arm_opcode[] = {0xfe, 0xde, 0xff, 0xe7};
+ static const uint8_t g_thumb_opcode[] = {0x01, 0xde};
+
+ switch (GetArchitecture().GetMachine()) {
+ case llvm::Triple::arm:
+ switch (size_hint) {
+ case 2:
+ return llvm::makeArrayRef(g_thumb_opcode);
+ case 4:
+ return llvm::makeArrayRef(g_arm_opcode);
+ default:
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Unrecognised trap opcode size hint!");
+ }
+ default:
+ return NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_hint);
+ }
+}
+
Status NativeProcessFreeBSD::Resume(const ResumeActionList &resume_actions) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
LLDB_LOG(log, "pid {0}", GetID());
@@ -623,9 +688,8 @@ size_t NativeProcessFreeBSD::UpdateThreads() { return m_threads.size(); }
Status NativeProcessFreeBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size,
bool hardware) {
if (hardware)
- return Status("NativeProcessFreeBSD does not support hardware breakpoints");
- else
- return SetSoftwareBreakpoint(addr, size);
+ return SetHardwareBreakpoint(addr, size);
+ return SetSoftwareBreakpoint(addr, size);
}
Status NativeProcessFreeBSD::GetLoadedModuleFileSpec(const char *module_path,
@@ -668,17 +732,17 @@ NativeProcessFreeBSD::GetFileLoadAddress(const llvm::StringRef &file_name,
void NativeProcessFreeBSD::SigchldHandler() {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- // Process all pending waitpid notifications.
int status;
::pid_t wait_pid =
llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WNOHANG);
if (wait_pid == 0)
- return; // We are done.
+ return;
if (wait_pid == -1) {
Status error(errno, eErrorTypePOSIX);
LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);
+ return;
}
WaitStatus wait_status = WaitStatus::Decode(status);
@@ -848,7 +912,7 @@ Status NativeProcessFreeBSD::SetupTrace() {
PtraceWrapper(PT_GET_EVENT_MASK, GetID(), &events, sizeof(events));
if (status.Fail())
return status;
- events |= PTRACE_LWP;
+ events |= PTRACE_LWP | PTRACE_FORK | PTRACE_VFORK;
status = PtraceWrapper(PT_SET_EVENT_MASK, GetID(), &events, sizeof(events));
if (status.Fail())
return status;
@@ -878,3 +942,70 @@ Status NativeProcessFreeBSD::ReinitializeThreads() {
return error;
}
+
+bool NativeProcessFreeBSD::SupportHardwareSingleStepping() const {
+ return !m_arch.IsMIPS();
+}
+
+void NativeProcessFreeBSD::MonitorClone(::pid_t child_pid, bool is_vfork,
+ NativeThreadFreeBSD &parent_thread) {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ LLDB_LOG(log, "fork, child_pid={0}", child_pid);
+
+ int status;
+ ::pid_t wait_pid =
+ llvm::sys::RetryAfterSignal(-1, ::waitpid, child_pid, &status, 0);
+ if (wait_pid != child_pid) {
+ LLDB_LOG(log,
+ "waiting for pid {0} failed. Assuming the pid has "
+ "disappeared in the meantime",
+ child_pid);
+ return;
+ }
+ if (WIFEXITED(status)) {
+ LLDB_LOG(log,
+ "waiting for pid {0} returned an 'exited' event. Not "
+ "tracking it.",
+ child_pid);
+ return;
+ }
+
+ struct ptrace_lwpinfo info;
+ const auto siginfo_err = PtraceWrapper(PT_LWPINFO, child_pid, &info, sizeof(info));
+ if (siginfo_err.Fail()) {
+ LLDB_LOG(log, "PT_LWPINFO failed {0}", siginfo_err);
+ return;
+ }
+ assert(info.pl_event == PL_EVENT_SIGNAL);
+ lldb::tid_t child_tid = info.pl_lwpid;
+
+ std::unique_ptr<NativeProcessFreeBSD> child_process{
+ new NativeProcessFreeBSD(static_cast<::pid_t>(child_pid), m_terminal_fd,
+ m_delegate, m_arch, m_main_loop)};
+ if (!is_vfork)
+ child_process->m_software_breakpoints = m_software_breakpoints;
+
+ Extension expected_ext = is_vfork ? Extension::vfork : Extension::fork;
+ if ((m_enabled_extensions & expected_ext) == expected_ext) {
+ child_process->SetupTrace();
+ for (const auto &thread : child_process->m_threads)
+ static_cast<NativeThreadFreeBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
+ child_process->SetState(StateType::eStateStopped, false);
+
+ m_delegate.NewSubprocess(this, std::move(child_process));
+ if (is_vfork)
+ parent_thread.SetStoppedByVFork(child_pid, child_tid);
+ else
+ parent_thread.SetStoppedByFork(child_pid, child_tid);
+ SetState(StateType::eStateStopped, true);
+ } else {
+ child_process->Detach();
+ Status pt_error =
+ PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1), 0);
+ if (pt_error.Fail()) {
+ LLDB_LOG_ERROR(log, pt_error.ToError(),
+ "unable to resume parent process {1}: {0}", GetID());
+ SetState(StateType::eStateInvalid);
+ }
+ }
+}
diff --git a/lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.h b/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.h
index 3c7a9400f9c4..7ec9d17d4cf4 100644
--- a/lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.h
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.h
@@ -10,6 +10,8 @@
#define liblldb_NativeProcessFreeBSD_H_
#include "Plugins/Process/POSIX/NativeProcessELF.h"
+#include "Plugins/Process/Utility/NativeProcessSoftwareSingleStep.h"
+
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/FileSpec.h"
@@ -25,7 +27,8 @@ namespace process_freebsd {
/// for debugging.
///
/// Changes in the inferior process state are broadcasted.
-class NativeProcessFreeBSD : public NativeProcessELF {
+class NativeProcessFreeBSD : public NativeProcessELF,
+ private NativeProcessSoftwareSingleStep {
public:
class Factory : public NativeProcessProtocol::Factory {
public:
@@ -36,6 +39,8 @@ public:
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
MainLoop &mainloop) const override;
+
+ Extension GetSupportedExtensions() const override;
};
// NativeProcessProtocol Interface
@@ -84,9 +89,16 @@ public:
static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr = nullptr,
int data = 0, int *result = nullptr);
+ bool SupportHardwareSingleStepping() const;
+
+protected:
+ llvm::Expected<llvm::ArrayRef<uint8_t>>
+ GetSoftwareBreakpointTrapOpcode(size_t size_hint) override;
+
private:
MainLoop::SignalHandleUP m_sigchld_handle;
ArchSpec m_arch;
+ MainLoop& m_main_loop;
LazyBool m_supports_mem_region = eLazyBoolCalculate;
std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache;
@@ -104,6 +116,8 @@ private:
void MonitorSIGSTOP(lldb::pid_t pid);
void MonitorSIGTRAP(lldb::pid_t pid);
void MonitorSignal(lldb::pid_t pid, int signal);
+ void MonitorClone(::pid_t child_pid, bool is_vfork,
+ NativeThreadFreeBSD &parent_thread);
Status PopulateMemoryRegionCache();
void SigchldHandler();
diff --git a/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.cpp
index ac3cc4fe788a..3d744f773a26 100644
--- a/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.cpp
@@ -8,7 +8,7 @@
#include "NativeRegisterContextFreeBSD.h"
-#include "Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.h"
+#include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
diff --git a/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.h b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h
index 0000484beac9..0000484beac9 100644
--- a/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.h
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.cpp
new file mode 100644
index 000000000000..c4ee3773eaeb
--- /dev/null
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.cpp
@@ -0,0 +1,202 @@
+//===-- NativeRegisterContextFreeBSD_arm.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
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__arm__)
+
+#include "NativeRegisterContextFreeBSD_arm.h"
+
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Status.h"
+
+#include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
+
+// clang-format off
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+// clang-format on
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_freebsd;
+
+NativeRegisterContextFreeBSD *
+NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+ return new NativeRegisterContextFreeBSD_arm(target_arch, native_thread);
+}
+
+NativeRegisterContextFreeBSD_arm::NativeRegisterContextFreeBSD_arm(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+ : NativeRegisterContextRegisterInfo(
+ native_thread, new RegisterInfoPOSIX_arm(target_arch)) {}
+
+RegisterInfoPOSIX_arm &
+NativeRegisterContextFreeBSD_arm::GetRegisterInfo() const {
+ return static_cast<RegisterInfoPOSIX_arm &>(*m_register_info_interface_up);
+}
+
+uint32_t NativeRegisterContextFreeBSD_arm::GetRegisterSetCount() const {
+ return GetRegisterInfo().GetRegisterSetCount();
+}
+
+const RegisterSet *
+NativeRegisterContextFreeBSD_arm::GetRegisterSet(uint32_t set_index) const {
+ return GetRegisterInfo().GetRegisterSet(set_index);
+}
+
+uint32_t NativeRegisterContextFreeBSD_arm::GetUserRegisterCount() const {
+ uint32_t count = 0;
+ for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
+ count += GetRegisterSet(set_index)->num_registers;
+ return count;
+}
+
+Status NativeRegisterContextFreeBSD_arm::ReadRegisterSet(uint32_t set) {
+ switch (set) {
+ case RegisterInfoPOSIX_arm::GPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(),
+ m_reg_data.data());
+ case RegisterInfoPOSIX_arm::FPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(
+ PT_GETVFPREGS, m_thread.GetID(),
+ m_reg_data.data() + sizeof(RegisterInfoPOSIX_arm::GPR));
+ }
+ llvm_unreachable("NativeRegisterContextFreeBSD_arm::ReadRegisterSet");
+}
+
+Status NativeRegisterContextFreeBSD_arm::WriteRegisterSet(uint32_t set) {
+ switch (set) {
+ case RegisterInfoPOSIX_arm::GPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(),
+ m_reg_data.data());
+ case RegisterInfoPOSIX_arm::FPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(
+ PT_SETVFPREGS, m_thread.GetID(),
+ m_reg_data.data() + sizeof(RegisterInfoPOSIX_arm::GPR));
+ }
+ llvm_unreachable("NativeRegisterContextFreeBSD_arm::WriteRegisterSet");
+}
+
+Status
+NativeRegisterContextFreeBSD_arm::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) {
+ Status error;
+
+ if (!reg_info) {
+ error.SetErrorString("reg_info NULL");
+ return error;
+ }
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (reg == LLDB_INVALID_REGNUM)
+ return Status("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
+
+ uint32_t set = GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg);
+ error = ReadRegisterSet(set);
+ if (error.Fail())
+ return error;
+
+ assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+ reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset,
+ reg_info->byte_size, endian::InlHostByteOrder());
+ return error;
+}
+
+Status NativeRegisterContextFreeBSD_arm::WriteRegister(
+ const RegisterInfo *reg_info, const RegisterValue &reg_value) {
+ Status error;
+
+ if (!reg_info)
+ return Status("reg_info NULL");
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (reg == LLDB_INVALID_REGNUM)
+ return Status("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
+
+ uint32_t set = GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg);
+ error = ReadRegisterSet(set);
+ if (error.Fail())
+ return error;
+
+ assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+ ::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(),
+ reg_info->byte_size);
+
+ return WriteRegisterSet(set);
+}
+
+Status NativeRegisterContextFreeBSD_arm::ReadAllRegisterValues(
+ lldb::DataBufferSP &data_sp) {
+ Status error;
+
+ error = ReadRegisterSet(RegisterInfoPOSIX_arm::GPRegSet);
+ if (error.Fail())
+ return error;
+
+ error = ReadRegisterSet(RegisterInfoPOSIX_arm::FPRegSet);
+ if (error.Fail())
+ return error;
+
+ data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0));
+ uint8_t *dst = data_sp->GetBytes();
+ ::memcpy(dst, m_reg_data.data(), m_reg_data.size());
+
+ return error;
+}
+
+Status NativeRegisterContextFreeBSD_arm::WriteAllRegisterValues(
+ const lldb::DataBufferSP &data_sp) {
+ Status error;
+
+ if (!data_sp) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextFreeBSD_arm::%s invalid data_sp provided",
+ __FUNCTION__);
+ return error;
+ }
+
+ if (data_sp->GetByteSize() != m_reg_data.size()) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextFreeBSD_arm::%s data_sp contained mismatched "
+ "data size, expected %" PRIu64 ", actual %" PRIu64,
+ __FUNCTION__, m_reg_data.size(), data_sp->GetByteSize());
+ return error;
+ }
+
+ uint8_t *src = data_sp->GetBytes();
+ if (src == nullptr) {
+ error.SetErrorStringWithFormat("NativeRegisterContextFreeBSD_arm::%s "
+ "DataBuffer::GetBytes() returned a null "
+ "pointer",
+ __FUNCTION__);
+ return error;
+ }
+ ::memcpy(m_reg_data.data(), src, m_reg_data.size());
+
+ error = WriteRegisterSet(RegisterInfoPOSIX_arm::GPRegSet);
+ if (error.Fail())
+ return error;
+
+ return WriteRegisterSet(RegisterInfoPOSIX_arm::FPRegSet);
+}
+
+llvm::Error NativeRegisterContextFreeBSD_arm::CopyHardwareWatchpointsFrom(
+ NativeRegisterContextFreeBSD &source) {
+ return llvm::Error::success();
+}
+
+#endif // defined (__arm__)
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.h b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.h
new file mode 100644
index 000000000000..4be75b958fc1
--- /dev/null
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.h
@@ -0,0 +1,68 @@
+//===-- NativeRegisterContextFreeBSD_arm.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
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__arm__)
+
+#ifndef lldb_NativeRegisterContextFreeBSD_arm_h
+#define lldb_NativeRegisterContextFreeBSD_arm_h
+
+// clang-format off
+#include <sys/types.h>
+#include <machine/reg.h>
+#include <machine/vfp.h>
+// clang-format on
+
+#include "Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h"
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
+
+#include <array>
+
+namespace lldb_private {
+namespace process_freebsd {
+
+class NativeProcessFreeBSD;
+
+class NativeRegisterContextFreeBSD_arm : public NativeRegisterContextFreeBSD {
+public:
+ NativeRegisterContextFreeBSD_arm(const ArchSpec &target_arch,
+ NativeThreadProtocol &native_thread);
+
+ uint32_t GetRegisterSetCount() const override;
+
+ uint32_t GetUserRegisterCount() const override;
+
+ const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
+
+ Status ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) override;
+
+ Status WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue &reg_value) override;
+
+ Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+
+ Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+
+ llvm::Error
+ CopyHardwareWatchpointsFrom(NativeRegisterContextFreeBSD &source) override;
+
+private:
+ std::array<uint8_t, sizeof(reg) + sizeof(vfp_state)> m_reg_data;
+
+ Status ReadRegisterSet(uint32_t set);
+ Status WriteRegisterSet(uint32_t set);
+
+ RegisterInfoPOSIX_arm &GetRegisterInfo() const;
+};
+
+} // namespace process_freebsd
+} // namespace lldb_private
+
+#endif // #ifndef lldb_NativeRegisterContextFreeBSD_arm_h
+
+#endif // defined (__arm__)
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
new file mode 100644
index 000000000000..4578138a89b3
--- /dev/null
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
@@ -0,0 +1,282 @@
+//===-- NativeRegisterContextFreeBSD_arm64.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
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__aarch64__)
+
+#include "NativeRegisterContextFreeBSD_arm64.h"
+
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Status.h"
+
+#include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"
+#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
+
+// clang-format off
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+// clang-format on
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_freebsd;
+
+NativeRegisterContextFreeBSD *
+NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+ return new NativeRegisterContextFreeBSD_arm64(target_arch, native_thread);
+}
+
+NativeRegisterContextFreeBSD_arm64::NativeRegisterContextFreeBSD_arm64(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+ : NativeRegisterContextRegisterInfo(
+ native_thread, new RegisterInfoPOSIX_arm64(target_arch, 0))
+#ifdef LLDB_HAS_FREEBSD_WATCHPOINT
+ ,
+ m_read_dbreg(false)
+#endif
+{
+ ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
+ ::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs));
+}
+
+RegisterInfoPOSIX_arm64 &
+NativeRegisterContextFreeBSD_arm64::GetRegisterInfo() const {
+ return static_cast<RegisterInfoPOSIX_arm64 &>(*m_register_info_interface_up);
+}
+
+uint32_t NativeRegisterContextFreeBSD_arm64::GetRegisterSetCount() const {
+ return GetRegisterInfo().GetRegisterSetCount();
+}
+
+const RegisterSet *
+NativeRegisterContextFreeBSD_arm64::GetRegisterSet(uint32_t set_index) const {
+ return GetRegisterInfo().GetRegisterSet(set_index);
+}
+
+uint32_t NativeRegisterContextFreeBSD_arm64::GetUserRegisterCount() const {
+ uint32_t count = 0;
+ for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
+ count += GetRegisterSet(set_index)->num_registers;
+ return count;
+}
+
+Status NativeRegisterContextFreeBSD_arm64::ReadRegisterSet(uint32_t set) {
+ switch (set) {
+ case RegisterInfoPOSIX_arm64::GPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(),
+ m_reg_data.data());
+ case RegisterInfoPOSIX_arm64::FPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(
+ PT_GETFPREGS, m_thread.GetID(),
+ m_reg_data.data() + sizeof(RegisterInfoPOSIX_arm64::GPR));
+ }
+ llvm_unreachable("NativeRegisterContextFreeBSD_arm64::ReadRegisterSet");
+}
+
+Status NativeRegisterContextFreeBSD_arm64::WriteRegisterSet(uint32_t set) {
+ switch (set) {
+ case RegisterInfoPOSIX_arm64::GPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(),
+ m_reg_data.data());
+ case RegisterInfoPOSIX_arm64::FPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(
+ PT_SETFPREGS, m_thread.GetID(),
+ m_reg_data.data() + sizeof(RegisterInfoPOSIX_arm64::GPR));
+ }
+ llvm_unreachable("NativeRegisterContextFreeBSD_arm64::WriteRegisterSet");
+}
+
+Status
+NativeRegisterContextFreeBSD_arm64::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) {
+ Status error;
+
+ if (!reg_info) {
+ error.SetErrorString("reg_info NULL");
+ return error;
+ }
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (reg == LLDB_INVALID_REGNUM)
+ return Status("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
+
+ uint32_t set = GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg);
+ error = ReadRegisterSet(set);
+ if (error.Fail())
+ return error;
+
+ assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+ reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset,
+ reg_info->byte_size, endian::InlHostByteOrder());
+ return error;
+}
+
+Status NativeRegisterContextFreeBSD_arm64::WriteRegister(
+ const RegisterInfo *reg_info, const RegisterValue &reg_value) {
+ Status error;
+
+ if (!reg_info)
+ return Status("reg_info NULL");
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (reg == LLDB_INVALID_REGNUM)
+ return Status("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
+
+ uint32_t set = GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg);
+ error = ReadRegisterSet(set);
+ if (error.Fail())
+ return error;
+
+ assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+ ::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(),
+ reg_info->byte_size);
+
+ return WriteRegisterSet(set);
+}
+
+Status NativeRegisterContextFreeBSD_arm64::ReadAllRegisterValues(
+ lldb::DataBufferSP &data_sp) {
+ Status error;
+
+ error = ReadRegisterSet(RegisterInfoPOSIX_arm64::GPRegSet);
+ if (error.Fail())
+ return error;
+
+ error = ReadRegisterSet(RegisterInfoPOSIX_arm64::FPRegSet);
+ if (error.Fail())
+ return error;
+
+ data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0));
+ uint8_t *dst = data_sp->GetBytes();
+ ::memcpy(dst, m_reg_data.data(), m_reg_data.size());
+
+ return error;
+}
+
+Status NativeRegisterContextFreeBSD_arm64::WriteAllRegisterValues(
+ const lldb::DataBufferSP &data_sp) {
+ Status error;
+
+ if (!data_sp) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextFreeBSD_arm64::%s invalid data_sp provided",
+ __FUNCTION__);
+ return error;
+ }
+
+ if (data_sp->GetByteSize() != m_reg_data.size()) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextFreeBSD_arm64::%s data_sp contained mismatched "
+ "data size, expected %" PRIu64 ", actual %" PRIu64,
+ __FUNCTION__, m_reg_data.size(), data_sp->GetByteSize());
+ return error;
+ }
+
+ uint8_t *src = data_sp->GetBytes();
+ if (src == nullptr) {
+ error.SetErrorStringWithFormat("NativeRegisterContextFreeBSD_arm64::%s "
+ "DataBuffer::GetBytes() returned a null "
+ "pointer",
+ __FUNCTION__);
+ return error;
+ }
+ ::memcpy(m_reg_data.data(), src, m_reg_data.size());
+
+ error = WriteRegisterSet(RegisterInfoPOSIX_arm64::GPRegSet);
+ if (error.Fail())
+ return error;
+
+ return WriteRegisterSet(RegisterInfoPOSIX_arm64::FPRegSet);
+}
+
+llvm::Error NativeRegisterContextFreeBSD_arm64::CopyHardwareWatchpointsFrom(
+ NativeRegisterContextFreeBSD &source) {
+#ifdef LLDB_HAS_FREEBSD_WATCHPOINT
+ auto &r_source = static_cast<NativeRegisterContextFreeBSD_arm64 &>(source);
+ llvm::Error error = r_source.ReadHardwareDebugInfo();
+ if (error)
+ return error;
+
+ m_dbreg = r_source.m_dbreg;
+ m_hbp_regs = r_source.m_hbp_regs;
+ m_hwp_regs = r_source.m_hwp_regs;
+ m_max_hbp_supported = r_source.m_max_hbp_supported;
+ m_max_hwp_supported = r_source.m_max_hwp_supported;
+ m_read_dbreg = true;
+
+ // on FreeBSD this writes both breakpoints and watchpoints
+ return WriteHardwareDebugRegs(eDREGTypeWATCH);
+#else
+ return llvm::Error::success();
+#endif
+}
+
+llvm::Error NativeRegisterContextFreeBSD_arm64::ReadHardwareDebugInfo() {
+#ifdef LLDB_HAS_FREEBSD_WATCHPOINT
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS));
+
+ // we're fully stateful, so no need to reread control registers ever
+ if (m_read_dbreg)
+ return llvm::Error::success();
+
+ Status res = NativeProcessFreeBSD::PtraceWrapper(PT_GETDBREGS,
+ m_thread.GetID(), &m_dbreg);
+ if (res.Fail())
+ return res.ToError();
+
+ LLDB_LOG(log, "m_dbreg read: debug_ver={0}, nbkpts={1}, nwtpts={2}",
+ m_dbreg.db_debug_ver, m_dbreg.db_nbkpts, m_dbreg.db_nwtpts);
+ m_max_hbp_supported = m_dbreg.db_nbkpts;
+ m_max_hwp_supported = m_dbreg.db_nwtpts;
+ assert(m_max_hbp_supported <= m_hbp_regs.size());
+ assert(m_max_hwp_supported <= m_hwp_regs.size());
+
+ m_read_dbreg = true;
+ return llvm::Error::success();
+#else
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Hardware breakpoints/watchpoints require FreeBSD 14.0");
+#endif
+}
+
+llvm::Error
+NativeRegisterContextFreeBSD_arm64::WriteHardwareDebugRegs(DREGType) {
+#ifdef LLDB_HAS_FREEBSD_WATCHPOINT
+ assert(m_read_dbreg && "dbregs must be read before writing them back");
+
+ // copy data from m_*_regs to m_dbreg before writing it back
+ for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
+ m_dbreg.db_breakregs[i].dbr_addr = m_hbp_regs[i].address;
+ m_dbreg.db_breakregs[i].dbr_ctrl = m_hbp_regs[i].control;
+ }
+ for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
+ m_dbreg.db_watchregs[i].dbw_addr = m_hwp_regs[i].address;
+ m_dbreg.db_watchregs[i].dbw_ctrl = m_hwp_regs[i].control;
+ }
+
+ return NativeProcessFreeBSD::PtraceWrapper(PT_SETDBREGS, m_thread.GetID(),
+ &m_dbreg)
+ .ToError();
+#else
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Hardware breakpoints/watchpoints require FreeBSD 14.0");
+#endif
+}
+
+#endif // defined (__aarch64__)
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h
new file mode 100644
index 000000000000..a230f8fed48a
--- /dev/null
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h
@@ -0,0 +1,86 @@
+//===-- NativeRegisterContextFreeBSD_arm64.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
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__aarch64__)
+
+#ifndef lldb_NativeRegisterContextFreeBSD_arm64_h
+#define lldb_NativeRegisterContextFreeBSD_arm64_h
+
+// clang-format off
+#include <sys/types.h>
+#include <sys/param.h>
+#include <machine/reg.h>
+// clang-format on
+
+#include "Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h"
+#include "Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h"
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
+
+#include <array>
+
+#if __FreeBSD_version >= 1300139
+# define LLDB_HAS_FREEBSD_WATCHPOINT 1
+#endif
+
+namespace lldb_private {
+namespace process_freebsd {
+
+class NativeProcessFreeBSD;
+
+class NativeRegisterContextFreeBSD_arm64
+ : public NativeRegisterContextFreeBSD,
+ public NativeRegisterContextDBReg_arm64 {
+public:
+ NativeRegisterContextFreeBSD_arm64(const ArchSpec &target_arch,
+ NativeThreadProtocol &native_thread);
+
+ uint32_t GetRegisterSetCount() const override;
+
+ uint32_t GetUserRegisterCount() const override;
+
+ const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
+
+ Status ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) override;
+
+ Status WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue &reg_value) override;
+
+ Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+
+ Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+
+ llvm::Error
+ CopyHardwareWatchpointsFrom(NativeRegisterContextFreeBSD &source) override;
+
+private:
+ // Due to alignment, FreeBSD reg/fpreg are a few bytes larger than
+ // LLDB's GPR/FPU structs. However, all fields have matching offsets
+ // and sizes, so we do not have to worry about these (and we have
+ // a unittest to assert that).
+ std::array<uint8_t, sizeof(reg) + sizeof(fpreg)> m_reg_data;
+#ifdef LLDB_HAS_FREEBSD_WATCHPOINT
+ dbreg m_dbreg;
+ bool m_read_dbreg;
+#endif
+
+ Status ReadRegisterSet(uint32_t set);
+ Status WriteRegisterSet(uint32_t set);
+
+ llvm::Error ReadHardwareDebugInfo() override;
+ llvm::Error WriteHardwareDebugRegs(DREGType hwbType) override;
+
+ RegisterInfoPOSIX_arm64 &GetRegisterInfo() const;
+};
+
+} // namespace process_freebsd
+} // namespace lldb_private
+
+#endif // #ifndef lldb_NativeRegisterContextFreeBSD_arm64_h
+
+#endif // defined (__aarch64__)
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp
new file mode 100644
index 000000000000..8e722c09314c
--- /dev/null
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp
@@ -0,0 +1,186 @@
+//===-- NativeRegisterContextFreeBSD_mips64.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
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__mips64__)
+
+#include "NativeRegisterContextFreeBSD_mips64.h"
+
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Status.h"
+
+#include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"
+
+// clang-format off
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+// clang-format on
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_freebsd;
+
+NativeRegisterContextFreeBSD *
+NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+ return new NativeRegisterContextFreeBSD_mips64(target_arch, native_thread);
+}
+
+NativeRegisterContextFreeBSD_mips64::NativeRegisterContextFreeBSD_mips64(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+ : NativeRegisterContextRegisterInfo(
+ native_thread, new RegisterContextFreeBSD_mips64(target_arch)) {}
+
+RegisterContextFreeBSD_mips64 &
+NativeRegisterContextFreeBSD_mips64::GetRegisterInfo() const {
+ return static_cast<RegisterContextFreeBSD_mips64 &>(
+ *m_register_info_interface_up);
+}
+
+uint32_t NativeRegisterContextFreeBSD_mips64::GetRegisterSetCount() const {
+ return GetRegisterInfo().GetRegisterSetCount();
+}
+
+const RegisterSet *
+NativeRegisterContextFreeBSD_mips64::GetRegisterSet(uint32_t set_index) const {
+ return GetRegisterInfo().GetRegisterSet(set_index);
+}
+
+uint32_t NativeRegisterContextFreeBSD_mips64::GetUserRegisterCount() const {
+ uint32_t count = 0;
+ for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
+ count += GetRegisterSet(set_index)->num_registers;
+ return count;
+}
+
+Status NativeRegisterContextFreeBSD_mips64::ReadRegisterSet(RegSetKind set) {
+ switch (set) {
+ case GPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(),
+ m_reg_data.data());
+ }
+ llvm_unreachable("NativeRegisterContextFreeBSD_mips64::ReadRegisterSet");
+}
+
+Status NativeRegisterContextFreeBSD_mips64::WriteRegisterSet(RegSetKind set) {
+ switch (set) {
+ case GPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(),
+ m_reg_data.data());
+ }
+ llvm_unreachable("NativeRegisterContextFreeBSD_mips64::WriteRegisterSet");
+}
+
+Status
+NativeRegisterContextFreeBSD_mips64::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) {
+ Status error;
+
+ if (!reg_info) {
+ error.SetErrorString("reg_info NULL");
+ return error;
+ }
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (reg == LLDB_INVALID_REGNUM)
+ return Status("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
+
+ RegSetKind set = GPRegSet;
+ error = ReadRegisterSet(set);
+ if (error.Fail())
+ return error;
+
+ assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+ reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset,
+ reg_info->byte_size, endian::InlHostByteOrder());
+ return error;
+}
+
+Status NativeRegisterContextFreeBSD_mips64::WriteRegister(
+ const RegisterInfo *reg_info, const RegisterValue &reg_value) {
+ Status error;
+
+ if (!reg_info)
+ return Status("reg_info NULL");
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (reg == LLDB_INVALID_REGNUM)
+ return Status("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
+
+ RegSetKind set = GPRegSet;
+ error = ReadRegisterSet(set);
+ if (error.Fail())
+ return error;
+
+ assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+ ::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(),
+ reg_info->byte_size);
+
+ return WriteRegisterSet(set);
+}
+
+Status NativeRegisterContextFreeBSD_mips64::ReadAllRegisterValues(
+ lldb::DataBufferSP &data_sp) {
+ Status error;
+
+ error = ReadRegisterSet(GPRegSet);
+ if (error.Fail())
+ return error;
+
+ data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0));
+ uint8_t *dst = data_sp->GetBytes();
+ ::memcpy(dst, m_reg_data.data(), m_reg_data.size());
+
+ return error;
+}
+
+Status NativeRegisterContextFreeBSD_mips64::WriteAllRegisterValues(
+ const lldb::DataBufferSP &data_sp) {
+ Status error;
+
+ if (!data_sp) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextFreeBSD_mips64::%s invalid data_sp provided",
+ __FUNCTION__);
+ return error;
+ }
+
+ if (data_sp->GetByteSize() != m_reg_data.size()) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextFreeBSD_mips64::%s data_sp contained mismatched "
+ "data size, expected %" PRIu64 ", actual %" PRIu64,
+ __FUNCTION__, m_reg_data.size(), data_sp->GetByteSize());
+ return error;
+ }
+
+ uint8_t *src = data_sp->GetBytes();
+ if (src == nullptr) {
+ error.SetErrorStringWithFormat("NativeRegisterContextFreeBSD_mips64::%s "
+ "DataBuffer::GetBytes() returned a null "
+ "pointer",
+ __FUNCTION__);
+ return error;
+ }
+ ::memcpy(m_reg_data.data(), src, m_reg_data.size());
+
+ return WriteRegisterSet(GPRegSet);
+}
+
+llvm::Error NativeRegisterContextFreeBSD_mips64::CopyHardwareWatchpointsFrom(
+ NativeRegisterContextFreeBSD &source) {
+ return llvm::Error::success();
+}
+
+#endif // defined (__mips64__)
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.h b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.h
new file mode 100644
index 000000000000..6a3eb86a9231
--- /dev/null
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.h
@@ -0,0 +1,71 @@
+//===-- NativeRegisterContextFreeBSD_mips64.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
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__mips64__)
+
+#ifndef lldb_NativeRegisterContextFreeBSD_mips64_h
+#define lldb_NativeRegisterContextFreeBSD_mips64_h
+
+// clang-format off
+#include <sys/types.h>
+#include <machine/reg.h>
+// clang-format on
+
+#include "Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
+
+#include <array>
+
+namespace lldb_private {
+namespace process_freebsd {
+
+class NativeProcessFreeBSD;
+
+class NativeRegisterContextFreeBSD_mips64
+ : public NativeRegisterContextFreeBSD {
+public:
+ NativeRegisterContextFreeBSD_mips64(const ArchSpec &target_arch,
+ NativeThreadProtocol &native_thread);
+
+ uint32_t GetRegisterSetCount() const override;
+
+ uint32_t GetUserRegisterCount() const override;
+
+ const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
+
+ Status ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) override;
+
+ Status WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue &reg_value) override;
+
+ Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+
+ Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+
+ llvm::Error
+ CopyHardwareWatchpointsFrom(NativeRegisterContextFreeBSD &source) override;
+
+private:
+ enum RegSetKind {
+ GPRegSet,
+ };
+ std::array<uint8_t, sizeof(reg)> m_reg_data;
+
+ Status ReadRegisterSet(RegSetKind set);
+ Status WriteRegisterSet(RegSetKind set);
+
+ RegisterContextFreeBSD_mips64 &GetRegisterInfo() const;
+};
+
+} // namespace process_freebsd
+} // namespace lldb_private
+
+#endif // #ifndef lldb_NativeRegisterContextFreeBSD_mips64_h
+
+#endif // defined (__mips64__)
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.cpp
new file mode 100644
index 000000000000..5b5d44a308b1
--- /dev/null
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.cpp
@@ -0,0 +1,289 @@
+//===-- NativeRegisterContextFreeBSD_powerpc.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
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__powerpc__)
+
+#include "NativeRegisterContextFreeBSD_powerpc.h"
+
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Status.h"
+
+#include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"
+// for register enum definitions
+#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
+
+// clang-format off
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+// clang-format on
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_freebsd;
+
+static const uint32_t g_gpr_regnums[] = {
+ gpr_r0_powerpc, gpr_r1_powerpc, gpr_r2_powerpc, gpr_r3_powerpc,
+ gpr_r4_powerpc, gpr_r5_powerpc, gpr_r6_powerpc, gpr_r7_powerpc,
+ gpr_r8_powerpc, gpr_r9_powerpc, gpr_r10_powerpc, gpr_r11_powerpc,
+ gpr_r12_powerpc, gpr_r13_powerpc, gpr_r14_powerpc, gpr_r15_powerpc,
+ gpr_r16_powerpc, gpr_r17_powerpc, gpr_r18_powerpc, gpr_r19_powerpc,
+ gpr_r20_powerpc, gpr_r21_powerpc, gpr_r22_powerpc, gpr_r23_powerpc,
+ gpr_r24_powerpc, gpr_r25_powerpc, gpr_r26_powerpc, gpr_r27_powerpc,
+ gpr_r28_powerpc, gpr_r29_powerpc, gpr_r30_powerpc, gpr_r31_powerpc,
+ gpr_lr_powerpc, gpr_cr_powerpc, gpr_xer_powerpc, gpr_ctr_powerpc,
+ gpr_pc_powerpc,
+};
+
+static const uint32_t g_fpr_regnums[] = {
+ fpr_f0_powerpc, fpr_f1_powerpc, fpr_f2_powerpc, fpr_f3_powerpc,
+ fpr_f4_powerpc, fpr_f5_powerpc, fpr_f6_powerpc, fpr_f7_powerpc,
+ fpr_f8_powerpc, fpr_f9_powerpc, fpr_f10_powerpc, fpr_f11_powerpc,
+ fpr_f12_powerpc, fpr_f13_powerpc, fpr_f14_powerpc, fpr_f15_powerpc,
+ fpr_f16_powerpc, fpr_f17_powerpc, fpr_f18_powerpc, fpr_f19_powerpc,
+ fpr_f20_powerpc, fpr_f21_powerpc, fpr_f22_powerpc, fpr_f23_powerpc,
+ fpr_f24_powerpc, fpr_f25_powerpc, fpr_f26_powerpc, fpr_f27_powerpc,
+ fpr_f28_powerpc, fpr_f29_powerpc, fpr_f30_powerpc, fpr_f31_powerpc,
+ fpr_fpscr_powerpc,
+};
+
+// Number of register sets provided by this context.
+enum { k_num_register_sets = 2 };
+
+static const RegisterSet g_reg_sets_powerpc[k_num_register_sets] = {
+ {"General Purpose Registers", "gpr", k_num_gpr_registers_powerpc,
+ g_gpr_regnums},
+ {"Floating Point Registers", "fpr", k_num_fpr_registers_powerpc,
+ g_fpr_regnums},
+};
+
+NativeRegisterContextFreeBSD *
+NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+ return new NativeRegisterContextFreeBSD_powerpc(target_arch, native_thread);
+}
+
+static RegisterInfoInterface *
+CreateRegisterInfoInterface(const ArchSpec &target_arch) {
+ if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) {
+ return new RegisterContextFreeBSD_powerpc32(target_arch);
+ } else {
+ assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
+ "Register setting path assumes this is a 64-bit host");
+ return new RegisterContextFreeBSD_powerpc64(target_arch);
+ }
+}
+
+NativeRegisterContextFreeBSD_powerpc::NativeRegisterContextFreeBSD_powerpc(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+ : NativeRegisterContextRegisterInfo(
+ native_thread, CreateRegisterInfoInterface(target_arch)) {}
+
+RegisterContextFreeBSD_powerpc &
+NativeRegisterContextFreeBSD_powerpc::GetRegisterInfo() const {
+ return static_cast<RegisterContextFreeBSD_powerpc &>(
+ *m_register_info_interface_up);
+}
+
+uint32_t NativeRegisterContextFreeBSD_powerpc::GetRegisterSetCount() const {
+ return k_num_register_sets;
+}
+
+const RegisterSet *
+NativeRegisterContextFreeBSD_powerpc::GetRegisterSet(uint32_t set_index) const {
+ switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
+ case llvm::Triple::ppc:
+ return &g_reg_sets_powerpc[set_index];
+ default:
+ llvm_unreachable("Unhandled target architecture.");
+ }
+}
+
+llvm::Optional<NativeRegisterContextFreeBSD_powerpc::RegSetKind>
+NativeRegisterContextFreeBSD_powerpc::GetSetForNativeRegNum(
+ uint32_t reg_num) const {
+ switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
+ case llvm::Triple::ppc:
+ if (reg_num >= k_first_gpr_powerpc && reg_num <= k_last_gpr_powerpc)
+ return GPRegSet;
+ if (reg_num >= k_first_fpr && reg_num <= k_last_fpr)
+ return FPRegSet;
+ break;
+ default:
+ llvm_unreachable("Unhandled target architecture.");
+ }
+
+ llvm_unreachable("Register does not belong to any register set");
+}
+
+uint32_t NativeRegisterContextFreeBSD_powerpc::GetUserRegisterCount() const {
+ uint32_t count = 0;
+ for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
+ count += GetRegisterSet(set_index)->num_registers;
+ return count;
+}
+
+Status NativeRegisterContextFreeBSD_powerpc::ReadRegisterSet(RegSetKind set) {
+ switch (set) {
+ case GPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(),
+ m_reg_data.data());
+ case FPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_GETFPREGS, m_thread.GetID(),
+ m_reg_data.data() + sizeof(reg));
+ }
+ llvm_unreachable("NativeRegisterContextFreeBSD_powerpc::ReadRegisterSet");
+}
+
+Status NativeRegisterContextFreeBSD_powerpc::WriteRegisterSet(RegSetKind set) {
+ switch (set) {
+ case GPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(),
+ m_reg_data.data());
+ case FPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_SETFPREGS, m_thread.GetID(),
+ m_reg_data.data() + sizeof(reg));
+ }
+ llvm_unreachable("NativeRegisterContextFreeBSD_powerpc::WriteRegisterSet");
+}
+
+Status
+NativeRegisterContextFreeBSD_powerpc::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) {
+ Status error;
+
+ if (!reg_info) {
+ error.SetErrorString("reg_info NULL");
+ return error;
+ }
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (reg == LLDB_INVALID_REGNUM)
+ return Status("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
+
+ llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);
+ if (!opt_set) {
+ // This is likely an internal register for lldb use only and should not be
+ // directly queried.
+ error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
+ reg_info->name);
+ return error;
+ }
+
+ RegSetKind set = opt_set.getValue();
+ error = ReadRegisterSet(set);
+ if (error.Fail())
+ return error;
+
+ assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+ reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset,
+ reg_info->byte_size, endian::InlHostByteOrder());
+ return error;
+}
+
+Status NativeRegisterContextFreeBSD_powerpc::WriteRegister(
+ const RegisterInfo *reg_info, const RegisterValue &reg_value) {
+ Status error;
+
+ if (!reg_info)
+ return Status("reg_info NULL");
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (reg == LLDB_INVALID_REGNUM)
+ return Status("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
+
+ llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);
+ if (!opt_set) {
+ // This is likely an internal register for lldb use only and should not be
+ // directly queried.
+ error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
+ reg_info->name);
+ return error;
+ }
+
+ RegSetKind set = opt_set.getValue();
+ error = ReadRegisterSet(set);
+ if (error.Fail())
+ return error;
+
+ assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+ ::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(),
+ reg_info->byte_size);
+
+ return WriteRegisterSet(set);
+}
+
+Status NativeRegisterContextFreeBSD_powerpc::ReadAllRegisterValues(
+ lldb::DataBufferSP &data_sp) {
+ Status error;
+
+ error = ReadRegisterSet(GPRegSet);
+ if (error.Fail())
+ return error;
+
+ error = ReadRegisterSet(FPRegSet);
+ if (error.Fail())
+ return error;
+
+ data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0));
+ uint8_t *dst = data_sp->GetBytes();
+ ::memcpy(dst, m_reg_data.data(), m_reg_data.size());
+
+ return error;
+}
+
+Status NativeRegisterContextFreeBSD_powerpc::WriteAllRegisterValues(
+ const lldb::DataBufferSP &data_sp) {
+ Status error;
+
+ if (!data_sp) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextFreeBSD_powerpc::%s invalid data_sp provided",
+ __FUNCTION__);
+ return error;
+ }
+
+ if (data_sp->GetByteSize() != m_reg_data.size()) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextFreeBSD_powerpc::%s data_sp contained mismatched "
+ "data size, expected %zu, actual %" PRIu64,
+ __FUNCTION__, m_reg_data.size(), data_sp->GetByteSize());
+ return error;
+ }
+
+ uint8_t *src = data_sp->GetBytes();
+ if (src == nullptr) {
+ error.SetErrorStringWithFormat("NativeRegisterContextFreeBSD_powerpc::%s "
+ "DataBuffer::GetBytes() returned a null "
+ "pointer",
+ __FUNCTION__);
+ return error;
+ }
+ ::memcpy(m_reg_data.data(), src, m_reg_data.size());
+
+ error = WriteRegisterSet(GPRegSet);
+ if (error.Fail())
+ return error;
+
+ return WriteRegisterSet(FPRegSet);
+}
+
+llvm::Error NativeRegisterContextFreeBSD_powerpc::CopyHardwareWatchpointsFrom(
+ NativeRegisterContextFreeBSD &source) {
+ return llvm::Error::success();
+}
+
+#endif // defined (__powerpc__)
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.h b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.h
new file mode 100644
index 000000000000..884c25988ce1
--- /dev/null
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.h
@@ -0,0 +1,74 @@
+//===-- NativeRegisterContextFreeBSD_powerpc.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
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__powerpc__)
+
+#ifndef lldb_NativeRegisterContextFreeBSD_powerpc_h
+#define lldb_NativeRegisterContextFreeBSD_powerpc_h
+
+// clang-format off
+#include <sys/types.h>
+#include <machine/reg.h>
+// clang-format on
+
+#include "Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
+
+#include <array>
+
+namespace lldb_private {
+namespace process_freebsd {
+
+class NativeProcessFreeBSD;
+
+class NativeRegisterContextFreeBSD_powerpc
+ : public NativeRegisterContextFreeBSD {
+public:
+ NativeRegisterContextFreeBSD_powerpc(const ArchSpec &target_arch,
+ NativeThreadProtocol &native_thread);
+
+ uint32_t GetRegisterSetCount() const override;
+
+ uint32_t GetUserRegisterCount() const override;
+
+ const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
+
+ Status ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) override;
+
+ Status WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue &reg_value) override;
+
+ Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+
+ Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+
+ llvm::Error
+ CopyHardwareWatchpointsFrom(NativeRegisterContextFreeBSD &source) override;
+
+private:
+ enum RegSetKind {
+ GPRegSet,
+ FPRegSet,
+ };
+ std::array<uint8_t, sizeof(reg) + sizeof(fpreg)> m_reg_data;
+
+ llvm::Optional<RegSetKind> GetSetForNativeRegNum(uint32_t reg_num) const;
+
+ Status ReadRegisterSet(RegSetKind set);
+ Status WriteRegisterSet(RegSetKind set);
+
+ RegisterContextFreeBSD_powerpc &GetRegisterInfo() const;
+};
+
+} // namespace process_freebsd
+} // namespace lldb_private
+
+#endif // #ifndef lldb_NativeRegisterContextFreeBSD_powerpc_h
+
+#endif // defined (__powerpc__)
diff --git a/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp
index d5052e7d1b3a..9328d606ad26 100644
--- a/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp
@@ -260,7 +260,7 @@ NativeRegisterContextFreeBSD_x86_64::NativeRegisterContextFreeBSD_x86_64(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
: NativeRegisterContextRegisterInfo(
native_thread, CreateRegisterInfoInterface(target_arch)),
- m_regset_offsets({0}) {
+ NativeRegisterContextDBReg_x86(native_thread), m_regset_offsets({0}) {
assert(m_gpr.size() == GetRegisterInfoInterface().GetGPRSize());
std::array<uint32_t, MaxRegSet + 1> first_regnos;
diff --git a/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.h b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.h
index 673cffd6e849..efd0f91f77b9 100644
--- a/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.h
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.h
@@ -20,9 +20,9 @@
#include <array>
-#include "Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.h"
+#include "Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h"
#include "Plugins/Process/Utility/RegisterContext_x86.h"
-#include "Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.h"
+#include "Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h"
#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
#define LLDB_INVALID_XSAVE_OFFSET UINT32_MAX
@@ -34,7 +34,7 @@ class NativeProcessFreeBSD;
class NativeRegisterContextFreeBSD_x86_64
: public NativeRegisterContextFreeBSD,
- public NativeRegisterContextWatchpoint_x86 {
+ public NativeRegisterContextDBReg_x86 {
public:
NativeRegisterContextFreeBSD_x86_64(const ArchSpec &target_arch,
NativeThreadProtocol &native_thread);
diff --git a/lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp
index 43494871be07..80b3527aebce 100644
--- a/lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp
@@ -46,6 +46,11 @@ Status NativeThreadFreeBSD::Resume() {
if (!ret.Success())
return ret;
ret = NativeProcessFreeBSD::PtraceWrapper(PT_CLEARSTEP, GetID());
+ // we can get EINVAL if the architecture in question does not support
+ // hardware single-stepping -- that's fine, we have nothing to clear
+ // then
+ if (ret.GetError() == EINVAL)
+ ret.Clear();
if (ret.Success())
SetRunning();
return ret;
@@ -125,6 +130,30 @@ void NativeThreadFreeBSD::SetStoppedByWatchpoint(uint32_t wp_index) {
m_stop_info.details.signal.signo = SIGTRAP;
}
+void NativeThreadFreeBSD::SetStoppedByFork(lldb::pid_t child_pid,
+ lldb::tid_t child_tid) {
+ SetStopped();
+
+ m_stop_info.reason = StopReason::eStopReasonFork;
+ m_stop_info.details.fork.child_pid = child_pid;
+ m_stop_info.details.fork.child_tid = child_tid;
+}
+
+void NativeThreadFreeBSD::SetStoppedByVFork(lldb::pid_t child_pid,
+ lldb::tid_t child_tid) {
+ SetStopped();
+
+ m_stop_info.reason = StopReason::eStopReasonVFork;
+ m_stop_info.details.fork.child_pid = child_pid;
+ m_stop_info.details.fork.child_tid = child_tid;
+}
+
+void NativeThreadFreeBSD::SetStoppedByVForkDone() {
+ SetStopped();
+
+ m_stop_info.reason = StopReason::eStopReasonVForkDone;
+}
+
void NativeThreadFreeBSD::SetStoppedWithNoReason() {
SetStopped();
diff --git a/lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.h b/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h
index 4e997b3fb4bb..3ec6daa409e4 100644
--- a/lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.h
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h
@@ -11,7 +11,7 @@
#include "lldb/Host/common/NativeThreadProtocol.h"
-#include "Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.h"
+#include "Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h"
#include <csignal>
#include <map>
@@ -59,6 +59,9 @@ private:
void SetStoppedByTrace();
void SetStoppedByExec();
void SetStoppedByWatchpoint(uint32_t wp_index);
+ void SetStoppedByFork(lldb::pid_t child_pid, lldb::tid_t child_tid);
+ void SetStoppedByVFork(lldb::pid_t child_pid, lldb::tid_t child_tid);
+ void SetStoppedByVForkDone();
void SetStoppedWithNoReason();
void SetStopped();
void SetRunning();
diff --git a/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp b/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp
deleted file mode 100644
index 4e6f3afda0ab..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-//===-- POSIXStopInfo.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 "POSIXStopInfo.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-//===----------------------------------------------------------------------===//
-// POSIXLimboStopInfo
-
-POSIXLimboStopInfo::~POSIXLimboStopInfo() {}
-
-lldb::StopReason POSIXLimboStopInfo::GetStopReason() const {
- return lldb::eStopReasonThreadExiting;
-}
-
-const char *POSIXLimboStopInfo::GetDescription() { return "thread exiting"; }
-
-bool POSIXLimboStopInfo::ShouldStop(Event *event_ptr) { return false; }
-
-bool POSIXLimboStopInfo::ShouldNotify(Event *event_ptr) { return false; }
-
-//===----------------------------------------------------------------------===//
-// POSIXNewThreadStopInfo
-
-POSIXNewThreadStopInfo::~POSIXNewThreadStopInfo() {}
-
-lldb::StopReason POSIXNewThreadStopInfo::GetStopReason() const {
- return lldb::eStopReasonNone;
-}
-
-const char *POSIXNewThreadStopInfo::GetDescription() {
- return "thread spawned";
-}
-
-bool POSIXNewThreadStopInfo::ShouldStop(Event *event_ptr) { return false; }
-
-bool POSIXNewThreadStopInfo::ShouldNotify(Event *event_ptr) { return false; }
diff --git a/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h b/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h
deleted file mode 100644
index 5a022c485b68..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h
+++ /dev/null
@@ -1,66 +0,0 @@
-//===-- POSIXStopInfo.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_POSIXStopInfo_H_
-#define liblldb_POSIXStopInfo_H_
-
-#include "FreeBSDThread.h"
-#include "Plugins/Process/POSIX/CrashReason.h"
-#include "lldb/Target/StopInfo.h"
-#include <string>
-
-//===----------------------------------------------------------------------===//
-/// \class POSIXStopInfo
-/// Simple base class for all POSIX-specific StopInfo objects.
-///
-class POSIXStopInfo : public lldb_private::StopInfo {
-public:
- POSIXStopInfo(lldb_private::Thread &thread, uint32_t status)
- : StopInfo(thread, status) {}
-};
-
-//===----------------------------------------------------------------------===//
-/// \class POSIXLimboStopInfo
-/// Represents the stop state of a process ready to exit.
-///
-class POSIXLimboStopInfo : public POSIXStopInfo {
-public:
- POSIXLimboStopInfo(FreeBSDThread &thread) : POSIXStopInfo(thread, 0) {}
-
- ~POSIXLimboStopInfo();
-
- lldb::StopReason GetStopReason() const override;
-
- const char *GetDescription() override;
-
- bool ShouldStop(lldb_private::Event *event_ptr) override;
-
- bool ShouldNotify(lldb_private::Event *event_ptr) override;
-};
-
-//===----------------------------------------------------------------------===//
-/// \class POSIXNewThreadStopInfo
-/// Represents the stop state of process when a new thread is spawned.
-///
-
-class POSIXNewThreadStopInfo : public POSIXStopInfo {
-public:
- POSIXNewThreadStopInfo(FreeBSDThread &thread) : POSIXStopInfo(thread, 0) {}
-
- ~POSIXNewThreadStopInfo();
-
- lldb::StopReason GetStopReason() const override;
-
- const char *GetDescription() override;
-
- bool ShouldStop(lldb_private::Event *event_ptr) override;
-
- bool ShouldNotify(lldb_private::Event *event_ptr) override;
-};
-
-#endif
diff --git a/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
deleted file mode 100644
index a1fe45b84ca2..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
+++ /dev/null
@@ -1,1080 +0,0 @@
-//===-- ProcessFreeBSD.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 <errno.h>
-#include <pthread.h>
-#include <pthread_np.h>
-#include <stdlib.h>
-#include <sys/sysctl.h>
-#include <sys/types.h>
-#include <sys/user.h>
-#include <machine/elf.h>
-
-#include <mutex>
-#include <unordered_map>
-
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Host/FileSystem.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Target/DynamicLoader.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Utility/RegisterValue.h"
-#include "lldb/Utility/State.h"
-
-#include "FreeBSDThread.h"
-#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
-#include "Plugins/Process/Utility/FreeBSDSignals.h"
-#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
-#include "ProcessFreeBSD.h"
-#include "ProcessMonitor.h"
-
-#include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Breakpoint/Watchpoint.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Target/DynamicLoader.h"
-#include "lldb/Target/Platform.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Utility/DataBufferHeap.h"
-#include "lldb/Utility/FileSpec.h"
-#include "lldb/Utility/State.h"
-
-#include "lldb/Host/posix/Fcntl.h"
-
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Threading.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-LLDB_PLUGIN_DEFINE(ProcessFreeBSD)
-
-namespace {
-UnixSignalsSP &GetFreeBSDSignals() {
- static UnixSignalsSP s_freebsd_signals_sp(new FreeBSDSignals());
- return s_freebsd_signals_sp;
-}
-}
-
-// Static functions.
-
-lldb::ProcessSP
-ProcessFreeBSD::CreateInstance(lldb::TargetSP target_sp,
- lldb::ListenerSP listener_sp,
- const FileSpec *crash_file_path,
- bool can_connect) {
- lldb::ProcessSP process_sp;
- if (crash_file_path == NULL && !can_connect)
- process_sp.reset(
- new ProcessFreeBSD(target_sp, listener_sp, GetFreeBSDSignals()));
- return process_sp;
-}
-
-void ProcessFreeBSD::Initialize() {
- static llvm::once_flag g_once_flag;
-
- llvm::call_once(g_once_flag, []() {
- PluginManager::RegisterPlugin(GetPluginNameStatic(),
- GetPluginDescriptionStatic(), CreateInstance);
- });
-}
-
-lldb_private::ConstString ProcessFreeBSD::GetPluginNameStatic() {
- static ConstString g_name("freebsd");
- return g_name;
-}
-
-const char *ProcessFreeBSD::GetPluginDescriptionStatic() {
- return "Process plugin for FreeBSD";
-}
-
-// ProcessInterface protocol.
-
-lldb_private::ConstString ProcessFreeBSD::GetPluginName() {
- return GetPluginNameStatic();
-}
-
-uint32_t ProcessFreeBSD::GetPluginVersion() { return 1; }
-
-void ProcessFreeBSD::Terminate() {}
-
-Status ProcessFreeBSD::DoDetach(bool keep_stopped) {
- Status error;
- if (keep_stopped) {
- error.SetErrorString("Detaching with keep_stopped true is not currently "
- "supported on FreeBSD.");
- return error;
- }
-
- error = m_monitor->Detach(GetID());
-
- if (error.Success())
- SetPrivateState(eStateDetached);
-
- return error;
-}
-
-Status ProcessFreeBSD::DoResume() {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
-
- SetPrivateState(eStateRunning);
-
- std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
- bool do_step = false;
- bool software_single_step = !SupportHardwareSingleStepping();
-
- for (tid_collection::const_iterator t_pos = m_run_tids.begin(),
- t_end = m_run_tids.end();
- t_pos != t_end; ++t_pos) {
- m_monitor->ThreadSuspend(*t_pos, false);
- }
- for (tid_collection::const_iterator t_pos = m_step_tids.begin(),
- t_end = m_step_tids.end();
- t_pos != t_end; ++t_pos) {
- m_monitor->ThreadSuspend(*t_pos, false);
- do_step = true;
- if (software_single_step) {
- Status error = SetupSoftwareSingleStepping(*t_pos);
- if (error.Fail())
- return error;
- }
- }
- for (tid_collection::const_iterator t_pos = m_suspend_tids.begin(),
- t_end = m_suspend_tids.end();
- t_pos != t_end; ++t_pos) {
- m_monitor->ThreadSuspend(*t_pos, true);
- // XXX Cannot PT_CONTINUE properly with suspended threads.
- do_step = true;
- }
-
- LLDB_LOGF(log, "process %" PRIu64 " resuming (%s)", GetID(),
- do_step ? "step" : "continue");
- if (do_step && !software_single_step)
- m_monitor->SingleStep(GetID(), m_resume_signo);
- else
- m_monitor->Resume(GetID(), m_resume_signo);
-
- return Status();
-}
-
-bool ProcessFreeBSD::DoUpdateThreadList(ThreadList &old_thread_list,
- ThreadList &new_thread_list) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- LLDB_LOGF(log, "ProcessFreeBSD::%s (pid = %" PRIu64 ")", __FUNCTION__,
- GetID());
-
- std::vector<lldb::pid_t> tds;
- if (!GetMonitor().GetCurrentThreadIDs(tds)) {
- return false;
- }
-
- ThreadList old_thread_list_copy(old_thread_list);
- for (size_t i = 0; i < tds.size(); ++i) {
- tid_t tid = tds[i];
- ThreadSP thread_sp(old_thread_list_copy.RemoveThreadByID(tid, false));
- if (!thread_sp) {
- thread_sp.reset(new FreeBSDThread(*this, tid));
- LLDB_LOGF(log, "ProcessFreeBSD::%s new tid = %" PRIu64, __FUNCTION__,
- tid);
- } else {
- LLDB_LOGF(log, "ProcessFreeBSD::%s existing tid = %" PRIu64, __FUNCTION__,
- tid);
- }
- new_thread_list.AddThread(thread_sp);
- }
- for (size_t i = 0; i < old_thread_list_copy.GetSize(false); ++i) {
- ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false));
- if (old_thread_sp) {
- LLDB_LOGF(log, "ProcessFreeBSD::%s remove tid", __FUNCTION__);
- }
- }
-
- return true;
-}
-
-Status ProcessFreeBSD::WillResume() {
- m_resume_signo = 0;
- m_suspend_tids.clear();
- m_run_tids.clear();
- m_step_tids.clear();
- return Process::WillResume();
-}
-
-void ProcessFreeBSD::SendMessage(const ProcessMessage &message) {
- std::lock_guard<std::recursive_mutex> guard(m_message_mutex);
-
- switch (message.GetKind()) {
- case ProcessMessage::eInvalidMessage:
- return;
-
- case ProcessMessage::eAttachMessage:
- SetPrivateState(eStateStopped);
- return;
-
- case ProcessMessage::eLimboMessage:
- case ProcessMessage::eExitMessage:
- SetExitStatus(message.GetExitStatus(), NULL);
- break;
-
- case ProcessMessage::eSignalMessage:
- case ProcessMessage::eSignalDeliveredMessage:
- case ProcessMessage::eBreakpointMessage:
- case ProcessMessage::eTraceMessage:
- case ProcessMessage::eWatchpointMessage:
- case ProcessMessage::eCrashMessage:
- SetPrivateState(eStateStopped);
- break;
-
- case ProcessMessage::eNewThreadMessage:
- llvm_unreachable("eNewThreadMessage unexpected on FreeBSD");
- break;
-
- case ProcessMessage::eExecMessage:
- SetPrivateState(eStateStopped);
- break;
- }
-
- m_message_queue.push(message);
-}
-
-// Constructors and destructors.
-
-ProcessFreeBSD::ProcessFreeBSD(lldb::TargetSP target_sp,
- lldb::ListenerSP listener_sp,
- UnixSignalsSP &unix_signals_sp)
- : Process(target_sp, listener_sp, unix_signals_sp),
- m_byte_order(endian::InlHostByteOrder()), m_monitor(NULL), m_module(NULL),
- m_message_mutex(), m_exit_now(false), m_seen_initial_stop(),
- m_resume_signo(0) {
- // FIXME: Putting this code in the ctor and saving the byte order in a
- // member variable is a hack to avoid const qual issues in GetByteOrder.
- lldb::ModuleSP module = GetTarget().GetExecutableModule();
- if (module && module->GetObjectFile())
- m_byte_order = module->GetObjectFile()->GetByteOrder();
-}
-
-ProcessFreeBSD::~ProcessFreeBSD() { delete m_monitor; }
-
-// Process protocol.
-void ProcessFreeBSD::Finalize() {
- Process::Finalize();
-
- if (m_monitor)
- m_monitor->StopMonitor();
-}
-
-bool ProcessFreeBSD::CanDebug(lldb::TargetSP target_sp,
- bool plugin_specified_by_name) {
- // For now we are just making sure the file exists for a given module
- ModuleSP exe_module_sp(target_sp->GetExecutableModule());
- if (exe_module_sp.get())
- return FileSystem::Instance().Exists(exe_module_sp->GetFileSpec());
- // If there is no executable module, we return true since we might be
- // preparing to attach.
- return true;
-}
-
-Status
-ProcessFreeBSD::DoAttachToProcessWithID(lldb::pid_t pid,
- const ProcessAttachInfo &attach_info) {
- Status error;
- assert(m_monitor == NULL);
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- LLDB_LOGV(log, "pid = {0}", GetID());
-
- m_monitor = new ProcessMonitor(this, pid, error);
-
- if (!error.Success())
- return error;
-
- PlatformSP platform_sp(GetTarget().GetPlatform());
- assert(platform_sp.get());
- if (!platform_sp)
- return error; // FIXME: Detatch?
-
- // Find out what we can about this process
- ProcessInstanceInfo process_info;
- platform_sp->GetProcessInfo(pid, process_info);
-
- // Resolve the executable module
- ModuleSP exe_module_sp;
- FileSpecList executable_search_paths(
- Target::GetDefaultExecutableSearchPaths());
- ModuleSpec exe_module_spec(process_info.GetExecutableFile(),
- GetTarget().GetArchitecture());
- error = platform_sp->ResolveExecutable(
- exe_module_spec, exe_module_sp,
- executable_search_paths.GetSize() ? &executable_search_paths : NULL);
- if (!error.Success())
- return error;
-
- // Fix the target architecture if necessary
- const ArchSpec &module_arch = exe_module_sp->GetArchitecture();
- if (module_arch.IsValid() &&
- !GetTarget().GetArchitecture().IsExactMatch(module_arch))
- GetTarget().SetArchitecture(module_arch);
-
- // Initialize the target module list
- GetTarget().SetExecutableModule(exe_module_sp, eLoadDependentsYes);
-
- SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());
-
- SetID(pid);
-
- return error;
-}
-
-Status ProcessFreeBSD::WillLaunch(Module *module) {
- Status error;
- return error;
-}
-
-FileSpec
-ProcessFreeBSD::GetFileSpec(const lldb_private::FileAction *file_action,
- const FileSpec &default_file_spec,
- const FileSpec &dbg_pts_file_spec) {
- FileSpec file_spec{};
-
- if (file_action && file_action->GetAction() == FileAction::eFileActionOpen) {
- file_spec = file_action->GetFileSpec();
- // By default the stdio paths passed in will be pseudo-terminal (/dev/pts).
- // If so, convert to using a different default path instead to redirect I/O
- // to the debugger console. This should also handle user overrides to
- // /dev/null or a different file.
- if (!file_spec || file_spec == dbg_pts_file_spec)
- file_spec = default_file_spec;
- }
- return file_spec;
-}
-
-Status ProcessFreeBSD::DoLaunch(Module *module,
- ProcessLaunchInfo &launch_info) {
- Status error;
- assert(m_monitor == NULL);
-
- FileSpec working_dir = launch_info.GetWorkingDirectory();
- if (working_dir) {
- FileSystem::Instance().Resolve(working_dir);
- if (!FileSystem::Instance().IsDirectory(working_dir.GetPath())) {
- error.SetErrorStringWithFormat("No such file or directory: %s",
- working_dir.GetCString());
- return error;
- }
- }
-
- SetPrivateState(eStateLaunching);
-
- const lldb_private::FileAction *file_action;
-
- // Default of empty will mean to use existing open file descriptors
- FileSpec stdin_file_spec{};
- FileSpec stdout_file_spec{};
- FileSpec stderr_file_spec{};
-
- const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSecondaryName()};
-
- file_action = launch_info.GetFileActionForFD(STDIN_FILENO);
- stdin_file_spec =
- GetFileSpec(file_action, stdin_file_spec, dbg_pts_file_spec);
-
- file_action = launch_info.GetFileActionForFD(STDOUT_FILENO);
- stdout_file_spec =
- GetFileSpec(file_action, stdout_file_spec, dbg_pts_file_spec);
-
- file_action = launch_info.GetFileActionForFD(STDERR_FILENO);
- stderr_file_spec =
- GetFileSpec(file_action, stderr_file_spec, dbg_pts_file_spec);
-
- m_monitor = new ProcessMonitor(
- this, module, launch_info.GetArguments().GetConstArgumentVector(),
- launch_info.GetEnvironment(), stdin_file_spec, stdout_file_spec,
- stderr_file_spec, working_dir, launch_info, error);
-
- m_module = module;
-
- if (!error.Success())
- return error;
-
- int terminal = m_monitor->GetTerminalFD();
- if (terminal >= 0) {
-// The reader thread will close the file descriptor when done, so we pass it a
-// copy.
-#ifdef F_DUPFD_CLOEXEC
- int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0);
- if (stdio == -1) {
- error.SetErrorToErrno();
- return error;
- }
-#else
- // Special case when F_DUPFD_CLOEXEC does not exist (Debian kFreeBSD)
- int stdio = fcntl(terminal, F_DUPFD, 0);
- if (stdio == -1) {
- error.SetErrorToErrno();
- return error;
- }
- stdio = fcntl(terminal, F_SETFD, FD_CLOEXEC);
- if (stdio == -1) {
- error.SetErrorToErrno();
- return error;
- }
-#endif
- SetSTDIOFileDescriptor(stdio);
- }
-
- SetID(m_monitor->GetPID());
- return error;
-}
-
-void ProcessFreeBSD::DidLaunch() {}
-
-addr_t ProcessFreeBSD::GetImageInfoAddress() {
- Target *target = &GetTarget();
- ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
- Address addr = obj_file->GetImageInfoAddress(target);
-
- if (addr.IsValid())
- return addr.GetLoadAddress(target);
- return LLDB_INVALID_ADDRESS;
-}
-
-Status ProcessFreeBSD::DoHalt(bool &caused_stop) {
- Status error;
-
- if (IsStopped()) {
- caused_stop = false;
- } else if (kill(GetID(), SIGSTOP)) {
- caused_stop = false;
- error.SetErrorToErrno();
- } else {
- caused_stop = true;
- }
- return error;
-}
-
-Status ProcessFreeBSD::DoSignal(int signal) {
- Status error;
-
- if (kill(GetID(), signal))
- error.SetErrorToErrno();
-
- return error;
-}
-
-Status ProcessFreeBSD::DoDestroy() {
- Status error;
-
- if (!HasExited()) {
- assert(m_monitor);
- m_exit_now = true;
- if (GetID() == LLDB_INVALID_PROCESS_ID) {
- error.SetErrorString("invalid process id");
- return error;
- }
- if (!m_monitor->Kill()) {
- error.SetErrorToErrno();
- return error;
- }
-
- SetPrivateState(eStateExited);
- }
-
- return error;
-}
-
-void ProcessFreeBSD::DoDidExec() {
- Target *target = &GetTarget();
- if (target) {
- PlatformSP platform_sp(target->GetPlatform());
- assert(platform_sp.get());
- if (platform_sp) {
- ProcessInstanceInfo process_info;
- platform_sp->GetProcessInfo(GetID(), process_info);
- ModuleSP exe_module_sp;
- ModuleSpec exe_module_spec(process_info.GetExecutableFile(),
- target->GetArchitecture());
- FileSpecList executable_search_paths(
- Target::GetDefaultExecutableSearchPaths());
- Status error = platform_sp->ResolveExecutable(
- exe_module_spec, exe_module_sp,
- executable_search_paths.GetSize() ? &executable_search_paths : NULL);
- if (!error.Success())
- return;
- target->SetExecutableModule(exe_module_sp, eLoadDependentsYes);
- }
- }
-}
-
-bool ProcessFreeBSD::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid) {
- bool added_to_set = false;
- ThreadStopSet::iterator it = m_seen_initial_stop.find(stop_tid);
- if (it == m_seen_initial_stop.end()) {
- m_seen_initial_stop.insert(stop_tid);
- added_to_set = true;
- }
- return added_to_set;
-}
-
-bool ProcessFreeBSD::WaitingForInitialStop(lldb::tid_t stop_tid) {
- return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end());
-}
-
-FreeBSDThread *
-ProcessFreeBSD::CreateNewFreeBSDThread(lldb_private::Process &process,
- lldb::tid_t tid) {
- return new FreeBSDThread(process, tid);
-}
-
-void ProcessFreeBSD::RefreshStateAfterStop() {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- LLDB_LOGV(log, "message_queue size = {0}", m_message_queue.size());
-
- std::lock_guard<std::recursive_mutex> guard(m_message_mutex);
-
- // This method used to only handle one message. Changing it to loop allows
- // it to handle the case where we hit a breakpoint while handling a different
- // breakpoint.
- while (!m_message_queue.empty()) {
- ProcessMessage &message = m_message_queue.front();
-
- // Resolve the thread this message corresponds to and pass it along.
- lldb::tid_t tid = message.GetTID();
- LLDB_LOGV(log, " message_queue size = {0}, pid = {1}",
- m_message_queue.size(), tid);
-
- m_thread_list.RefreshStateAfterStop();
-
- FreeBSDThread *thread = static_cast<FreeBSDThread *>(
- GetThreadList().FindThreadByID(tid, false).get());
- if (thread)
- thread->Notify(message);
-
- if (message.GetKind() == ProcessMessage::eExitMessage) {
- // FIXME: We should tell the user about this, but the limbo message is
- // probably better for that.
- LLDB_LOG(log, "removing thread, tid = {0}", tid);
- std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
-
- ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false);
- thread_sp.reset();
- m_seen_initial_stop.erase(tid);
- }
-
- m_message_queue.pop();
- }
-}
-
-bool ProcessFreeBSD::IsAlive() {
- StateType state = GetPrivateState();
- return state != eStateDetached && state != eStateExited &&
- state != eStateInvalid && state != eStateUnloaded;
-}
-
-size_t ProcessFreeBSD::DoReadMemory(addr_t vm_addr, void *buf, size_t size,
- Status &error) {
- assert(m_monitor);
- return m_monitor->ReadMemory(vm_addr, buf, size, error);
-}
-
-size_t ProcessFreeBSD::DoWriteMemory(addr_t vm_addr, const void *buf,
- size_t size, Status &error) {
- assert(m_monitor);
- return m_monitor->WriteMemory(vm_addr, buf, size, error);
-}
-
-addr_t ProcessFreeBSD::DoAllocateMemory(size_t size, uint32_t permissions,
- Status &error) {
- addr_t allocated_addr = LLDB_INVALID_ADDRESS;
-
- unsigned prot = 0;
- if (permissions & lldb::ePermissionsReadable)
- prot |= eMmapProtRead;
- if (permissions & lldb::ePermissionsWritable)
- prot |= eMmapProtWrite;
- if (permissions & lldb::ePermissionsExecutable)
- prot |= eMmapProtExec;
-
- if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
- eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
- m_addr_to_mmap_size[allocated_addr] = size;
- error.Clear();
- } else {
- allocated_addr = LLDB_INVALID_ADDRESS;
- error.SetErrorStringWithFormat(
- "unable to allocate %zu bytes of memory with permissions %s", size,
- GetPermissionsAsCString(permissions));
- }
-
- return allocated_addr;
-}
-
-Status ProcessFreeBSD::DoDeallocateMemory(lldb::addr_t addr) {
- Status error;
- MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
- if (pos != m_addr_to_mmap_size.end() &&
- InferiorCallMunmap(this, addr, pos->second))
- m_addr_to_mmap_size.erase(pos);
- else
- error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64,
- addr);
-
- return error;
-}
-
-size_t
-ProcessFreeBSD::GetSoftwareBreakpointTrapOpcode(BreakpointSite *bp_site) {
- static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x20, 0xD4};
- static const uint8_t g_i386_opcode[] = {0xCC};
-
- ArchSpec arch = GetTarget().GetArchitecture();
- const uint8_t *opcode = NULL;
- size_t opcode_size = 0;
-
- switch (arch.GetMachine()) {
- default:
- assert(false && "CPU type not supported!");
- break;
-
- case llvm::Triple::arm: {
- // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the
- // linux kernel does otherwise.
- static const uint8_t g_arm_breakpoint_opcode[] = {0xf0, 0x01, 0xf0, 0xe7};
- static const uint8_t g_thumb_breakpoint_opcode[] = {0x01, 0xde};
-
- lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0));
- AddressClass addr_class = AddressClass::eUnknown;
-
- if (bp_loc_sp)
- addr_class = bp_loc_sp->GetAddress().GetAddressClass();
-
- if (addr_class == AddressClass::eCodeAlternateISA ||
- (addr_class == AddressClass::eUnknown &&
- bp_loc_sp->GetAddress().GetOffset() & 1)) {
- opcode = g_thumb_breakpoint_opcode;
- opcode_size = sizeof(g_thumb_breakpoint_opcode);
- } else {
- opcode = g_arm_breakpoint_opcode;
- opcode_size = sizeof(g_arm_breakpoint_opcode);
- }
- } break;
- case llvm::Triple::aarch64:
- opcode = g_aarch64_opcode;
- opcode_size = sizeof(g_aarch64_opcode);
- break;
-
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- opcode = g_i386_opcode;
- opcode_size = sizeof(g_i386_opcode);
- break;
- }
-
- bp_site->SetTrapOpcode(opcode, opcode_size);
- return opcode_size;
-}
-
-Status ProcessFreeBSD::EnableBreakpointSite(BreakpointSite *bp_site) {
- if (bp_site->HardwareRequired())
- return Status("Hardware breakpoints are not supported.");
-
- return EnableSoftwareBreakpoint(bp_site);
-}
-
-Status ProcessFreeBSD::DisableBreakpointSite(BreakpointSite *bp_site) {
- return DisableSoftwareBreakpoint(bp_site);
-}
-
-Status ProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify) {
- Status error;
- if (wp) {
- user_id_t watchID = wp->GetID();
- addr_t addr = wp->GetLoadAddress();
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- LLDB_LOGF(log, "ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 ")",
- watchID);
- if (wp->IsEnabled()) {
- LLDB_LOGF(log,
- "ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64
- ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.",
- watchID, (uint64_t)addr);
- return error;
- }
-
- // Try to find a vacant watchpoint slot in the inferiors' main thread
- uint32_t wp_hw_index = LLDB_INVALID_INDEX32;
- std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
- FreeBSDThread *thread = static_cast<FreeBSDThread *>(
- m_thread_list.GetThreadAtIndex(0, false).get());
-
- if (thread)
- wp_hw_index = thread->FindVacantWatchpointIndex();
-
- if (wp_hw_index == LLDB_INVALID_INDEX32) {
- error.SetErrorString("Setting hardware watchpoint failed.");
- } else {
- wp->SetHardwareIndex(wp_hw_index);
- bool wp_enabled = true;
- uint32_t thread_count = m_thread_list.GetSize(false);
- for (uint32_t i = 0; i < thread_count; ++i) {
- thread = static_cast<FreeBSDThread *>(
- m_thread_list.GetThreadAtIndex(i, false).get());
- if (thread)
- wp_enabled &= thread->EnableHardwareWatchpoint(wp);
- else
- wp_enabled = false;
- }
- if (wp_enabled) {
- wp->SetEnabled(true, notify);
- return error;
- } else {
- // Watchpoint enabling failed on at least one of the threads so roll
- // back all of them
- DisableWatchpoint(wp, false);
- error.SetErrorString("Setting hardware watchpoint failed");
- }
- }
- } else
- error.SetErrorString("Watchpoint argument was NULL.");
- return error;
-}
-
-Status ProcessFreeBSD::DisableWatchpoint(Watchpoint *wp, bool notify) {
- Status error;
- if (wp) {
- user_id_t watchID = wp->GetID();
- addr_t addr = wp->GetLoadAddress();
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- LLDB_LOGF(log, "ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 ")",
- watchID);
- if (!wp->IsEnabled()) {
- LLDB_LOGF(log,
- "ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64
- ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.",
- watchID, (uint64_t)addr);
- // This is needed (for now) to keep watchpoints disabled correctly
- wp->SetEnabled(false, notify);
- return error;
- }
-
- if (wp->IsHardware()) {
- bool wp_disabled = true;
- std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
- uint32_t thread_count = m_thread_list.GetSize(false);
- for (uint32_t i = 0; i < thread_count; ++i) {
- FreeBSDThread *thread = static_cast<FreeBSDThread *>(
- m_thread_list.GetThreadAtIndex(i, false).get());
- if (thread)
- wp_disabled &= thread->DisableHardwareWatchpoint(wp);
- else
- wp_disabled = false;
- }
- if (wp_disabled) {
- wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
- wp->SetEnabled(false, notify);
- return error;
- } else
- error.SetErrorString("Disabling hardware watchpoint failed");
- }
- } else
- error.SetErrorString("Watchpoint argument was NULL.");
- return error;
-}
-
-Status ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num) {
- Status error;
- std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
- FreeBSDThread *thread = static_cast<FreeBSDThread *>(
- m_thread_list.GetThreadAtIndex(0, false).get());
- if (thread)
- num = thread->NumSupportedHardwareWatchpoints();
- else
- error.SetErrorString("Process does not exist.");
- return error;
-}
-
-Status ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num, bool &after) {
- Status error = GetWatchpointSupportInfo(num);
- // Watchpoints trigger and halt the inferior after the corresponding
- // instruction has been executed.
- after = true;
- return error;
-}
-
-uint32_t ProcessFreeBSD::UpdateThreadListIfNeeded() {
- std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
- // Do not allow recursive updates.
- return m_thread_list.GetSize(false);
-}
-
-ByteOrder ProcessFreeBSD::GetByteOrder() const {
- // FIXME: We should be able to extract this value directly. See comment in
- // ProcessFreeBSD().
- return m_byte_order;
-}
-
-size_t ProcessFreeBSD::PutSTDIN(const char *buf, size_t len, Status &error) {
- ssize_t status;
- if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0) {
- error.SetErrorToErrno();
- return 0;
- }
- return status;
-}
-
-// Utility functions.
-
-bool ProcessFreeBSD::HasExited() {
- switch (GetPrivateState()) {
- default:
- break;
-
- case eStateDetached:
- case eStateExited:
- return true;
- }
-
- return false;
-}
-
-bool ProcessFreeBSD::IsStopped() {
- switch (GetPrivateState()) {
- default:
- break;
-
- case eStateStopped:
- case eStateCrashed:
- case eStateSuspended:
- return true;
- }
-
- return false;
-}
-
-bool ProcessFreeBSD::IsAThreadRunning() {
- bool is_running = false;
- std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
- uint32_t thread_count = m_thread_list.GetSize(false);
- for (uint32_t i = 0; i < thread_count; ++i) {
- FreeBSDThread *thread = static_cast<FreeBSDThread *>(
- m_thread_list.GetThreadAtIndex(i, false).get());
- StateType thread_state = thread->GetState();
- if (thread_state == eStateRunning || thread_state == eStateStepping) {
- is_running = true;
- break;
- }
- }
- return is_running;
-}
-
-lldb_private::DataExtractor ProcessFreeBSD::GetAuxvData() {
- // If we're the local platform, we can ask the host for auxv data.
- PlatformSP platform_sp = GetTarget().GetPlatform();
- assert(platform_sp && platform_sp->IsHost());
-
- int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_AUXV, (int)m_process->GetID()};
- size_t auxv_size = AT_COUNT * sizeof(Elf_Auxinfo);
- DataBufferSP buf_sp(new DataBufferHeap(auxv_size, 0));
-
- if (::sysctl(mib, 4, buf_sp->GetBytes(), &auxv_size, NULL, 0) != 0) {
- perror("sysctl failed on auxv");
- buf_sp.reset();
- }
-
- return DataExtractor(buf_sp, GetByteOrder(), GetAddressByteSize());
-}
-
-struct EmulatorBaton {
- ProcessFreeBSD *m_process;
- RegisterContext *m_reg_context;
-
- // eRegisterKindDWARF -> RegisterValue
- std::unordered_map<uint32_t, RegisterValue> m_register_values;
-
- EmulatorBaton(ProcessFreeBSD *process, RegisterContext *reg_context)
- : m_process(process), m_reg_context(reg_context) {}
-};
-
-static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton,
- const EmulateInstruction::Context &context,
- lldb::addr_t addr, void *dst, size_t length) {
- EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
-
- Status error;
- size_t bytes_read =
- emulator_baton->m_process->DoReadMemory(addr, dst, length, error);
- if (!error.Success())
- bytes_read = 0;
- return bytes_read;
-}
-
-static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton,
- const RegisterInfo *reg_info,
- RegisterValue &reg_value) {
- EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
-
- auto it = emulator_baton->m_register_values.find(
- reg_info->kinds[eRegisterKindDWARF]);
- if (it != emulator_baton->m_register_values.end()) {
- reg_value = it->second;
- return true;
- }
-
- // The emulator only fills in the dwarf register numbers (and in some cases
- // the generic register numbers). Get the full register info from the
- // register context based on the dwarf register numbers.
- const RegisterInfo *full_reg_info =
- emulator_baton->m_reg_context->GetRegisterInfo(
- eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]);
-
- bool error =
- emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value);
- return error;
-}
-
-static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton,
- const EmulateInstruction::Context &context,
- const RegisterInfo *reg_info,
- const RegisterValue &reg_value) {
- EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
- emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] =
- reg_value;
- return true;
-}
-
-static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton,
- const EmulateInstruction::Context &context,
- lldb::addr_t addr, const void *dst,
- size_t length) {
- return length;
-}
-
-bool ProcessFreeBSD::SingleStepBreakpointHit(
- void *baton, lldb_private::StoppointCallbackContext *context,
- lldb::user_id_t break_id, lldb::user_id_t break_loc_id) {
- return false;
-}
-
-Status ProcessFreeBSD::SetSoftwareSingleStepBreakpoint(lldb::tid_t tid,
- lldb::addr_t addr) {
- Status error;
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- if (log) {
- LLDB_LOGF(log, "ProcessFreeBSD::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
- LLDB_LOGF(log, "SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__,
- addr);
- }
-
- // Validate the address.
- if (addr == LLDB_INVALID_ADDRESS)
- return Status("ProcessFreeBSD::%s invalid load address specified.",
- __FUNCTION__);
-
- Breakpoint *const sw_step_break =
- m_process->GetTarget().CreateBreakpoint(addr, true, false).get();
- sw_step_break->SetCallback(SingleStepBreakpointHit, this, true);
- sw_step_break->SetBreakpointKind("software-single-step");
-
- LLDB_LOGF(log, "ProcessFreeBSD::%s addr = 0x%" PRIx64 " -- SUCCESS",
- __FUNCTION__, addr);
-
- m_threads_stepping_with_breakpoint.insert({tid, sw_step_break->GetID()});
- return Status();
-}
-
-bool ProcessFreeBSD::IsSoftwareStepBreakpoint(lldb::tid_t tid) {
- ThreadSP thread = GetThreadList().FindThreadByID(tid);
- if (!thread)
- return false;
-
- assert(thread->GetRegisterContext());
- lldb::addr_t stop_pc = thread->GetRegisterContext()->GetPC();
-
- const auto &iter = m_threads_stepping_with_breakpoint.find(tid);
- if (iter == m_threads_stepping_with_breakpoint.end())
- return false;
-
- lldb::break_id_t bp_id = iter->second;
- BreakpointSP bp = GetTarget().GetBreakpointByID(bp_id);
- if (!bp)
- return false;
-
- BreakpointLocationSP bp_loc = bp->FindLocationByAddress(stop_pc);
- if (!bp_loc)
- return false;
-
- GetTarget().RemoveBreakpointByID(bp_id);
- m_threads_stepping_with_breakpoint.erase(tid);
- return true;
-}
-
-bool ProcessFreeBSD::SupportHardwareSingleStepping() const {
- lldb_private::ArchSpec arch = GetTarget().GetArchitecture();
- if (arch.GetMachine() == llvm::Triple::arm || arch.IsMIPS())
- return false;
- return true;
-}
-
-Status ProcessFreeBSD::SetupSoftwareSingleStepping(lldb::tid_t tid) {
- std::unique_ptr<EmulateInstruction> emulator_up(
- EmulateInstruction::FindPlugin(GetTarget().GetArchitecture(),
- eInstructionTypePCModifying, nullptr));
-
- if (emulator_up == nullptr)
- return Status("Instruction emulator not found!");
-
- FreeBSDThread *thread = static_cast<FreeBSDThread *>(
- m_thread_list.FindThreadByID(tid, false).get());
- if (thread == NULL)
- return Status("Thread not found not found!");
-
- lldb::RegisterContextSP register_context_sp = thread->GetRegisterContext();
-
- EmulatorBaton baton(this, register_context_sp.get());
- emulator_up->SetBaton(&baton);
- emulator_up->SetReadMemCallback(&ReadMemoryCallback);
- emulator_up->SetReadRegCallback(&ReadRegisterCallback);
- emulator_up->SetWriteMemCallback(&WriteMemoryCallback);
- emulator_up->SetWriteRegCallback(&WriteRegisterCallback);
-
- if (!emulator_up->ReadInstruction())
- return Status("Read instruction failed!");
-
- bool emulation_result =
- emulator_up->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
- const RegisterInfo *reg_info_pc = register_context_sp->GetRegisterInfo(
- eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
- auto pc_it =
- baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]);
-
- lldb::addr_t next_pc;
- if (emulation_result) {
- assert(pc_it != baton.m_register_values.end() &&
- "Emulation was successful but PC wasn't updated");
- next_pc = pc_it->second.GetAsUInt64();
- } else if (pc_it == baton.m_register_values.end()) {
- // Emulate instruction failed and it haven't changed PC. Advance PC with
- // the size of the current opcode because the emulation of all
- // PC modifying instruction should be successful. The failure most
- // likely caused by a not supported instruction which don't modify PC.
- next_pc =
- register_context_sp->GetPC() + emulator_up->GetOpcode().GetByteSize();
- } else {
- // The instruction emulation failed after it modified the PC. It is an
- // unknown error where we can't continue because the next instruction is
- // modifying the PC but we don't know how.
- return Status("Instruction emulation failed unexpectedly");
- }
-
- SetSoftwareSingleStepBreakpoint(tid, next_pc);
- return Status();
-}
diff --git a/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h b/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
deleted file mode 100644
index b60bcd279021..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
+++ /dev/null
@@ -1,221 +0,0 @@
-//===-- ProcessFreeBSD.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_ProcessFreeBSD_H_
-#define liblldb_ProcessFreeBSD_H_
-
-#include "Plugins/Process/POSIX/ProcessMessage.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/ThreadList.h"
-#include <mutex>
-#include <queue>
-#include <set>
-
-class ProcessMonitor;
-class FreeBSDThread;
-
-class ProcessFreeBSD : public lldb_private::Process {
-
-public:
- // Static functions.
- static lldb::ProcessSP
- CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
- const lldb_private::FileSpec *crash_file_path,
- bool can_connect);
-
- static void Initialize();
-
- static void Terminate();
-
- static lldb_private::ConstString GetPluginNameStatic();
-
- static const char *GetPluginDescriptionStatic();
-
- // Constructors and destructors
- ProcessFreeBSD(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
- lldb::UnixSignalsSP &unix_signals_sp);
-
- ~ProcessFreeBSD();
-
- virtual lldb_private::Status WillResume() override;
-
- // PluginInterface protocol
- virtual lldb_private::ConstString GetPluginName() override;
-
- virtual uint32_t GetPluginVersion() override;
-
-public:
- // Process protocol.
- void Finalize() override;
-
- bool CanDebug(lldb::TargetSP target_sp,
- bool plugin_specified_by_name) override;
-
- lldb_private::Status WillLaunch(lldb_private::Module *module) override;
-
- lldb_private::Status DoAttachToProcessWithID(
- lldb::pid_t pid,
- const lldb_private::ProcessAttachInfo &attach_info) override;
-
- lldb_private::Status
- DoLaunch(lldb_private::Module *exe_module,
- lldb_private::ProcessLaunchInfo &launch_info) override;
-
- void DidLaunch() override;
-
- lldb_private::Status DoResume() override;
-
- lldb_private::Status DoHalt(bool &caused_stop) override;
-
- lldb_private::Status DoDetach(bool keep_stopped) override;
-
- lldb_private::Status DoSignal(int signal) override;
-
- lldb_private::Status DoDestroy() override;
-
- void DoDidExec() override;
-
- void RefreshStateAfterStop() override;
-
- bool IsAlive() override;
-
- size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
- lldb_private::Status &error) override;
-
- size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
- lldb_private::Status &error) override;
-
- lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions,
- lldb_private::Status &error) override;
-
- lldb_private::Status DoDeallocateMemory(lldb::addr_t ptr) override;
-
- virtual size_t
- GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite *bp_site);
-
- lldb_private::Status
- EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
-
- lldb_private::Status
- DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
-
- lldb_private::Status EnableWatchpoint(lldb_private::Watchpoint *wp,
- bool notify = true) override;
-
- lldb_private::Status DisableWatchpoint(lldb_private::Watchpoint *wp,
- bool notify = true) override;
-
- lldb_private::Status GetWatchpointSupportInfo(uint32_t &num) override;
-
- lldb_private::Status GetWatchpointSupportInfo(uint32_t &num,
- bool &after) override;
-
- virtual uint32_t UpdateThreadListIfNeeded();
-
- bool DoUpdateThreadList(lldb_private::ThreadList &old_thread_list,
- lldb_private::ThreadList &new_thread_list) override;
-
- virtual lldb::ByteOrder GetByteOrder() const;
-
- lldb::addr_t GetImageInfoAddress() override;
-
- size_t PutSTDIN(const char *buf, size_t len,
- lldb_private::Status &error) override;
-
- lldb_private::DataExtractor GetAuxvData() override;
-
- // ProcessFreeBSD internal API.
-
- /// Registers the given message with this process.
- virtual void SendMessage(const ProcessMessage &message);
-
- ProcessMonitor &GetMonitor() {
- assert(m_monitor);
- return *m_monitor;
- }
-
- lldb_private::FileSpec
- GetFileSpec(const lldb_private::FileAction *file_action,
- const lldb_private::FileSpec &default_file_spec,
- const lldb_private::FileSpec &dbg_pts_file_spec);
-
- /// Adds the thread to the list of threads for which we have received the
- /// initial stopping signal.
- /// The \p stop_tid parameter indicates the thread which the stop happened
- /// for.
- bool AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid);
-
- bool WaitingForInitialStop(lldb::tid_t stop_tid);
-
- virtual FreeBSDThread *CreateNewFreeBSDThread(lldb_private::Process &process,
- lldb::tid_t tid);
-
- static bool SingleStepBreakpointHit(
- void *baton, lldb_private::StoppointCallbackContext *context,
- lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
-
- lldb_private::Status SetupSoftwareSingleStepping(lldb::tid_t tid);
-
- lldb_private::Status SetSoftwareSingleStepBreakpoint(lldb::tid_t tid,
- lldb::addr_t addr);
-
- bool IsSoftwareStepBreakpoint(lldb::tid_t tid);
-
- bool SupportHardwareSingleStepping() const;
-
- typedef std::vector<lldb::tid_t> tid_collection;
- tid_collection &GetStepTids() { return m_step_tids; }
-
-protected:
- static const size_t MAX_TRAP_OPCODE_SIZE = 8;
-
- /// Target byte order.
- lldb::ByteOrder m_byte_order;
-
- /// Process monitor;
- ProcessMonitor *m_monitor;
-
- /// The module we are executing.
- lldb_private::Module *m_module;
-
- /// Message queue notifying this instance of inferior process state changes.
- std::recursive_mutex m_message_mutex;
- std::queue<ProcessMessage> m_message_queue;
-
- /// Drive any exit events to completion.
- bool m_exit_now;
-
- /// Returns true if the process has exited.
- bool HasExited();
-
- /// Returns true if the process is stopped.
- bool IsStopped();
-
- /// Returns true if at least one running is currently running
- bool IsAThreadRunning();
-
- typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
- MMapMap m_addr_to_mmap_size;
-
- typedef std::set<lldb::tid_t> ThreadStopSet;
- /// Every thread begins with a stop signal. This keeps track
- /// of the threads for which we have received the stop signal.
- ThreadStopSet m_seen_initial_stop;
-
- friend class FreeBSDThread;
-
- tid_collection m_suspend_tids;
- tid_collection m_run_tids;
- tid_collection m_step_tids;
- std::map<lldb::tid_t, lldb::break_id_t> m_threads_stepping_with_breakpoint;
-
- int m_resume_signo;
-};
-
-#endif // liblldb_ProcessFreeBSD_H_
diff --git a/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
deleted file mode 100644
index 4637458b53c3..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ /dev/null
@@ -1,1424 +0,0 @@
-//===-- ProcessMonitor.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 <errno.h>
-#include <poll.h>
-#include <signal.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/ptrace.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include "lldb/Host/Host.h"
-#include "lldb/Host/PseudoTerminal.h"
-#include "lldb/Host/ThreadLauncher.h"
-#include "lldb/Target/RegisterContext.h"
-#include "lldb/Target/Thread.h"
-#include "lldb/Target/UnixSignals.h"
-#include "lldb/Utility/RegisterValue.h"
-#include "lldb/Utility/Scalar.h"
-#include "lldb/Utility/Status.h"
-#include "llvm/Support/Errno.h"
-
-#include "FreeBSDThread.h"
-#include "Plugins/Process/POSIX/CrashReason.h"
-#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
-#include "ProcessFreeBSD.h"
-#include "ProcessMonitor.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-// Wrapper for ptrace to catch errors and log calls.
-
-const char *Get_PT_IO_OP(int op) {
- switch (op) {
- case PIOD_READ_D:
- return "READ_D";
- case PIOD_WRITE_D:
- return "WRITE_D";
- case PIOD_READ_I:
- return "READ_I";
- case PIOD_WRITE_I:
- return "WRITE_I";
- default:
- return "Unknown op";
- }
-}
-
-// Wrapper for ptrace to catch errors and log calls. Note that ptrace sets
-// errno on error because -1 is reserved as a valid result.
-extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data,
- const char *reqName, const char *file, int line) {
- long int result;
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
-
- if (log) {
- LLDB_LOGF(log,
- "ptrace(%s, %" PRIu64 ", %p, %x) called from file %s line %d",
- reqName, pid, addr, data, file, line);
- if (req == PT_IO) {
- struct ptrace_io_desc *pi = (struct ptrace_io_desc *)addr;
-
- LLDB_LOGF(log, "PT_IO: op=%s offs=%zx size=%zu",
- Get_PT_IO_OP(pi->piod_op), (size_t)pi->piod_offs, pi->piod_len);
- }
- }
-
- // PtraceDisplayBytes(req, data);
-
- errno = 0;
- result = ptrace(req, pid, (caddr_t)addr, data);
-
- // PtraceDisplayBytes(req, data);
-
- if (log && errno != 0) {
- const char *str;
- switch (errno) {
- case ESRCH:
- str = "ESRCH";
- break;
- case EINVAL:
- str = "EINVAL";
- break;
- case EBUSY:
- str = "EBUSY";
- break;
- case EPERM:
- str = "EPERM";
- break;
- default:
- str = "<unknown>";
- }
- LLDB_LOGF(log, "ptrace() failed; errno=%d (%s)", errno, str);
- }
-
- if (log) {
-#ifdef __amd64__
- if (req == PT_GETREGS) {
- struct reg *r = (struct reg *)addr;
-
- LLDB_LOGF(log, "PT_GETREGS: rip=0x%lx rsp=0x%lx rbp=0x%lx rax=0x%lx",
- r->r_rip, r->r_rsp, r->r_rbp, r->r_rax);
- }
- if (req == PT_GETDBREGS || req == PT_SETDBREGS) {
- struct dbreg *r = (struct dbreg *)addr;
- char setget = (req == PT_GETDBREGS) ? 'G' : 'S';
-
- for (int i = 0; i <= 7; i++)
- LLDB_LOGF(log, "PT_%cETDBREGS: dr[%d]=0x%lx", setget, i, r->dr[i]);
- }
-#endif
- }
-
- return result;
-}
-
-// Wrapper for ptrace when logging is not required. Sets errno to 0 prior to
-// calling ptrace.
-extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data) {
- long result = 0;
- errno = 0;
- result = ptrace(req, pid, (caddr_t)addr, data);
- return result;
-}
-
-#define PTRACE(req, pid, addr, data) \
- PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__)
-
-// Static implementations of ProcessMonitor::ReadMemory and
-// ProcessMonitor::WriteMemory. This enables mutual recursion between these
-// functions without needed to go thru the thread funnel.
-
-static size_t DoReadMemory(lldb::pid_t pid, lldb::addr_t vm_addr, void *buf,
- size_t size, Status &error) {
- struct ptrace_io_desc pi_desc;
-
- pi_desc.piod_op = PIOD_READ_D;
- pi_desc.piod_offs = (void *)vm_addr;
- pi_desc.piod_addr = buf;
- pi_desc.piod_len = size;
-
- if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) {
- error.SetErrorToErrno();
- return 0;
- }
- return pi_desc.piod_len;
-}
-
-static size_t DoWriteMemory(lldb::pid_t pid, lldb::addr_t vm_addr,
- const void *buf, size_t size, Status &error) {
- struct ptrace_io_desc pi_desc;
-
- pi_desc.piod_op = PIOD_WRITE_D;
- pi_desc.piod_offs = (void *)vm_addr;
- pi_desc.piod_addr = const_cast<void *>(buf);
- pi_desc.piod_len = size;
-
- if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) {
- error.SetErrorToErrno();
- return 0;
- }
- return pi_desc.piod_len;
-}
-
-// Simple helper function to ensure flags are enabled on the given file
-// descriptor.
-static bool EnsureFDFlags(int fd, int flags, Status &error) {
- int status;
-
- if ((status = fcntl(fd, F_GETFL)) == -1) {
- error.SetErrorToErrno();
- return false;
- }
-
- if (fcntl(fd, F_SETFL, status | flags) == -1) {
- error.SetErrorToErrno();
- return false;
- }
-
- return true;
-}
-
-/// \class Operation
-/// Represents a ProcessMonitor operation.
-///
-/// Under FreeBSD, it is not possible to ptrace() from any other thread but
-/// the one that spawned or attached to the process from the start.
-/// Therefore, when a ProcessMonitor is asked to deliver or change the state
-/// of an inferior process the operation must be "funneled" to a specific
-/// thread to perform the task. The Operation class provides an abstract base
-/// for all services the ProcessMonitor must perform via the single virtual
-/// function Execute, thus encapsulating the code that needs to run in the
-/// privileged context.
-class Operation {
-public:
- virtual ~Operation() {}
- virtual void Execute(ProcessMonitor *monitor) = 0;
-};
-
-/// \class ReadOperation
-/// Implements ProcessMonitor::ReadMemory.
-class ReadOperation : public Operation {
-public:
- ReadOperation(lldb::addr_t addr, void *buff, size_t size, Status &error,
- size_t &result)
- : m_addr(addr), m_buff(buff), m_size(size), m_error(error),
- m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::addr_t m_addr;
- void *m_buff;
- size_t m_size;
- Status &m_error;
- size_t &m_result;
-};
-
-void ReadOperation::Execute(ProcessMonitor *monitor) {
- lldb::pid_t pid = monitor->GetPID();
-
- m_result = DoReadMemory(pid, m_addr, m_buff, m_size, m_error);
-}
-
-/// \class WriteOperation
-/// Implements ProcessMonitor::WriteMemory.
-class WriteOperation : public Operation {
-public:
- WriteOperation(lldb::addr_t addr, const void *buff, size_t size,
- Status &error, size_t &result)
- : m_addr(addr), m_buff(buff), m_size(size), m_error(error),
- m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::addr_t m_addr;
- const void *m_buff;
- size_t m_size;
- Status &m_error;
- size_t &m_result;
-};
-
-void WriteOperation::Execute(ProcessMonitor *monitor) {
- lldb::pid_t pid = monitor->GetPID();
-
- m_result = DoWriteMemory(pid, m_addr, m_buff, m_size, m_error);
-}
-
-/// \class ReadRegOperation
-/// Implements ProcessMonitor::ReadRegisterValue.
-class ReadRegOperation : public Operation {
-public:
- ReadRegOperation(lldb::tid_t tid, unsigned offset, unsigned size,
- RegisterValue &value, bool &result)
- : m_tid(tid), m_offset(offset), m_size(size), m_value(value),
- m_result(result) {}
-
- void Execute(ProcessMonitor *monitor);
-
-private:
- lldb::tid_t m_tid;
- unsigned m_offset;
- unsigned m_size;
- RegisterValue &m_value;
- bool &m_result;
-};
-
-void ReadRegOperation::Execute(ProcessMonitor *monitor) {
- struct reg regs;
- int rc;
-
- if ((rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)&regs, 0)) < 0) {
- m_result = false;
- } else {
- // 'struct reg' contains only 32- or 64-bit register values. Punt on
- // others. Also, not all entries may be uintptr_t sized, such as 32-bit
- // processes on powerpc64 (probably the same for i386 on amd64)
- if (m_size == sizeof(uint32_t))
- m_value = *(uint32_t *)(((caddr_t)&regs) + m_offset);
- else if (m_size == sizeof(uint64_t))
- m_value = *(uint64_t *)(((caddr_t)&regs) + m_offset);
- else
- memcpy((void *)&m_value, (((caddr_t)&regs) + m_offset), m_size);
- m_result = true;
- }
-}
-
-/// \class WriteRegOperation
-/// Implements ProcessMonitor::WriteRegisterValue.
-class WriteRegOperation : public Operation {
-public:
- WriteRegOperation(lldb::tid_t tid, unsigned offset,
- const RegisterValue &value, bool &result)
- : m_tid(tid), m_offset(offset), m_value(value), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- unsigned m_offset;
- const RegisterValue &m_value;
- bool &m_result;
-};
-
-void WriteRegOperation::Execute(ProcessMonitor *monitor) {
- struct reg regs;
-
- if (PTRACE(PT_GETREGS, m_tid, (caddr_t)&regs, 0) < 0) {
- m_result = false;
- return;
- }
- *(uintptr_t *)(((caddr_t)&regs) + m_offset) =
- (uintptr_t)m_value.GetAsUInt64();
- if (PTRACE(PT_SETREGS, m_tid, (caddr_t)&regs, 0) < 0)
- m_result = false;
- else
- m_result = true;
-}
-
-/// \class ReadDebugRegOperation
-/// Implements ProcessMonitor::ReadDebugRegisterValue.
-class ReadDebugRegOperation : public Operation {
-public:
- ReadDebugRegOperation(lldb::tid_t tid, unsigned offset, unsigned size,
- RegisterValue &value, bool &result)
- : m_tid(tid), m_offset(offset), m_size(size), m_value(value),
- m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- unsigned m_offset;
- unsigned m_size;
- RegisterValue &m_value;
- bool &m_result;
-};
-
-void ReadDebugRegOperation::Execute(ProcessMonitor *monitor) {
- struct dbreg regs;
- int rc;
-
- if ((rc = PTRACE(PT_GETDBREGS, m_tid, (caddr_t)&regs, 0)) < 0) {
- m_result = false;
- } else {
- if (m_size == sizeof(uintptr_t))
- m_value = *(uintptr_t *)(((caddr_t)&regs) + m_offset);
- else
- memcpy((void *)&m_value, (((caddr_t)&regs) + m_offset), m_size);
- m_result = true;
- }
-}
-
-/// \class WriteDebugRegOperation
-/// Implements ProcessMonitor::WriteDebugRegisterValue.
-class WriteDebugRegOperation : public Operation {
-public:
- WriteDebugRegOperation(lldb::tid_t tid, unsigned offset,
- const RegisterValue &value, bool &result)
- : m_tid(tid), m_offset(offset), m_value(value), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- unsigned m_offset;
- const RegisterValue &m_value;
- bool &m_result;
-};
-
-void WriteDebugRegOperation::Execute(ProcessMonitor *monitor) {
- struct dbreg regs;
-
- if (PTRACE(PT_GETDBREGS, m_tid, (caddr_t)&regs, 0) < 0) {
- m_result = false;
- return;
- }
- *(uintptr_t *)(((caddr_t)&regs) + m_offset) =
- (uintptr_t)m_value.GetAsUInt64();
- if (PTRACE(PT_SETDBREGS, m_tid, (caddr_t)&regs, 0) < 0)
- m_result = false;
- else
- m_result = true;
-}
-
-/// \class ReadGPROperation
-/// Implements ProcessMonitor::ReadGPR.
-class ReadGPROperation : public Operation {
-public:
- ReadGPROperation(lldb::tid_t tid, void *buf, bool &result)
- : m_tid(tid), m_buf(buf), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- void *m_buf;
- bool &m_result;
-};
-
-void ReadGPROperation::Execute(ProcessMonitor *monitor) {
- int rc;
-
- errno = 0;
- rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)m_buf, 0);
- if (errno != 0)
- m_result = false;
- else
- m_result = true;
-}
-
-/// \class ReadFPROperation
-/// Implements ProcessMonitor::ReadFPR.
-class ReadFPROperation : public Operation {
-public:
- ReadFPROperation(lldb::tid_t tid, void *buf, bool &result)
- : m_tid(tid), m_buf(buf), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- void *m_buf;
- bool &m_result;
-};
-
-void ReadFPROperation::Execute(ProcessMonitor *monitor) {
- if (PTRACE(PT_GETFPREGS, m_tid, (caddr_t)m_buf, 0) < 0)
- m_result = false;
- else
- m_result = true;
-}
-
-/// \class WriteGPROperation
-/// Implements ProcessMonitor::WriteGPR.
-class WriteGPROperation : public Operation {
-public:
- WriteGPROperation(lldb::tid_t tid, void *buf, bool &result)
- : m_tid(tid), m_buf(buf), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- void *m_buf;
- bool &m_result;
-};
-
-void WriteGPROperation::Execute(ProcessMonitor *monitor) {
- if (PTRACE(PT_SETREGS, m_tid, (caddr_t)m_buf, 0) < 0)
- m_result = false;
- else
- m_result = true;
-}
-
-/// \class WriteFPROperation
-/// Implements ProcessMonitor::WriteFPR.
-class WriteFPROperation : public Operation {
-public:
- WriteFPROperation(lldb::tid_t tid, void *buf, bool &result)
- : m_tid(tid), m_buf(buf), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- void *m_buf;
- bool &m_result;
-};
-
-void WriteFPROperation::Execute(ProcessMonitor *monitor) {
- if (PTRACE(PT_SETFPREGS, m_tid, (caddr_t)m_buf, 0) < 0)
- m_result = false;
- else
- m_result = true;
-}
-
-/// \class ResumeOperation
-/// Implements ProcessMonitor::Resume.
-class ResumeOperation : public Operation {
-public:
- ResumeOperation(uint32_t signo, bool &result)
- : m_signo(signo), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- uint32_t m_signo;
- bool &m_result;
-};
-
-void ResumeOperation::Execute(ProcessMonitor *monitor) {
- lldb::pid_t pid = monitor->GetPID();
- int data = 0;
-
- if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
- data = m_signo;
-
- if (PTRACE(PT_CONTINUE, pid, (caddr_t)1, data)) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- LLDB_LOG(log, "ResumeOperation ({0}) failed: {1}", pid,
- llvm::sys::StrError(errno));
- m_result = false;
- } else
- m_result = true;
-}
-
-/// \class SingleStepOperation
-/// Implements ProcessMonitor::SingleStep.
-class SingleStepOperation : public Operation {
-public:
- SingleStepOperation(uint32_t signo, bool &result)
- : m_signo(signo), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- uint32_t m_signo;
- bool &m_result;
-};
-
-void SingleStepOperation::Execute(ProcessMonitor *monitor) {
- lldb::pid_t pid = monitor->GetPID();
- int data = 0;
-
- if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
- data = m_signo;
-
- if (PTRACE(PT_STEP, pid, NULL, data))
- m_result = false;
- else
- m_result = true;
-}
-
-/// \class LwpInfoOperation
-/// Implements ProcessMonitor::GetLwpInfo.
-class LwpInfoOperation : public Operation {
-public:
- LwpInfoOperation(lldb::tid_t tid, void *info, bool &result, int &ptrace_err)
- : m_tid(tid), m_info(info), m_result(result), m_err(ptrace_err) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- void *m_info;
- bool &m_result;
- int &m_err;
-};
-
-void LwpInfoOperation::Execute(ProcessMonitor *monitor) {
- struct ptrace_lwpinfo plwp;
-
- if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) {
- m_result = false;
- m_err = errno;
- } else {
- memcpy(m_info, &plwp, sizeof(plwp));
- m_result = true;
- }
-}
-
-/// \class ThreadSuspendOperation
-/// Implements ProcessMonitor::ThreadSuspend.
-class ThreadSuspendOperation : public Operation {
-public:
- ThreadSuspendOperation(lldb::tid_t tid, bool suspend, bool &result)
- : m_tid(tid), m_suspend(suspend), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- bool m_suspend;
- bool &m_result;
-};
-
-void ThreadSuspendOperation::Execute(ProcessMonitor *monitor) {
- m_result = !PTRACE(m_suspend ? PT_SUSPEND : PT_RESUME, m_tid, NULL, 0);
-}
-
-/// \class EventMessageOperation
-/// Implements ProcessMonitor::GetEventMessage.
-class EventMessageOperation : public Operation {
-public:
- EventMessageOperation(lldb::tid_t tid, unsigned long *message, bool &result)
- : m_tid(tid), m_message(message), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- unsigned long *m_message;
- bool &m_result;
-};
-
-void EventMessageOperation::Execute(ProcessMonitor *monitor) {
- struct ptrace_lwpinfo plwp;
-
- if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp)))
- m_result = false;
- else {
- if (plwp.pl_flags & PL_FLAG_FORKED) {
- *m_message = plwp.pl_child_pid;
- m_result = true;
- } else
- m_result = false;
- }
-}
-
-/// \class KillOperation
-/// Implements ProcessMonitor::Kill.
-class KillOperation : public Operation {
-public:
- KillOperation(bool &result) : m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- bool &m_result;
-};
-
-void KillOperation::Execute(ProcessMonitor *monitor) {
- lldb::pid_t pid = monitor->GetPID();
-
- if (PTRACE(PT_KILL, pid, NULL, 0))
- m_result = false;
- else
- m_result = true;
-}
-
-/// \class DetachOperation
-/// Implements ProcessMonitor::Detach.
-class DetachOperation : public Operation {
-public:
- DetachOperation(Status &result) : m_error(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- Status &m_error;
-};
-
-void DetachOperation::Execute(ProcessMonitor *monitor) {
- lldb::pid_t pid = monitor->GetPID();
-
- if (PTRACE(PT_DETACH, pid, NULL, 0) < 0)
- m_error.SetErrorToErrno();
-}
-
-ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor)
- : m_monitor(monitor) {
- sem_init(&m_semaphore, 0, 0);
-}
-
-ProcessMonitor::OperationArgs::~OperationArgs() { sem_destroy(&m_semaphore); }
-
-ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor,
- lldb_private::Module *module,
- char const **argv, Environment env,
- const FileSpec &stdin_file_spec,
- const FileSpec &stdout_file_spec,
- const FileSpec &stderr_file_spec,
- const FileSpec &working_dir)
- : OperationArgs(monitor), m_module(module), m_argv(argv),
- m_env(std::move(env)), m_stdin_file_spec(stdin_file_spec),
- m_stdout_file_spec(stdout_file_spec),
- m_stderr_file_spec(stderr_file_spec), m_working_dir(working_dir) {}
-
-ProcessMonitor::LaunchArgs::~LaunchArgs() {}
-
-ProcessMonitor::AttachArgs::AttachArgs(ProcessMonitor *monitor, lldb::pid_t pid)
- : OperationArgs(monitor), m_pid(pid) {}
-
-ProcessMonitor::AttachArgs::~AttachArgs() {}
-
-/// The basic design of the ProcessMonitor is built around two threads.
-///
-/// One thread (@see SignalThread) simply blocks on a call to waitpid()
-/// looking for changes in the debugee state. When a change is detected a
-/// ProcessMessage is sent to the associated ProcessFreeBSD instance. This
-/// thread "drives" state changes in the debugger.
-///
-/// The second thread (@see OperationThread) is responsible for two things 1)
-/// launching or attaching to the inferior process, and then 2) servicing
-/// operations such as register reads/writes, stepping, etc. See the comments
-/// on the Operation class for more info as to why this is needed.
-ProcessMonitor::ProcessMonitor(
- ProcessFreeBSD *process, Module *module, const char *argv[],
- Environment env, const FileSpec &stdin_file_spec,
- const FileSpec &stdout_file_spec, const FileSpec &stderr_file_spec,
- const FileSpec &working_dir,
- const lldb_private::ProcessLaunchInfo & /* launch_info */,
- lldb_private::Status &error)
- : m_process(static_cast<ProcessFreeBSD *>(process)),
- m_operation_thread(), m_monitor_thread(), m_pid(LLDB_INVALID_PROCESS_ID), m_terminal_fd(-1), m_operation(0) {
- using namespace std::placeholders;
-
- std::unique_ptr<LaunchArgs> args(
- new LaunchArgs(this, module, argv, std::move(env), stdin_file_spec,
- stdout_file_spec, stderr_file_spec, working_dir));
-
- sem_init(&m_operation_pending, 0, 0);
- sem_init(&m_operation_done, 0, 0);
-
- StartLaunchOpThread(args.get(), error);
- if (!error.Success())
- return;
-
- if (llvm::sys::RetryAfterSignal(-1, sem_wait, &args->m_semaphore) == -1) {
- error.SetErrorToErrno();
- return;
- }
-
- // Check that the launch was a success.
- if (!args->m_error.Success()) {
- StopOpThread();
- error = args->m_error;
- return;
- }
-
- // Finally, start monitoring the child process for change in state.
- llvm::Expected<lldb_private::HostThread> monitor_thread =
- Host::StartMonitoringChildProcess(
- std::bind(&ProcessMonitor::MonitorCallback, this, _1, _2, _3, _4),
- GetPID(), true);
- if (!monitor_thread || !monitor_thread->IsJoinable()) {
- error.SetErrorToGenericError();
- error.SetErrorString("Process launch failed.");
- return;
- }
- m_monitor_thread = *monitor_thread;
-}
-
-ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid,
- lldb_private::Status &error)
- : m_process(static_cast<ProcessFreeBSD *>(process)),
- m_operation_thread(), m_monitor_thread(), m_pid(pid), m_terminal_fd(-1), m_operation(0) {
- using namespace std::placeholders;
-
- sem_init(&m_operation_pending, 0, 0);
- sem_init(&m_operation_done, 0, 0);
-
- std::unique_ptr<AttachArgs> args(new AttachArgs(this, pid));
-
- StartAttachOpThread(args.get(), error);
- if (!error.Success())
- return;
-
- if (llvm::sys::RetryAfterSignal(-1, sem_wait, &args->m_semaphore) == -1) {
- error.SetErrorToErrno();
- return;
- }
-
- // Check that the attach was a success.
- if (!args->m_error.Success()) {
- StopOpThread();
- error = args->m_error;
- return;
- }
-
- // Finally, start monitoring the child process for change in state.
- llvm::Expected<lldb_private::HostThread> monitor_thread =
- Host::StartMonitoringChildProcess(
- std::bind(&ProcessMonitor::MonitorCallback, this, _1, _2, _3, _4),
- GetPID(), true);
- if (!monitor_thread || !monitor_thread->IsJoinable()) {
- error.SetErrorToGenericError();
- error.SetErrorString("Process attach failed.");
- return;
- }
- m_monitor_thread = *monitor_thread;
-}
-
-ProcessMonitor::~ProcessMonitor() { StopMonitor(); }
-
-// Thread setup and tear down.
-void ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Status &error) {
- static const char *g_thread_name = "lldb.process.freebsd.operation";
-
- if (m_operation_thread && m_operation_thread->IsJoinable())
- return;
-
- llvm::Expected<lldb_private::HostThread> operation_thread =
- ThreadLauncher::LaunchThread(g_thread_name, LaunchOpThread, args);
- if (operation_thread)
- m_operation_thread = *operation_thread;
- else
- error = operation_thread.takeError();
-}
-
-void *ProcessMonitor::LaunchOpThread(void *arg) {
- LaunchArgs *args = static_cast<LaunchArgs *>(arg);
-
- if (!Launch(args)) {
- sem_post(&args->m_semaphore);
- return NULL;
- }
-
- ServeOperation(args);
- return NULL;
-}
-
-bool ProcessMonitor::Launch(LaunchArgs *args) {
- ProcessMonitor *monitor = args->m_monitor;
- ProcessFreeBSD &process = monitor->GetProcess();
- const char **argv = args->m_argv;
- const FileSpec &stdin_file_spec = args->m_stdin_file_spec;
- const FileSpec &stdout_file_spec = args->m_stdout_file_spec;
- const FileSpec &stderr_file_spec = args->m_stderr_file_spec;
- const FileSpec &working_dir = args->m_working_dir;
-
- PseudoTerminal terminal;
-
- // Propagate the environment if one is not supplied.
- Environment::Envp envp =
- (args->m_env.empty() ? Host::GetEnvironment() : args->m_env).getEnvp();
-
- llvm::Expected<lldb::pid_t> pid = terminal.Fork();
- if (!pid) {
- args->m_error = pid.takeError();
- goto FINISH;
- }
-
- // Recognized child exit status codes.
- enum {
- ePtraceFailed = 1,
- eDupStdinFailed,
- eDupStdoutFailed,
- eDupStderrFailed,
- eChdirFailed,
- eExecFailed,
- eSetGidFailed
- };
-
- // Child process.
- if (*pid == 0) {
- // Trace this process.
- if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0)
- exit(ePtraceFailed);
-
- // terminal has already dupped the tty descriptors to stdin/out/err. This
- // closes original fd from which they were copied (and avoids leaking
- // descriptors to the debugged process.
- terminal.CloseSecondaryFileDescriptor();
-
- // Do not inherit setgid powers.
- if (setgid(getgid()) != 0)
- exit(eSetGidFailed);
-
- // Let us have our own process group.
- setpgid(0, 0);
-
- // Dup file descriptors if needed.
- //
- // FIXME: If two or more of the paths are the same we needlessly open
- // the same file multiple times.
- if (stdin_file_spec)
- if (!DupDescriptor(stdin_file_spec, STDIN_FILENO, O_RDONLY))
- exit(eDupStdinFailed);
-
- if (stdout_file_spec)
- if (!DupDescriptor(stdout_file_spec, STDOUT_FILENO, O_WRONLY | O_CREAT))
- exit(eDupStdoutFailed);
-
- if (stderr_file_spec)
- if (!DupDescriptor(stderr_file_spec, STDERR_FILENO, O_WRONLY | O_CREAT))
- exit(eDupStderrFailed);
-
- // Change working directory
- if (working_dir && 0 != ::chdir(working_dir.GetCString()))
- exit(eChdirFailed);
-
- // Execute. We should never return.
- execve(argv[0], const_cast<char *const *>(argv), envp);
- exit(eExecFailed);
- }
-
- // Wait for the child process to to trap on its call to execve.
- ::pid_t wpid;
- int status;
- if ((wpid = waitpid(*pid, &status, 0)) < 0) {
- args->m_error.SetErrorToErrno();
- goto FINISH;
- } else if (WIFEXITED(status)) {
- // open, dup or execve likely failed for some reason.
- args->m_error.SetErrorToGenericError();
- switch (WEXITSTATUS(status)) {
- case ePtraceFailed:
- args->m_error.SetErrorString("Child ptrace failed.");
- break;
- case eDupStdinFailed:
- args->m_error.SetErrorString("Child open stdin failed.");
- break;
- case eDupStdoutFailed:
- args->m_error.SetErrorString("Child open stdout failed.");
- break;
- case eDupStderrFailed:
- args->m_error.SetErrorString("Child open stderr failed.");
- break;
- case eChdirFailed:
- args->m_error.SetErrorString("Child failed to set working directory.");
- break;
- case eExecFailed:
- args->m_error.SetErrorString("Child exec failed.");
- break;
- case eSetGidFailed:
- args->m_error.SetErrorString("Child setgid failed.");
- break;
- default:
- args->m_error.SetErrorString("Child returned unknown exit status.");
- break;
- }
- goto FINISH;
- }
- assert(WIFSTOPPED(status) && wpid == (::pid_t)*pid &&
- "Could not sync with inferior process.");
-
-#ifdef notyet
- // Have the child raise an event on exit. This is used to keep the child in
- // limbo until it is destroyed.
- if (PTRACE(PTRACE_SETOPTIONS, *pid, NULL, PTRACE_O_TRACEEXIT) < 0) {
- args->m_error.SetErrorToErrno();
- goto FINISH;
- }
-#endif
- // Release the master terminal descriptor and pass it off to the
- // ProcessMonitor instance. Similarly stash the inferior pid.
- monitor->m_terminal_fd = terminal.ReleasePrimaryFileDescriptor();
- monitor->m_pid = *pid;
-
- // Set the terminal fd to be in non blocking mode (it simplifies the
- // implementation of ProcessFreeBSD::GetSTDOUT to have a non-blocking
- // descriptor to read from).
- if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error))
- goto FINISH;
-
- process.SendMessage(ProcessMessage::Attach(*pid));
-
-FINISH:
- return args->m_error.Success();
-}
-
-void ProcessMonitor::StartAttachOpThread(AttachArgs *args,
- lldb_private::Status &error) {
- static const char *g_thread_name = "lldb.process.freebsd.operation";
-
- if (m_operation_thread && m_operation_thread->IsJoinable())
- return;
-
- llvm::Expected<lldb_private::HostThread> operation_thread =
- ThreadLauncher::LaunchThread(g_thread_name, AttachOpThread, args);
- if (operation_thread)
- m_operation_thread = *operation_thread;
- else
- error = operation_thread.takeError();
-}
-
-void *ProcessMonitor::AttachOpThread(void *arg) {
- AttachArgs *args = static_cast<AttachArgs *>(arg);
-
- Attach(args);
-
- ServeOperation(args);
- return NULL;
-}
-
-void ProcessMonitor::Attach(AttachArgs *args) {
- lldb::pid_t pid = args->m_pid;
-
- ProcessMonitor *monitor = args->m_monitor;
- ProcessFreeBSD &process = monitor->GetProcess();
-
- if (pid <= 1) {
- args->m_error.SetErrorToGenericError();
- args->m_error.SetErrorString("Attaching to process 1 is not allowed.");
- return;
- }
-
- // Attach to the requested process.
- if (PTRACE(PT_ATTACH, pid, NULL, 0) < 0) {
- args->m_error.SetErrorToErrno();
- return;
- }
-
- int status;
- if ((status = waitpid(pid, NULL, 0)) < 0) {
- args->m_error.SetErrorToErrno();
- return;
- }
-
- process.SendMessage(ProcessMessage::Attach(pid));
-}
-
-size_t
-ProcessMonitor::GetCurrentThreadIDs(std::vector<lldb::tid_t> &thread_ids) {
- lwpid_t *tids;
- int tdcnt;
-
- thread_ids.clear();
-
- tdcnt = PTRACE(PT_GETNUMLWPS, m_pid, NULL, 0);
- if (tdcnt <= 0)
- return 0;
- tids = (lwpid_t *)malloc(tdcnt * sizeof(*tids));
- if (tids == NULL)
- return 0;
- if (PTRACE(PT_GETLWPLIST, m_pid, (void *)tids, tdcnt) < 0) {
- free(tids);
- return 0;
- }
- thread_ids = std::vector<lldb::tid_t>(tids, tids + tdcnt);
- free(tids);
- return thread_ids.size();
-}
-
-bool ProcessMonitor::MonitorCallback(ProcessMonitor *monitor, lldb::pid_t pid,
- bool exited, int signal, int status) {
- ProcessMessage message;
- ProcessFreeBSD *process = monitor->m_process;
- assert(process);
- bool stop_monitoring;
- struct ptrace_lwpinfo plwp;
- int ptrace_err;
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
-
- if (exited) {
- LLDB_LOGF(log, "ProcessMonitor::%s() got exit signal, tid = %" PRIu64,
- __FUNCTION__, pid);
- message = ProcessMessage::Exit(pid, status);
- process->SendMessage(message);
- return pid == process->GetID();
- }
-
- if (!monitor->GetLwpInfo(pid, &plwp, ptrace_err))
- stop_monitoring = true; // pid is gone. Bail.
- else {
- switch (plwp.pl_siginfo.si_signo) {
- case SIGTRAP:
- message = MonitorSIGTRAP(monitor, &plwp.pl_siginfo, plwp.pl_lwpid);
- break;
-
- default:
- message = MonitorSignal(monitor, &plwp.pl_siginfo, plwp.pl_lwpid);
- break;
- }
-
- process->SendMessage(message);
- stop_monitoring = message.GetKind() == ProcessMessage::eExitMessage;
- }
-
- return stop_monitoring;
-}
-
-ProcessMessage ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor,
- const siginfo_t *info,
- lldb::tid_t tid) {
- ProcessMessage message;
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
-
- assert(monitor);
- assert(info && info->si_signo == SIGTRAP && "Unexpected child signal!");
-
- switch (info->si_code) {
- default:
- assert(false && "Unexpected SIGTRAP code!");
- break;
-
- case (SIGTRAP /* | (PTRACE_EVENT_EXIT << 8) */): {
- // The inferior process is about to exit. Maintain the process in a state
- // of "limbo" until we are explicitly commanded to detach, destroy, resume,
- // etc.
- unsigned long data = 0;
- if (!monitor->GetEventMessage(tid, &data))
- data = -1;
- LLDB_LOGF(log,
- "ProcessMonitor::%s() received exit? event, data = %lx, tid "
- "= %" PRIu64,
- __FUNCTION__, data, tid);
- message = ProcessMessage::Limbo(tid, (data >> 8));
- break;
- }
-
- case 0:
- case TRAP_TRACE:
-#ifdef TRAP_CAP
- // Map TRAP_CAP to a trace trap in the absense of a more specific handler.
- case TRAP_CAP:
-#endif
- LLDB_LOGF(log,
- "ProcessMonitor::%s() received trace event, tid = %" PRIu64
- " : si_code = %d",
- __FUNCTION__, tid, info->si_code);
- message = ProcessMessage::Trace(tid);
- break;
-
- case SI_KERNEL:
- case TRAP_BRKPT:
- if (monitor->m_process->IsSoftwareStepBreakpoint(tid)) {
- LLDB_LOGF(log,
- "ProcessMonitor::%s() received sw single step breakpoint "
- "event, tid = %" PRIu64,
- __FUNCTION__, tid);
- message = ProcessMessage::Trace(tid);
- } else {
- LLDB_LOGF(
- log, "ProcessMonitor::%s() received breakpoint event, tid = %" PRIu64,
- __FUNCTION__, tid);
- message = ProcessMessage::Break(tid);
- }
- break;
- }
-
- return message;
-}
-
-ProcessMessage ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
- const siginfo_t *info,
- lldb::tid_t tid) {
- ProcessMessage message;
- int signo = info->si_signo;
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
-
- // POSIX says that process behaviour is undefined after it ignores a SIGFPE,
- // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a kill(2)
- // or raise(3). Similarly for tgkill(2) on FreeBSD.
- //
- // IOW, user generated signals never generate what we consider to be a
- // "crash".
- //
- // Similarly, ACK signals generated by this monitor.
- if (info->si_code == SI_USER) {
- LLDB_LOGF(log,
- "ProcessMonitor::%s() received signal %s with code %s, pid = %d",
- __FUNCTION__,
- monitor->m_process->GetUnixSignals()->GetSignalAsCString(signo),
- "SI_USER", info->si_pid);
- if (info->si_pid == getpid())
- return ProcessMessage::SignalDelivered(tid, signo);
- else
- return ProcessMessage::Signal(tid, signo);
- }
-
- LLDB_LOGF(log, "ProcessMonitor::%s() received signal %s", __FUNCTION__,
- monitor->m_process->GetUnixSignals()->GetSignalAsCString(signo));
-
- switch (signo) {
- case SIGSEGV:
- case SIGILL:
- case SIGFPE:
- case SIGBUS:
- lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
- const auto reason = GetCrashReason(*info);
- if (reason != CrashReason::eInvalidCrashReason) {
- return ProcessMessage::Crash(tid, reason, signo, fault_addr);
- } // else; Use atleast si_signo info for other si_code
- }
-
- // Everything else is "normal" and does not require any special action on our
- // part.
- return ProcessMessage::Signal(tid, signo);
-}
-
-void ProcessMonitor::ServeOperation(OperationArgs *args) {
- ProcessMonitor *monitor = args->m_monitor;
-
- // We are finised with the arguments and are ready to go. Sync with the
- // parent thread and start serving operations on the inferior.
- sem_post(&args->m_semaphore);
-
- for (;;) {
- // wait for next pending operation
- sem_wait(&monitor->m_operation_pending);
-
- monitor->m_operation->Execute(monitor);
-
- // notify calling thread that operation is complete
- sem_post(&monitor->m_operation_done);
- }
-}
-
-void ProcessMonitor::DoOperation(Operation *op) {
- std::lock_guard<std::mutex> guard(m_operation_mutex);
-
- m_operation = op;
-
- // notify operation thread that an operation is ready to be processed
- sem_post(&m_operation_pending);
-
- // wait for operation to complete
- sem_wait(&m_operation_done);
-}
-
-size_t ProcessMonitor::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
- Status &error) {
- size_t result;
- ReadOperation op(vm_addr, buf, size, error, result);
- DoOperation(&op);
- return result;
-}
-
-size_t ProcessMonitor::WriteMemory(lldb::addr_t vm_addr, const void *buf,
- size_t size, lldb_private::Status &error) {
- size_t result;
- WriteOperation op(vm_addr, buf, size, error, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::ReadRegisterValue(lldb::tid_t tid, unsigned offset,
- const char *reg_name, unsigned size,
- RegisterValue &value) {
- bool result;
- ReadRegOperation op(tid, offset, size, value, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::WriteRegisterValue(lldb::tid_t tid, unsigned offset,
- const char *reg_name,
- const RegisterValue &value) {
- bool result;
- WriteRegOperation op(tid, offset, value, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::ReadDebugRegisterValue(
- lldb::tid_t tid, unsigned offset, const char *reg_name, unsigned size,
- lldb_private::RegisterValue &value) {
- bool result;
- ReadDebugRegOperation op(tid, offset, size, value, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::WriteDebugRegisterValue(
- lldb::tid_t tid, unsigned offset, const char *reg_name,
- const lldb_private::RegisterValue &value) {
- bool result;
- WriteDebugRegOperation op(tid, offset, value, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size) {
- bool result;
- ReadGPROperation op(tid, buf, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size) {
- bool result;
- ReadFPROperation op(tid, buf, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::ReadRegisterSet(lldb::tid_t tid, void *buf,
- size_t buf_size, unsigned int regset) {
- return false;
-}
-
-bool ProcessMonitor::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size) {
- bool result;
- WriteGPROperation op(tid, buf, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size) {
- bool result;
- WriteFPROperation op(tid, buf, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::WriteRegisterSet(lldb::tid_t tid, void *buf,
- size_t buf_size, unsigned int regset) {
- return false;
-}
-
-bool ProcessMonitor::ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value) {
- return false;
-}
-
-bool ProcessMonitor::Resume(lldb::tid_t unused, uint32_t signo) {
- bool result;
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
-
- if (log) {
- const char *signame =
- m_process->GetUnixSignals()->GetSignalAsCString(signo);
- if (signame == nullptr)
- signame = "<none>";
- LLDB_LOGF(log,
- "ProcessMonitor::%s() resuming pid %" PRIu64 " with signal %s",
- __FUNCTION__, GetPID(), signame);
- }
- ResumeOperation op(signo, result);
- DoOperation(&op);
- LLDB_LOGF(log, "ProcessMonitor::%s() resuming result = %s", __FUNCTION__,
- result ? "true" : "false");
- return result;
-}
-
-bool ProcessMonitor::SingleStep(lldb::tid_t unused, uint32_t signo) {
- bool result;
- SingleStepOperation op(signo, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::Kill() {
- bool result;
- KillOperation op(result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::GetLwpInfo(lldb::tid_t tid, void *lwpinfo,
- int &ptrace_err) {
- bool result;
- LwpInfoOperation op(tid, lwpinfo, result, ptrace_err);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::ThreadSuspend(lldb::tid_t tid, bool suspend) {
- bool result;
- ThreadSuspendOperation op(tid, suspend, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::GetEventMessage(lldb::tid_t tid, unsigned long *message) {
- bool result;
- EventMessageOperation op(tid, message, result);
- DoOperation(&op);
- return result;
-}
-
-lldb_private::Status ProcessMonitor::Detach(lldb::tid_t tid) {
- lldb_private::Status error;
- if (tid != LLDB_INVALID_THREAD_ID) {
- DetachOperation op(error);
- DoOperation(&op);
- }
- return error;
-}
-
-bool ProcessMonitor::DupDescriptor(const FileSpec &file_spec, int fd,
- int flags) {
- int target_fd = llvm::sys::RetryAfterSignal(-1, open,
- file_spec.GetCString(), flags, 0666);
-
- if (target_fd == -1)
- return false;
-
- if (dup2(target_fd, fd) == -1)
- return false;
-
- return (close(target_fd) == -1) ? false : true;
-}
-
-void ProcessMonitor::StopMonitoringChildProcess() {
- if (m_monitor_thread && m_monitor_thread->IsJoinable()) {
- m_monitor_thread->Cancel();
- m_monitor_thread->Join(nullptr);
- m_monitor_thread->Reset();
- }
-}
-
-void ProcessMonitor::StopMonitor() {
- StopMonitoringChildProcess();
- StopOpThread();
- sem_destroy(&m_operation_pending);
- sem_destroy(&m_operation_done);
- if (m_terminal_fd >= 0) {
- close(m_terminal_fd);
- m_terminal_fd = -1;
- }
-}
-
-// FIXME: On Linux, when a new thread is created, we receive to notifications,
-// (1) a SIGTRAP|PTRACE_EVENT_CLONE from the main process thread with the child
-// thread id as additional information, and (2) a SIGSTOP|SI_USER from the new
-// child thread indicating that it has is stopped because we attached. We have
-// no guarantee of the order in which these arrive, but we need both before we
-// are ready to proceed. We currently keep a list of threads which have sent
-// the initial SIGSTOP|SI_USER event. Then when we receive the
-// SIGTRAP|PTRACE_EVENT_CLONE notification, if the initial stop has not
-// occurred we call ProcessMonitor::WaitForInitialTIDStop() to wait for it.
-//
-// Right now, the above logic is in ProcessPOSIX, so we need a definition of
-// this function in the FreeBSD ProcessMonitor implementation even if it isn't
-// logically needed.
-//
-// We really should figure out what actually happens on FreeBSD and move the
-// Linux-specific logic out of ProcessPOSIX as needed.
-
-bool ProcessMonitor::WaitForInitialTIDStop(lldb::tid_t tid) { return true; }
-
-void ProcessMonitor::StopOpThread() {
- if (m_operation_thread && m_operation_thread->IsJoinable()) {
- m_operation_thread->Cancel();
- m_operation_thread->Join(nullptr);
- m_operation_thread->Reset();
- }
-}
diff --git a/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h
deleted file mode 100644
index c5edfc0be95a..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h
+++ /dev/null
@@ -1,279 +0,0 @@
-//===-- ProcessMonitor.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_ProcessMonitor_H_
-#define liblldb_ProcessMonitor_H_
-
-#include <semaphore.h>
-#include <signal.h>
-
-#include <mutex>
-
-#include "lldb/Host/HostThread.h"
-#include "lldb/Utility/FileSpec.h"
-#include "lldb/lldb-types.h"
-
-namespace lldb_private {
-class Status;
-class Module;
-class Scalar;
-} // End lldb_private namespace.
-
-class ProcessFreeBSD;
-class Operation;
-
-/// \class ProcessMonitor
-/// Manages communication with the inferior (debugee) process.
-///
-/// Upon construction, this class prepares and launches an inferior process
-/// for debugging.
-///
-/// Changes in the inferior process state are propagated to the associated
-/// ProcessFreeBSD instance by calling ProcessFreeBSD::SendMessage with the
-/// appropriate ProcessMessage events.
-///
-/// A purposely minimal set of operations are provided to interrogate and change
-/// the inferior process state.
-class ProcessMonitor {
-public:
- /// Launches an inferior process ready for debugging. Forms the
- /// implementation of Process::DoLaunch.
- ProcessMonitor(ProcessFreeBSD *process, lldb_private::Module *module,
- char const *argv[], lldb_private::Environment env,
- const lldb_private::FileSpec &stdin_file_spec,
- const lldb_private::FileSpec &stdout_file_spec,
- const lldb_private::FileSpec &stderr_file_spec,
- const lldb_private::FileSpec &working_dir,
- const lldb_private::ProcessLaunchInfo &launch_info,
- lldb_private::Status &error);
-
- ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid,
- lldb_private::Status &error);
-
- ~ProcessMonitor();
-
- /// Provides the process number of debugee.
- lldb::pid_t GetPID() const { return m_pid; }
-
- /// Returns the process associated with this ProcessMonitor.
- ProcessFreeBSD &GetProcess() { return *m_process; }
-
- /// Returns a file descriptor to the controlling terminal of the inferior
- /// process.
- ///
- /// Reads from this file descriptor yield both the standard output and
- /// standard error of this debugee. Even if stderr and stdout were
- /// redirected on launch it may still happen that data is available on this
- /// descriptor (if the inferior process opens /dev/tty, for example). This
- /// descriptor is closed after a call to StopMonitor().
- ///
- /// If this monitor was attached to an existing process this method returns
- /// -1.
- int GetTerminalFD() const { return m_terminal_fd; }
-
- /// Reads \p size bytes from address @vm_adder in the inferior process
- /// address space.
- ///
- /// This method is provided to implement Process::DoReadMemory.
- size_t ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
- lldb_private::Status &error);
-
- /// Writes \p size bytes from address \p vm_adder in the inferior process
- /// address space.
- ///
- /// This method is provided to implement Process::DoWriteMemory.
- size_t WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
- lldb_private::Status &error);
-
- /// Reads the contents from the register identified by the given
- /// (architecture dependent) offset.
- ///
- /// This method is provided for use by RegisterContextFreeBSD derivatives.
- bool ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
- unsigned size, lldb_private::RegisterValue &value);
-
- /// Writes the given value to the register identified by the given
- /// (architecture dependent) offset.
- ///
- /// This method is provided for use by RegisterContextFreeBSD derivatives.
- bool WriteRegisterValue(lldb::tid_t tid, unsigned offset,
- const char *reg_name,
- const lldb_private::RegisterValue &value);
-
- /// Reads the contents from the debug register identified by the given
- /// (architecture dependent) offset.
- ///
- /// This method is provided for use by RegisterContextFreeBSD derivatives.
- bool ReadDebugRegisterValue(lldb::tid_t tid, unsigned offset,
- const char *reg_name, unsigned size,
- lldb_private::RegisterValue &value);
-
- /// Writes the given value to the debug register identified by the given
- /// (architecture dependent) offset.
- ///
- /// This method is provided for use by RegisterContextFreeBSD derivatives.
- bool WriteDebugRegisterValue(lldb::tid_t tid, unsigned offset,
- const char *reg_name,
- const lldb_private::RegisterValue &value);
- /// Reads all general purpose registers into the specified buffer.
- bool ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size);
-
- /// Reads all floating point registers into the specified buffer.
- bool ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size);
-
- /// Reads the specified register set into the specified buffer.
- ///
- /// This method is provided for use by RegisterContextFreeBSD derivatives.
- bool ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size,
- unsigned int regset);
-
- /// Writes all general purpose registers into the specified buffer.
- bool WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size);
-
- /// Writes all floating point registers into the specified buffer.
- bool WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size);
-
- /// Writes the specified register set into the specified buffer.
- ///
- /// This method is provided for use by RegisterContextFreeBSD derivatives.
- bool WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size,
- unsigned int regset);
-
- /// Reads the value of the thread-specific pointer for a given thread ID.
- bool ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value);
-
- /// Returns current thread IDs in process
- size_t GetCurrentThreadIDs(std::vector<lldb::tid_t> &thread_ids);
-
- /// Writes a ptrace_lwpinfo structure corresponding to the given thread ID
- /// to the memory region pointed to by \p lwpinfo.
- bool GetLwpInfo(lldb::tid_t tid, void *lwpinfo, int &error_no);
-
- /// Suspends or unsuspends a thread prior to process resume or step.
- bool ThreadSuspend(lldb::tid_t tid, bool suspend);
-
- /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
- /// corresponding to the given thread IDto the memory pointed to by @p
- /// message.
- bool GetEventMessage(lldb::tid_t tid, unsigned long *message);
-
- /// Resumes the process. If \p signo is anything but
- /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the process.
- bool Resume(lldb::tid_t unused, uint32_t signo);
-
- /// Single steps the process. If \p signo is anything but
- /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the process.
- bool SingleStep(lldb::tid_t unused, uint32_t signo);
-
- /// Terminate the traced process.
- bool Kill();
-
- lldb_private::Status Detach(lldb::tid_t tid);
-
- void StopMonitor();
-
- // Waits for the initial stop message from a new thread.
- bool WaitForInitialTIDStop(lldb::tid_t tid);
-
-private:
- ProcessFreeBSD *m_process;
-
- llvm::Optional<lldb_private::HostThread> m_operation_thread;
- llvm::Optional<lldb_private::HostThread> m_monitor_thread;
- lldb::pid_t m_pid;
-
- int m_terminal_fd;
-
- // current operation which must be executed on the privileged thread
- Operation *m_operation;
- std::mutex m_operation_mutex;
-
- // semaphores notified when Operation is ready to be processed and when
- // the operation is complete.
- sem_t m_operation_pending;
- sem_t m_operation_done;
-
- struct OperationArgs {
- OperationArgs(ProcessMonitor *monitor);
-
- ~OperationArgs();
-
- ProcessMonitor *m_monitor; // The monitor performing the attach.
- sem_t m_semaphore; // Posted to once operation complete.
- lldb_private::Status m_error; // Set if process operation failed.
- };
-
- /// \class LauchArgs
- ///
- /// Simple structure to pass data to the thread responsible for launching a
- /// child process.
- struct LaunchArgs : OperationArgs {
- LaunchArgs(ProcessMonitor *monitor, lldb_private::Module *module,
- char const **argv, lldb_private::Environment env,
- const lldb_private::FileSpec &stdin_file_spec,
- const lldb_private::FileSpec &stdout_file_spec,
- const lldb_private::FileSpec &stderr_file_spec,
- const lldb_private::FileSpec &working_dir);
-
- ~LaunchArgs();
-
- lldb_private::Module *m_module; // The executable image to launch.
- char const **m_argv; // Process arguments.
- lldb_private::Environment m_env; // Process environment.
- const lldb_private::FileSpec m_stdin_file_spec; // Redirect stdin or empty.
- const lldb_private::FileSpec
- m_stdout_file_spec; // Redirect stdout or empty.
- const lldb_private::FileSpec
- m_stderr_file_spec; // Redirect stderr or empty.
- const lldb_private::FileSpec m_working_dir; // Working directory or empty.
- };
-
- void StartLaunchOpThread(LaunchArgs *args, lldb_private::Status &error);
-
- static void *LaunchOpThread(void *arg);
-
- static bool Launch(LaunchArgs *args);
-
- struct AttachArgs : OperationArgs {
- AttachArgs(ProcessMonitor *monitor, lldb::pid_t pid);
-
- ~AttachArgs();
-
- lldb::pid_t m_pid; // pid of the process to be attached.
- };
-
- void StartAttachOpThread(AttachArgs *args, lldb_private::Status &error);
-
- static void *AttachOpThread(void *args);
-
- static void Attach(AttachArgs *args);
-
- static void ServeOperation(OperationArgs *args);
-
- static bool DupDescriptor(const lldb_private::FileSpec &file_spec, int fd,
- int flags);
-
- static bool MonitorCallback(ProcessMonitor *monitor, lldb::pid_t pid,
- bool exited, int signal, int status);
-
- static ProcessMessage MonitorSIGTRAP(ProcessMonitor *monitor,
- const siginfo_t *info, lldb::pid_t pid);
-
- static ProcessMessage MonitorSignal(ProcessMonitor *monitor,
- const siginfo_t *info, lldb::pid_t pid);
-
- void DoOperation(Operation *op);
-
- /// Stops the child monitor thread.
- void StopMonitoringChildProcess();
-
- /// Stops the operation thread used to attach/launch a process.
- void StopOpThread();
-};
-
-#endif // #ifndef liblldb_ProcessMonitor_H_
diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h
deleted file mode 100644
index cf52a065232c..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//===-- RegisterContextPOSIX.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_RegisterContextPOSIX_H_
-#define liblldb_RegisterContextPOSIX_H_
-
-#include "Plugins/Process/Utility/RegisterInfoInterface.h"
-#include "lldb/Target/RegisterContext.h"
-#include "lldb/Utility/ArchSpec.h"
-
-/// \class POSIXBreakpointProtocol
-///
-/// Extends RegisterClass with a few virtual operations useful on POSIX.
-class POSIXBreakpointProtocol {
-public:
- POSIXBreakpointProtocol() { m_watchpoints_initialized = false; }
- virtual ~POSIXBreakpointProtocol() {}
-
- /// Updates the register state of the associated thread after hitting a
- /// breakpoint (if that make sense for the architecture). Default
- /// implementation simply returns true for architectures which do not
- /// require any update.
- ///
- /// \return
- /// True if the operation succeeded and false otherwise.
- virtual bool UpdateAfterBreakpoint() = 0;
-
- /// Determines the index in lldb's register file given a kernel byte offset.
- virtual unsigned GetRegisterIndexFromOffset(unsigned offset) = 0;
-
- // Checks to see if a watchpoint specified by hw_index caused the inferior
- // to stop.
- virtual bool IsWatchpointHit(uint32_t hw_index) = 0;
-
- // Resets any watchpoints that have been hit.
- virtual bool ClearWatchpointHits() = 0;
-
- // Returns the watchpoint address associated with a watchpoint hardware
- // index.
- virtual lldb::addr_t GetWatchpointAddress(uint32_t hw_index) = 0;
-
- virtual bool IsWatchpointVacant(uint32_t hw_index) = 0;
-
- virtual bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
- bool read, bool write,
- uint32_t hw_index) = 0;
-
- // From lldb_private::RegisterContext
- virtual uint32_t NumSupportedHardwareWatchpoints() = 0;
-
- // Force m_watchpoints_initialized to TRUE
- void ForceWatchpointsInitialized() { m_watchpoints_initialized = true; }
-
-protected:
- bool m_watchpoints_initialized;
-};
-
-#endif // #ifndef liblldb_RegisterContextPOSIX_H_
diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
deleted file mode 100644
index afb92e848466..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
+++ /dev/null
@@ -1,260 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_arm.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 "lldb/Target/Thread.h"
-#include "lldb/Utility/DataBufferHeap.h"
-#include "lldb/Utility/RegisterValue.h"
-
-#include "ProcessFreeBSD.h"
-#include "ProcessMonitor.h"
-#include "RegisterContextPOSIXProcessMonitor_arm.h"
-#include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h"
-#include "Plugins/Process/Utility/lldb-arm-register-enums.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-#define REG_CONTEXT_SIZE (GetGPRSize())
-
-RegisterContextPOSIXProcessMonitor_arm::RegisterContextPOSIXProcessMonitor_arm(
- lldb_private::Thread &thread,
- std::unique_ptr<RegisterInfoPOSIX_arm> register_info)
- : RegisterContextPOSIX_arm(thread, std::move(register_info)) {}
-
-ProcessMonitor &RegisterContextPOSIXProcessMonitor_arm::GetMonitor() {
- ProcessSP base = CalculateProcess();
- ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get());
- return process->GetMonitor();
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::ReadGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadGPR(m_thread.GetID(), &m_gpr_arm, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::ReadFPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadFPR(m_thread.GetID(), &m_fpr, sizeof(m_fpr));
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::WriteGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteGPR(m_thread.GetID(), &m_gpr_arm, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::WriteFPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteFPR(m_thread.GetID(), &m_fpr, sizeof(m_fpr));
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::ReadRegister(
- const unsigned reg, RegisterValue &value) {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
- GetRegisterName(reg), GetRegisterSize(reg),
- value);
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::WriteRegister(
- const unsigned reg, const RegisterValue &value) {
- unsigned reg_to_write = reg;
- RegisterValue value_to_write = value;
-
- // Check if this is a subregister of a full register.
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
- if (reg_info->invalidate_regs &&
- (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
- RegisterValue full_value;
- uint32_t full_reg = reg_info->invalidate_regs[0];
- const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
-
- // Read the full register.
- if (ReadRegister(full_reg_info, full_value)) {
- Status error;
- ByteOrder byte_order = GetByteOrder();
- uint8_t dst[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the full register.
- const uint32_t dest_size = full_value.GetAsMemoryData(
- full_reg_info, dst, sizeof(dst), byte_order, error);
- if (error.Success() && dest_size) {
- uint8_t src[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the source data.
- const uint32_t src_size = value.GetAsMemoryData(
- reg_info, src, sizeof(src), byte_order, error);
- if (error.Success() && src_size && (src_size < dest_size)) {
- // Copy the src bytes to the destination.
- memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
- // Set this full register as the value to write.
- value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
- value_to_write.SetType(full_reg_info);
- reg_to_write = full_reg;
- }
- }
- }
- }
-
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteRegisterValue(
- m_thread.GetID(), GetRegisterOffset(reg_to_write),
- GetRegisterName(reg_to_write), value_to_write);
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::ReadRegister(
- const RegisterInfo *reg_info, RegisterValue &value) {
- if (!reg_info)
- return false;
-
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- if (IsFPR(reg)) {
- if (!ReadFPR())
- return false;
- } else {
- return ReadRegister(reg, value);
- }
-
- // Get pointer to m_fpr variable and set the data from it.
- assert(reg_info->byte_offset < sizeof m_fpr);
- uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset;
- switch (reg_info->byte_size) {
- case 2:
- value.SetUInt16(*(uint16_t *)src);
- return true;
- case 4:
- value.SetUInt32(*(uint32_t *)src);
- return true;
- case 8:
- value.SetUInt64(*(uint64_t *)src);
- return true;
- default:
- assert(false && "Unhandled data size.");
- return false;
- }
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::WriteRegister(
- const RegisterInfo *reg_info, const RegisterValue &value) {
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- if (IsGPR(reg)) {
- return WriteRegister(reg, value);
- } else if (IsFPR(reg)) {
- return WriteFPR();
- }
-
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::ReadAllRegisterValues(
- DataBufferSP &data_sp) {
- bool success = false;
- data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
- if (ReadGPR() && ReadFPR()) {
- uint8_t *dst = data_sp->GetBytes();
- success = dst != 0;
-
- if (success) {
- ::memcpy(dst, &m_gpr_arm, GetGPRSize());
- dst += GetGPRSize();
- ::memcpy(dst, &m_fpr, sizeof(m_fpr));
- }
- }
- return success;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::WriteAllRegisterValues(
- const DataBufferSP &data_sp) {
- bool success = false;
- if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
- uint8_t *src = data_sp->GetBytes();
- if (src) {
- ::memcpy(&m_gpr_arm, src, GetGPRSize());
-
- if (WriteGPR()) {
- src += GetGPRSize();
- ::memcpy(&m_fpr, src, sizeof(m_fpr));
-
- success = WriteFPR();
- }
- }
- }
- return success;
-}
-
-uint32_t RegisterContextPOSIXProcessMonitor_arm::SetHardwareWatchpoint(
- addr_t addr, size_t size, bool read, bool write) {
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
- uint32_t hw_index;
-
- for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) {
- if (IsWatchpointVacant(hw_index))
- return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index);
- }
-
- return LLDB_INVALID_INDEX32;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::ClearHardwareWatchpoint(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::HardwareSingleStep(bool enable) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::UpdateAfterBreakpoint() {
- lldb::addr_t pc;
-
- if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
- return false;
-
- return true;
-}
-
-unsigned RegisterContextPOSIXProcessMonitor_arm::GetRegisterIndexFromOffset(
- unsigned offset) {
- unsigned reg;
- for (reg = 0; reg < k_num_registers_arm; reg++) {
- if (GetRegisterInfo()[reg].byte_offset == offset)
- break;
- }
- assert(reg < k_num_registers_arm && "Invalid register offset.");
- return reg;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::IsWatchpointHit(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::ClearWatchpointHits() {
- return false;
-}
-
-addr_t RegisterContextPOSIXProcessMonitor_arm::GetWatchpointAddress(
- uint32_t hw_index) {
- return LLDB_INVALID_ADDRESS;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::IsWatchpointVacant(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::SetHardwareWatchpointWithIndex(
- addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) {
- return false;
-}
-
-uint32_t
-RegisterContextPOSIXProcessMonitor_arm::NumSupportedHardwareWatchpoints() {
- return 0;
-}
diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h
deleted file mode 100644
index bb455841dff1..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h
+++ /dev/null
@@ -1,80 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_arm.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_RegisterContextPOSIXProcessMonitor_arm_H_
-#define liblldb_RegisterContextPOSIXProcessMonitor_arm_H_
-
-#include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h"
-#include "RegisterContextPOSIX.h"
-
-class RegisterContextPOSIXProcessMonitor_arm : public RegisterContextPOSIX_arm,
- public POSIXBreakpointProtocol {
-public:
- RegisterContextPOSIXProcessMonitor_arm(
- lldb_private::Thread &thread,
- std::unique_ptr<RegisterInfoPOSIX_arm> register_info);
-
-protected:
- bool ReadGPR() override;
-
- bool ReadFPR() override;
-
- bool WriteGPR() override;
-
- bool WriteFPR() override;
-
- // lldb_private::RegisterContext
- bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
-
- bool WriteRegister(const unsigned reg,
- const lldb_private::RegisterValue &value);
-
- bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &value) override;
-
- bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value) override;
-
- bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
-
- bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
-
- uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,
- bool write) override;
-
- bool ClearHardwareWatchpoint(uint32_t hw_index) override;
-
- bool HardwareSingleStep(bool enable) override;
-
- // POSIXBreakpointProtocol
- bool UpdateAfterBreakpoint() override;
-
- unsigned GetRegisterIndexFromOffset(unsigned offset) override;
-
- bool IsWatchpointHit(uint32_t hw_index) override;
-
- bool ClearWatchpointHits() override;
-
- lldb::addr_t GetWatchpointAddress(uint32_t hw_index) override;
-
- bool IsWatchpointVacant(uint32_t hw_index) override;
-
- bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read,
- bool write, uint32_t hw_index) override;
-
- uint32_t NumSupportedHardwareWatchpoints() override;
-
-private:
- RegisterInfoPOSIX_arm::GPR m_gpr_arm;
-
- RegisterInfoPOSIX_arm::FPU m_fpr;
-
- ProcessMonitor &GetMonitor();
-};
-
-#endif
diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp
deleted file mode 100644
index 39ae0b9b9e7f..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_arm64.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 "lldb/Target/Thread.h"
-#include "lldb/Utility/DataBufferHeap.h"
-#include "lldb/Utility/RegisterValue.h"
-
-#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
-#include "ProcessFreeBSD.h"
-#include "ProcessMonitor.h"
-#include "RegisterContextPOSIXProcessMonitor_arm64.h"
-
-#define REG_CONTEXT_SIZE (GetGPRSize())
-
-using namespace lldb;
-using namespace lldb_private;
-
-RegisterContextPOSIXProcessMonitor_arm64::
- RegisterContextPOSIXProcessMonitor_arm64(
- lldb_private::Thread &thread,
- std::unique_ptr<RegisterInfoPOSIX_arm64> register_info)
- : RegisterContextPOSIX_arm64(thread, std::move(register_info)) {
- ::memset(&m_gpr_arm64, 0, sizeof m_gpr_arm64);
- ::memset(&m_fpr, 0, sizeof m_fpr);
-}
-
-ProcessMonitor &RegisterContextPOSIXProcessMonitor_arm64::GetMonitor() {
- lldb::ProcessSP base = CalculateProcess();
- ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get());
- return process->GetMonitor();
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::ReadGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::ReadFPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr);
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::WriteGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::WriteFPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr);
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::ReadRegister(
- const unsigned reg, lldb_private::RegisterValue &value) {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
- GetRegisterName(reg), GetRegisterSize(reg),
- value);
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::WriteRegister(
- const unsigned reg, const lldb_private::RegisterValue &value) {
- unsigned reg_to_write = reg;
- lldb_private::RegisterValue value_to_write = value;
-
- // Check if this is a subregister of a full register.
- const lldb_private::RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
- if (reg_info->invalidate_regs &&
- (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
- lldb_private::RegisterValue full_value;
- uint32_t full_reg = reg_info->invalidate_regs[0];
- const lldb_private::RegisterInfo *full_reg_info =
- GetRegisterInfoAtIndex(full_reg);
-
- // Read the full register.
- if (ReadRegister(full_reg_info, full_value)) {
- lldb_private::Status error;
- lldb::ByteOrder byte_order = GetByteOrder();
- uint8_t dst[lldb_private::RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the full register.
- const uint32_t dest_size = full_value.GetAsMemoryData(
- full_reg_info, dst, sizeof(dst), byte_order, error);
- if (error.Success() && dest_size) {
- uint8_t src[lldb_private::RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the source data.
- const uint32_t src_size = value.GetAsMemoryData(
- reg_info, src, sizeof(src), byte_order, error);
- if (error.Success() && src_size && (src_size < dest_size)) {
- // Copy the src bytes to the destination.
- ::memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
- // Set this full register as the value to write.
- value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
- value_to_write.SetType(full_reg_info);
- reg_to_write = full_reg;
- }
- }
- }
- }
-
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteRegisterValue(
- m_thread.GetID(), GetRegisterOffset(reg_to_write),
- GetRegisterName(reg_to_write), value_to_write);
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::ReadRegister(
- const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &value) {
- if (!reg_info)
- return false;
-
- const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
-
- if (IsFPR(reg)) {
- if (!ReadFPR())
- return false;
- } else {
- uint32_t full_reg = reg;
- bool is_subreg = reg_info->invalidate_regs &&
- (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
-
- if (is_subreg) {
- // Read the full aligned 64-bit register.
- full_reg = reg_info->invalidate_regs[0];
- }
- return ReadRegister(full_reg, value);
- }
-
- // Get pointer to m_fpr variable and set the data from it.
- assert(reg_info->byte_offset < sizeof m_fpr);
- uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset;
- switch (reg_info->byte_size) {
- case 2:
- value.SetUInt16(*(uint16_t *)src);
- return true;
- case 4:
- value.SetUInt32(*(uint32_t *)src);
- return true;
- case 8:
- value.SetUInt64(*(uint64_t *)src);
- return true;
- default:
- assert(false && "Unhandled data size.");
- return false;
- }
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::WriteRegister(
- const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value) {
- const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
-
- if (IsGPR(reg))
- return WriteRegister(reg, value);
-
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::ReadAllRegisterValues(
- lldb::DataBufferSP &data_sp) {
- bool success = false;
- data_sp.reset(new lldb_private::DataBufferHeap(REG_CONTEXT_SIZE, 0));
- if (ReadGPR() && ReadFPR()) {
- uint8_t *dst = data_sp->GetBytes();
- success = dst != 0;
-
- if (success) {
- ::memcpy(dst, &m_gpr_arm64, GetGPRSize());
- dst += GetGPRSize();
- ::memcpy(dst, &m_fpr, sizeof m_fpr);
- }
- }
- return success;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::WriteAllRegisterValues(
- const lldb::DataBufferSP &data_sp) {
- bool success = false;
- if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
- uint8_t *src = data_sp->GetBytes();
- if (src) {
- ::memcpy(&m_gpr_arm64, src, GetGPRSize());
- if (WriteGPR()) {
- src += GetGPRSize();
- ::memcpy(&m_fpr, src, sizeof m_fpr);
- success = WriteFPR();
- }
- }
- }
- return success;
-}
-
-uint32_t RegisterContextPOSIXProcessMonitor_arm64::SetHardwareWatchpoint(
- lldb::addr_t addr, size_t size, bool read, bool write) {
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
- uint32_t hw_index;
-
- for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) {
- if (IsWatchpointVacant(hw_index))
- return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index);
- }
-
- return LLDB_INVALID_INDEX32;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::ClearHardwareWatchpoint(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::HardwareSingleStep(bool enable) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::UpdateAfterBreakpoint() {
- if (GetPC() == LLDB_INVALID_ADDRESS)
- return false;
-
- return true;
-}
-
-unsigned RegisterContextPOSIXProcessMonitor_arm64::GetRegisterIndexFromOffset(
- unsigned offset) {
- unsigned reg;
- for (reg = 0; reg < GetRegisterCount(); reg++) {
- if (GetRegisterInfo()[reg].byte_offset == offset)
- break;
- }
- assert(reg < GetRegisterCount() && "Invalid register offset.");
- return reg;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::IsWatchpointHit(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::ClearWatchpointHits() {
- return false;
-}
-
-lldb::addr_t RegisterContextPOSIXProcessMonitor_arm64::GetWatchpointAddress(
- uint32_t hw_index) {
- return LLDB_INVALID_ADDRESS;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::IsWatchpointVacant(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::SetHardwareWatchpointWithIndex(
- lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) {
- return false;
-}
-
-uint32_t
-RegisterContextPOSIXProcessMonitor_arm64::NumSupportedHardwareWatchpoints() {
- return 0;
-}
diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h
deleted file mode 100644
index dcae1d46de9b..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h
+++ /dev/null
@@ -1,82 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_arm64.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_RegisterContextPOSIXProcessMonitor_arm64_H_
-#define liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_
-
-#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
-#include "RegisterContextPOSIX.h"
-
-class RegisterContextPOSIXProcessMonitor_arm64
- : public RegisterContextPOSIX_arm64,
- public POSIXBreakpointProtocol {
-public:
- RegisterContextPOSIXProcessMonitor_arm64(
- lldb_private::Thread &thread,
- std::unique_ptr<RegisterInfoPOSIX_arm64> register_info);
-
-protected:
- bool ReadGPR() override;
-
- bool ReadFPR() override;
-
- bool WriteGPR() override;
-
- bool WriteFPR() override;
-
- // lldb_private::RegisterContext
- bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
-
- bool WriteRegister(const unsigned reg,
- const lldb_private::RegisterValue &value);
-
- bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &value) override;
-
- bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value) override;
-
- bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
-
- bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
-
- uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,
- bool write) override;
-
- bool ClearHardwareWatchpoint(uint32_t hw_index) override;
-
- bool HardwareSingleStep(bool enable) override;
-
- // POSIXBreakpointProtocol
- bool UpdateAfterBreakpoint() override;
-
- unsigned GetRegisterIndexFromOffset(unsigned offset) override;
-
- bool IsWatchpointHit(uint32_t hw_index) override;
-
- bool ClearWatchpointHits() override;
-
- lldb::addr_t GetWatchpointAddress(uint32_t hw_index) override;
-
- bool IsWatchpointVacant(uint32_t hw_index) override;
-
- bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read,
- bool write, uint32_t hw_index) override;
-
- uint32_t NumSupportedHardwareWatchpoints() override;
-
-private:
- RegisterInfoPOSIX_arm64::GPR m_gpr_arm64; // 64-bit general purpose registers.
-
- RegisterInfoPOSIX_arm64::FPU
- m_fpr; // floating-point registers including extended register sets.
-
- ProcessMonitor &GetMonitor();
-};
-
-#endif
diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
deleted file mode 100644
index 23c76f234c8e..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_mips64.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 "lldb/Target/Thread.h"
-#include "lldb/Utility/DataBufferHeap.h"
-#include "lldb/Utility/RegisterValue.h"
-
-#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h"
-#include "ProcessFreeBSD.h"
-#include "ProcessMonitor.h"
-#include "RegisterContextPOSIXProcessMonitor_mips64.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-#define REG_CONTEXT_SIZE (GetGPRSize())
-
-RegisterContextPOSIXProcessMonitor_mips64::
- RegisterContextPOSIXProcessMonitor_mips64(
- Thread &thread, uint32_t concrete_frame_idx,
- lldb_private::RegisterInfoInterface *register_info)
- : RegisterContextPOSIX_mips64(thread, concrete_frame_idx, register_info) {}
-
-ProcessMonitor &RegisterContextPOSIXProcessMonitor_mips64::GetMonitor() {
- ProcessSP base = CalculateProcess();
- ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get());
- return process->GetMonitor();
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::ReadGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::ReadFPR() {
- // XXX not yet implemented
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::WriteGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::WriteFPR() {
- // XXX not yet implemented
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::ReadRegister(
- const unsigned reg, RegisterValue &value) {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
- GetRegisterName(reg), GetRegisterSize(reg),
- value);
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::WriteRegister(
- const unsigned reg, const RegisterValue &value) {
- unsigned reg_to_write = reg;
- RegisterValue value_to_write = value;
-
- // Check if this is a subregister of a full register.
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
- if (reg_info->invalidate_regs &&
- (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
- RegisterValue full_value;
- uint32_t full_reg = reg_info->invalidate_regs[0];
- const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
-
- // Read the full register.
- if (ReadRegister(full_reg_info, full_value)) {
- Status error;
- ByteOrder byte_order = GetByteOrder();
- uint8_t dst[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the full register.
- const uint32_t dest_size = full_value.GetAsMemoryData(
- full_reg_info, dst, sizeof(dst), byte_order, error);
- if (error.Success() && dest_size) {
- uint8_t src[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the source data.
- const uint32_t src_size = value.GetAsMemoryData(
- reg_info, src, sizeof(src), byte_order, error);
- if (error.Success() && src_size && (src_size < dest_size)) {
- // Copy the src bytes to the destination.
- memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
- // Set this full register as the value to write.
- value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
- value_to_write.SetType(full_reg_info);
- reg_to_write = full_reg;
- }
- }
- }
- }
-
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteRegisterValue(
- m_thread.GetID(), GetRegisterOffset(reg_to_write),
- GetRegisterName(reg_to_write), value_to_write);
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::ReadRegister(
- const RegisterInfo *reg_info, RegisterValue &value) {
- if (!reg_info)
- return false;
-
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- if (IsFPR(reg)) {
- if (!ReadFPR())
- return false;
- } else {
- uint32_t full_reg = reg;
- bool is_subreg = reg_info->invalidate_regs &&
- (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
-
- if (is_subreg) {
- // Read the full aligned 64-bit register.
- full_reg = reg_info->invalidate_regs[0];
- }
-
- bool success = ReadRegister(full_reg, value);
-
- if (success) {
- // If our read was not aligned (for ah,bh,ch,dh), shift our returned
- // value one byte to the right.
- if (is_subreg && (reg_info->byte_offset & 0x1))
- value.SetUInt64(value.GetAsUInt64() >> 8);
-
- // If our return byte size was greater than the return value reg size,
- // then use the type specified by reg_info rather than the uint64_t
- // default
- if (value.GetByteSize() > reg_info->byte_size)
- value.SetType(reg_info);
- }
- return success;
- }
-
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::WriteRegister(
- const RegisterInfo *reg_info, const RegisterValue &value) {
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- if (IsGPR(reg))
- return WriteRegister(reg, value);
-
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::ReadAllRegisterValues(
- DataBufferSP &data_sp) {
- bool success = false;
- data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
- if (ReadGPR() && ReadFPR()) {
- uint8_t *dst = data_sp->GetBytes();
- success = dst != 0;
-
- if (success) {
- ::memcpy(dst, &m_gpr_mips64, GetGPRSize());
- }
- }
- return success;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::WriteAllRegisterValues(
- const DataBufferSP &data_sp) {
- bool success = false;
- if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
- uint8_t *src = data_sp->GetBytes();
- if (src) {
- ::memcpy(&m_gpr_mips64, src, GetGPRSize());
-
- if (WriteGPR()) {
- src += GetGPRSize();
- }
- }
- }
- return success;
-}
-
-uint32_t RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpoint(
- addr_t addr, size_t size, bool read, bool write) {
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
- uint32_t hw_index;
-
- for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) {
- if (IsWatchpointVacant(hw_index))
- return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index);
- }
-
- return LLDB_INVALID_INDEX32;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::ClearHardwareWatchpoint(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::HardwareSingleStep(
- bool enable) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::UpdateAfterBreakpoint() {
- // PC points one byte past the int3 responsible for the breakpoint.
- lldb::addr_t pc;
-
- if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
- return false;
-
- SetPC(pc - 1);
- return true;
-}
-
-unsigned RegisterContextPOSIXProcessMonitor_mips64::GetRegisterIndexFromOffset(
- unsigned offset) {
- unsigned reg;
- for (reg = 0; reg < k_num_registers_mips64; reg++) {
- if (GetRegisterInfo()[reg].byte_offset == offset)
- break;
- }
- assert(reg < k_num_registers_mips64 && "Invalid register offset.");
- return reg;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointHit(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::ClearWatchpointHits() {
- return false;
-}
-
-addr_t RegisterContextPOSIXProcessMonitor_mips64::GetWatchpointAddress(
- uint32_t hw_index) {
- return LLDB_INVALID_ADDRESS;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointVacant(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpointWithIndex(
- addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) {
- return false;
-}
-
-uint32_t
-RegisterContextPOSIXProcessMonitor_mips64::NumSupportedHardwareWatchpoints() {
- return 0;
-}
diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h
deleted file mode 100644
index be404cc08c34..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h
+++ /dev/null
@@ -1,82 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_mips64.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_RegisterContextPOSIXProcessMonitor_mips64_H_
-#define liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_
-
-#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h"
-#include "Plugins/Process/Utility/lldb-mips-freebsd-register-enums.h"
-#include "RegisterContextPOSIX.h"
-
-class ProcessMonitor;
-
-class RegisterContextPOSIXProcessMonitor_mips64
- : public RegisterContextPOSIX_mips64,
- public POSIXBreakpointProtocol {
-public:
- RegisterContextPOSIXProcessMonitor_mips64(
- lldb_private::Thread &thread, uint32_t concrete_frame_idx,
- lldb_private::RegisterInfoInterface *register_info);
-
-protected:
- bool ReadGPR() override;
-
- bool ReadFPR() override;
-
- bool WriteGPR() override;
-
- bool WriteFPR() override;
-
- // lldb_private::RegisterContext
- bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
-
- bool WriteRegister(const unsigned reg,
- const lldb_private::RegisterValue &value);
-
- bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &value) override;
-
- bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value) override;
-
- bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
-
- bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
-
- uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,
- bool write) override;
-
- bool ClearHardwareWatchpoint(uint32_t hw_index) override;
-
- bool HardwareSingleStep(bool enable) override;
-
- // POSIXBreakpointProtocol
- bool UpdateAfterBreakpoint() override;
-
- unsigned GetRegisterIndexFromOffset(unsigned offset) override;
-
- bool IsWatchpointHit(uint32_t hw_index) override;
-
- bool ClearWatchpointHits() override;
-
- lldb::addr_t GetWatchpointAddress(uint32_t hw_index) override;
-
- bool IsWatchpointVacant(uint32_t hw_index) override;
-
- bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read,
- bool write, uint32_t hw_index) override;
-
- uint32_t NumSupportedHardwareWatchpoints() override;
-
-private:
- uint64_t
- m_gpr_mips64[lldb_private::k_num_gpr_registers_mips64]; // general purpose registers.
- ProcessMonitor &GetMonitor();
-};
-
-#endif
diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
deleted file mode 100644
index f8342775a81b..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
+++ /dev/null
@@ -1,274 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_powerpc.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 "lldb/Target/Thread.h"
-#include "lldb/Utility/DataBufferHeap.h"
-#include "lldb/Utility/RegisterValue.h"
-
-#include "ProcessFreeBSD.h"
-#include "ProcessMonitor.h"
-#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
-#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-#define REG_CONTEXT_SIZE (GetGPRSize())
-
-RegisterContextPOSIXProcessMonitor_powerpc::
- RegisterContextPOSIXProcessMonitor_powerpc(
- Thread &thread, uint32_t concrete_frame_idx,
- lldb_private::RegisterInfoInterface *register_info)
- : RegisterContextPOSIX_powerpc(thread, concrete_frame_idx, register_info) {}
-
-ProcessMonitor &RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor() {
- ProcessSP base = CalculateProcess();
- ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get());
- return process->GetMonitor();
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::ReadGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::ReadFPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadFPR(m_thread.GetID(), &m_fpr_powerpc,
- sizeof(m_fpr_powerpc));
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::ReadVMX() {
- // XXX: Need a way to read/write process VMX registers with ptrace.
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::WriteGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::WriteFPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteFPR(m_thread.GetID(), &m_fpr_powerpc,
- sizeof(m_fpr_powerpc));
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::WriteVMX() {
- // XXX: Need a way to read/write process VMX registers with ptrace.
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(
- const unsigned reg, RegisterValue &value) {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
- GetRegisterName(reg), GetRegisterSize(reg),
- value);
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(
- const unsigned reg, const RegisterValue &value) {
- unsigned reg_to_write = reg;
- RegisterValue value_to_write = value;
-
- // Check if this is a subregister of a full register.
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
- if (reg_info->invalidate_regs &&
- (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
- RegisterValue full_value;
- uint32_t full_reg = reg_info->invalidate_regs[0];
- const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
-
- // Read the full register.
- if (ReadRegister(full_reg_info, full_value)) {
- Status error;
- ByteOrder byte_order = GetByteOrder();
- uint8_t dst[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the full register.
- const uint32_t dest_size = full_value.GetAsMemoryData(
- full_reg_info, dst, sizeof(dst), byte_order, error);
- if (error.Success() && dest_size) {
- uint8_t src[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the source data.
- const uint32_t src_size = value.GetAsMemoryData(
- reg_info, src, sizeof(src), byte_order, error);
- if (error.Success() && src_size && (src_size < dest_size)) {
- // Copy the src bytes to the destination.
- memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
- // Set this full register as the value to write.
- value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
- value_to_write.SetType(full_reg_info);
- reg_to_write = full_reg;
- }
- }
- }
- }
-
- ProcessMonitor &monitor = GetMonitor();
- // Account for the fact that 32-bit targets on powerpc64 really use 64-bit
- // registers in ptrace, but expose here 32-bit registers with a higher
- // offset.
- uint64_t offset = GetRegisterOffset(reg_to_write);
- offset &= ~(sizeof(uintptr_t) - 1);
- return monitor.WriteRegisterValue(
- m_thread.GetID(), offset, GetRegisterName(reg_to_write), value_to_write);
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(
- const RegisterInfo *reg_info, RegisterValue &value) {
- if (!reg_info)
- return false;
-
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- if (IsFPR(reg)) {
- if (!ReadFPR())
- return false;
- uint8_t *src = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset;
- value.SetUInt64(*(uint64_t *)src);
- } else if (IsGPR(reg)) {
- bool success = ReadRegister(reg, value);
-
- if (success) {
- // If our return byte size was greater than the return value reg size,
- // then use the type specified by reg_info rather than the uint64_t
- // default
- if (value.GetByteSize() > reg_info->byte_size)
- value.SetType(reg_info);
- }
- return success;
- }
-
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(
- const RegisterInfo *reg_info, const RegisterValue &value) {
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- if (IsGPR(reg)) {
- return WriteRegister(reg, value);
- } else if (IsFPR(reg)) {
- assert(reg_info->byte_offset < sizeof(m_fpr_powerpc));
- uint8_t *dst = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset;
- *(uint64_t *)dst = value.GetAsUInt64();
- return WriteFPR();
- }
-
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::ReadAllRegisterValues(
- DataBufferSP &data_sp) {
- bool success = false;
- data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
- if (ReadGPR() && ReadFPR()) {
- uint8_t *dst = data_sp->GetBytes();
- success = dst != 0;
-
- if (success) {
- ::memcpy(dst, &m_gpr_powerpc, GetGPRSize());
- dst += GetGPRSize();
- }
- }
- return success;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::WriteAllRegisterValues(
- const DataBufferSP &data_sp) {
- bool success = false;
- if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
- uint8_t *src = data_sp->GetBytes();
- if (src) {
- ::memcpy(&m_gpr_powerpc, src, GetGPRSize());
-
- if (WriteGPR()) {
- src += GetGPRSize();
- ::memcpy(&m_fpr_powerpc, src, sizeof(m_fpr_powerpc));
-
- success = WriteFPR();
- }
- }
- }
- return success;
-}
-
-uint32_t RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpoint(
- addr_t addr, size_t size, bool read, bool write) {
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
- uint32_t hw_index;
-
- for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) {
- if (IsWatchpointVacant(hw_index))
- return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index);
- }
-
- return LLDB_INVALID_INDEX32;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::ClearHardwareWatchpoint(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::HardwareSingleStep(
- bool enable) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::UpdateAfterBreakpoint() {
- lldb::addr_t pc;
-
- if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
- return false;
-
- return true;
-}
-
-unsigned RegisterContextPOSIXProcessMonitor_powerpc::GetRegisterIndexFromOffset(
- unsigned offset) {
- unsigned reg;
- for (reg = 0; reg < k_num_registers_powerpc; reg++) {
- if (GetRegisterInfo()[reg].byte_offset == offset)
- break;
- }
- assert(reg < k_num_registers_powerpc && "Invalid register offset.");
- return reg;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointHit(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::ClearWatchpointHits() {
- return false;
-}
-
-addr_t RegisterContextPOSIXProcessMonitor_powerpc::GetWatchpointAddress(
- uint32_t hw_index) {
- return LLDB_INVALID_ADDRESS;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointVacant(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpointWithIndex(
- addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) {
- return false;
-}
-
-uint32_t
-RegisterContextPOSIXProcessMonitor_powerpc::NumSupportedHardwareWatchpoints() {
- return 0;
-}
diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h
deleted file mode 100644
index 328db4479ce6..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h
+++ /dev/null
@@ -1,84 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_powerpc.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_RegisterContextPOSIXProcessMonitor_powerpc_H_
-#define liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_
-
-#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
-#include "RegisterContextPOSIX.h"
-
-class RegisterContextPOSIXProcessMonitor_powerpc
- : public RegisterContextPOSIX_powerpc,
- public POSIXBreakpointProtocol {
-public:
- RegisterContextPOSIXProcessMonitor_powerpc(
- lldb_private::Thread &thread, uint32_t concrete_frame_idx,
- lldb_private::RegisterInfoInterface *register_info);
-
-protected:
- bool IsVMX();
-
- bool ReadGPR() override;
-
- bool ReadFPR() override;
-
- bool ReadVMX() override;
-
- bool WriteGPR() override;
-
- bool WriteFPR() override;
-
- bool WriteVMX() override;
-
- // lldb_private::RegisterContext
- bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
-
- bool WriteRegister(const unsigned reg,
- const lldb_private::RegisterValue &value);
-
- bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &value) override;
-
- bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value) override;
-
- bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
-
- bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
-
- uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,
- bool write) override;
-
- bool ClearHardwareWatchpoint(uint32_t hw_index) override;
-
- bool HardwareSingleStep(bool enable) override;
-
- // POSIXBreakpointProtocol
- bool UpdateAfterBreakpoint() override;
-
- unsigned GetRegisterIndexFromOffset(unsigned offset) override;
-
- bool IsWatchpointHit(uint32_t hw_index) override;
-
- bool ClearWatchpointHits() override;
-
- lldb::addr_t GetWatchpointAddress(uint32_t hw_index) override;
-
- bool IsWatchpointVacant(uint32_t hw_index) override;
-
- bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read,
- bool write, uint32_t hw_index) override;
-
- uint32_t NumSupportedHardwareWatchpoints() override;
-
-private:
- ProcessMonitor &GetMonitor();
-};
-
-#endif
diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
deleted file mode 100644
index b1739e1e3bd8..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
+++ /dev/null
@@ -1,613 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_x86.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 "lldb/Target/Thread.h"
-#include "lldb/Utility/DataBufferHeap.h"
-#include "lldb/Utility/RegisterValue.h"
-
-#include "Plugins/Process/FreeBSD/ProcessFreeBSD.h"
-#include "Plugins/Process/FreeBSD/ProcessMonitor.h"
-#include "RegisterContextPOSIXProcessMonitor_x86.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-// Support ptrace extensions even when compiled without required kernel support
-#ifndef NT_X86_XSTATE
-#define NT_X86_XSTATE 0x202
-#endif
-
-#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(FPR))
-
-static uint32_t size_and_rw_bits(size_t size, bool read, bool write) {
- uint32_t rw;
-
- if (read)
- rw = 0x3; // READ or READ/WRITE
- else if (write)
- rw = 0x1; // WRITE
- else
- assert(0 && "read and write cannot both be false");
-
- switch (size) {
- case 1:
- return rw;
- case 2:
- return (0x1 << 2) | rw;
- case 4:
- return (0x3 << 2) | rw;
- case 8:
- return (0x2 << 2) | rw;
- default:
- assert(0 && "invalid size, must be one of 1, 2, 4, or 8");
- return 0; // Unreachable. Just to silence compiler.
- }
-}
-
-RegisterContextPOSIXProcessMonitor_x86_64::
- RegisterContextPOSIXProcessMonitor_x86_64(
- Thread &thread, uint32_t concrete_frame_idx,
- lldb_private::RegisterInfoInterface *register_info)
- : RegisterContextPOSIX_x86(thread, concrete_frame_idx, register_info) {
- // Store byte offset of fctrl (i.e. first register of FPR) wrt 'UserArea'
- const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl");
- m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset;
-
- m_iovec.iov_base = &m_fpr.xsave;
- m_iovec.iov_len = sizeof(m_fpr.xsave);
-}
-
-ProcessMonitor &RegisterContextPOSIXProcessMonitor_x86_64::GetMonitor() {
- ProcessSP base = CalculateProcess();
- ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get());
- return process->GetMonitor();
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::ReadGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadGPR(m_thread.GetID(), &m_gpr_x86_64, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::ReadFPR() {
- ProcessMonitor &monitor = GetMonitor();
- if (GetFPRType() == eFXSAVE)
- return monitor.ReadFPR(m_thread.GetID(), &m_fpr.fxsave,
- sizeof(m_fpr.fxsave));
-
- if (GetFPRType() == eXSAVE)
- return monitor.ReadRegisterSet(m_thread.GetID(), &m_iovec,
- sizeof(m_fpr.xsave), NT_X86_XSTATE);
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::WriteGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteGPR(m_thread.GetID(), &m_gpr_x86_64, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::WriteFPR() {
- ProcessMonitor &monitor = GetMonitor();
- if (GetFPRType() == eFXSAVE)
- return monitor.WriteFPR(m_thread.GetID(), &m_fpr.fxsave,
- sizeof(m_fpr.fxsave));
-
- if (GetFPRType() == eXSAVE)
- return monitor.WriteRegisterSet(m_thread.GetID(), &m_iovec,
- sizeof(m_fpr.xsave), NT_X86_XSTATE);
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(
- const unsigned reg, RegisterValue &value) {
- ProcessMonitor &monitor = GetMonitor();
-
-#if defined(__FreeBSD__)
- if (reg >= m_reg_info.first_dr)
- return monitor.ReadDebugRegisterValue(
- m_thread.GetID(), GetRegisterOffset(reg), GetRegisterName(reg),
- GetRegisterSize(reg), value);
-#endif
- return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
- GetRegisterName(reg), GetRegisterSize(reg),
- value);
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(
- const unsigned reg, const RegisterValue &value) {
- unsigned reg_to_write = reg;
- RegisterValue value_to_write = value;
-
- // Check if this is a subregister of a full register.
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
- if (reg_info->invalidate_regs &&
- (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
- RegisterValue full_value;
- uint32_t full_reg = reg_info->invalidate_regs[0];
- const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
-
- // Read the full register.
- if (ReadRegister(full_reg_info, full_value)) {
- Status error;
- ByteOrder byte_order = GetByteOrder();
- uint8_t dst[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the full register.
- const uint32_t dest_size = full_value.GetAsMemoryData(
- full_reg_info, dst, sizeof(dst), byte_order, error);
- if (error.Success() && dest_size) {
- uint8_t src[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the source data.
- const uint32_t src_size = value.GetAsMemoryData(
- reg_info, src, sizeof(src), byte_order, error);
- if (error.Success() && src_size && (src_size < dest_size)) {
- // Copy the src bytes to the destination.
- memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
- // Set this full register as the value to write.
- value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
- value_to_write.SetType(full_reg_info);
- reg_to_write = full_reg;
- }
- }
- }
- }
-
- ProcessMonitor &monitor = GetMonitor();
-#if defined(__FreeBSD__)
- if (reg >= m_reg_info.first_dr)
- return monitor.WriteDebugRegisterValue(
- m_thread.GetID(), GetRegisterOffset(reg_to_write),
- GetRegisterName(reg_to_write), value_to_write);
-#endif
- return monitor.WriteRegisterValue(
- m_thread.GetID(), GetRegisterOffset(reg_to_write),
- GetRegisterName(reg_to_write), value_to_write);
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(
- const RegisterInfo *reg_info, RegisterValue &value) {
- if (!reg_info)
- return false;
-
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- if (IsFPR(reg, GetFPRType())) {
- if (!ReadFPR())
- return false;
- } else {
- uint32_t full_reg = reg;
- bool is_subreg = reg_info->invalidate_regs &&
- (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
-
- if (is_subreg) {
- // Read the full aligned 64-bit register.
- full_reg = reg_info->invalidate_regs[0];
- }
-
- bool success = ReadRegister(full_reg, value);
-
- if (success) {
- // If our read was not aligned (for ah,bh,ch,dh), shift our returned
- // value one byte to the right.
- if (is_subreg && (reg_info->byte_offset & 0x1))
- value.SetUInt64(value.GetAsUInt64() >> 8);
-
- // If our return byte size was greater than the return value reg size,
- // then use the type specified by reg_info rather than the uint64_t
- // default
- if (value.GetByteSize() > reg_info->byte_size)
- value.SetType(reg_info);
- }
- return success;
- }
-
- if (reg_info->encoding == eEncodingVector) {
- ByteOrder byte_order = GetByteOrder();
-
- if (byte_order != ByteOrder::eByteOrderInvalid) {
- if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
- value.SetBytes(m_fpr.fxsave.stmm[reg - m_reg_info.first_st].bytes,
- reg_info->byte_size, byte_order);
- if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
- value.SetBytes(m_fpr.fxsave.stmm[reg - m_reg_info.first_mm].bytes,
- reg_info->byte_size, byte_order);
- if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
- value.SetBytes(m_fpr.fxsave.xmm[reg - m_reg_info.first_xmm].bytes,
- reg_info->byte_size, byte_order);
- if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) {
- // Concatenate ymm using the register halves in xmm.bytes and
- // ymmh.bytes
- if (GetFPRType() == eXSAVE && CopyXSTATEtoYMM(reg, byte_order))
- value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
- reg_info->byte_size, byte_order);
- else
- return false;
- }
- return value.GetType() == RegisterValue::eTypeBytes;
- }
- return false;
- }
-
- // Get pointer to m_fpr.fxsave variable and set the data from it. Byte
- // offsets of all registers are calculated wrt 'UserArea' structure. However,
- // ReadFPR() reads fpu registers {using ptrace(PT_GETFPREGS,..)} and stores
- // them in 'm_fpr' (of type FPR structure). To extract values of fpu
- // registers, m_fpr should be read at byte offsets calculated wrt to FPR
- // structure.
-
- // Since, FPR structure is also one of the member of UserArea structure.
- // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
- // byte_offset(fctrl wrt UserArea)
- assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr));
- uint8_t *src =
- (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea;
- switch (reg_info->byte_size) {
- case 1:
- value.SetUInt8(*(uint8_t *)src);
- return true;
- case 2:
- value.SetUInt16(*(uint16_t *)src);
- return true;
- case 4:
- value.SetUInt32(*(uint32_t *)src);
- return true;
- case 8:
- value.SetUInt64(*(uint64_t *)src);
- return true;
- default:
- assert(false && "Unhandled data size.");
- return false;
- }
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(
- const RegisterInfo *reg_info, const RegisterValue &value) {
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- if (IsGPR(reg))
- return WriteRegister(reg, value);
-
- if (IsFPR(reg, GetFPRType())) {
- if (reg_info->encoding == eEncodingVector) {
- if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
- ::memcpy(m_fpr.fxsave.stmm[reg - m_reg_info.first_st].bytes,
- value.GetBytes(), value.GetByteSize());
-
- if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
- ::memcpy(m_fpr.fxsave.stmm[reg - m_reg_info.first_mm].bytes,
- value.GetBytes(), value.GetByteSize());
-
- if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
- ::memcpy(m_fpr.fxsave.xmm[reg - m_reg_info.first_xmm].bytes,
- value.GetBytes(), value.GetByteSize());
-
- if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) {
- if (GetFPRType() != eXSAVE)
- return false; // the target processor does not support AVX
-
- // Store ymm register content, and split into the register halves in
- // xmm.bytes and ymmh.bytes
- ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
- value.GetBytes(), value.GetByteSize());
- if (false == CopyYMMtoXSTATE(reg, GetByteOrder()))
- return false;
- }
- } else {
- // Get pointer to m_fpr.fxsave variable and set the data to it. Byte
- // offsets of all registers are calculated wrt 'UserArea' structure.
- // However, WriteFPR() takes m_fpr (of type FPR structure) and writes
- // only fpu registers using ptrace(PT_SETFPREGS,..) API. Hence fpu
- // registers should be written in m_fpr at byte offsets calculated wrt
- // FPR structure.
-
- // Since, FPR structure is also one of the member of UserArea structure.
- // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
- // byte_offset(fctrl wrt UserArea)
- assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) <
- sizeof(m_fpr));
- uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset -
- m_fctrl_offset_in_userarea;
- switch (reg_info->byte_size) {
- case 1:
- *(uint8_t *)dst = value.GetAsUInt8();
- break;
- case 2:
- *(uint16_t *)dst = value.GetAsUInt16();
- break;
- case 4:
- *(uint32_t *)dst = value.GetAsUInt32();
- break;
- case 8:
- *(uint64_t *)dst = value.GetAsUInt64();
- break;
- default:
- assert(false && "Unhandled data size.");
- return false;
- }
- }
-
- if (WriteFPR()) {
- if (IsAVX(reg))
- return CopyYMMtoXSTATE(reg, GetByteOrder());
- return true;
- }
- }
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::ReadAllRegisterValues(
- DataBufferSP &data_sp) {
- bool success = false;
- data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
- if (ReadGPR() && ReadFPR()) {
- uint8_t *dst = data_sp->GetBytes();
- success = dst != 0;
-
- if (success) {
- ::memcpy(dst, &m_gpr_x86_64, GetGPRSize());
- dst += GetGPRSize();
- if (GetFPRType() == eFXSAVE)
- ::memcpy(dst, &m_fpr.fxsave, sizeof(m_fpr.fxsave));
- }
-
- if (GetFPRType() == eXSAVE) {
- ByteOrder byte_order = GetByteOrder();
-
- // Assemble the YMM register content from the register halves.
- for (uint32_t reg = m_reg_info.first_ymm;
- success && reg <= m_reg_info.last_ymm; ++reg)
- success = CopyXSTATEtoYMM(reg, byte_order);
-
- if (success) {
- // Copy the extended register state including the assembled ymm
- // registers.
- ::memcpy(dst, &m_fpr, sizeof(m_fpr));
- }
- }
- }
- return success;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::WriteAllRegisterValues(
- const DataBufferSP &data_sp) {
- bool success = false;
- if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
- uint8_t *src = data_sp->GetBytes();
- if (src) {
- ::memcpy(&m_gpr_x86_64, src, GetGPRSize());
-
- if (WriteGPR()) {
- src += GetGPRSize();
- if (GetFPRType() == eFXSAVE)
- ::memcpy(&m_fpr.fxsave, src, sizeof(m_fpr.fxsave));
- if (GetFPRType() == eXSAVE)
- ::memcpy(&m_fpr.xsave, src, sizeof(m_fpr.xsave));
-
- success = WriteFPR();
- if (success) {
- if (GetFPRType() == eXSAVE) {
- ByteOrder byte_order = GetByteOrder();
-
- // Parse the YMM register content from the register halves.
- for (uint32_t reg = m_reg_info.first_ymm;
- success && reg <= m_reg_info.last_ymm; ++reg)
- success = CopyYMMtoXSTATE(reg, byte_order);
- }
- }
- }
- }
- }
- return success;
-}
-
-uint32_t RegisterContextPOSIXProcessMonitor_x86_64::SetHardwareWatchpoint(
- addr_t addr, size_t size, bool read, bool write) {
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
- uint32_t hw_index;
-
- for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) {
- if (IsWatchpointVacant(hw_index))
- return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index);
- }
-
- return LLDB_INVALID_INDEX32;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::ClearHardwareWatchpoint(
- uint32_t hw_index) {
- if (hw_index < NumSupportedHardwareWatchpoints()) {
- RegisterValue current_dr7_bits;
-
- if (ReadRegister(m_reg_info.first_dr + 7, current_dr7_bits)) {
- uint64_t new_dr7_bits =
- current_dr7_bits.GetAsUInt64() & ~(3 << (2 * hw_index));
-
- if (WriteRegister(m_reg_info.first_dr + 7, RegisterValue(new_dr7_bits)))
- return true;
- }
- }
-
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::HardwareSingleStep(
- bool enable) {
- enum { TRACE_BIT = 0x100 };
- uint64_t rflags;
-
- if ((rflags = ReadRegisterAsUnsigned(m_reg_info.gpr_flags, -1UL)) == -1UL)
- return false;
-
- if (enable) {
- if (rflags & TRACE_BIT)
- return true;
-
- rflags |= TRACE_BIT;
- } else {
- if (!(rflags & TRACE_BIT))
- return false;
-
- rflags &= ~TRACE_BIT;
- }
-
- return WriteRegisterFromUnsigned(m_reg_info.gpr_flags, rflags);
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::UpdateAfterBreakpoint() {
- // PC points one byte past the int3 responsible for the breakpoint.
- lldb::addr_t pc;
-
- if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
- return false;
-
- SetPC(pc - 1);
- return true;
-}
-
-unsigned RegisterContextPOSIXProcessMonitor_x86_64::GetRegisterIndexFromOffset(
- unsigned offset) {
- unsigned reg;
- for (reg = 0; reg < m_reg_info.num_registers; reg++) {
- if (GetRegisterInfo()[reg].byte_offset == offset)
- break;
- }
- assert(reg < m_reg_info.num_registers && "Invalid register offset.");
- return reg;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointHit(
- uint32_t hw_index) {
- bool is_hit = false;
-
- if (m_watchpoints_initialized == false) {
- // Reset the debug status and debug control registers
- RegisterValue zero_bits = RegisterValue(uint64_t(0));
- if (!WriteRegister(m_reg_info.first_dr + 6, zero_bits) ||
- !WriteRegister(m_reg_info.first_dr + 7, zero_bits))
- assert(false && "Could not initialize watchpoint registers");
- m_watchpoints_initialized = true;
- }
-
- if (hw_index < NumSupportedHardwareWatchpoints()) {
- RegisterValue value;
-
- if (ReadRegister(m_reg_info.first_dr + 6, value)) {
- uint64_t val = value.GetAsUInt64();
- is_hit = val & (1 << hw_index);
- }
- }
-
- return is_hit;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::ClearWatchpointHits() {
- return WriteRegister(m_reg_info.first_dr + 6, RegisterValue((uint64_t)0));
-}
-
-addr_t RegisterContextPOSIXProcessMonitor_x86_64::GetWatchpointAddress(
- uint32_t hw_index) {
- addr_t wp_monitor_addr = LLDB_INVALID_ADDRESS;
-
- if (hw_index < NumSupportedHardwareWatchpoints()) {
- if (!IsWatchpointVacant(hw_index)) {
- RegisterValue value;
-
- if (ReadRegister(m_reg_info.first_dr + hw_index, value))
- wp_monitor_addr = value.GetAsUInt64();
- }
- }
-
- return wp_monitor_addr;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointVacant(
- uint32_t hw_index) {
- bool is_vacant = false;
- RegisterValue value;
-
- assert(hw_index < NumSupportedHardwareWatchpoints());
-
- if (m_watchpoints_initialized == false) {
- // Reset the debug status and debug control registers
- RegisterValue zero_bits = RegisterValue(uint64_t(0));
- if (!WriteRegister(m_reg_info.first_dr + 6, zero_bits) ||
- !WriteRegister(m_reg_info.first_dr + 7, zero_bits))
- assert(false && "Could not initialize watchpoint registers");
- m_watchpoints_initialized = true;
- }
-
- if (ReadRegister(m_reg_info.first_dr + 7, value)) {
- uint64_t val = value.GetAsUInt64();
- is_vacant = (val & (3 << 2 * hw_index)) == 0;
- }
-
- return is_vacant;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::SetHardwareWatchpointWithIndex(
- addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) {
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
-
- if (num_hw_watchpoints == 0 || hw_index >= num_hw_watchpoints)
- return false;
-
- if (!(size == 1 || size == 2 || size == 4 || size == 8))
- return false;
-
- if (read == false && write == false)
- return false;
-
- if (!IsWatchpointVacant(hw_index))
- return false;
-
- // Set both dr7 (debug control register) and dri (debug address register).
-
- // dr7{7-0} encodes the local/global enable bits:
- // global enable --. .-- local enable
- // | |
- // v v
- // dr0 -> bits{1-0}
- // dr1 -> bits{3-2}
- // dr2 -> bits{5-4}
- // dr3 -> bits{7-6}
- //
- // dr7{31-16} encodes the rw/len bits:
- // b_x+3, b_x+2, b_x+1, b_x
- // where bits{x+1, x} => rw
- // 0b00: execute, 0b01: write, 0b11: read-or-write,
- // 0b10: io read-or-write (unused)
- // and bits{x+3, x+2} => len
- // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte
- //
- // dr0 -> bits{19-16}
- // dr1 -> bits{23-20}
- // dr2 -> bits{27-24}
- // dr3 -> bits{31-28}
- if (hw_index < num_hw_watchpoints) {
- RegisterValue current_dr7_bits;
-
- if (ReadRegister(m_reg_info.first_dr + 7, current_dr7_bits)) {
- uint64_t new_dr7_bits =
- current_dr7_bits.GetAsUInt64() |
- (1 << (2 * hw_index) |
- size_and_rw_bits(size, read, write) << (16 + 4 * hw_index));
-
- if (WriteRegister(m_reg_info.first_dr + hw_index, RegisterValue(addr)) &&
- WriteRegister(m_reg_info.first_dr + 7, RegisterValue(new_dr7_bits)))
- return true;
- }
- }
-
- return false;
-}
-
-uint32_t
-RegisterContextPOSIXProcessMonitor_x86_64::NumSupportedHardwareWatchpoints() {
- // Available debug address registers: dr0, dr1, dr2, dr3
- return 4;
-}
diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h
deleted file mode 100644
index 1afb366eeba3..000000000000
--- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h
+++ /dev/null
@@ -1,81 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_x86.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_RegisterContextPOSIXProcessMonitor_x86_H_
-#define liblldb_RegisterContextPOSIXProcessMonitor_x86_H_
-
-#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h"
-#include "RegisterContextPOSIX.h"
-#include <sys/uio.h>
-
-class RegisterContextPOSIXProcessMonitor_x86_64
- : public RegisterContextPOSIX_x86,
- public POSIXBreakpointProtocol {
-public:
- RegisterContextPOSIXProcessMonitor_x86_64(
- lldb_private::Thread &thread, uint32_t concrete_frame_idx,
- lldb_private::RegisterInfoInterface *register_info);
-
-protected:
- bool ReadGPR() override;
-
- bool ReadFPR() override;
-
- bool WriteGPR() override;
-
- bool WriteFPR() override;
-
- // lldb_private::RegisterContext
- bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
-
- bool WriteRegister(const unsigned reg,
- const lldb_private::RegisterValue &value);
-
- bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &value) override;
-
- bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value) override;
-
- bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
-
- bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
-
- uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,
- bool write) override;
-
- bool ClearHardwareWatchpoint(uint32_t hw_index) override;
-
- bool HardwareSingleStep(bool enable) override;
-
- // POSIXBreakpointProtocol
- bool UpdateAfterBreakpoint() override;
-
- unsigned GetRegisterIndexFromOffset(unsigned offset) override;
-
- bool IsWatchpointHit(uint32_t hw_index) override;
-
- bool ClearWatchpointHits() override;
-
- lldb::addr_t GetWatchpointAddress(uint32_t hw_index) override;
-
- bool IsWatchpointVacant(uint32_t hw_index) override;
-
- bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read,
- bool write, uint32_t hw_index) override;
-
- uint32_t NumSupportedHardwareWatchpoints() override;
-
-private:
- ProcessMonitor &GetMonitor();
- uint32_t
- m_fctrl_offset_in_userarea; // Offset of 'fctrl' in 'UserArea' Structure
- struct iovec m_iovec;
-};
-
-#endif
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
index 57f0eb3cceb6..9ea1a16b8785 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
@@ -133,13 +133,20 @@ NativeProcessNetBSD::Factory::Attach(
return std::move(process_up);
}
+NativeProcessNetBSD::Extension
+NativeProcessNetBSD::Factory::GetSupportedExtensions() const {
+ return Extension::multiprocess | Extension::fork | Extension::vfork |
+ Extension::pass_signals | Extension::auxv | Extension::libraries_svr4;
+}
+
// Public Instance Methods
NativeProcessNetBSD::NativeProcessNetBSD(::pid_t pid, int terminal_fd,
NativeDelegate &delegate,
const ArchSpec &arch,
MainLoop &mainloop)
- : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch) {
+ : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch),
+ m_main_loop(mainloop) {
if (m_terminal_fd != -1) {
Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
assert(status.Success());
@@ -256,6 +263,33 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
SetState(StateType::eStateStopped, true);
return;
}
+ case TRAP_CHLD: {
+ ptrace_state_t pst;
+ Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst));
+ if (error.Fail()) {
+ SetState(StateType::eStateInvalid);
+ return;
+ }
+
+ assert(thread);
+ if (pst.pe_report_event == PTRACE_VFORK_DONE) {
+ if ((m_enabled_extensions & Extension::vfork) == Extension::vfork) {
+ thread->SetStoppedByVForkDone();
+ SetState(StateType::eStateStopped, true);
+ } else {
+ Status error =
+ PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void *>(1), 0);
+ if (error.Fail())
+ SetState(StateType::eStateInvalid);
+ }
+ } else {
+ assert(pst.pe_report_event == PTRACE_FORK ||
+ pst.pe_report_event == PTRACE_VFORK);
+ MonitorClone(pst.pe_other_pid, pst.pe_report_event == PTRACE_VFORK,
+ *thread);
+ }
+ return;
+ }
case TRAP_LWP: {
ptrace_state_t pst;
Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst));
@@ -510,7 +544,7 @@ Status NativeProcessNetBSD::Detach() {
if (GetID() == LLDB_INVALID_PROCESS_ID)
return error;
- return PtraceWrapper(PT_DETACH, GetID());
+ return PtraceWrapper(PT_DETACH, GetID(), reinterpret_cast<void *>(1));
}
Status NativeProcessNetBSD::Signal(int signo) {
@@ -738,17 +772,17 @@ Status NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef &file_name,
void NativeProcessNetBSD::SigchldHandler() {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- // Process all pending waitpid notifications.
int status;
::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status,
WALLSIG | WNOHANG);
if (wait_pid == 0)
- return; // We are done.
+ return;
if (wait_pid == -1) {
Status error(errno, eErrorTypePOSIX);
LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);
+ return;
}
WaitStatus wait_status = WaitStatus::Decode(status);
@@ -936,8 +970,9 @@ Status NativeProcessNetBSD::SetupTrace() {
PtraceWrapper(PT_GET_EVENT_MASK, GetID(), &events, sizeof(events));
if (status.Fail())
return status;
- // TODO: PTRACE_FORK | PTRACE_VFORK | PTRACE_POSIX_SPAWN?
- events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT;
+ // TODO: PTRACE_POSIX_SPAWN?
+ events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT | PTRACE_FORK |
+ PTRACE_VFORK | PTRACE_VFORK_DONE;
status = PtraceWrapper(PT_SET_EVENT_MASK, GetID(), &events, sizeof(events));
if (status.Fail())
return status;
@@ -974,3 +1009,67 @@ Status NativeProcessNetBSD::ReinitializeThreads() {
return error;
}
+
+void NativeProcessNetBSD::MonitorClone(::pid_t child_pid, bool is_vfork,
+ NativeThreadNetBSD &parent_thread) {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ LLDB_LOG(log, "clone, child_pid={0}", child_pid);
+
+ int status;
+ ::pid_t wait_pid =
+ llvm::sys::RetryAfterSignal(-1, ::waitpid, child_pid, &status, 0);
+ if (wait_pid != child_pid) {
+ LLDB_LOG(log,
+ "waiting for pid {0} failed. Assuming the pid has "
+ "disappeared in the meantime",
+ child_pid);
+ return;
+ }
+ if (WIFEXITED(status)) {
+ LLDB_LOG(log,
+ "waiting for pid {0} returned an 'exited' event. Not "
+ "tracking it.",
+ child_pid);
+ return;
+ }
+
+ ptrace_siginfo_t info;
+ const auto siginfo_err =
+ PtraceWrapper(PT_GET_SIGINFO, child_pid, &info, sizeof(info));
+ if (siginfo_err.Fail()) {
+ LLDB_LOG(log, "PT_GET_SIGINFO failed {0}", siginfo_err);
+ return;
+ }
+ assert(info.psi_lwpid >= 0);
+ lldb::tid_t child_tid = info.psi_lwpid;
+
+ std::unique_ptr<NativeProcessNetBSD> child_process{
+ new NativeProcessNetBSD(static_cast<::pid_t>(child_pid), m_terminal_fd,
+ m_delegate, m_arch, m_main_loop)};
+ if (!is_vfork)
+ child_process->m_software_breakpoints = m_software_breakpoints;
+
+ Extension expected_ext = is_vfork ? Extension::vfork : Extension::fork;
+ if ((m_enabled_extensions & expected_ext) == expected_ext) {
+ child_process->SetupTrace();
+ for (const auto &thread : child_process->m_threads)
+ static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
+ child_process->SetState(StateType::eStateStopped, false);
+
+ m_delegate.NewSubprocess(this, std::move(child_process));
+ if (is_vfork)
+ parent_thread.SetStoppedByVFork(child_pid, child_tid);
+ else
+ parent_thread.SetStoppedByFork(child_pid, child_tid);
+ SetState(StateType::eStateStopped, true);
+ } else {
+ child_process->Detach();
+ Status pt_error =
+ PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1), 0);
+ if (pt_error.Fail()) {
+ LLDB_LOG_ERROR(log, std::move(pt_error.ToError()),
+ "unable to resume parent process {1}: {0}", GetID());
+ SetState(StateType::eStateInvalid);
+ }
+ }
+}
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
index 3d59a4f72e94..90d32aa6069d 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
@@ -36,6 +36,8 @@ public:
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
MainLoop &mainloop) const override;
+
+ Extension GetSupportedExtensions() const override;
};
// NativeProcessProtocol Interface
@@ -89,6 +91,7 @@ public:
private:
MainLoop::SignalHandleUP m_sigchld_handle;
ArchSpec m_arch;
+ MainLoop& m_main_loop;
LazyBool m_supports_mem_region = eLazyBoolCalculate;
std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache;
@@ -106,6 +109,8 @@ private:
void MonitorSIGSTOP(lldb::pid_t pid);
void MonitorSIGTRAP(lldb::pid_t pid);
void MonitorSignal(lldb::pid_t pid, int signal);
+ void MonitorClone(::pid_t child_pid, bool is_vfork,
+ NativeThreadNetBSD &parent_thread);
Status PopulateMemoryRegionCache();
void SigchldHandler();
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
index ed1884c94a4b..3d164eadbea7 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
@@ -29,8 +29,8 @@
#include <x86/specialreg.h>
#include <elf.h>
#include <err.h>
-#include <stdint.h>
-#include <stdlib.h>
+#include <cstdint>
+#include <cstdlib>
// clang-format on
using namespace lldb_private;
@@ -267,7 +267,7 @@ NativeRegisterContextNetBSD_x86_64::NativeRegisterContextNetBSD_x86_64(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
: NativeRegisterContextRegisterInfo(
native_thread, CreateRegisterInfoInterface(target_arch)),
- m_regset_offsets({0}) {
+ NativeRegisterContextDBReg_x86(native_thread), m_regset_offsets({0}) {
assert(m_gpr.size() == GetRegisterInfoInterface().GetGPRSize());
std::array<uint32_t, MaxRegularRegSet + 1> first_regnos;
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
index d20fd67cdc5d..31005952dd75 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
@@ -22,7 +22,7 @@
#include "Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h"
#include "Plugins/Process/Utility/RegisterContext_x86.h"
-#include "Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.h"
+#include "Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h"
#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
namespace lldb_private {
@@ -32,7 +32,7 @@ class NativeProcessNetBSD;
class NativeRegisterContextNetBSD_x86_64
: public NativeRegisterContextNetBSD,
- public NativeRegisterContextWatchpoint_x86 {
+ public NativeRegisterContextDBReg_x86 {
public:
NativeRegisterContextNetBSD_x86_64(const ArchSpec &target_arch,
NativeThreadProtocol &native_thread);
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
index 1a3fd4d646ae..400b89a5fddf 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
@@ -130,6 +130,30 @@ void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) {
m_stop_info.details.signal.signo = SIGTRAP;
}
+void NativeThreadNetBSD::SetStoppedByFork(lldb::pid_t child_pid,
+ lldb::tid_t child_tid) {
+ SetStopped();
+
+ m_stop_info.reason = StopReason::eStopReasonFork;
+ m_stop_info.details.fork.child_pid = child_pid;
+ m_stop_info.details.fork.child_tid = child_tid;
+}
+
+void NativeThreadNetBSD::SetStoppedByVFork(lldb::pid_t child_pid,
+ lldb::tid_t child_tid) {
+ SetStopped();
+
+ m_stop_info.reason = StopReason::eStopReasonVFork;
+ m_stop_info.details.fork.child_pid = child_pid;
+ m_stop_info.details.fork.child_tid = child_tid;
+}
+
+void NativeThreadNetBSD::SetStoppedByVForkDone() {
+ SetStopped();
+
+ m_stop_info.reason = StopReason::eStopReasonVForkDone;
+}
+
void NativeThreadNetBSD::SetStoppedWithNoReason() {
SetStopped();
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
index d4e21bd2bdaa..ee9305337fda 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
@@ -59,6 +59,9 @@ private:
void SetStoppedByTrace();
void SetStoppedByExec();
void SetStoppedByWatchpoint(uint32_t wp_index);
+ void SetStoppedByFork(lldb::pid_t child_pid, lldb::tid_t child_tid);
+ void SetStoppedByVFork(lldb::pid_t child_pid, lldb::tid_t child_tid);
+ void SetStoppedByVForkDone();
void SetStoppedWithNoReason();
void SetStopped();
void SetRunning();
diff --git a/lldb/source/Plugins/Process/POSIX/CrashReason.h b/lldb/source/Plugins/Process/POSIX/CrashReason.h
index f5213891d976..24acdc08e900 100644
--- a/lldb/source/Plugins/Process/POSIX/CrashReason.h
+++ b/lldb/source/Plugins/Process/POSIX/CrashReason.h
@@ -11,7 +11,7 @@
#include "lldb/lldb-types.h"
-#include <signal.h>
+#include <csignal>
#include <string>
diff --git a/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h b/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h
index dcfa9290ff50..c01409940daa 100644
--- a/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h
+++ b/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h
@@ -21,6 +21,9 @@ namespace lldb_private {
class NativeProcessELF : public NativeProcessProtocol {
using NativeProcessProtocol::NativeProcessProtocol;
+public:
+ llvm::Optional<uint64_t> GetAuxValue(enum AuxVector::EntryType type);
+
protected:
template <typename T> struct ELFLinkMap {
T l_addr;
@@ -30,8 +33,6 @@ protected:
T l_prev;
};
- llvm::Optional<uint64_t> GetAuxValue(enum AuxVector::EntryType type);
-
lldb::addr_t GetSharedLibraryInfoAddress() override;
template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN>
diff --git a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
index 5463a071503c..a85d7bd6f525 100644
--- a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
+++ b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -697,6 +697,14 @@ RegisterInfo *DynamicRegisterInfo::GetRegisterInfoAtIndex(uint32_t i) {
return nullptr;
}
+const RegisterInfo *DynamicRegisterInfo::GetRegisterInfo(uint32_t kind,
+ uint32_t num) const {
+ uint32_t reg_index = ConvertRegisterKindToRegisterNumber(kind, num);
+ if (reg_index != LLDB_INVALID_REGNUM)
+ return &m_regs[reg_index];
+ return nullptr;
+}
+
const RegisterSet *DynamicRegisterInfo::GetRegisterSet(uint32_t i) const {
if (i < m_sets.size())
return &m_sets[i];
diff --git a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
index fbf9db685b71..7e90454c6d9d 100644
--- a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
+++ b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
@@ -60,6 +60,9 @@ public:
uint32_t ConvertRegisterKindToRegisterNumber(uint32_t kind,
uint32_t num) const;
+ const lldb_private::RegisterInfo *GetRegisterInfo(uint32_t kind,
+ uint32_t num) const;
+
void Dump() const;
void Clear();
diff --git a/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp b/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp
index 9b9522955de9..7749dc6f5d51 100644
--- a/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp
+++ b/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp
@@ -30,7 +30,7 @@ HistoryUnwind::HistoryUnwind(Thread &thread, std::vector<lldb::addr_t> pcs,
// Destructor
-HistoryUnwind::~HistoryUnwind() {}
+HistoryUnwind::~HistoryUnwind() = default;
void HistoryUnwind::DoClear() {
std::lock_guard<std::recursive_mutex> guard(m_unwind_mutex);
diff --git a/lldb/source/Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h b/lldb/source/Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h
index 7f6f7cf5832d..817dca336de7 100644
--- a/lldb/source/Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h
+++ b/lldb/source/Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h
@@ -9,7 +9,7 @@
#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LINUXPTRACEDEFINES_ARM64SVE_H
#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LINUXPTRACEDEFINES_ARM64SVE_H
-#include <stdint.h>
+#include <cstdint>
namespace lldb_private {
namespace sve {
@@ -65,7 +65,7 @@ const uint16_t sve_context_size = 16;
* The same convention applies when returning from a signal: a caller
* will need to remove or resize the sve_context block if it wants to
* make the SVE registers live when they were previously non-live or
- * vice-versa. This may require the the caller to allocate fresh
+ * vice-versa. This may require the caller to allocate fresh
* memory and/or move other context blocks in the signal frame.
*
* Changing the vector length during signal return is not permitted:
diff --git a/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp b/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp
new file mode 100644
index 000000000000..d74b66b58afc
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp
@@ -0,0 +1,200 @@
+//===-- MemoryTagManagerAArch64MTE.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 "MemoryTagManagerAArch64MTE.h"
+
+using namespace lldb_private;
+
+static const unsigned MTE_START_BIT = 56;
+static const unsigned MTE_TAG_MAX = 0xf;
+static const unsigned MTE_GRANULE_SIZE = 16;
+
+lldb::addr_t
+MemoryTagManagerAArch64MTE::GetLogicalTag(lldb::addr_t addr) const {
+ return (addr >> MTE_START_BIT) & MTE_TAG_MAX;
+}
+
+lldb::addr_t
+MemoryTagManagerAArch64MTE::RemoveNonAddressBits(lldb::addr_t addr) const {
+ // Here we're ignoring the whole top byte. If you've got MTE
+ // you must also have TBI (top byte ignore).
+ // The other 4 bits could contain other extension bits or
+ // user metadata.
+ return addr & ~((lldb::addr_t)0xFF << MTE_START_BIT);
+}
+
+ptrdiff_t MemoryTagManagerAArch64MTE::AddressDiff(lldb::addr_t addr1,
+ lldb::addr_t addr2) const {
+ return RemoveNonAddressBits(addr1) - RemoveNonAddressBits(addr2);
+}
+
+lldb::addr_t MemoryTagManagerAArch64MTE::GetGranuleSize() const {
+ return MTE_GRANULE_SIZE;
+}
+
+int32_t MemoryTagManagerAArch64MTE::GetAllocationTagType() const {
+ return eMTE_allocation;
+}
+
+size_t MemoryTagManagerAArch64MTE::GetTagSizeInBytes() const { return 1; }
+
+MemoryTagManagerAArch64MTE::TagRange
+MemoryTagManagerAArch64MTE::ExpandToGranule(TagRange range) const {
+ // Ignore reading a length of 0
+ if (!range.IsValid())
+ return range;
+
+ const size_t granule = GetGranuleSize();
+
+ // Align start down to granule start
+ lldb::addr_t new_start = range.GetRangeBase();
+ lldb::addr_t align_down_amount = new_start % granule;
+ new_start -= align_down_amount;
+
+ // Account for the distance we moved the start above
+ size_t new_len = range.GetByteSize() + align_down_amount;
+ // Then align up to the end of the granule
+ size_t align_up_amount = granule - (new_len % granule);
+ if (align_up_amount != granule)
+ new_len += align_up_amount;
+
+ return TagRange(new_start, new_len);
+}
+
+llvm::Expected<MemoryTagManager::TagRange>
+MemoryTagManagerAArch64MTE::MakeTaggedRange(
+ lldb::addr_t addr, lldb::addr_t end_addr,
+ const lldb_private::MemoryRegionInfos &memory_regions) const {
+ // First check that the range is not inverted.
+ // We must remove tags here otherwise an address with a higher
+ // tag value will always be > the other.
+ ptrdiff_t len = AddressDiff(end_addr, addr);
+ if (len <= 0) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "End address (0x%" PRIx64
+ ") must be greater than the start address (0x%" PRIx64 ")",
+ end_addr, addr);
+ }
+
+ // Region addresses will not have memory tags. So when searching
+ // we must use an untagged address.
+ MemoryRegionInfo::RangeType tag_range(RemoveNonAddressBits(addr), len);
+ tag_range = ExpandToGranule(tag_range);
+
+ // Make a copy so we can use the original for errors and the final return.
+ MemoryRegionInfo::RangeType remaining_range(tag_range);
+
+ // While there are parts of the range that don't have a matching tagged memory
+ // region
+ while (remaining_range.IsValid()) {
+ // Search for a region that contains the start of the range
+ MemoryRegionInfos::const_iterator region = std::find_if(
+ memory_regions.cbegin(), memory_regions.cend(),
+ [&remaining_range](const MemoryRegionInfo &region) {
+ return region.GetRange().Contains(remaining_range.GetRangeBase());
+ });
+
+ if (region == memory_regions.cend() ||
+ region->GetMemoryTagged() != MemoryRegionInfo::eYes) {
+ // Some part of this range is untagged (or unmapped) so error
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Address range 0x%" PRIx64 ":0x%" PRIx64
+ " is not in a memory tagged region",
+ tag_range.GetRangeBase(),
+ tag_range.GetRangeEnd());
+ }
+
+ // We've found some part of the range so remove that part and continue
+ // searching for the rest. Moving the base "slides" the range so we need to
+ // save/restore the original end. If old_end is less than the new base, the
+ // range will be set to have 0 size and we'll exit the while.
+ lldb::addr_t old_end = remaining_range.GetRangeEnd();
+ remaining_range.SetRangeBase(region->GetRange().GetRangeEnd());
+ remaining_range.SetRangeEnd(old_end);
+ }
+
+ // Every part of the range is contained within a tagged memory region.
+ return tag_range;
+}
+
+llvm::Expected<std::vector<lldb::addr_t>>
+MemoryTagManagerAArch64MTE::UnpackTagsData(const std::vector<uint8_t> &tags,
+ size_t granules /*=0*/) const {
+ // 0 means don't check the number of tags before unpacking
+ if (granules) {
+ size_t num_tags = tags.size() / GetTagSizeInBytes();
+ if (num_tags != granules) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Packed tag data size does not match expected number of tags. "
+ "Expected %zu tag(s) for %zu granule(s), got %zu tag(s).",
+ granules, granules, num_tags);
+ }
+ }
+
+ // (if bytes per tag was not 1, we would reconstruct them here)
+
+ std::vector<lldb::addr_t> unpacked;
+ unpacked.reserve(tags.size());
+ for (auto it = tags.begin(); it != tags.end(); ++it) {
+ // Check all tags are in range
+ if (*it > MTE_TAG_MAX) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Found tag 0x%x which is > max MTE tag value of 0x%x.", *it,
+ MTE_TAG_MAX);
+ }
+ unpacked.push_back(*it);
+ }
+
+ return unpacked;
+}
+
+llvm::Expected<std::vector<uint8_t>> MemoryTagManagerAArch64MTE::PackTags(
+ const std::vector<lldb::addr_t> &tags) const {
+ std::vector<uint8_t> packed;
+ packed.reserve(tags.size() * GetTagSizeInBytes());
+
+ for (auto tag : tags) {
+ if (tag > MTE_TAG_MAX) {
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Found tag 0x%" PRIx64
+ " which is > max MTE tag value of 0x%x.",
+ tag, MTE_TAG_MAX);
+ }
+ packed.push_back(static_cast<uint8_t>(tag));
+ }
+
+ return packed;
+}
+
+llvm::Expected<std::vector<lldb::addr_t>>
+MemoryTagManagerAArch64MTE::RepeatTagsForRange(
+ const std::vector<lldb::addr_t> &tags, TagRange range) const {
+ std::vector<lldb::addr_t> new_tags;
+
+ // If the range is not empty
+ if (range.IsValid()) {
+ if (tags.empty()) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Expected some tags to cover given range, got zero.");
+ }
+
+ // We assume that this range has already been expanded/aligned to granules
+ size_t granules = range.GetByteSize() / GetGranuleSize();
+ new_tags.reserve(granules);
+ for (size_t to_copy = 0; granules > 0; granules -= to_copy) {
+ to_copy = granules > tags.size() ? tags.size() : granules;
+ new_tags.insert(new_tags.end(), tags.begin(), tags.begin() + to_copy);
+ }
+ }
+
+ return new_tags;
+}
diff --git a/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h b/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h
new file mode 100644
index 000000000000..d4e8249da93f
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h
@@ -0,0 +1,53 @@
+//===-- MemoryTagManagerAArch64MTE.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_SOURCE_PLUGINS_PROCESS_UTILITY_MEMORYTAGMANAGERAARCH64MTE_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_MEMORYTAGMANAGERAARCH64MTE_H
+
+#include "lldb/Target/MemoryTagManager.h"
+
+namespace lldb_private {
+
+class MemoryTagManagerAArch64MTE : public MemoryTagManager {
+public:
+ // This enum is supposed to be shared for all of AArch64 but until
+ // there are more tag types than MTE, it will live here.
+ enum MTETagTypes {
+ eMTE_logical = 0,
+ eMTE_allocation = 1,
+ };
+
+ lldb::addr_t GetGranuleSize() const override;
+ int32_t GetAllocationTagType() const override;
+ size_t GetTagSizeInBytes() const override;
+
+ lldb::addr_t GetLogicalTag(lldb::addr_t addr) const override;
+ lldb::addr_t RemoveNonAddressBits(lldb::addr_t addr) const override;
+ ptrdiff_t AddressDiff(lldb::addr_t addr1, lldb::addr_t addr2) const override;
+
+ TagRange ExpandToGranule(TagRange range) const override;
+
+ llvm::Expected<TagRange> MakeTaggedRange(
+ lldb::addr_t addr, lldb::addr_t end_addr,
+ const lldb_private::MemoryRegionInfos &memory_regions) const override;
+
+ llvm::Expected<std::vector<lldb::addr_t>>
+ UnpackTagsData(const std::vector<uint8_t> &tags,
+ size_t granules = 0) const override;
+
+ llvm::Expected<std::vector<uint8_t>>
+ PackTags(const std::vector<lldb::addr_t> &tags) const override;
+
+ llvm::Expected<std::vector<lldb::addr_t>>
+ RepeatTagsForRange(const std::vector<lldb::addr_t> &tags,
+ TagRange range) const override;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_MEMORYTAGMANAGERAARCH64MTE_H
diff --git a/lldb/source/Plugins/Process/Utility/NativeProcessSoftwareSingleStep.cpp b/lldb/source/Plugins/Process/Utility/NativeProcessSoftwareSingleStep.cpp
new file mode 100644
index 000000000000..ee5295bf6565
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/NativeProcessSoftwareSingleStep.cpp
@@ -0,0 +1,182 @@
+//===-- NativeProcessSoftwareSingleStep.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 "NativeProcessSoftwareSingleStep.h"
+
+#include "lldb/Core/EmulateInstruction.h"
+#include "lldb/Host/common/NativeRegisterContext.h"
+#include "lldb/Utility/RegisterValue.h"
+
+#include <unordered_map>
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace {
+
+struct EmulatorBaton {
+ NativeProcessProtocol &m_process;
+ NativeRegisterContext &m_reg_context;
+
+ // eRegisterKindDWARF -> RegsiterValue
+ std::unordered_map<uint32_t, RegisterValue> m_register_values;
+
+ EmulatorBaton(NativeProcessProtocol &process,
+ NativeRegisterContext &reg_context)
+ : m_process(process), m_reg_context(reg_context) {}
+};
+
+} // anonymous namespace
+
+static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton,
+ const EmulateInstruction::Context &context,
+ lldb::addr_t addr, void *dst, size_t length) {
+ EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
+
+ size_t bytes_read;
+ emulator_baton->m_process.ReadMemory(addr, dst, length, bytes_read);
+ return bytes_read;
+}
+
+static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton,
+ const RegisterInfo *reg_info,
+ RegisterValue &reg_value) {
+ EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
+
+ auto it = emulator_baton->m_register_values.find(
+ reg_info->kinds[eRegisterKindDWARF]);
+ if (it != emulator_baton->m_register_values.end()) {
+ reg_value = it->second;
+ return true;
+ }
+
+ // The emulator only fill in the dwarf regsiter numbers (and in some case the
+ // generic register numbers). Get the full register info from the register
+ // context based on the dwarf register numbers.
+ const RegisterInfo *full_reg_info =
+ emulator_baton->m_reg_context.GetRegisterInfo(
+ eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]);
+
+ Status error =
+ emulator_baton->m_reg_context.ReadRegister(full_reg_info, reg_value);
+ if (error.Success())
+ return true;
+
+ return false;
+}
+
+static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton,
+ const EmulateInstruction::Context &context,
+ const RegisterInfo *reg_info,
+ const RegisterValue &reg_value) {
+ EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
+ emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] =
+ reg_value;
+ return true;
+}
+
+static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton,
+ const EmulateInstruction::Context &context,
+ lldb::addr_t addr, const void *dst,
+ size_t length) {
+ return length;
+}
+
+static lldb::addr_t ReadFlags(NativeRegisterContext &regsiter_context) {
+ const RegisterInfo *flags_info = regsiter_context.GetRegisterInfo(
+ eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
+ return regsiter_context.ReadRegisterAsUnsigned(flags_info,
+ LLDB_INVALID_ADDRESS);
+}
+
+Status NativeProcessSoftwareSingleStep::SetupSoftwareSingleStepping(
+ NativeThreadProtocol &thread) {
+ Status error;
+ NativeProcessProtocol &process = thread.GetProcess();
+ NativeRegisterContext &register_context = thread.GetRegisterContext();
+ const ArchSpec &arch = process.GetArchitecture();
+
+ std::unique_ptr<EmulateInstruction> emulator_up(
+ EmulateInstruction::FindPlugin(arch, eInstructionTypePCModifying,
+ nullptr));
+
+ if (emulator_up == nullptr)
+ return Status("Instruction emulator not found!");
+
+ EmulatorBaton baton(process, register_context);
+ emulator_up->SetBaton(&baton);
+ emulator_up->SetReadMemCallback(&ReadMemoryCallback);
+ emulator_up->SetReadRegCallback(&ReadRegisterCallback);
+ emulator_up->SetWriteMemCallback(&WriteMemoryCallback);
+ emulator_up->SetWriteRegCallback(&WriteRegisterCallback);
+
+ if (!emulator_up->ReadInstruction())
+ return Status("Read instruction failed!");
+
+ bool emulation_result =
+ emulator_up->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
+
+ const RegisterInfo *reg_info_pc = register_context.GetRegisterInfo(
+ eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ const RegisterInfo *reg_info_flags = register_context.GetRegisterInfo(
+ eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
+
+ auto pc_it =
+ baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]);
+ auto flags_it =
+ baton.m_register_values.find(reg_info_flags->kinds[eRegisterKindDWARF]);
+
+ lldb::addr_t next_pc;
+ lldb::addr_t next_flags;
+ if (emulation_result) {
+ assert(pc_it != baton.m_register_values.end() &&
+ "Emulation was successfull but PC wasn't updated");
+ next_pc = pc_it->second.GetAsUInt64();
+
+ if (flags_it != baton.m_register_values.end())
+ next_flags = flags_it->second.GetAsUInt64();
+ else
+ next_flags = ReadFlags(register_context);
+ } else if (pc_it == baton.m_register_values.end()) {
+ // Emulate instruction failed and it haven't changed PC. Advance PC with
+ // the size of the current opcode because the emulation of all
+ // PC modifying instruction should be successful. The failure most
+ // likely caused by a not supported instruction which don't modify PC.
+ next_pc = register_context.GetPC() + emulator_up->GetOpcode().GetByteSize();
+ next_flags = ReadFlags(register_context);
+ } else {
+ // The instruction emulation failed after it modified the PC. It is an
+ // unknown error where we can't continue because the next instruction is
+ // modifying the PC but we don't know how.
+ return Status("Instruction emulation failed unexpectedly.");
+ }
+
+ int size_hint = 0;
+ if (arch.GetMachine() == llvm::Triple::arm) {
+ if (next_flags & 0x20) {
+ // Thumb mode
+ size_hint = 2;
+ } else {
+ // Arm mode
+ size_hint = 4;
+ }
+ } else if (arch.IsMIPS() || arch.GetTriple().isPPC64())
+ size_hint = 4;
+ error = process.SetBreakpoint(next_pc, size_hint, /*hardware=*/false);
+
+ // If setting the breakpoint fails because next_pc is out of the address
+ // space, ignore it and let the debugee segfault.
+ if (error.GetError() == EIO || error.GetError() == EFAULT) {
+ return Status();
+ } else if (error.Fail())
+ return error;
+
+ m_threads_stepping_with_breakpoint.insert({thread.GetID(), next_pc});
+
+ return Status();
+}
diff --git a/lldb/source/Plugins/Process/Utility/NativeProcessSoftwareSingleStep.h b/lldb/source/Plugins/Process/Utility/NativeProcessSoftwareSingleStep.h
new file mode 100644
index 000000000000..f9435b7a84ba
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/NativeProcessSoftwareSingleStep.h
@@ -0,0 +1,31 @@
+//===-- NativeProcessSoftwareSingleStep.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_NativeProcessSoftwareSingleStep_h
+#define lldb_NativeProcessSoftwareSingleStep_h
+
+#include "lldb/Host/common/NativeProcessProtocol.h"
+#include "lldb/Host/common/NativeThreadProtocol.h"
+
+#include <map>
+
+namespace lldb_private {
+
+class NativeProcessSoftwareSingleStep {
+public:
+ Status SetupSoftwareSingleStepping(NativeThreadProtocol &thread);
+
+protected:
+ // List of thread ids stepping with a breakpoint with the address of
+ // the relevan breakpoint
+ std::map<lldb::tid_t, lldb::addr_t> m_threads_stepping_with_breakpoint;
+};
+
+} // namespace lldb_private
+
+#endif // #ifndef lldb_NativeProcessSoftwareSingleStep_h
diff --git a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.cpp b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.cpp
new file mode 100644
index 000000000000..feee857cfe5f
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.cpp
@@ -0,0 +1,469 @@
+//===-- NativeRegisterContextDBReg_arm64.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 "NativeRegisterContextDBReg_arm64.h"
+
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
+
+using namespace lldb_private;
+
+// E (bit 0), used to enable breakpoint/watchpoint
+constexpr uint32_t g_enable_bit = 1;
+// PAC (bits 2:1): 0b10
+constexpr uint32_t g_pac_bits = (2 << 1);
+
+// Returns appropriate control register bits for the specified size
+static constexpr inline uint64_t GetSizeBits(int size) {
+ // BAS (bits 12:5) hold a bit-mask of addresses to watch
+ // e.g. 0b00000001 means 1 byte at address
+ // 0b00000011 means 2 bytes (addr..addr+1)
+ // ...
+ // 0b11111111 means 8 bytes (addr..addr+7)
+ return ((1 << size) - 1) << 5;
+}
+
+uint32_t NativeRegisterContextDBReg_arm64::NumSupportedHardwareBreakpoints() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ llvm::Error error = ReadHardwareDebugInfo();
+ if (error) {
+ LLDB_LOG_ERROR(log, std::move(error),
+ "failed to read debug registers: {0}");
+ return 0;
+ }
+
+ return m_max_hbp_supported;
+}
+
+uint32_t
+NativeRegisterContextDBReg_arm64::SetHardwareBreakpoint(lldb::addr_t addr,
+ size_t size) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ LLDB_LOG(log, "addr: {0:x}, size: {1:x}", addr, size);
+
+ // Read hardware breakpoint and watchpoint information.
+ llvm::Error error = ReadHardwareDebugInfo();
+ if (error) {
+ LLDB_LOG_ERROR(
+ log, std::move(error),
+ "unable to set breakpoint: failed to read debug registers: {0}");
+ return LLDB_INVALID_INDEX32;
+ }
+
+ uint32_t control_value = 0, bp_index = 0;
+
+ // Check if size has a valid hardware breakpoint length.
+ if (size != 4)
+ return LLDB_INVALID_INDEX32; // Invalid size for a AArch64 hardware
+ // breakpoint
+
+ // Check 4-byte alignment for hardware breakpoint target address.
+ if (addr & 0x03)
+ return LLDB_INVALID_INDEX32; // Invalid address, should be 4-byte aligned.
+
+ // Setup control value
+ control_value = g_enable_bit | g_pac_bits | GetSizeBits(size);
+
+ // Iterate over stored breakpoints and find a free bp_index
+ bp_index = LLDB_INVALID_INDEX32;
+ for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
+ if (!BreakpointIsEnabled(i))
+ bp_index = i; // Mark last free slot
+ else if (m_hbp_regs[i].address == addr)
+ return LLDB_INVALID_INDEX32; // We do not support duplicate breakpoints.
+ }
+
+ if (bp_index == LLDB_INVALID_INDEX32)
+ return LLDB_INVALID_INDEX32;
+
+ // Update breakpoint in local cache
+ m_hbp_regs[bp_index].real_addr = addr;
+ m_hbp_regs[bp_index].address = addr;
+ m_hbp_regs[bp_index].control = control_value;
+
+ // PTRACE call to set corresponding hardware breakpoint register.
+ error = WriteHardwareDebugRegs(eDREGTypeBREAK);
+
+ if (error) {
+ m_hbp_regs[bp_index].address = 0;
+ m_hbp_regs[bp_index].control &= ~1;
+
+ LLDB_LOG_ERROR(
+ log, std::move(error),
+ "unable to set breakpoint: failed to write debug registers: {0}");
+ return LLDB_INVALID_INDEX32;
+ }
+
+ return bp_index;
+}
+
+bool NativeRegisterContextDBReg_arm64::ClearHardwareBreakpoint(
+ uint32_t hw_idx) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ LLDB_LOG(log, "hw_idx: {0}", hw_idx);
+
+ // Read hardware breakpoint and watchpoint information.
+ llvm::Error error = ReadHardwareDebugInfo();
+ if (error) {
+ LLDB_LOG_ERROR(
+ log, std::move(error),
+ "unable to clear breakpoint: failed to read debug registers: {0}");
+ return false;
+ }
+
+ if (hw_idx >= m_max_hbp_supported)
+ return false;
+
+ // Create a backup we can revert to in case of failure.
+ lldb::addr_t tempAddr = m_hbp_regs[hw_idx].address;
+ uint32_t tempControl = m_hbp_regs[hw_idx].control;
+
+ m_hbp_regs[hw_idx].control &= ~g_enable_bit;
+ m_hbp_regs[hw_idx].address = 0;
+
+ // PTRACE call to clear corresponding hardware breakpoint register.
+ error = WriteHardwareDebugRegs(eDREGTypeBREAK);
+
+ if (error) {
+ m_hbp_regs[hw_idx].control = tempControl;
+ m_hbp_regs[hw_idx].address = tempAddr;
+
+ LLDB_LOG_ERROR(
+ log, std::move(error),
+ "unable to clear breakpoint: failed to write debug registers: {0}");
+ return false;
+ }
+
+ return true;
+}
+
+Status NativeRegisterContextDBReg_arm64::GetHardwareBreakHitIndex(
+ uint32_t &bp_index, lldb::addr_t trap_addr) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+
+ LLDB_LOGF(log, "NativeRegisterContextDBReg_arm64::%s()", __FUNCTION__);
+
+ lldb::addr_t break_addr;
+
+ for (bp_index = 0; bp_index < m_max_hbp_supported; ++bp_index) {
+ break_addr = m_hbp_regs[bp_index].address;
+
+ if (BreakpointIsEnabled(bp_index) && trap_addr == break_addr) {
+ m_hbp_regs[bp_index].hit_addr = trap_addr;
+ return Status();
+ }
+ }
+
+ bp_index = LLDB_INVALID_INDEX32;
+ return Status();
+}
+
+Status NativeRegisterContextDBReg_arm64::ClearAllHardwareBreakpoints() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+
+ LLDB_LOGF(log, "NativeRegisterContextDBReg_arm64::%s()", __FUNCTION__);
+
+ // Read hardware breakpoint and watchpoint information.
+ llvm::Error error = ReadHardwareDebugInfo();
+ if (error)
+ return Status(std::move(error));
+
+ for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
+ if (BreakpointIsEnabled(i)) {
+ // Create a backup we can revert to in case of failure.
+ lldb::addr_t tempAddr = m_hbp_regs[i].address;
+ uint32_t tempControl = m_hbp_regs[i].control;
+
+ // Clear watchpoints in local cache
+ m_hbp_regs[i].control &= ~g_enable_bit;
+ m_hbp_regs[i].address = 0;
+
+ // Ptrace call to update hardware debug registers
+ error = WriteHardwareDebugRegs(eDREGTypeBREAK);
+
+ if (error) {
+ m_hbp_regs[i].control = tempControl;
+ m_hbp_regs[i].address = tempAddr;
+
+ return Status(std::move(error));
+ }
+ }
+ }
+
+ return Status();
+}
+
+bool NativeRegisterContextDBReg_arm64::BreakpointIsEnabled(uint32_t bp_index) {
+ if ((m_hbp_regs[bp_index].control & g_enable_bit) != 0)
+ return true;
+ else
+ return false;
+}
+
+uint32_t NativeRegisterContextDBReg_arm64::NumSupportedHardwareWatchpoints() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ llvm::Error error = ReadHardwareDebugInfo();
+ if (error) {
+ LLDB_LOG_ERROR(log, std::move(error),
+ "failed to read debug registers: {0}");
+ return 0;
+ }
+
+ return m_max_hwp_supported;
+}
+
+uint32_t NativeRegisterContextDBReg_arm64::SetHardwareWatchpoint(
+ lldb::addr_t addr, size_t size, uint32_t watch_flags) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size,
+ watch_flags);
+
+ // Read hardware breakpoint and watchpoint information.
+ llvm::Error error = ReadHardwareDebugInfo();
+ if (error) {
+ LLDB_LOG_ERROR(
+ log, std::move(error),
+ "unable to set watchpoint: failed to read debug registers: {0}");
+ return LLDB_INVALID_INDEX32;
+ }
+
+ uint32_t control_value = 0, wp_index = 0;
+ lldb::addr_t real_addr = addr;
+
+ // Check if we are setting watchpoint other than read/write/access Also
+ // update watchpoint flag to match AArch64 write-read bit configuration.
+ switch (watch_flags) {
+ case 1:
+ watch_flags = 2;
+ break;
+ case 2:
+ watch_flags = 1;
+ break;
+ case 3:
+ break;
+ default:
+ return LLDB_INVALID_INDEX32;
+ }
+
+ // Check if size has a valid hardware watchpoint length.
+ if (size != 1 && size != 2 && size != 4 && size != 8)
+ return LLDB_INVALID_INDEX32;
+
+ // Check 8-byte alignment for hardware watchpoint target address. Below is a
+ // hack to recalculate address and size in order to make sure we can watch
+ // non 8-byte aligned addresses as well.
+ if (addr & 0x07) {
+ uint8_t watch_mask = (addr & 0x07) + size;
+
+ if (watch_mask > 0x08)
+ return LLDB_INVALID_INDEX32;
+ else if (watch_mask <= 0x02)
+ size = 2;
+ else if (watch_mask <= 0x04)
+ size = 4;
+ else
+ size = 8;
+
+ addr = addr & (~0x07);
+ }
+
+ // Setup control value
+ control_value = g_enable_bit | g_pac_bits | GetSizeBits(size);
+ control_value |= watch_flags << 3;
+
+ // Iterate over stored watchpoints and find a free wp_index
+ wp_index = LLDB_INVALID_INDEX32;
+ for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
+ if (!WatchpointIsEnabled(i))
+ wp_index = i; // Mark last free slot
+ else if (m_hwp_regs[i].address == addr) {
+ return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints.
+ }
+ }
+
+ if (wp_index == LLDB_INVALID_INDEX32)
+ return LLDB_INVALID_INDEX32;
+
+ // Update watchpoint in local cache
+ m_hwp_regs[wp_index].real_addr = real_addr;
+ m_hwp_regs[wp_index].address = addr;
+ m_hwp_regs[wp_index].control = control_value;
+
+ // PTRACE call to set corresponding watchpoint register.
+ error = WriteHardwareDebugRegs(eDREGTypeWATCH);
+
+ if (error) {
+ m_hwp_regs[wp_index].address = 0;
+ m_hwp_regs[wp_index].control &= ~g_enable_bit;
+
+ LLDB_LOG_ERROR(
+ log, std::move(error),
+ "unable to set watchpoint: failed to write debug registers: {0}");
+ return LLDB_INVALID_INDEX32;
+ }
+
+ return wp_index;
+}
+
+bool NativeRegisterContextDBReg_arm64::ClearHardwareWatchpoint(
+ uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
+
+ // Read hardware breakpoint and watchpoint information.
+ llvm::Error error = ReadHardwareDebugInfo();
+ if (error) {
+ LLDB_LOG_ERROR(
+ log, std::move(error),
+ "unable to clear watchpoint: failed to read debug registers: {0}");
+ return false;
+ }
+
+ if (wp_index >= m_max_hwp_supported)
+ return false;
+
+ // Create a backup we can revert to in case of failure.
+ lldb::addr_t tempAddr = m_hwp_regs[wp_index].address;
+ uint32_t tempControl = m_hwp_regs[wp_index].control;
+
+ // Update watchpoint in local cache
+ m_hwp_regs[wp_index].control &= ~g_enable_bit;
+ m_hwp_regs[wp_index].address = 0;
+
+ // Ptrace call to update hardware debug registers
+ error = WriteHardwareDebugRegs(eDREGTypeWATCH);
+
+ if (error) {
+ m_hwp_regs[wp_index].control = tempControl;
+ m_hwp_regs[wp_index].address = tempAddr;
+
+ LLDB_LOG_ERROR(
+ log, std::move(error),
+ "unable to clear watchpoint: failed to write debug registers: {0}");
+ return false;
+ }
+
+ return true;
+}
+
+Status NativeRegisterContextDBReg_arm64::ClearAllHardwareWatchpoints() {
+ // Read hardware breakpoint and watchpoint information.
+ llvm::Error error = ReadHardwareDebugInfo();
+ if (error)
+ return Status(std::move(error));
+
+ for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
+ if (WatchpointIsEnabled(i)) {
+ // Create a backup we can revert to in case of failure.
+ lldb::addr_t tempAddr = m_hwp_regs[i].address;
+ uint32_t tempControl = m_hwp_regs[i].control;
+
+ // Clear watchpoints in local cache
+ m_hwp_regs[i].control &= ~g_enable_bit;
+ m_hwp_regs[i].address = 0;
+
+ // Ptrace call to update hardware debug registers
+ error = WriteHardwareDebugRegs(eDREGTypeWATCH);
+
+ if (error) {
+ m_hwp_regs[i].control = tempControl;
+ m_hwp_regs[i].address = tempAddr;
+
+ return Status(std::move(error));
+ }
+ }
+ }
+
+ return Status();
+}
+
+uint32_t
+NativeRegisterContextDBReg_arm64::GetWatchpointSize(uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
+
+ switch ((m_hwp_regs[wp_index].control >> 5) & 0xff) {
+ case 0x01:
+ return 1;
+ case 0x03:
+ return 2;
+ case 0x0f:
+ return 4;
+ case 0xff:
+ return 8;
+ default:
+ return 0;
+ }
+}
+
+bool NativeRegisterContextDBReg_arm64::WatchpointIsEnabled(uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
+
+ if ((m_hwp_regs[wp_index].control & g_enable_bit) != 0)
+ return true;
+ else
+ return false;
+}
+
+Status NativeRegisterContextDBReg_arm64::GetWatchpointHitIndex(
+ uint32_t &wp_index, lldb::addr_t trap_addr) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr);
+
+ // Read hardware breakpoint and watchpoint information.
+ llvm::Error error = ReadHardwareDebugInfo();
+ if (error)
+ return Status(std::move(error));
+
+ // Mask off ignored bits from watchpoint trap address.
+ trap_addr = FixWatchpointHitAddress(trap_addr);
+
+ uint32_t watch_size;
+ lldb::addr_t watch_addr;
+
+ for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) {
+ watch_size = GetWatchpointSize(wp_index);
+ watch_addr = m_hwp_regs[wp_index].address;
+
+ if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr &&
+ trap_addr < watch_addr + watch_size) {
+ m_hwp_regs[wp_index].hit_addr = trap_addr;
+ return Status();
+ }
+ }
+
+ wp_index = LLDB_INVALID_INDEX32;
+ return Status();
+}
+
+lldb::addr_t
+NativeRegisterContextDBReg_arm64::GetWatchpointAddress(uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
+
+ if (wp_index >= m_max_hwp_supported)
+ return LLDB_INVALID_ADDRESS;
+
+ if (WatchpointIsEnabled(wp_index))
+ return m_hwp_regs[wp_index].real_addr;
+ return LLDB_INVALID_ADDRESS;
+}
+
+lldb::addr_t
+NativeRegisterContextDBReg_arm64::GetWatchpointHitAddress(uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
+
+ if (wp_index >= m_max_hwp_supported)
+ return LLDB_INVALID_ADDRESS;
+
+ if (WatchpointIsEnabled(wp_index))
+ return m_hwp_regs[wp_index].hit_addr;
+ return LLDB_INVALID_ADDRESS;
+}
diff --git a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h
new file mode 100644
index 000000000000..3da0b0407ce6
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h
@@ -0,0 +1,82 @@
+//===-- NativeRegisterContextDBReg_arm64.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_NativeRegisterContextDBReg_arm64_h
+#define lldb_NativeRegisterContextDBReg_arm64_h
+
+#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h"
+
+#include <array>
+
+namespace lldb_private {
+
+class NativeRegisterContextDBReg_arm64
+ : public virtual NativeRegisterContextRegisterInfo {
+public:
+ uint32_t NumSupportedHardwareBreakpoints() override;
+
+ uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override;
+
+ bool ClearHardwareBreakpoint(uint32_t hw_idx) override;
+
+ Status ClearAllHardwareBreakpoints() override;
+
+ Status GetHardwareBreakHitIndex(uint32_t &bp_index,
+ lldb::addr_t trap_addr) override;
+
+ bool BreakpointIsEnabled(uint32_t bp_index);
+
+ uint32_t NumSupportedHardwareWatchpoints() override;
+
+ uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
+ uint32_t watch_flags) override;
+
+ bool ClearHardwareWatchpoint(uint32_t hw_index) override;
+
+ Status ClearAllHardwareWatchpoints() override;
+
+ Status GetWatchpointHitIndex(uint32_t &wp_index,
+ lldb::addr_t trap_addr) override;
+
+ lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index) override;
+
+ lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;
+
+ uint32_t GetWatchpointSize(uint32_t wp_index);
+
+ bool WatchpointIsEnabled(uint32_t wp_index);
+
+ // Debug register type select
+ enum DREGType { eDREGTypeWATCH = 0, eDREGTypeBREAK };
+
+protected:
+ // Debug register info for hardware breakpoints and watchpoints management.
+ struct DREG {
+ lldb::addr_t address; // Breakpoint/watchpoint address value.
+ lldb::addr_t hit_addr; // Address at which last watchpoint trigger exception
+ // occurred.
+ lldb::addr_t real_addr; // Address value that should cause target to stop.
+ uint32_t control; // Breakpoint/watchpoint control value.
+ };
+
+ std::array<struct DREG, 16> m_hbp_regs; // hardware breakpoints
+ std::array<struct DREG, 16> m_hwp_regs; // hardware watchpoints
+
+ uint32_t m_max_hbp_supported;
+ uint32_t m_max_hwp_supported;
+
+ virtual llvm::Error ReadHardwareDebugInfo() = 0;
+ virtual llvm::Error WriteHardwareDebugRegs(DREGType hwbType) = 0;
+ virtual lldb::addr_t FixWatchpointHitAddress(lldb::addr_t hit_addr) {
+ return hit_addr;
+ }
+};
+
+} // namespace lldb_private
+
+#endif // #ifndef lldb_NativeRegisterContextDBReg_arm64_h
diff --git a/lldb/source/Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.cpp b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.cpp
index 0f57f2ed3f35..56c1757ee89d 100644
--- a/lldb/source/Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.cpp
+++ b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.cpp
@@ -1,4 +1,4 @@
-//===-- NativeRegisterContextWatchpoint_x86.cpp ---------------------------===//
+//===-- NativeRegisterContextDBReg_x86.cpp --------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "NativeRegisterContextWatchpoint_x86.h"
+#include "NativeRegisterContextDBReg_x86.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegisterValue.h"
@@ -80,7 +80,7 @@ static inline uint64_t GetWatchControlBitmask(uint32_t wp_index) {
// Bit mask for control bits regarding all watchpoints.
static constexpr uint64_t watchpoint_all_control_bit_mask = 0xFFFF00FF;
-const RegisterInfo *NativeRegisterContextWatchpoint_x86::GetDR(int num) const {
+const RegisterInfo *NativeRegisterContextDBReg_x86::GetDR(int num) const {
assert(num >= 0 && num <= 7);
switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
case llvm::Triple::x86:
@@ -92,8 +92,8 @@ const RegisterInfo *NativeRegisterContextWatchpoint_x86::GetDR(int num) const {
}
}
-Status NativeRegisterContextWatchpoint_x86::IsWatchpointHit(uint32_t wp_index,
- bool &is_hit) {
+Status NativeRegisterContextDBReg_x86::IsWatchpointHit(uint32_t wp_index,
+ bool &is_hit) {
if (wp_index >= NumSupportedHardwareWatchpoints())
return Status("Watchpoint index out of range");
@@ -107,8 +107,9 @@ Status NativeRegisterContextWatchpoint_x86::IsWatchpointHit(uint32_t wp_index,
return error;
}
-Status NativeRegisterContextWatchpoint_x86::GetWatchpointHitIndex(
- uint32_t &wp_index, lldb::addr_t trap_addr) {
+Status
+NativeRegisterContextDBReg_x86::GetWatchpointHitIndex(uint32_t &wp_index,
+ lldb::addr_t trap_addr) {
uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) {
bool is_hit;
@@ -124,9 +125,8 @@ Status NativeRegisterContextWatchpoint_x86::GetWatchpointHitIndex(
return Status();
}
-Status
-NativeRegisterContextWatchpoint_x86::IsWatchpointVacant(uint32_t wp_index,
- bool &is_vacant) {
+Status NativeRegisterContextDBReg_x86::IsWatchpointVacant(uint32_t wp_index,
+ bool &is_vacant) {
if (wp_index >= NumSupportedHardwareWatchpoints())
return Status("Watchpoint index out of range");
@@ -140,7 +140,7 @@ NativeRegisterContextWatchpoint_x86::IsWatchpointVacant(uint32_t wp_index,
return error;
}
-Status NativeRegisterContextWatchpoint_x86::SetHardwareWatchpointWithIndex(
+Status NativeRegisterContextDBReg_x86::SetHardwareWatchpointWithIndex(
lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
if (wp_index >= NumSupportedHardwareWatchpoints())
@@ -202,7 +202,7 @@ Status NativeRegisterContextWatchpoint_x86::SetHardwareWatchpointWithIndex(
return error;
}
-bool NativeRegisterContextWatchpoint_x86::ClearHardwareWatchpoint(
+bool NativeRegisterContextDBReg_x86::ClearHardwareWatchpoint(
uint32_t wp_index) {
if (wp_index >= NumSupportedHardwareWatchpoints())
return false;
@@ -217,8 +217,7 @@ bool NativeRegisterContextWatchpoint_x86::ClearHardwareWatchpoint(
.Success();
}
-Status
-NativeRegisterContextWatchpoint_x86::ClearWatchpointHit(uint32_t wp_index) {
+Status NativeRegisterContextDBReg_x86::ClearWatchpointHit(uint32_t wp_index) {
if (wp_index >= NumSupportedHardwareWatchpoints())
return Status("Watchpoint index out of range");
@@ -231,7 +230,7 @@ NativeRegisterContextWatchpoint_x86::ClearWatchpointHit(uint32_t wp_index) {
GetDR(6), RegisterValue(dr6.GetAsUInt64() & ~GetStatusBit(wp_index)));
}
-Status NativeRegisterContextWatchpoint_x86::ClearAllHardwareWatchpoints() {
+Status NativeRegisterContextDBReg_x86::ClearAllHardwareWatchpoints() {
RegisterValue dr7;
Status error = ReadRegister(GetDR(7), dr7);
if (error.Fail())
@@ -241,7 +240,7 @@ Status NativeRegisterContextWatchpoint_x86::ClearAllHardwareWatchpoints() {
RegisterValue(dr7.GetAsUInt64() & ~watchpoint_all_control_bit_mask));
}
-uint32_t NativeRegisterContextWatchpoint_x86::SetHardwareWatchpoint(
+uint32_t NativeRegisterContextDBReg_x86::SetHardwareWatchpoint(
lldb::addr_t addr, size_t size, uint32_t watch_flags) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
@@ -254,7 +253,7 @@ uint32_t NativeRegisterContextWatchpoint_x86::SetHardwareWatchpoint(
return wp_index;
}
if (error.Fail() && log) {
- LLDB_LOGF(log, "NativeRegisterContextWatchpoint_x86::%s Error: %s",
+ LLDB_LOGF(log, "NativeRegisterContextDBReg_x86::%s Error: %s",
__FUNCTION__, error.AsCString());
}
}
@@ -262,7 +261,7 @@ uint32_t NativeRegisterContextWatchpoint_x86::SetHardwareWatchpoint(
}
lldb::addr_t
-NativeRegisterContextWatchpoint_x86::GetWatchpointAddress(uint32_t wp_index) {
+NativeRegisterContextDBReg_x86::GetWatchpointAddress(uint32_t wp_index) {
if (wp_index >= NumSupportedHardwareWatchpoints())
return LLDB_INVALID_ADDRESS;
RegisterValue drN;
@@ -271,8 +270,7 @@ NativeRegisterContextWatchpoint_x86::GetWatchpointAddress(uint32_t wp_index) {
return drN.GetAsUInt64();
}
-uint32_t
-NativeRegisterContextWatchpoint_x86::NumSupportedHardwareWatchpoints() {
+uint32_t NativeRegisterContextDBReg_x86::NumSupportedHardwareWatchpoints() {
// Available debug address registers: dr0, dr1, dr2, dr3
return 4;
}
diff --git a/lldb/source/Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.h b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h
index cfb8900a4fd2..a4ed8bfb97ea 100644
--- a/lldb/source/Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.h
+++ b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h
@@ -1,4 +1,4 @@
-//===-- NativeRegisterContextWatchpoint_x86.h -------------------*- C++ -*-===//
+//===-- NativeRegisterContextDBReg_x86.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,16 +6,22 @@
//
//===----------------------------------------------------------------------===//
-#ifndef lldb_NativeRegisterContextWatchpoint_x86_h
-#define lldb_NativeRegisterContextWatchpoint_x86_h
+#ifndef lldb_NativeRegisterContextDBReg_x86_h
+#define lldb_NativeRegisterContextDBReg_x86_h
#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h"
namespace lldb_private {
-class NativeRegisterContextWatchpoint_x86
+class NativeRegisterContextDBReg_x86
: public virtual NativeRegisterContextRegisterInfo {
public:
+ // NB: This constructor is here only because gcc<=6.5 requires a virtual base
+ // class initializer on abstract class (even though it is never used). It can
+ // be deleted once we move to gcc>=7.0.
+ NativeRegisterContextDBReg_x86(NativeThreadProtocol &thread)
+ : NativeRegisterContextRegisterInfo(thread, nullptr) {}
+
Status IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
Status GetWatchpointHitIndex(uint32_t &wp_index,
@@ -45,4 +51,4 @@ public:
} // namespace lldb_private
-#endif // #ifndef lldb_NativeRegisterContextWatchpoint_x86_h
+#endif // #ifndef lldb_NativeRegisterContextDBReg_x86_h
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
index eef4541e7edd..7e38091738e3 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
@@ -922,7 +922,7 @@ RegisterContextDarwin_arm::RegisterContextDarwin_arm(
}
}
-RegisterContextDarwin_arm::~RegisterContextDarwin_arm() {}
+RegisterContextDarwin_arm::~RegisterContextDarwin_arm() = default;
void RegisterContextDarwin_arm::InvalidateAllRegisters() {
InvalidateAllRegisterStates();
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
index 9fc275276699..b98b2f35c23e 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
@@ -104,7 +104,7 @@ RegisterContextDarwin_arm64::RegisterContextDarwin_arm64(
}
}
-RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64() {}
+RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64() = default;
void RegisterContextDarwin_arm64::InvalidateAllRegisters() {
InvalidateAllRegisterStates();
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
index c5ebddc56b6c..95f8132a990c 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
@@ -15,7 +15,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
-#include <stddef.h>
+#include <cstddef>
#include <memory>
@@ -405,7 +405,7 @@ RegisterContextDarwin_i386::RegisterContextDarwin_i386(
}
}
-RegisterContextDarwin_i386::~RegisterContextDarwin_i386() {}
+RegisterContextDarwin_i386::~RegisterContextDarwin_i386() = default;
void RegisterContextDarwin_i386::InvalidateAllRegisters() {
InvalidateAllRegisterStates();
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
index 38cd00aea9cc..03e5ea424e39 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
-#include <inttypes.h>
-#include <stdarg.h>
-#include <stddef.h>
+#include <cinttypes>
+#include <cstdarg>
+#include <cstddef>
#include <memory>
@@ -467,7 +467,7 @@ RegisterContextDarwin_x86_64::RegisterContextDarwin_x86_64(
}
}
-RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64() {}
+RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64() = default;
void RegisterContextDarwin_x86_64::InvalidateAllRegisters() {
InvalidateAllRegisterStates();
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp
index 9fe6255d698e..2991bd3c5f2c 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp
@@ -178,7 +178,7 @@ RegisterContextFreeBSD_powerpc::RegisterContextFreeBSD_powerpc(
const ArchSpec &target_arch)
: RegisterInfoInterface(target_arch) {}
-RegisterContextFreeBSD_powerpc::~RegisterContextFreeBSD_powerpc() {}
+RegisterContextFreeBSD_powerpc::~RegisterContextFreeBSD_powerpc() = default;
size_t RegisterContextFreeBSD_powerpc::GetGPRSize() const {
// This is an 'abstract' base, so no GPR struct.
@@ -197,7 +197,7 @@ RegisterContextFreeBSD_powerpc32::RegisterContextFreeBSD_powerpc32(
const ArchSpec &target_arch)
: RegisterContextFreeBSD_powerpc(target_arch) {}
-RegisterContextFreeBSD_powerpc32::~RegisterContextFreeBSD_powerpc32() {}
+RegisterContextFreeBSD_powerpc32::~RegisterContextFreeBSD_powerpc32() = default;
size_t RegisterContextFreeBSD_powerpc32::GetGPRSize() const {
return sizeof(GPR32);
@@ -217,7 +217,7 @@ RegisterContextFreeBSD_powerpc64::RegisterContextFreeBSD_powerpc64(
const ArchSpec &target_arch)
: RegisterContextFreeBSD_powerpc(target_arch) {}
-RegisterContextFreeBSD_powerpc64::~RegisterContextFreeBSD_powerpc64() {}
+RegisterContextFreeBSD_powerpc64::~RegisterContextFreeBSD_powerpc64() = default;
size_t RegisterContextFreeBSD_powerpc64::GetGPRSize() const {
return sizeof(GPR64);
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp
deleted file mode 100644
index 837549e2a495..000000000000
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-//===-- RegisterContextLinux_mips.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 <stddef.h>
-#include <vector>
-
-// For eh_frame and DWARF Register numbers
-#include "RegisterContextLinux_mips.h"
-
-// Internal codes for mips registers
-#include "lldb-mips-linux-register-enums.h"
-
-// For GP and FP buffers
-#include "RegisterContext_mips.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-// Include RegisterInfos_mips to declare our g_register_infos_mips structure.
-#define DECLARE_REGISTER_INFOS_MIPS_STRUCT
-#include "RegisterInfos_mips.h"
-#undef DECLARE_REGISTER_INFOS_MIPS_STRUCT
-
-// mips general purpose registers.
-const uint32_t g_gp_regnums_mips[] = {
- gpr_zero_mips, gpr_r1_mips, gpr_r2_mips, gpr_r3_mips,
- gpr_r4_mips, gpr_r5_mips, gpr_r6_mips, gpr_r7_mips,
- gpr_r8_mips, gpr_r9_mips, gpr_r10_mips, gpr_r11_mips,
- gpr_r12_mips, gpr_r13_mips, gpr_r14_mips, gpr_r15_mips,
- gpr_r16_mips, gpr_r17_mips, gpr_r18_mips, gpr_r19_mips,
- gpr_r20_mips, gpr_r21_mips, gpr_r22_mips, gpr_r23_mips,
- gpr_r24_mips, gpr_r25_mips, gpr_r26_mips, gpr_r27_mips,
- gpr_gp_mips, gpr_sp_mips, gpr_r30_mips, gpr_ra_mips,
- gpr_sr_mips, gpr_mullo_mips, gpr_mulhi_mips, gpr_badvaddr_mips,
- gpr_cause_mips, gpr_pc_mips, gpr_config5_mips,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
-};
-
-static_assert((sizeof(g_gp_regnums_mips) / sizeof(g_gp_regnums_mips[0])) - 1 ==
- k_num_gpr_registers_mips,
- "g_gp_regnums_mips has wrong number of register infos");
-// mips floating point registers.
-const uint32_t g_fp_regnums_mips[] = {
- fpr_f0_mips, fpr_f1_mips, fpr_f2_mips, fpr_f3_mips,
- fpr_f4_mips, fpr_f5_mips, fpr_f6_mips, fpr_f7_mips,
- fpr_f8_mips, fpr_f9_mips, fpr_f10_mips, fpr_f11_mips,
- fpr_f12_mips, fpr_f13_mips, fpr_f14_mips, fpr_f15_mips,
- fpr_f16_mips, fpr_f17_mips, fpr_f18_mips, fpr_f19_mips,
- fpr_f20_mips, fpr_f21_mips, fpr_f22_mips, fpr_f23_mips,
- fpr_f24_mips, fpr_f25_mips, fpr_f26_mips, fpr_f27_mips,
- fpr_f28_mips, fpr_f29_mips, fpr_f30_mips, fpr_f31_mips,
- fpr_fcsr_mips, fpr_fir_mips, fpr_config5_mips,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
-};
-
-static_assert((sizeof(g_fp_regnums_mips) / sizeof(g_fp_regnums_mips[0])) - 1 ==
- k_num_fpr_registers_mips,
- "g_fp_regnums_mips has wrong number of register infos");
-
-// mips MSA registers.
-const uint32_t g_msa_regnums_mips[] = {
- msa_w0_mips, msa_w1_mips, msa_w2_mips, msa_w3_mips,
- msa_w4_mips, msa_w5_mips, msa_w6_mips, msa_w7_mips,
- msa_w8_mips, msa_w9_mips, msa_w10_mips, msa_w11_mips,
- msa_w12_mips, msa_w13_mips, msa_w14_mips, msa_w15_mips,
- msa_w16_mips, msa_w17_mips, msa_w18_mips, msa_w19_mips,
- msa_w20_mips, msa_w21_mips, msa_w22_mips, msa_w23_mips,
- msa_w24_mips, msa_w25_mips, msa_w26_mips, msa_w27_mips,
- msa_w28_mips, msa_w29_mips, msa_w30_mips, msa_w31_mips,
- msa_fcsr_mips, msa_fir_mips, msa_mcsr_mips, msa_mir_mips,
- msa_config5_mips,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
-};
-
-static_assert((sizeof(g_msa_regnums_mips) / sizeof(g_msa_regnums_mips[0])) -
- 1 ==
- k_num_msa_registers_mips,
- "g_msa_regnums_mips has wrong number of register infos");
-
-// Number of register sets provided by this context.
-constexpr size_t k_num_register_sets = 3;
-
-// Register sets for mips.
-static const RegisterSet g_reg_sets_mips[k_num_register_sets] = {
- {"General Purpose Registers", "gpr", k_num_gpr_registers_mips,
- g_gp_regnums_mips},
- {"Floating Point Registers", "fpu", k_num_fpr_registers_mips,
- g_fp_regnums_mips},
- {"MSA Registers", "msa", k_num_msa_registers_mips, g_msa_regnums_mips}};
-
-uint32_t GetUserRegisterInfoCount(bool msa_present) {
- if (msa_present)
- return static_cast<uint32_t>(k_num_user_registers_mips);
- return static_cast<uint32_t>(k_num_user_registers_mips -
- k_num_msa_registers_mips);
-}
-
-RegisterContextLinux_mips::RegisterContextLinux_mips(
- const ArchSpec &target_arch, bool msa_present)
- : RegisterInfoInterface(target_arch),
- m_user_register_count(GetUserRegisterInfoCount(msa_present)) {}
-
-size_t RegisterContextLinux_mips::GetGPRSize() const {
- return sizeof(GPR_linux_mips);
-}
-
-const RegisterInfo *RegisterContextLinux_mips::GetRegisterInfo() const {
- switch (m_target_arch.GetMachine()) {
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- return g_register_infos_mips;
- default:
- assert(false && "Unhandled target architecture.");
- return nullptr;
- }
-}
-
-const RegisterSet *
-RegisterContextLinux_mips::GetRegisterSet(size_t set) const {
- if (set >= k_num_register_sets)
- return nullptr;
- switch (m_target_arch.GetMachine()) {
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- return &g_reg_sets_mips[set];
- default:
- assert(false && "Unhandled target architecture.");
- return nullptr;
- }
-}
-
-size_t
-RegisterContextLinux_mips::GetRegisterSetCount() const {
- return k_num_register_sets;
-}
-
-uint32_t RegisterContextLinux_mips::GetRegisterCount() const {
- return static_cast<uint32_t>(sizeof(g_register_infos_mips) /
- sizeof(g_register_infos_mips[0]));
-}
-
-uint32_t RegisterContextLinux_mips::GetUserRegisterCount() const {
- return static_cast<uint32_t>(m_user_register_count);
-}
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h
deleted file mode 100644
index 9b59ab421ff4..000000000000
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===-- RegisterContextLinux_mips.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_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_MIPS_H
-#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_MIPS_H
-
-#include "RegisterInfoInterface.h"
-#include "lldb/lldb-private.h"
-
-class RegisterContextLinux_mips : public lldb_private::RegisterInfoInterface {
-public:
- RegisterContextLinux_mips(const lldb_private::ArchSpec &target_arch,
- bool msa_present = true);
-
- size_t GetGPRSize() const override;
-
- const lldb_private::RegisterInfo *GetRegisterInfo() const override;
-
- const lldb_private::RegisterSet *GetRegisterSet(size_t set) const;
-
- size_t GetRegisterSetCount() const;
-
- uint32_t GetRegisterCount() const override;
-
- uint32_t GetUserRegisterCount() const override;
-
-private:
- uint32_t m_user_register_count;
-};
-
-#endif
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp
deleted file mode 100644
index 432a78129fde..000000000000
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-//===-- RegisterContextLinux_mips64.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 <stddef.h>
-#include <vector>
-
-// For eh_frame and DWARF Register numbers
-#include "RegisterContextLinux_mips64.h"
-
-// For GP and FP buffers
-#include "RegisterContext_mips.h"
-
-// Internal codes for all mips32 and mips64 registers
-#include "lldb-mips-linux-register-enums.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-// Include RegisterInfos_mips64 to declare our g_register_infos_mips64
-// structure.
-#define DECLARE_REGISTER_INFOS_MIPS64_STRUCT
-#define LINUX_MIPS64
-#include "RegisterInfos_mips64.h"
-#undef LINUX_MIPS64
-#undef DECLARE_REGISTER_INFOS_MIPS64_STRUCT
-
-// Include RegisterInfos_mips to declare our g_register_infos_mips structure.
-#define DECLARE_REGISTER_INFOS_MIPS_STRUCT
-#include "RegisterInfos_mips.h"
-#undef DECLARE_REGISTER_INFOS_MIPS_STRUCT
-
-// mips64 general purpose registers.
-const uint32_t g_gp_regnums_mips64[] = {
- gpr_zero_mips64, gpr_r1_mips64, gpr_r2_mips64,
- gpr_r3_mips64, gpr_r4_mips64, gpr_r5_mips64,
- gpr_r6_mips64, gpr_r7_mips64, gpr_r8_mips64,
- gpr_r9_mips64, gpr_r10_mips64, gpr_r11_mips64,
- gpr_r12_mips64, gpr_r13_mips64, gpr_r14_mips64,
- gpr_r15_mips64, gpr_r16_mips64, gpr_r17_mips64,
- gpr_r18_mips64, gpr_r19_mips64, gpr_r20_mips64,
- gpr_r21_mips64, gpr_r22_mips64, gpr_r23_mips64,
- gpr_r24_mips64, gpr_r25_mips64, gpr_r26_mips64,
- gpr_r27_mips64, gpr_gp_mips64, gpr_sp_mips64,
- gpr_r30_mips64, gpr_ra_mips64, gpr_sr_mips64,
- gpr_mullo_mips64, gpr_mulhi_mips64, gpr_badvaddr_mips64,
- gpr_cause_mips64, gpr_pc_mips64, gpr_config5_mips64,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
-};
-
-static_assert((sizeof(g_gp_regnums_mips64) / sizeof(g_gp_regnums_mips64[0])) -
- 1 ==
- k_num_gpr_registers_mips64,
- "g_gp_regnums_mips64 has wrong number of register infos");
-
-// mips64 floating point registers.
-const uint32_t g_fp_regnums_mips64[] = {
- fpr_f0_mips64, fpr_f1_mips64, fpr_f2_mips64, fpr_f3_mips64,
- fpr_f4_mips64, fpr_f5_mips64, fpr_f6_mips64, fpr_f7_mips64,
- fpr_f8_mips64, fpr_f9_mips64, fpr_f10_mips64, fpr_f11_mips64,
- fpr_f12_mips64, fpr_f13_mips64, fpr_f14_mips64, fpr_f15_mips64,
- fpr_f16_mips64, fpr_f17_mips64, fpr_f18_mips64, fpr_f19_mips64,
- fpr_f20_mips64, fpr_f21_mips64, fpr_f22_mips64, fpr_f23_mips64,
- fpr_f24_mips64, fpr_f25_mips64, fpr_f26_mips64, fpr_f27_mips64,
- fpr_f28_mips64, fpr_f29_mips64, fpr_f30_mips64, fpr_f31_mips64,
- fpr_fcsr_mips64, fpr_fir_mips64, fpr_config5_mips64,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
-};
-
-static_assert((sizeof(g_fp_regnums_mips64) / sizeof(g_fp_regnums_mips64[0])) -
- 1 ==
- k_num_fpr_registers_mips64,
- "g_fp_regnums_mips64 has wrong number of register infos");
-
-// mips64 MSA registers.
-const uint32_t g_msa_regnums_mips64[] = {
- msa_w0_mips64, msa_w1_mips64, msa_w2_mips64, msa_w3_mips64,
- msa_w4_mips64, msa_w5_mips64, msa_w6_mips64, msa_w7_mips64,
- msa_w8_mips64, msa_w9_mips64, msa_w10_mips64, msa_w11_mips64,
- msa_w12_mips64, msa_w13_mips64, msa_w14_mips64, msa_w15_mips64,
- msa_w16_mips64, msa_w17_mips64, msa_w18_mips64, msa_w19_mips64,
- msa_w20_mips64, msa_w21_mips64, msa_w22_mips64, msa_w23_mips64,
- msa_w24_mips64, msa_w25_mips64, msa_w26_mips64, msa_w27_mips64,
- msa_w28_mips64, msa_w29_mips64, msa_w30_mips64, msa_w31_mips64,
- msa_fcsr_mips64, msa_fir_mips64, msa_mcsr_mips64, msa_mir_mips64,
- msa_config5_mips64,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
-};
-
-static_assert((sizeof(g_msa_regnums_mips64) / sizeof(g_msa_regnums_mips64[0])) -
- 1 ==
- k_num_msa_registers_mips64,
- "g_msa_regnums_mips64 has wrong number of register infos");
-
-// Number of register sets provided by this context.
-constexpr size_t k_num_register_sets = 3;
-
-// Register sets for mips64.
-static const RegisterSet g_reg_sets_mips64[k_num_register_sets] = {
- {"General Purpose Registers", "gpr", k_num_gpr_registers_mips64,
- g_gp_regnums_mips64},
- {"Floating Point Registers", "fpu", k_num_fpr_registers_mips64,
- g_fp_regnums_mips64},
- {"MSA Registers", "msa", k_num_msa_registers_mips64, g_msa_regnums_mips64},
-};
-
-const RegisterSet *
-RegisterContextLinux_mips64::GetRegisterSet(size_t set) const {
- if (set >= k_num_register_sets)
- return nullptr;
-
- switch (m_target_arch.GetMachine()) {
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- return &g_reg_sets_mips64[set];
- default:
- assert(false && "Unhandled target architecture.");
- return nullptr;
- }
- return nullptr;
-}
-
-size_t
-RegisterContextLinux_mips64::GetRegisterSetCount() const {
- return k_num_register_sets;
-}
-
-static const RegisterInfo *GetRegisterInfoPtr(const ArchSpec &target_arch) {
- switch (target_arch.GetMachine()) {
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- return g_register_infos_mips64;
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- return g_register_infos_mips;
- default:
- assert(false && "Unhandled target architecture.");
- return nullptr;
- }
-}
-
-static uint32_t GetRegisterInfoCount(const ArchSpec &target_arch) {
- switch (target_arch.GetMachine()) {
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- return static_cast<uint32_t>(sizeof(g_register_infos_mips64) /
- sizeof(g_register_infos_mips64[0]));
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- return static_cast<uint32_t>(sizeof(g_register_infos_mips) /
- sizeof(g_register_infos_mips[0]));
- default:
- assert(false && "Unhandled target architecture.");
- return 0;
- }
-}
-
-uint32_t GetUserRegisterInfoCount(const ArchSpec &target_arch,
- bool msa_present) {
- switch (target_arch.GetMachine()) {
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- if (msa_present)
- return static_cast<uint32_t>(k_num_user_registers_mips);
- return static_cast<uint32_t>(k_num_user_registers_mips -
- k_num_msa_registers_mips);
- case llvm::Triple::mips64el:
- case llvm::Triple::mips64:
- if (msa_present)
- return static_cast<uint32_t>(k_num_user_registers_mips64);
- return static_cast<uint32_t>(k_num_user_registers_mips64 -
- k_num_msa_registers_mips64);
- default:
- assert(false && "Unhandled target architecture.");
- return 0;
- }
-}
-
-RegisterContextLinux_mips64::RegisterContextLinux_mips64(
- const ArchSpec &target_arch, bool msa_present)
- : lldb_private::RegisterInfoInterface(target_arch),
- m_register_info_p(GetRegisterInfoPtr(target_arch)),
- m_register_info_count(GetRegisterInfoCount(target_arch)),
- m_user_register_count(
- GetUserRegisterInfoCount(target_arch, msa_present)) {}
-
-size_t RegisterContextLinux_mips64::GetGPRSize() const {
- return sizeof(GPR_linux_mips);
-}
-
-const RegisterInfo *RegisterContextLinux_mips64::GetRegisterInfo() const {
- return m_register_info_p;
-}
-
-uint32_t RegisterContextLinux_mips64::GetRegisterCount() const {
- return m_register_info_count;
-}
-
-uint32_t RegisterContextLinux_mips64::GetUserRegisterCount() const {
- return m_user_register_count;
-}
-
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h
deleted file mode 100644
index 899f0a40e4ae..000000000000
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//===-- RegisterContextLinux_mips64.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_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_MIPS64_H
-#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_MIPS64_H
-
-#include "RegisterInfoInterface.h"
-#include "lldb/lldb-private.h"
-
-class RegisterContextLinux_mips64 : public lldb_private::RegisterInfoInterface {
-public:
- RegisterContextLinux_mips64(const lldb_private::ArchSpec &target_arch,
- bool msa_present = true);
-
- size_t GetGPRSize() const override;
-
- const lldb_private::RegisterInfo *GetRegisterInfo() const override;
-
- const lldb_private::RegisterSet *GetRegisterSet(size_t set) const;
-
- size_t GetRegisterSetCount() const;
-
- uint32_t GetRegisterCount() const override;
-
- uint32_t GetUserRegisterCount() const override;
-
-private:
- const lldb_private::RegisterInfo *m_register_info_p;
- uint32_t m_register_info_count;
- uint32_t m_user_register_count;
-};
-
-#endif
-
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp
index 1394cb7f00a1..067d1c3705e4 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp
@@ -21,7 +21,7 @@ RegisterContextMach_arm::RegisterContextMach_arm(Thread &thread,
uint32_t concrete_frame_idx)
: RegisterContextDarwin_arm(thread, concrete_frame_idx) {}
-RegisterContextMach_arm::~RegisterContextMach_arm() {}
+RegisterContextMach_arm::~RegisterContextMach_arm() = default;
int RegisterContextMach_arm::DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) {
mach_msg_type_number_t count = GPRWordCount;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp
index b97166b6eebe..fe5cecef1b0c 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp
@@ -19,7 +19,7 @@ RegisterContextMach_i386::RegisterContextMach_i386(Thread &thread,
uint32_t concrete_frame_idx)
: RegisterContextDarwin_i386(thread, concrete_frame_idx) {}
-RegisterContextMach_i386::~RegisterContextMach_i386() {}
+RegisterContextMach_i386::~RegisterContextMach_i386() = default;
int RegisterContextMach_i386::DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) {
mach_msg_type_number_t count = GPRWordCount;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp
index 8933f136789f..a3d8c4f649d2 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp
@@ -19,7 +19,7 @@ RegisterContextMach_x86_64::RegisterContextMach_x86_64(
Thread &thread, uint32_t concrete_frame_idx)
: RegisterContextDarwin_x86_64(thread, concrete_frame_idx) {}
-RegisterContextMach_x86_64::~RegisterContextMach_x86_64() {}
+RegisterContextMach_x86_64::~RegisterContextMach_x86_64() = default;
int RegisterContextMach_x86_64::DoReadGPR(lldb::tid_t tid, int flavor,
GPR &gpr) {
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp
index f2d230b54053..c55ffebb03e7 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp
@@ -39,7 +39,7 @@ RegisterContextMemory::RegisterContextMemory(Thread &thread,
}
// Destructor
-RegisterContextMemory::~RegisterContextMemory() {}
+RegisterContextMemory::~RegisterContextMemory() = default;
void RegisterContextMemory::InvalidateAllRegisters() {
if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
index 97a760396ba9..684176bccdf0 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#include <cerrno>
+#include <cstdint>
#include <cstring>
-#include <errno.h>
-#include <stdint.h>
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -45,7 +45,7 @@ RegisterContextPOSIX_arm::RegisterContextPOSIX_arm(
: lldb_private::RegisterContext(thread, 0),
m_register_info_up(std::move(register_info)) {}
-RegisterContextPOSIX_arm::~RegisterContextPOSIX_arm() {}
+RegisterContextPOSIX_arm::~RegisterContextPOSIX_arm() = default;
void RegisterContextPOSIX_arm::Invalidate() {}
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
index 3f52501c35f3..676e450c4846 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#include <cerrno>
+#include <cstdint>
#include <cstring>
-#include <errno.h>
-#include <stdint.h>
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -40,10 +40,11 @@ bool RegisterContextPOSIX_arm64::IsFPR(unsigned reg) {
}
bool RegisterContextPOSIX_arm64::IsSVE(unsigned reg) const {
- if (m_register_info_up->GetRegisterSetFromRegisterIndex(reg) ==
- RegisterInfoPOSIX_arm64::SVERegSet)
- return true;
- return false;
+ return m_register_info_up->IsSVEReg(reg);
+}
+
+bool RegisterContextPOSIX_arm64::IsPAuth(unsigned reg) const {
+ return m_register_info_up->IsPAuthReg(reg);
}
RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64(
@@ -52,7 +53,7 @@ RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64(
: lldb_private::RegisterContext(thread, 0),
m_register_info_up(std::move(register_info)) {}
-RegisterContextPOSIX_arm64::~RegisterContextPOSIX_arm64() {}
+RegisterContextPOSIX_arm64::~RegisterContextPOSIX_arm64() = default;
void RegisterContextPOSIX_arm64::Invalidate() {}
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
index a3f07bb2823b..7c301599d3af 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
@@ -54,6 +54,7 @@ protected:
size_t GetFPUSize() { return sizeof(RegisterInfoPOSIX_arm64::FPU); }
bool IsSVE(unsigned reg) const;
+ bool IsPAuth(unsigned reg) const;
bool IsSVEZ(unsigned reg) const { return m_register_info_up->IsSVEZReg(reg); }
bool IsSVEP(unsigned reg) const { return m_register_info_up->IsSVEPReg(reg); }
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
index c41c4bd7a7ea..9e05737d8e62 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#include <cerrno>
+#include <cstdint>
#include <cstring>
-#include <errno.h>
-#include <stdint.h>
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -22,8 +22,6 @@
#include "RegisterContextPOSIX_mips64.h"
#include "RegisterContextFreeBSD_mips64.h"
-#include "RegisterContextLinux_mips64.h"
-#include "RegisterContextLinux_mips.h"
using namespace lldb_private;
using namespace lldb;
@@ -60,7 +58,7 @@ RegisterContextPOSIX_mips64::RegisterContextPOSIX_mips64(
m_registers_count[msa_registers_count]));
}
-RegisterContextPOSIX_mips64::~RegisterContextPOSIX_mips64() {}
+RegisterContextPOSIX_mips64::~RegisterContextPOSIX_mips64() = default;
void RegisterContextPOSIX_mips64::Invalidate() {}
@@ -102,17 +100,6 @@ RegisterContextPOSIX_mips64::GetRegisterInfoAtIndex(size_t reg) {
size_t RegisterContextPOSIX_mips64::GetRegisterSetCount() {
ArchSpec target_arch = m_register_info_up->GetTargetArchitecture();
switch (target_arch.GetTriple().getOS()) {
- case llvm::Triple::Linux: {
- if ((target_arch.GetMachine() == llvm::Triple::mipsel) ||
- (target_arch.GetMachine() == llvm::Triple::mips)) {
- const auto *context = static_cast<const RegisterContextLinux_mips *>(
- m_register_info_up.get());
- return context->GetRegisterSetCount();
- }
- const auto *context = static_cast<const RegisterContextLinux_mips64 *>(
- m_register_info_up.get());
- return context->GetRegisterSetCount();
- }
default: {
const auto *context = static_cast<const RegisterContextFreeBSD_mips64 *>(
m_register_info_up.get());
@@ -125,17 +112,6 @@ size_t RegisterContextPOSIX_mips64::GetRegisterSetCount() {
const RegisterSet *RegisterContextPOSIX_mips64::GetRegisterSet(size_t set) {
ArchSpec target_arch = m_register_info_up->GetTargetArchitecture();
switch (target_arch.GetTriple().getOS()) {
- case llvm::Triple::Linux: {
- if ((target_arch.GetMachine() == llvm::Triple::mipsel) ||
- (target_arch.GetMachine() == llvm::Triple::mips)) {
- const auto *context = static_cast<const RegisterContextLinux_mips *>(
- m_register_info_up.get());
- return context->GetRegisterSet(set);
- }
- const auto *context = static_cast<const RegisterContextLinux_mips64 *>(
- m_register_info_up.get());
- return context->GetRegisterSet(set);
- }
default: {
const auto *context = static_cast<const RegisterContextFreeBSD_mips64 *>(
m_register_info_up.get());
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
index cd65b96d373e..cffd2865e385 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#include <cerrno>
+#include <cstdint>
#include <cstring>
-#include <errno.h>
-#include <stdint.h>
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -95,7 +95,7 @@ RegisterContextPOSIX_powerpc::RegisterContextPOSIX_powerpc(
m_register_info_up.reset(register_info);
}
-RegisterContextPOSIX_powerpc::~RegisterContextPOSIX_powerpc() {}
+RegisterContextPOSIX_powerpc::~RegisterContextPOSIX_powerpc() = default;
void RegisterContextPOSIX_powerpc::Invalidate() {}
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp
index f670be2ef3c4..f70ddeba209c 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#include <cerrno>
+#include <cstdint>
#include <cstring>
-#include <errno.h>
-#include <stdint.h>
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp
index e746ec642b38..21c8160e5b41 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#include <cerrno>
+#include <cstdint>
#include <cstring>
-#include <errno.h>
-#include <stdint.h>
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -98,7 +98,7 @@ RegisterContextPOSIX_s390x::RegisterContextPOSIX_s390x(
}
}
-RegisterContextPOSIX_s390x::~RegisterContextPOSIX_s390x() {}
+RegisterContextPOSIX_s390x::~RegisterContextPOSIX_s390x() = default;
void RegisterContextPOSIX_s390x::Invalidate() {}
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
index 2c7f63503d7c..67e03ff1ea39 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#include <cerrno>
+#include <cstdint>
#include <cstring>
-#include <errno.h>
-#include <stdint.h>
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -448,7 +448,7 @@ RegisterContextPOSIX_x86::RegisterContextPOSIX_x86(
m_fpr_type = eNotValid;
}
-RegisterContextPOSIX_x86::~RegisterContextPOSIX_x86() {}
+RegisterContextPOSIX_x86::~RegisterContextPOSIX_x86() = default;
RegisterContextPOSIX_x86::FPRType RegisterContextPOSIX_x86::GetFPRType() {
if (m_fpr_type == eNotValid) {
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
index 31e2944084ed..4866cbd235e8 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
@@ -22,7 +22,7 @@ RegisterContextThreadMemory::RegisterContextThreadMemory(
: RegisterContext(thread, 0), m_thread_wp(thread.shared_from_this()),
m_reg_ctx_sp(), m_register_data_addr(register_data_addr), m_stop_id(0) {}
-RegisterContextThreadMemory::~RegisterContextThreadMemory() {}
+RegisterContextThreadMemory::~RegisterContextThreadMemory() = default;
void RegisterContextThreadMemory::UpdateRegisterContext() {
ThreadSP thread_sp(m_thread_wp.lock());
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h b/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
index 88c2ae7c5010..c05438338c88 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
@@ -22,7 +22,7 @@ class RegisterInfoInterface {
public:
RegisterInfoInterface(const lldb_private::ArchSpec &target_arch)
: m_target_arch(target_arch) {}
- virtual ~RegisterInfoInterface() {}
+ virtual ~RegisterInfoInterface() = default;
virtual size_t GetGPRSize() const = 0;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp
index 17b96f944cda..63461f7ab2db 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp
@@ -7,7 +7,7 @@
//===---------------------------------------------------------------------===//
#include <cassert>
-#include <stddef.h>
+#include <cstddef>
#include <vector>
#include "lldb/lldb-defines.h"
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
index 515c9f44e1e2..b878534b39db 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
@@ -7,7 +7,7 @@
//===---------------------------------------------------------------------===//
#include <cassert>
-#include <stddef.h>
+#include <cstddef>
#include <vector>
#include "lldb/lldb-defines.h"
@@ -72,23 +72,14 @@
#include "RegisterInfos_arm64_sve.h"
#undef DECLARE_REGISTER_INFOS_ARM64_STRUCT
-static const lldb_private::RegisterInfo *
-GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) {
- switch (target_arch.GetMachine()) {
- case llvm::Triple::aarch64:
- case llvm::Triple::aarch64_32:
- return g_register_infos_arm64_le;
- default:
- assert(false && "Unhandled target architecture.");
- return nullptr;
- }
-}
-
// Number of register sets provided by this context.
enum {
k_num_gpr_registers = gpr_w28 - gpr_x0 + 1,
k_num_fpr_registers = fpu_fpcr - fpu_v0 + 1,
k_num_sve_registers = sve_ffr - sve_vg + 1,
+ k_num_mte_register = 1,
+ k_num_pauth_register = 2,
+ k_num_register_sets_default = 2,
k_num_register_sets = 3
};
@@ -186,31 +177,66 @@ static const lldb_private::RegisterSet g_reg_sets_arm64[k_num_register_sets] = {
{"Scalable Vector Extension Registers", "sve", k_num_sve_registers,
g_sve_regnums_arm64}};
-static uint32_t
-GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) {
+static const lldb_private::RegisterSet g_reg_set_pauth_arm64 = {
+ "Pointer Authentication Registers", "pauth", k_num_pauth_register, NULL};
+
+static const lldb_private::RegisterSet g_reg_set_mte_arm64 = {
+ "MTE Control Register", "mte", k_num_mte_register, NULL};
+
+RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64(
+ const lldb_private::ArchSpec &target_arch, lldb_private::Flags opt_regsets)
+ : lldb_private::RegisterInfoAndSetInterface(target_arch),
+ m_opt_regsets(opt_regsets) {
switch (target_arch.GetMachine()) {
case llvm::Triple::aarch64:
- case llvm::Triple::aarch64_32:
- return static_cast<uint32_t>(sizeof(g_register_infos_arm64_le) /
- sizeof(g_register_infos_arm64_le[0]));
+ case llvm::Triple::aarch64_32: {
+ m_register_set_p = g_reg_sets_arm64;
+ m_register_set_count = k_num_register_sets_default;
+ m_per_regset_regnum_range[GPRegSet] = std::make_pair(gpr_x0, gpr_w28 + 1);
+ m_per_regset_regnum_range[FPRegSet] = std::make_pair(fpu_v0, fpu_fpcr + 1);
+
+ // Now configure register sets supported by current target. If we have a
+ // dynamic register set like MTE, Pointer Authentication regset then we need
+ // to create dynamic register infos and regset array. Push back all optional
+ // register infos and regset and calculate register offsets accordingly.
+ if (m_opt_regsets.AllSet(eRegsetMaskSVE)) {
+ m_register_info_p = g_register_infos_arm64_sve_le;
+ m_register_info_count = sve_ffr + 1;
+ m_per_regset_regnum_range[m_register_set_count++] =
+ std::make_pair(sve_vg, sve_ffr + 1);
+ } else {
+ m_register_info_p = g_register_infos_arm64_le;
+ m_register_info_count = fpu_fpcr + 1;
+ }
+
+ if (m_opt_regsets.AnySet(eRegsetMaskDynamic)) {
+ llvm::ArrayRef<lldb_private::RegisterInfo> reg_infos_ref =
+ llvm::makeArrayRef(m_register_info_p, m_register_info_count);
+ llvm::ArrayRef<lldb_private::RegisterSet> reg_sets_ref =
+ llvm::makeArrayRef(m_register_set_p, m_register_set_count);
+ llvm::copy(reg_infos_ref, std::back_inserter(m_dynamic_reg_infos));
+ llvm::copy(reg_sets_ref, std::back_inserter(m_dynamic_reg_sets));
+
+ if (m_opt_regsets.AllSet(eRegsetMaskPAuth))
+ AddRegSetPAuth();
+
+ if (m_opt_regsets.AllSet(eRegsetMaskMTE))
+ AddRegSetMTE();
+
+ m_register_info_count = m_dynamic_reg_infos.size();
+ m_register_info_p = m_dynamic_reg_infos.data();
+ m_register_set_p = m_dynamic_reg_sets.data();
+ m_register_set_count = m_dynamic_reg_sets.size();
+ }
+ break;
+ }
default:
assert(false && "Unhandled target architecture.");
- return 0;
}
}
-RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64(
- const lldb_private::ArchSpec &target_arch)
- : lldb_private::RegisterInfoAndSetInterface(target_arch),
- m_register_info_p(GetRegisterInfoPtr(target_arch)),
- m_register_info_count(GetRegisterInfoCount(target_arch)) {
-}
-
uint32_t RegisterInfoPOSIX_arm64::GetRegisterCount() const {
- if (IsSVEEnabled())
- return k_num_gpr_registers + k_num_fpr_registers + k_num_sve_registers;
-
- return k_num_gpr_registers + k_num_fpr_registers;
+ return m_register_info_count;
}
size_t RegisterInfoPOSIX_arm64::GetGPRSize() const {
@@ -227,31 +253,60 @@ RegisterInfoPOSIX_arm64::GetRegisterInfo() const {
}
size_t RegisterInfoPOSIX_arm64::GetRegisterSetCount() const {
- if (IsSVEEnabled())
- return k_num_register_sets;
- return k_num_register_sets - 1;
+ return m_register_set_count;
}
size_t RegisterInfoPOSIX_arm64::GetRegisterSetFromRegisterIndex(
uint32_t reg_index) const {
- if (reg_index <= gpr_w28)
- return GPRegSet;
- if (reg_index <= fpu_fpcr)
- return FPRegSet;
- if (reg_index <= sve_ffr)
- return SVERegSet;
+ for (const auto &regset_range : m_per_regset_regnum_range) {
+ if (reg_index >= regset_range.second.first &&
+ reg_index < regset_range.second.second)
+ return regset_range.first;
+ }
return LLDB_INVALID_REGNUM;
}
const lldb_private::RegisterSet *
RegisterInfoPOSIX_arm64::GetRegisterSet(size_t set_index) const {
if (set_index < GetRegisterSetCount())
- return &g_reg_sets_arm64[set_index];
+ return &m_register_set_p[set_index];
return nullptr;
}
-uint32_t
-RegisterInfoPOSIX_arm64::ConfigureVectorRegisterInfos(uint32_t sve_vq) {
+void RegisterInfoPOSIX_arm64::AddRegSetPAuth() {
+ uint32_t pa_regnum = m_dynamic_reg_infos.size();
+ for (uint32_t i = 0; i < k_num_pauth_register; i++) {
+ pauth_regnum_collection.push_back(pa_regnum + i);
+ m_dynamic_reg_infos.push_back(g_register_infos_pauth[i]);
+ m_dynamic_reg_infos[pa_regnum + i].byte_offset =
+ m_dynamic_reg_infos[pa_regnum + i - 1].byte_offset +
+ m_dynamic_reg_infos[pa_regnum + i - 1].byte_size;
+ m_dynamic_reg_infos[pa_regnum + i].kinds[lldb::eRegisterKindLLDB] =
+ pa_regnum + i;
+ }
+
+ m_per_regset_regnum_range[m_register_set_count] =
+ std::make_pair(pa_regnum, m_dynamic_reg_infos.size());
+ m_dynamic_reg_sets.push_back(g_reg_set_pauth_arm64);
+ m_dynamic_reg_sets.back().registers = pauth_regnum_collection.data();
+}
+
+void RegisterInfoPOSIX_arm64::AddRegSetMTE() {
+ uint32_t mte_regnum = m_dynamic_reg_infos.size();
+ m_mte_regnum_collection.push_back(mte_regnum);
+ m_dynamic_reg_infos.push_back(g_register_infos_mte[0]);
+ m_dynamic_reg_infos[mte_regnum].byte_offset =
+ m_dynamic_reg_infos[mte_regnum - 1].byte_offset +
+ m_dynamic_reg_infos[mte_regnum - 1].byte_size;
+ m_dynamic_reg_infos[mte_regnum].kinds[lldb::eRegisterKindLLDB] = mte_regnum;
+
+ m_per_regset_regnum_range[m_register_set_count] =
+ std::make_pair(mte_regnum, mte_regnum + 1);
+ m_dynamic_reg_sets.push_back(g_reg_set_mte_arm64);
+ m_dynamic_reg_sets.back().registers = m_mte_regnum_collection.data();
+}
+
+uint32_t RegisterInfoPOSIX_arm64::ConfigureVectorLength(uint32_t sve_vq) {
// sve_vq contains SVE Quad vector length in context of AArch64 SVE.
// SVE register infos if enabled cannot be disabled by selecting sve_vq = 0.
// Also if an invalid or previously set vector length is passed to this
@@ -266,28 +321,15 @@ RegisterInfoPOSIX_arm64::ConfigureVectorRegisterInfos(uint32_t sve_vq) {
m_vector_reg_vq = sve_vq;
- if (sve_vq == eVectorQuadwordAArch64) {
- m_register_info_count =
- static_cast<uint32_t>(sizeof(g_register_infos_arm64_le) /
- sizeof(g_register_infos_arm64_le[0]));
- m_register_info_p = g_register_infos_arm64_le;
-
+ if (sve_vq == eVectorQuadwordAArch64)
return m_vector_reg_vq;
- }
-
- m_register_info_count =
- static_cast<uint32_t>(sizeof(g_register_infos_arm64_sve_le) /
- sizeof(g_register_infos_arm64_sve_le[0]));
-
std::vector<lldb_private::RegisterInfo> &reg_info_ref =
m_per_vq_reg_infos[sve_vq];
if (reg_info_ref.empty()) {
- reg_info_ref = llvm::makeArrayRef(g_register_infos_arm64_sve_le,
- m_register_info_count);
+ reg_info_ref = llvm::makeArrayRef(m_register_info_p, m_register_info_count);
uint32_t offset = SVE_REGS_DEFAULT_OFFSET_LINUX;
-
reg_info_ref[fpu_fpsr].byte_offset = offset;
reg_info_ref[fpu_fpcr].byte_offset = offset + 4;
reg_info_ref[sve_vg].byte_offset = offset + 8;
@@ -316,13 +358,25 @@ RegisterInfoPOSIX_arm64::ConfigureVectorRegisterInfos(uint32_t sve_vq) {
offset += reg_info_ref[it].byte_size;
}
+ for (uint32_t it = sve_ffr + 1; it < m_register_info_count; it++) {
+ reg_info_ref[it].byte_offset = offset;
+ offset += reg_info_ref[it].byte_size;
+ }
+
m_per_vq_reg_infos[sve_vq] = reg_info_ref;
}
- m_register_info_p = reg_info_ref.data();
+ m_register_info_p = m_per_vq_reg_infos[sve_vq].data();
return m_vector_reg_vq;
}
+bool RegisterInfoPOSIX_arm64::IsSVEReg(unsigned reg) const {
+ if (m_vector_reg_vq > eVectorQuadwordAArch64)
+ return (sve_vg <= reg && reg <= sve_ffr);
+ else
+ return false;
+}
+
bool RegisterInfoPOSIX_arm64::IsSVEZReg(unsigned reg) const {
return (sve_z0 <= reg && reg <= sve_z31);
}
@@ -335,6 +389,18 @@ bool RegisterInfoPOSIX_arm64::IsSVERegVG(unsigned reg) const {
return sve_vg == reg;
}
+bool RegisterInfoPOSIX_arm64::IsPAuthReg(unsigned reg) const {
+ return std::find(pauth_regnum_collection.begin(),
+ pauth_regnum_collection.end(),
+ reg) != pauth_regnum_collection.end();
+}
+
+bool RegisterInfoPOSIX_arm64::IsMTEReg(unsigned reg) const {
+ return std::find(m_mte_regnum_collection.begin(),
+ m_mte_regnum_collection.end(),
+ reg) != m_mte_regnum_collection.end();
+}
+
uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEZ0() const { return sve_z0; }
uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEFFR() const { return sve_ffr; }
@@ -344,3 +410,11 @@ uint32_t RegisterInfoPOSIX_arm64::GetRegNumFPCR() const { return fpu_fpcr; }
uint32_t RegisterInfoPOSIX_arm64::GetRegNumFPSR() const { return fpu_fpsr; }
uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEVG() const { return sve_vg; }
+
+uint32_t RegisterInfoPOSIX_arm64::GetPAuthOffset() const {
+ return m_register_info_p[pauth_regnum_collection[0]].byte_offset;
+}
+
+uint32_t RegisterInfoPOSIX_arm64::GetMTEOffset() const {
+ return m_register_info_p[m_mte_regnum_collection[0]].byte_offset;
+}
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
index 2929f2009dd9..ba873ba4436b 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
@@ -11,6 +11,7 @@
#include "RegisterInfoAndSetInterface.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Utility/Flags.h"
#include "lldb/lldb-private.h"
#include <map>
@@ -19,7 +20,16 @@ enum class SVEState { Unknown, Disabled, FPSIMD, Full };
class RegisterInfoPOSIX_arm64
: public lldb_private::RegisterInfoAndSetInterface {
public:
- enum { GPRegSet = 0, FPRegSet, SVERegSet };
+ enum { GPRegSet = 0, FPRegSet };
+
+ // AArch64 register set mask value
+ enum {
+ eRegsetMaskDefault = 0,
+ eRegsetMaskSVE = 1,
+ eRegsetMaskPAuth = 2,
+ eRegsetMaskMTE = 4,
+ eRegsetMaskDynamic = ~1,
+ };
// AArch64 Register set FP/SIMD feature configuration
enum {
@@ -68,7 +78,8 @@ public:
uint64_t mdscr_el1;
};
- RegisterInfoPOSIX_arm64(const lldb_private::ArchSpec &target_arch);
+ RegisterInfoPOSIX_arm64(const lldb_private::ArchSpec &target_arch,
+ lldb_private::Flags opt_regsets);
size_t GetGPRSize() const override;
@@ -85,7 +96,11 @@ public:
size_t GetRegisterSetFromRegisterIndex(uint32_t reg_index) const override;
- uint32_t ConfigureVectorRegisterInfos(uint32_t sve_vq);
+ void AddRegSetPAuth();
+
+ void AddRegSetMTE();
+
+ uint32_t ConfigureVectorLength(uint32_t sve_vq);
bool VectorSizeIsValid(uint32_t vq) {
if (vq >= eVectorQuadwordAArch64 && vq <= eVectorQuadwordAArch64SVEMax)
@@ -93,17 +108,23 @@ public:
return false;
}
- bool IsSVEEnabled() const { return m_vector_reg_vq > eVectorQuadwordAArch64; }
+ bool IsSVEEnabled() const { return m_opt_regsets.AnySet(eRegsetMaskSVE); }
+ bool IsPAuthEnabled() const { return m_opt_regsets.AnySet(eRegsetMaskPAuth); }
+ bool IsSVEReg(unsigned reg) const;
bool IsSVEZReg(unsigned reg) const;
bool IsSVEPReg(unsigned reg) const;
bool IsSVERegVG(unsigned reg) const;
+ bool IsPAuthReg(unsigned reg) const;
+ bool IsMTEReg(unsigned reg) const;
uint32_t GetRegNumSVEZ0() const;
uint32_t GetRegNumSVEFFR() const;
uint32_t GetRegNumFPCR() const;
uint32_t GetRegNumFPSR() const;
uint32_t GetRegNumSVEVG() const;
+ uint32_t GetPAuthOffset() const;
+ uint32_t GetMTEOffset() const;
private:
typedef std::map<uint32_t, std::vector<lldb_private::RegisterInfo>>
@@ -115,6 +136,21 @@ private:
const lldb_private::RegisterInfo *m_register_info_p;
uint32_t m_register_info_count;
+
+ const lldb_private::RegisterSet *m_register_set_p;
+ uint32_t m_register_set_count;
+
+ // Contains pair of [start, end] register numbers of a register set with start
+ // and end included.
+ std::map<uint32_t, std::pair<uint32_t, uint32_t>> m_per_regset_regnum_range;
+
+ lldb_private::Flags m_opt_regsets;
+
+ std::vector<lldb_private::RegisterInfo> m_dynamic_reg_infos;
+ std::vector<lldb_private::RegisterSet> m_dynamic_reg_sets;
+
+ std::vector<uint32_t> pauth_regnum_collection;
+ std::vector<uint32_t> m_mte_regnum_collection;
};
#endif
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp
index 3461d38a3901..159fd2856443 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp
@@ -7,7 +7,7 @@
//===---------------------------------------------------------------------===//
#include <cassert>
-#include <stddef.h>
+#include <cstddef>
#include <vector>
#include "lldb/lldb-defines.h"
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h
index 74b9e3b2db32..4af0069eb6f3 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h
@@ -8,7 +8,7 @@
#ifdef DECLARE_REGISTER_INFOS_ARM_STRUCT
-#include <stddef.h>
+#include <cstddef>
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h
index 4aee55e7afba..47cedc31bcd7 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h
@@ -8,7 +8,7 @@
#ifdef DECLARE_REGISTER_INFOS_ARM64_STRUCT
-#include <stddef.h>
+#include <cstddef>
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
@@ -470,6 +470,13 @@ static uint32_t g_d31_invalidates[] = {fpu_v31, fpu_s31, LLDB_INVALID_REGNUM};
LLDB_INVALID_REGNUM, lldb_kind \
}
+// Generates register kinds array for registers with only lldb kind
+#define KIND_ALL_INVALID \
+ { \
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM \
+ }
+
// Generates register kinds array for vector registers
#define GPR64_KIND(reg, generic_kind) MISC_KIND(reg, gpr, generic_kind)
#define VREG_KIND(reg) MISC_KIND(reg, fpu, LLDB_INVALID_REGNUM)
@@ -526,6 +533,13 @@ static uint32_t g_d31_invalidates[] = {fpu_v31, fpu_s31, LLDB_INVALID_REGNUM};
nullptr, 0 \
}
+// Defines pointer authentication mask registers
+#define DEFINE_EXTENSION_REG(reg) \
+ { \
+ #reg, nullptr, 8, 0, lldb::eEncodingUint, lldb::eFormatHex, \
+ KIND_ALL_INVALID, nullptr, nullptr, nullptr, 0 \
+ }
+
static lldb_private::RegisterInfo g_register_infos_arm64_le[] = {
// DEFINE_GPR64(name, GENERIC KIND)
DEFINE_GPR64(x0, LLDB_REGNUM_GENERIC_ARG1),
@@ -772,7 +786,12 @@ static lldb_private::RegisterInfo g_register_infos_arm64_le[] = {
{DEFINE_DBG(wcr, 13)},
{DEFINE_DBG(wcr, 14)},
{DEFINE_DBG(wcr, 15)}
- // clang-format on
};
+// clang-format on
+static lldb_private::RegisterInfo g_register_infos_pauth[] = {
+ DEFINE_EXTENSION_REG(data_mask), DEFINE_EXTENSION_REG(code_mask)};
+
+static lldb_private::RegisterInfo g_register_infos_mte[] = {
+ DEFINE_EXTENSION_REG(mte_ctrl)};
#endif // DECLARE_REGISTER_INFOS_ARM64_STRUCT
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h
index 08201fd1191c..93f93d56fda2 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h
@@ -6,7 +6,7 @@
//
//===---------------------------------------------------------------------===//
-#include <stddef.h>
+#include <cstddef>
#include "lldb/Core/dwarf.h"
#include "llvm/Support/Compiler.h"
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h
index b6e218ea4414..b28b91810e48 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <stddef.h>
+#include <cstddef>
#include "lldb/Core/dwarf.h"
#include "llvm/Support/Compiler.h"
@@ -15,37 +15,11 @@
#ifdef DECLARE_REGISTER_INFOS_MIPS64_STRUCT
// Computes the offset of the given GPR in the user data area.
-#ifdef LINUX_MIPS64
-#define GPR_OFFSET(regname) \
- (LLVM_EXTENSION offsetof(UserArea, gpr) + \
- LLVM_EXTENSION offsetof(GPR_linux_mips, regname))
-#else
#define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR_freebsd_mips, regname))
-#endif
-
-// Computes the offset of the given FPR in the extended data area.
-#define FPR_OFFSET(regname) \
- (LLVM_EXTENSION offsetof(UserArea, fpr) + \
- LLVM_EXTENSION offsetof(FPR_linux_mips, regname))
-
-// Computes the offset of the given MSA in the extended data area.
-#define MSA_OFFSET(regname) \
- (LLVM_EXTENSION offsetof(UserArea, msa) + \
- LLVM_EXTENSION offsetof(MSA_linux_mips, regname))
// RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB
// Note that the size and offset will be updated by platform-specific classes.
-#ifdef LINUX_MIPS64
-#define DEFINE_GPR(reg, alt, kind1, kind2, kind3) \
- { \
- #reg, alt, sizeof(((GPR_linux_mips *) 0)->reg), \
- GPR_OFFSET(reg), eEncodingUint, eFormatHex, \
- {kind1, kind2, kind3, ptrace_##reg##_mips, \
- gpr_##reg##_mips64 }, \
- NULL, NULL, NULL, 0 \
- }
-#else
#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
{ \
#reg, alt, sizeof(((GPR_freebsd_mips *) 0)->reg), \
@@ -54,63 +28,10 @@
gpr_##reg##_mips64 }, \
NULL, NULL, NULL, 0 \
}
-#endif
-
-#define DEFINE_GPR_INFO(reg, alt, kind1, kind2, kind3) \
- { \
- #reg, alt, sizeof(((GPR_linux_mips *) 0)->reg) / 2, \
- GPR_OFFSET(reg), eEncodingUint, eFormatHex, \
- {kind1, kind2, kind3, ptrace_##reg##_mips, \
- gpr_##reg##_mips64 }, \
- NULL, NULL, NULL, 0 \
- }
-
-const uint8_t dwarf_opcode_mips64[] = {
- llvm::dwarf::DW_OP_regx, dwarf_sr_mips64, llvm::dwarf::DW_OP_lit1,
- llvm::dwarf::DW_OP_lit26, llvm::dwarf::DW_OP_shl, llvm::dwarf::DW_OP_and,
- llvm::dwarf::DW_OP_lit26, llvm::dwarf::DW_OP_shr};
-
-#define DEFINE_FPR(reg, alt, kind1, kind2, kind3) \
- { \
- #reg, alt, sizeof(((FPR_linux_mips *) 0)->reg), \
- FPR_OFFSET(reg), eEncodingIEEE754, eFormatFloat, \
- {kind1, kind2, kind3, ptrace_##reg##_mips, \
- fpr_##reg##_mips64 }, \
- NULL, NULL, dwarf_opcode_mips64, \
- sizeof(dwarf_opcode_mips64) \
- }
-
-#define DEFINE_FPR_INFO(reg, alt, kind1, kind2, kind3) \
- { \
- #reg, alt, sizeof(((FPR_linux_mips *) 0)->reg), \
- FPR_OFFSET(reg), eEncodingUint, eFormatHex, \
- {kind1, kind2, kind3, ptrace_##reg##_mips, \
- fpr_##reg##_mips64 }, \
- NULL, NULL, NULL, 0 \
- }
-
-#define DEFINE_MSA(reg, alt, kind1, kind2, kind3, kind4) \
- { \
- #reg, alt, sizeof(((MSA_linux_mips *) 0)->reg), \
- MSA_OFFSET(reg), eEncodingVector, eFormatVectorOfUInt8, \
- {kind1, kind2, kind3, kind4, \
- msa_##reg##_mips64 }, \
- NULL, NULL, NULL, 0 \
- }
-
-#define DEFINE_MSA_INFO(reg, alt, kind1, kind2, kind3, kind4) \
- { \
- #reg, alt, sizeof(((MSA_linux_mips *) 0)->reg), \
- MSA_OFFSET(reg), eEncodingUint, eFormatHex, \
- {kind1, kind2, kind3, kind4, \
- msa_##reg##_mips64 }, \
- NULL, NULL, NULL, 0 \
- }
static RegisterInfo g_register_infos_mips64[] = {
// General purpose registers. EH_Frame, DWARF,
// Generic, Process Plugin
-#ifndef LINUX_MIPS64
DEFINE_GPR(zero, "r0", dwarf_zero_mips64, dwarf_zero_mips64,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
DEFINE_GPR(r1, nullptr, dwarf_r1_mips64, dwarf_r1_mips64,
@@ -191,231 +112,6 @@ static RegisterInfo g_register_infos_mips64[] = {
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
DEFINE_GPR(dummy, nullptr, dwarf_dummy_mips64, dwarf_dummy_mips64,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
-#else
- DEFINE_GPR(zero, "r0", dwarf_zero_mips64, dwarf_zero_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r1, nullptr, dwarf_r1_mips64, dwarf_r1_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r2, nullptr, dwarf_r2_mips64, dwarf_r2_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r3, nullptr, dwarf_r3_mips64, dwarf_r3_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r4, nullptr, dwarf_r4_mips64, dwarf_r4_mips64,
- LLDB_REGNUM_GENERIC_ARG1),
- DEFINE_GPR(r5, nullptr, dwarf_r5_mips64, dwarf_r5_mips64,
- LLDB_REGNUM_GENERIC_ARG2),
- DEFINE_GPR(r6, nullptr, dwarf_r6_mips64, dwarf_r6_mips64,
- LLDB_REGNUM_GENERIC_ARG3),
- DEFINE_GPR(r7, nullptr, dwarf_r7_mips64, dwarf_r7_mips64,
- LLDB_REGNUM_GENERIC_ARG4),
- DEFINE_GPR(r8, nullptr, dwarf_r8_mips64, dwarf_r8_mips64,
- LLDB_REGNUM_GENERIC_ARG5),
- DEFINE_GPR(r9, nullptr, dwarf_r9_mips64, dwarf_r9_mips64,
- LLDB_REGNUM_GENERIC_ARG6),
- DEFINE_GPR(r10, nullptr, dwarf_r10_mips64, dwarf_r10_mips64,
- LLDB_REGNUM_GENERIC_ARG7),
- DEFINE_GPR(r11, nullptr, dwarf_r11_mips64, dwarf_r11_mips64,
- LLDB_REGNUM_GENERIC_ARG8),
- DEFINE_GPR(r12, nullptr, dwarf_r12_mips64, dwarf_r12_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r13, nullptr, dwarf_r13_mips64, dwarf_r13_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r14, nullptr, dwarf_r14_mips64, dwarf_r14_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r15, nullptr, dwarf_r15_mips64, dwarf_r15_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r16, nullptr, dwarf_r16_mips64, dwarf_r16_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r17, nullptr, dwarf_r17_mips64, dwarf_r17_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r18, nullptr, dwarf_r18_mips64, dwarf_r18_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r19, nullptr, dwarf_r19_mips64, dwarf_r19_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r20, nullptr, dwarf_r20_mips64, dwarf_r20_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r21, nullptr, dwarf_r21_mips64, dwarf_r21_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r22, nullptr, dwarf_r22_mips64, dwarf_r22_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r23, nullptr, dwarf_r23_mips64, dwarf_r23_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r24, nullptr, dwarf_r24_mips64, dwarf_r24_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r25, nullptr, dwarf_r25_mips64, dwarf_r25_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r26, nullptr, dwarf_r26_mips64, dwarf_r26_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r27, nullptr, dwarf_r27_mips64, dwarf_r27_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(gp, "r28", dwarf_gp_mips64, dwarf_gp_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(sp, "r29", dwarf_sp_mips64, dwarf_sp_mips64,
- LLDB_REGNUM_GENERIC_SP),
- DEFINE_GPR(r30, nullptr, dwarf_r30_mips64, dwarf_r30_mips64,
- LLDB_REGNUM_GENERIC_FP),
- DEFINE_GPR(ra, "r31", dwarf_ra_mips64, dwarf_ra_mips64,
- LLDB_REGNUM_GENERIC_RA),
- DEFINE_GPR_INFO(sr, nullptr, dwarf_sr_mips64, dwarf_sr_mips64,
- LLDB_REGNUM_GENERIC_FLAGS),
- DEFINE_GPR(mullo, nullptr, dwarf_lo_mips64, dwarf_lo_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(mulhi, nullptr, dwarf_hi_mips64, dwarf_hi_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(badvaddr, nullptr, dwarf_bad_mips64, dwarf_bad_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR_INFO(cause, nullptr, dwarf_cause_mips64, dwarf_cause_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(pc, "pc", dwarf_pc_mips64, dwarf_pc_mips64,
- LLDB_REGNUM_GENERIC_PC),
- DEFINE_GPR_INFO(config5, nullptr, dwarf_config5_mips64,
- dwarf_config5_mips64, LLDB_INVALID_REGNUM),
- DEFINE_FPR(f0, nullptr, dwarf_f0_mips64, dwarf_f0_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f1, nullptr, dwarf_f1_mips64, dwarf_f1_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f2, nullptr, dwarf_f2_mips64, dwarf_f2_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f3, nullptr, dwarf_f3_mips64, dwarf_f3_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f4, nullptr, dwarf_f4_mips64, dwarf_f4_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f5, nullptr, dwarf_f5_mips64, dwarf_f5_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f6, nullptr, dwarf_f6_mips64, dwarf_f6_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f7, nullptr, dwarf_f7_mips64, dwarf_f7_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f8, nullptr, dwarf_f8_mips64, dwarf_f8_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f9, nullptr, dwarf_f9_mips64, dwarf_f9_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f10, nullptr, dwarf_f10_mips64, dwarf_f10_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f11, nullptr, dwarf_f11_mips64, dwarf_f11_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f12, nullptr, dwarf_f12_mips64, dwarf_f12_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f13, nullptr, dwarf_f13_mips64, dwarf_f13_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f14, nullptr, dwarf_f14_mips64, dwarf_f14_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f15, nullptr, dwarf_f15_mips64, dwarf_f15_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f16, nullptr, dwarf_f16_mips64, dwarf_f16_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f17, nullptr, dwarf_f17_mips64, dwarf_f17_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f18, nullptr, dwarf_f18_mips64, dwarf_f18_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f19, nullptr, dwarf_f19_mips64, dwarf_f19_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f20, nullptr, dwarf_f20_mips64, dwarf_f20_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f21, nullptr, dwarf_f21_mips64, dwarf_f21_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f22, nullptr, dwarf_f22_mips64, dwarf_f22_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f23, nullptr, dwarf_f23_mips64, dwarf_f23_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f24, nullptr, dwarf_f24_mips64, dwarf_f24_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f25, nullptr, dwarf_f25_mips64, dwarf_f25_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f26, nullptr, dwarf_f26_mips64, dwarf_f26_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f27, nullptr, dwarf_f27_mips64, dwarf_f27_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f28, nullptr, dwarf_f28_mips64, dwarf_f28_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f29, nullptr, dwarf_f29_mips64, dwarf_f29_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f30, nullptr, dwarf_f30_mips64, dwarf_f30_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f31, nullptr, dwarf_f31_mips64, dwarf_f31_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR_INFO(fcsr, nullptr, dwarf_fcsr_mips64, dwarf_fcsr_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR_INFO(fir, nullptr, dwarf_fir_mips64, dwarf_fir_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR_INFO(config5, nullptr, dwarf_config5_mips64,
- dwarf_config5_mips64, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w0, nullptr, dwarf_w0_mips64, dwarf_w0_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w1, nullptr, dwarf_w1_mips64, dwarf_w1_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w2, nullptr, dwarf_w2_mips64, dwarf_w2_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w3, nullptr, dwarf_w3_mips64, dwarf_w3_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w4, nullptr, dwarf_w4_mips64, dwarf_w4_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w5, nullptr, dwarf_w5_mips64, dwarf_w5_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w6, nullptr, dwarf_w6_mips64, dwarf_w6_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w7, nullptr, dwarf_w7_mips64, dwarf_w7_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w8, nullptr, dwarf_w8_mips64, dwarf_w8_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w9, nullptr, dwarf_w9_mips64, dwarf_w9_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w10, nullptr, dwarf_w10_mips64, dwarf_w10_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w11, nullptr, dwarf_w11_mips64, dwarf_w11_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w12, nullptr, dwarf_w12_mips64, dwarf_w12_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w13, nullptr, dwarf_w13_mips64, dwarf_w13_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w14, nullptr, dwarf_w14_mips64, dwarf_w14_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w15, nullptr, dwarf_w15_mips64, dwarf_w15_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w16, nullptr, dwarf_w16_mips64, dwarf_w16_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w17, nullptr, dwarf_w17_mips64, dwarf_w17_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w18, nullptr, dwarf_w18_mips64, dwarf_w18_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w19, nullptr, dwarf_w19_mips64, dwarf_w19_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w20, nullptr, dwarf_w10_mips64, dwarf_w20_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w21, nullptr, dwarf_w21_mips64, dwarf_w21_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w22, nullptr, dwarf_w22_mips64, dwarf_w22_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w23, nullptr, dwarf_w23_mips64, dwarf_w23_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w24, nullptr, dwarf_w24_mips64, dwarf_w24_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w25, nullptr, dwarf_w25_mips64, dwarf_w25_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w26, nullptr, dwarf_w26_mips64, dwarf_w26_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w27, nullptr, dwarf_w27_mips64, dwarf_w27_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w28, nullptr, dwarf_w28_mips64, dwarf_w28_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w29, nullptr, dwarf_w29_mips64, dwarf_w29_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w30, nullptr, dwarf_w30_mips64, dwarf_w30_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w31, nullptr, dwarf_w31_mips64, dwarf_w31_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA_INFO(mcsr, nullptr, dwarf_mcsr_mips64, dwarf_mcsr_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA_INFO(mir, nullptr, dwarf_mir_mips64, dwarf_mir_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA_INFO(fcsr, nullptr, dwarf_fcsr_mips64, dwarf_fcsr_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA_INFO(fir, nullptr, dwarf_fir_mips64, dwarf_fir_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA_INFO(config5, nullptr, dwarf_config5_mips64,
- dwarf_config5_mips64, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM)
-#endif
};
static_assert((sizeof(g_register_infos_mips64) /
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
index 51be31f8e028..04b4171b6722 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
@@ -6,12 +6,12 @@
//
//===---------------------------------------------------------------------===//
-#include <stddef.h>
+#include <cstddef>
// Computes the offset of the given GPR in the user data area.
#define GPR_OFFSET(regname) (offsetof(GPR, regname))
-#define FPR_OFFSET(regname) (offsetof(FPR, regname))
-#define VMX_OFFSET(regname) (offsetof(VMX, regname))
+#define FPR_OFFSET(regname) (sizeof(GPR) + offsetof(FPR, regname))
+#define VMX_OFFSET(regname) (sizeof(GPR) + sizeof(FPR) + offsetof(VMX, regname))
#define GPR_SIZE(regname) (sizeof(((GPR *)NULL)->regname))
#ifdef DECLARE_REGISTER_INFOS_POWERPC_STRUCT
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h
index 1086d3db0b06..059dba45f9bb 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h
@@ -8,7 +8,7 @@
#ifdef DECLARE_REGISTER_INFOS_PPC64_STRUCT
-#include <stddef.h>
+#include <cstddef>
// Computes the offset of the given GPR_PPC64 in the user data area.
#define GPR_PPC64_OFFSET(regname) (offsetof(GPR_PPC64, regname))
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h
index 0b099a53d875..9937da2f3050 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h
@@ -8,7 +8,7 @@
#ifdef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT
-#include <stddef.h>
+#include <cstddef>
// Computes the offset of the given GPR in the user data area.
#define GPR_OFFSET(regname) (offsetof(GPR, regname))
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_s390x.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_s390x.h
index 11344ff8ee79..d1df7c606207 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfos_s390x.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_s390x.h
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <stddef.h>
+#include <cstddef>
#include "llvm/Support/Compiler.h"
diff --git a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
index 2d8e8ef21612..85785a20354d 100644
--- a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
+++ b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
@@ -509,7 +509,7 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
// operating system thread ID, so we can't make any assumptions about
// the thread ID so we must always report the breakpoint regardless
// of the thread.
- if (bp_site_sp->ValidForThisThread(&thread) ||
+ if (bp_site_sp->ValidForThisThread(thread) ||
thread.GetProcess()->GetOperatingSystem() != nullptr)
return StopInfo::CreateStopReasonWithBreakpointSiteID(
thread, bp_site_sp->GetID());
diff --git a/lldb/source/Plugins/Process/Utility/lldb-mips-linux-register-enums.h b/lldb/source/Plugins/Process/Utility/lldb-mips-linux-register-enums.h
deleted file mode 100644
index 348af27d2809..000000000000
--- a/lldb/source/Plugins/Process/Utility/lldb-mips-linux-register-enums.h
+++ /dev/null
@@ -1,360 +0,0 @@
-//===-- lldb-mips-linux-register-enums.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_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_MIPS_LINUX_REGISTER_ENUMS_H
-#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_MIPS_LINUX_REGISTER_ENUMS_H
-
-namespace lldb_private {
-// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB)
-
-// Internal codes for all mips registers.
-enum {
- k_first_gpr_mips,
- gpr_zero_mips = k_first_gpr_mips,
- gpr_r1_mips,
- gpr_r2_mips,
- gpr_r3_mips,
- gpr_r4_mips,
- gpr_r5_mips,
- gpr_r6_mips,
- gpr_r7_mips,
- gpr_r8_mips,
- gpr_r9_mips,
- gpr_r10_mips,
- gpr_r11_mips,
- gpr_r12_mips,
- gpr_r13_mips,
- gpr_r14_mips,
- gpr_r15_mips,
- gpr_r16_mips,
- gpr_r17_mips,
- gpr_r18_mips,
- gpr_r19_mips,
- gpr_r20_mips,
- gpr_r21_mips,
- gpr_r22_mips,
- gpr_r23_mips,
- gpr_r24_mips,
- gpr_r25_mips,
- gpr_r26_mips,
- gpr_r27_mips,
- gpr_gp_mips,
- gpr_sp_mips,
- gpr_r30_mips,
- gpr_ra_mips,
- gpr_sr_mips,
- gpr_mullo_mips,
- gpr_mulhi_mips,
- gpr_badvaddr_mips,
- gpr_cause_mips,
- gpr_pc_mips,
- gpr_config5_mips,
-
- k_last_gpr_mips = gpr_config5_mips,
-
- k_first_fpr_mips,
- fpr_f0_mips = k_first_fpr_mips,
- fpr_f1_mips,
- fpr_f2_mips,
- fpr_f3_mips,
- fpr_f4_mips,
- fpr_f5_mips,
- fpr_f6_mips,
- fpr_f7_mips,
- fpr_f8_mips,
- fpr_f9_mips,
- fpr_f10_mips,
- fpr_f11_mips,
- fpr_f12_mips,
- fpr_f13_mips,
- fpr_f14_mips,
- fpr_f15_mips,
- fpr_f16_mips,
- fpr_f17_mips,
- fpr_f18_mips,
- fpr_f19_mips,
- fpr_f20_mips,
- fpr_f21_mips,
- fpr_f22_mips,
- fpr_f23_mips,
- fpr_f24_mips,
- fpr_f25_mips,
- fpr_f26_mips,
- fpr_f27_mips,
- fpr_f28_mips,
- fpr_f29_mips,
- fpr_f30_mips,
- fpr_f31_mips,
- fpr_fcsr_mips,
- fpr_fir_mips,
- fpr_config5_mips,
- k_last_fpr_mips = fpr_config5_mips,
-
- k_first_msa_mips,
- msa_w0_mips = k_first_msa_mips,
- msa_w1_mips,
- msa_w2_mips,
- msa_w3_mips,
- msa_w4_mips,
- msa_w5_mips,
- msa_w6_mips,
- msa_w7_mips,
- msa_w8_mips,
- msa_w9_mips,
- msa_w10_mips,
- msa_w11_mips,
- msa_w12_mips,
- msa_w13_mips,
- msa_w14_mips,
- msa_w15_mips,
- msa_w16_mips,
- msa_w17_mips,
- msa_w18_mips,
- msa_w19_mips,
- msa_w20_mips,
- msa_w21_mips,
- msa_w22_mips,
- msa_w23_mips,
- msa_w24_mips,
- msa_w25_mips,
- msa_w26_mips,
- msa_w27_mips,
- msa_w28_mips,
- msa_w29_mips,
- msa_w30_mips,
- msa_w31_mips,
- msa_fcsr_mips,
- msa_fir_mips,
- msa_mcsr_mips,
- msa_mir_mips,
- msa_config5_mips,
- k_last_msa_mips = msa_config5_mips,
-
- k_num_registers_mips,
-
- k_num_gpr_registers_mips = k_last_gpr_mips - k_first_gpr_mips + 1,
- k_num_fpr_registers_mips = k_last_fpr_mips - k_first_fpr_mips + 1,
- k_num_msa_registers_mips = k_last_msa_mips - k_first_msa_mips + 1,
- k_num_user_registers_mips = k_num_gpr_registers_mips +
- k_num_fpr_registers_mips +
- k_num_msa_registers_mips
-};
-
-// Internal codes for all mips64 registers.
-enum {
- k_first_gpr_mips64,
- gpr_zero_mips64 = k_first_gpr_mips64,
- gpr_r1_mips64,
- gpr_r2_mips64,
- gpr_r3_mips64,
- gpr_r4_mips64,
- gpr_r5_mips64,
- gpr_r6_mips64,
- gpr_r7_mips64,
- gpr_r8_mips64,
- gpr_r9_mips64,
- gpr_r10_mips64,
- gpr_r11_mips64,
- gpr_r12_mips64,
- gpr_r13_mips64,
- gpr_r14_mips64,
- gpr_r15_mips64,
- gpr_r16_mips64,
- gpr_r17_mips64,
- gpr_r18_mips64,
- gpr_r19_mips64,
- gpr_r20_mips64,
- gpr_r21_mips64,
- gpr_r22_mips64,
- gpr_r23_mips64,
- gpr_r24_mips64,
- gpr_r25_mips64,
- gpr_r26_mips64,
- gpr_r27_mips64,
- gpr_gp_mips64,
- gpr_sp_mips64,
- gpr_r30_mips64,
- gpr_ra_mips64,
- gpr_sr_mips64,
- gpr_mullo_mips64,
- gpr_mulhi_mips64,
- gpr_badvaddr_mips64,
- gpr_cause_mips64,
- gpr_pc_mips64,
- gpr_config5_mips64,
- k_last_gpr_mips64 = gpr_config5_mips64,
-
- k_first_fpr_mips64,
- fpr_f0_mips64 = k_first_fpr_mips64,
- fpr_f1_mips64,
- fpr_f2_mips64,
- fpr_f3_mips64,
- fpr_f4_mips64,
- fpr_f5_mips64,
- fpr_f6_mips64,
- fpr_f7_mips64,
- fpr_f8_mips64,
- fpr_f9_mips64,
- fpr_f10_mips64,
- fpr_f11_mips64,
- fpr_f12_mips64,
- fpr_f13_mips64,
- fpr_f14_mips64,
- fpr_f15_mips64,
- fpr_f16_mips64,
- fpr_f17_mips64,
- fpr_f18_mips64,
- fpr_f19_mips64,
- fpr_f20_mips64,
- fpr_f21_mips64,
- fpr_f22_mips64,
- fpr_f23_mips64,
- fpr_f24_mips64,
- fpr_f25_mips64,
- fpr_f26_mips64,
- fpr_f27_mips64,
- fpr_f28_mips64,
- fpr_f29_mips64,
- fpr_f30_mips64,
- fpr_f31_mips64,
- fpr_fcsr_mips64,
- fpr_fir_mips64,
- fpr_config5_mips64,
- k_last_fpr_mips64 = fpr_config5_mips64,
-
- k_first_msa_mips64,
- msa_w0_mips64 = k_first_msa_mips64,
- msa_w1_mips64,
- msa_w2_mips64,
- msa_w3_mips64,
- msa_w4_mips64,
- msa_w5_mips64,
- msa_w6_mips64,
- msa_w7_mips64,
- msa_w8_mips64,
- msa_w9_mips64,
- msa_w10_mips64,
- msa_w11_mips64,
- msa_w12_mips64,
- msa_w13_mips64,
- msa_w14_mips64,
- msa_w15_mips64,
- msa_w16_mips64,
- msa_w17_mips64,
- msa_w18_mips64,
- msa_w19_mips64,
- msa_w20_mips64,
- msa_w21_mips64,
- msa_w22_mips64,
- msa_w23_mips64,
- msa_w24_mips64,
- msa_w25_mips64,
- msa_w26_mips64,
- msa_w27_mips64,
- msa_w28_mips64,
- msa_w29_mips64,
- msa_w30_mips64,
- msa_w31_mips64,
- msa_fcsr_mips64,
- msa_fir_mips64,
- msa_mcsr_mips64,
- msa_mir_mips64,
- msa_config5_mips64,
- k_last_msa_mips64 = msa_config5_mips64,
-
- k_num_registers_mips64,
-
- k_num_gpr_registers_mips64 = k_last_gpr_mips64 - k_first_gpr_mips64 + 1,
- k_num_fpr_registers_mips64 = k_last_fpr_mips64 - k_first_fpr_mips64 + 1,
- k_num_msa_registers_mips64 = k_last_msa_mips64 - k_first_msa_mips64 + 1,
- k_num_user_registers_mips64 = k_num_gpr_registers_mips64 +
- k_num_fpr_registers_mips64 +
- k_num_msa_registers_mips64
-};
-
-// Register no. for RegisterKind = eRegisterKindProcessPlugin
-// The ptrace request PTRACE_PEEKUSER/PTRACE_POKEUSER used this number
-enum {
- ptrace_zero_mips,
- ptrace_r1_mips,
- ptrace_r2_mips,
- ptrace_r3_mips,
- ptrace_r4_mips,
- ptrace_r5_mips,
- ptrace_r6_mips,
- ptrace_r7_mips,
- ptrace_r8_mips,
- ptrace_r9_mips,
- ptrace_r10_mips,
- ptrace_r11_mips,
- ptrace_r12_mips,
- ptrace_r13_mips,
- ptrace_r14_mips,
- ptrace_r15_mips,
- ptrace_r16_mips,
- ptrace_r17_mips,
- ptrace_r18_mips,
- ptrace_r19_mips,
- ptrace_r20_mips,
- ptrace_r21_mips,
- ptrace_r22_mips,
- ptrace_r23_mips,
- ptrace_r24_mips,
- ptrace_r25_mips,
- ptrace_r26_mips,
- ptrace_r27_mips,
- ptrace_gp_mips,
- ptrace_sp_mips,
- ptrace_r30_mips,
- ptrace_ra_mips,
- ptrace_f0_mips,
- ptrace_f1_mips,
- ptrace_f2_mips,
- ptrace_f3_mips,
- ptrace_f4_mips,
- ptrace_f5_mips,
- ptrace_f6_mips,
- ptrace_f7_mips,
- ptrace_f8_mips,
- ptrace_f9_mips,
- ptrace_f10_mips,
- ptrace_f11_mips,
- ptrace_f12_mips,
- ptrace_f13_mips,
- ptrace_f14_mips,
- ptrace_f15_mips,
- ptrace_f16_mips,
- ptrace_f17_mips,
- ptrace_f18_mips,
- ptrace_f19_mips,
- ptrace_f20_mips,
- ptrace_f21_mips,
- ptrace_f22_mips,
- ptrace_f23_mips,
- ptrace_f24_mips,
- ptrace_f25_mips,
- ptrace_f26_mips,
- ptrace_f27_mips,
- ptrace_f28_mips,
- ptrace_f29_mips,
- ptrace_f30_mips,
- ptrace_f31_mips,
- ptrace_pc_mips,
- ptrace_cause_mips,
- ptrace_badvaddr_mips,
- ptrace_mulhi_mips,
- ptrace_mullo_mips,
- ptrace_fcsr_mips,
- ptrace_fir_mips,
- ptrace_sr_mips,
- ptrace_config5_mips
-};
-}
-
-#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_MIPS_LINUX_REGISTER_ENUMS_H
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index ae19367ca3ae..12bc7390c729 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <stdlib.h>
+#include <cstdlib>
#include <memory>
#include <mutex>
@@ -353,7 +353,6 @@ size_t ProcessElfCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
const lldb::addr_t file_end = address_range->data.GetRangeEnd();
size_t bytes_to_read = size; // Number of bytes to read from the core file
size_t bytes_copied = 0; // Number of bytes actually read from the core file
- size_t zero_fill_size = 0; // Padding
lldb::addr_t bytes_left =
0; // Number of bytes available in the core file from the given address
@@ -367,24 +366,15 @@ size_t ProcessElfCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
if (file_end > file_start + offset)
bytes_left = file_end - (file_start + offset);
- // Figure out how many bytes we need to zero-fill if we are reading more
- // bytes than available in the on-disk segment
- if (bytes_to_read > bytes_left) {
- zero_fill_size = bytes_to_read - bytes_left;
+ if (bytes_to_read > bytes_left)
bytes_to_read = bytes_left;
- }
// If there is data available on the core file read it
if (bytes_to_read)
bytes_copied =
core_objfile->CopyData(offset + file_start, bytes_to_read, buf);
- assert(zero_fill_size <= size);
- // Pad remaining bytes
- if (zero_fill_size)
- memset(((char *)buf) + bytes_copied, 0, zero_fill_size);
-
- return bytes_copied + zero_fill_size;
+ return bytes_copied;
}
void ProcessElfCore::Clear() {
@@ -414,12 +404,8 @@ lldb::addr_t ProcessElfCore::GetImageInfoAddress() {
// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details.
static void ParseFreeBSDPrStatus(ThreadData &thread_data,
const DataExtractor &data,
- const ArchSpec &arch) {
+ bool lp64) {
lldb::offset_t offset = 0;
- bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 ||
- arch.GetMachine() == llvm::Triple::mips64 ||
- arch.GetMachine() == llvm::Triple::ppc64 ||
- arch.GetMachine() == llvm::Triple::x86_64);
int pr_version = data.GetU32(&offset);
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
@@ -443,6 +429,27 @@ static void ParseFreeBSDPrStatus(ThreadData &thread_data,
thread_data.gpregset = DataExtractor(data, offset, len);
}
+// Parse a FreeBSD NT_PRPSINFO note - see FreeBSD sys/procfs.h for details.
+static void ParseFreeBSDPrPsInfo(ProcessElfCore &process,
+ const DataExtractor &data,
+ bool lp64) {
+ lldb::offset_t offset = 0;
+ int pr_version = data.GetU32(&offset);
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log) {
+ if (pr_version > 1)
+ LLDB_LOGF(log, "FreeBSD PRPSINFO unexpected version %d", pr_version);
+ }
+
+ // Skip pr_psinfosz, pr_fname, pr_psargs
+ offset += 108;
+ if (lp64)
+ offset += 4;
+
+ process.SetID(data.GetU32(&offset)); // pr_pid
+}
+
static llvm::Error ParseNetBSDProcInfo(const DataExtractor &data,
uint32_t &cpi_nlwps,
uint32_t &cpi_signo,
@@ -522,6 +529,11 @@ ProcessElfCore::parseSegment(const DataExtractor &segment) {
}
llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) {
+ ArchSpec arch = GetArchitecture();
+ bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 ||
+ arch.GetMachine() == llvm::Triple::mips64 ||
+ arch.GetMachine() == llvm::Triple::ppc64 ||
+ arch.GetMachine() == llvm::Triple::x86_64);
bool have_prstatus = false;
bool have_prpsinfo = false;
ThreadData thread_data;
@@ -542,10 +554,11 @@ llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) {
switch (note.info.n_type) {
case ELF::NT_PRSTATUS:
have_prstatus = true;
- ParseFreeBSDPrStatus(thread_data, note.data, GetArchitecture());
+ ParseFreeBSDPrStatus(thread_data, note.data, lp64);
break;
case ELF::NT_PRPSINFO:
have_prpsinfo = true;
+ ParseFreeBSDPrPsInfo(*this, note.data, lp64);
break;
case ELF::NT_FREEBSD_THRMISC: {
lldb::offset_t offset = 0;
@@ -651,6 +664,32 @@ llvm::Error ProcessElfCore::parseNetBSDNotes(llvm::ArrayRef<CoreNote> notes) {
thread_data.notes.push_back(note);
}
} break;
+ case llvm::Triple::x86: {
+ // Assume order PT_GETREGS, PT_GETFPREGS
+ if (note.info.n_type == NETBSD::I386::NT_REGS) {
+ // If this is the next thread, push the previous one first.
+ if (had_nt_regs) {
+ m_thread_data.push_back(thread_data);
+ thread_data = ThreadData();
+ had_nt_regs = false;
+ }
+
+ thread_data.gpregset = note.data;
+ thread_data.tid = tid;
+ if (thread_data.gpregset.GetByteSize() == 0)
+ return llvm::make_error<llvm::StringError>(
+ "Could not find general purpose registers note in core file.",
+ llvm::inconvertibleErrorCode());
+ had_nt_regs = true;
+ } else if (note.info.n_type == NETBSD::I386::NT_FPREGS) {
+ if (!had_nt_regs || tid != thread_data.tid)
+ return llvm::make_error<llvm::StringError>(
+ "Error parsing NetBSD core(5) notes: Unexpected order "
+ "of NOTEs PT_GETFPREG before PT_GETREG",
+ llvm::inconvertibleErrorCode());
+ thread_data.notes.push_back(note);
+ }
+ } break;
case llvm::Triple::x86_64: {
// Assume order PT_GETREGS, PT_GETFPREGS
if (note.info.n_type == NETBSD::AMD64::NT_REGS) {
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
index 2f71f175a00d..f0aee04b5f62 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
@@ -25,7 +25,7 @@ RegisterContextCorePOSIX_arm::RegisterContextCorePOSIX_arm(
m_gpr.SetByteOrder(gpregset.GetByteOrder());
}
-RegisterContextCorePOSIX_arm::~RegisterContextCorePOSIX_arm() {}
+RegisterContextCorePOSIX_arm::~RegisterContextCorePOSIX_arm() = default;
bool RegisterContextCorePOSIX_arm::ReadGPR() { return true; }
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
index 129a887a550c..e56aa88b57d9 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
@@ -17,26 +17,52 @@
using namespace lldb_private;
+std::unique_ptr<RegisterContextCorePOSIX_arm64>
+RegisterContextCorePOSIX_arm64::Create(Thread &thread, const ArchSpec &arch,
+ const DataExtractor &gpregset,
+ llvm::ArrayRef<CoreNote> notes) {
+ Flags opt_regsets = RegisterInfoPOSIX_arm64::eRegsetMaskDefault;
+
+ DataExtractor sve_data = getRegset(notes, arch.GetTriple(), AARCH64_SVE_Desc);
+ if (sve_data.GetByteSize() > sizeof(sve::user_sve_header))
+ opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE);
+
+ // Pointer Authentication register set data is based on struct
+ // user_pac_mask declared in ptrace.h. See reference implementation
+ // in Linux kernel source at arch/arm64/include/uapi/asm/ptrace.h.
+ DataExtractor pac_data = getRegset(notes, arch.GetTriple(), AARCH64_PAC_Desc);
+ if (pac_data.GetByteSize() >= sizeof(uint64_t) * 2)
+ opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskPAuth);
+
+ auto register_info_up =
+ std::make_unique<RegisterInfoPOSIX_arm64>(arch, opt_regsets);
+ return std::unique_ptr<RegisterContextCorePOSIX_arm64>(
+ new RegisterContextCorePOSIX_arm64(thread, std::move(register_info_up),
+ gpregset, notes));
+}
+
RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64(
Thread &thread, std::unique_ptr<RegisterInfoPOSIX_arm64> register_info,
const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes)
: RegisterContextPOSIX_arm64(thread, std::move(register_info)) {
- m_gpr_buffer = std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
- gpregset.GetByteSize());
- m_gpr.SetData(m_gpr_buffer);
- m_gpr.SetByteOrder(gpregset.GetByteOrder());
+ m_gpr_data.SetData(std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
+ gpregset.GetByteSize()));
+ m_gpr_data.SetByteOrder(gpregset.GetByteOrder());
+
+ const llvm::Triple &target_triple =
+ m_register_info_up->GetTargetArchitecture().GetTriple();
+ m_fpr_data = getRegset(notes, target_triple, FPR_Desc);
- m_fpregset = getRegset(
- notes, m_register_info_up->GetTargetArchitecture().GetTriple(), FPR_Desc);
+ if (m_register_info_up->IsSVEEnabled())
+ m_sve_data = getRegset(notes, target_triple, AARCH64_SVE_Desc);
- m_sveregset =
- getRegset(notes, m_register_info_up->GetTargetArchitecture().GetTriple(),
- AARCH64_SVE_Desc);
+ if (m_register_info_up->IsPAuthEnabled())
+ m_pac_data = getRegset(notes, target_triple, AARCH64_PAC_Desc);
ConfigureRegisterContext();
}
-RegisterContextCorePOSIX_arm64::~RegisterContextCorePOSIX_arm64() {}
+RegisterContextCorePOSIX_arm64::~RegisterContextCorePOSIX_arm64() = default;
bool RegisterContextCorePOSIX_arm64::ReadGPR() { return true; }
@@ -53,16 +79,16 @@ bool RegisterContextCorePOSIX_arm64::WriteFPR() {
}
const uint8_t *RegisterContextCorePOSIX_arm64::GetSVEBuffer(uint64_t offset) {
- return m_sveregset.GetDataStart() + offset;
+ return m_sve_data.GetDataStart() + offset;
}
void RegisterContextCorePOSIX_arm64::ConfigureRegisterContext() {
- if (m_sveregset.GetByteSize() > sizeof(sve::user_sve_header)) {
+ if (m_sve_data.GetByteSize() > sizeof(sve::user_sve_header)) {
uint64_t sve_header_field_offset = 8;
- m_sve_vector_length = m_sveregset.GetU16(&sve_header_field_offset);
+ m_sve_vector_length = m_sve_data.GetU16(&sve_header_field_offset);
sve_header_field_offset = 12;
uint16_t sve_header_flags_field =
- m_sveregset.GetU16(&sve_header_field_offset);
+ m_sve_data.GetU16(&sve_header_field_offset);
if ((sve_header_flags_field & sve::ptrace_regs_mask) ==
sve::ptrace_regs_fpsimd)
m_sve_state = SVEState::FPSIMD;
@@ -70,15 +96,16 @@ void RegisterContextCorePOSIX_arm64::ConfigureRegisterContext() {
sve::ptrace_regs_sve)
m_sve_state = SVEState::Full;
- if (sve::vl_valid(m_sve_vector_length))
- m_register_info_up->ConfigureVectorRegisterInfos(
- sve::vq_from_vl(m_sve_vector_length));
- else {
+ if (!sve::vl_valid(m_sve_vector_length)) {
m_sve_state = SVEState::Disabled;
m_sve_vector_length = 0;
}
} else
m_sve_state = SVEState::Disabled;
+
+ if (m_sve_state != SVEState::Disabled)
+ m_register_info_up->ConfigureVectorLength(
+ sve::vq_from_vl(m_sve_vector_length));
}
uint32_t RegisterContextCorePOSIX_arm64::CalculateSVEOffset(
@@ -104,7 +131,7 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
offset = reg_info->byte_offset;
if (offset + reg_info->byte_size <= GetGPRSize()) {
- uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size);
+ uint64_t v = m_gpr_data.GetMaxU64(&offset, reg_info->byte_size);
if (offset == reg_info->byte_offset + reg_info->byte_size) {
value = v;
return true;
@@ -119,8 +146,8 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
if (m_sve_state == SVEState::Disabled) {
// SVE is disabled take legacy route for FPU register access
offset -= GetGPRSize();
- if (offset < m_fpregset.GetByteSize()) {
- value.SetFromMemoryData(reg_info, m_fpregset.GetDataStart() + offset,
+ if (offset < m_fpr_data.GetByteSize()) {
+ value.SetFromMemoryData(reg_info, m_fpr_data.GetDataStart() + offset,
reg_info->byte_size, lldb::eByteOrderLittle,
error);
return error.Success();
@@ -152,7 +179,7 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
}
assert(sve_reg_num != LLDB_INVALID_REGNUM);
- assert(offset < m_sveregset.GetByteSize());
+ assert(offset < m_sve_data.GetByteSize());
value.SetFromMemoryData(reg_info, GetSVEBuffer(offset),
reg_info->byte_size, lldb::eByteOrderLittle,
error);
@@ -174,7 +201,7 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
if (IsSVEZ(reg)) {
byte_size = 16;
offset = CalculateSVEOffset(reg_info);
- assert(offset < m_sveregset.GetByteSize());
+ assert(offset < m_sve_data.GetByteSize());
src = GetSVEBuffer(offset);
}
value.SetFromMemoryData(reg_info, src, byte_size, lldb::eByteOrderLittle,
@@ -182,7 +209,7 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
} break;
case SVEState::Full:
offset = CalculateSVEOffset(reg_info);
- assert(offset < m_sveregset.GetByteSize());
+ assert(offset < m_sve_data.GetByteSize());
value.SetFromMemoryData(reg_info, GetSVEBuffer(offset),
reg_info->byte_size, lldb::eByteOrderLittle,
error);
@@ -191,6 +218,11 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
default:
return false;
}
+ } else if (IsPAuth(reg)) {
+ offset = reg_info->byte_offset - m_register_info_up->GetPAuthOffset();
+ assert(offset < m_pac_data.GetByteSize());
+ value.SetFromMemoryData(reg_info, m_pac_data.GetDataStart() + offset,
+ reg_info->byte_size, lldb::eByteOrderLittle, error);
} else
return false;
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
index a4fdc4f14328..3988e3539b89 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
@@ -18,11 +18,10 @@
class RegisterContextCorePOSIX_arm64 : public RegisterContextPOSIX_arm64 {
public:
- RegisterContextCorePOSIX_arm64(
- lldb_private::Thread &thread,
- std::unique_ptr<RegisterInfoPOSIX_arm64> register_info,
- const lldb_private::DataExtractor &gpregset,
- llvm::ArrayRef<lldb_private::CoreNote> notes);
+ static std::unique_ptr<RegisterContextCorePOSIX_arm64>
+ Create(lldb_private::Thread &thread, const lldb_private::ArchSpec &arch,
+ const lldb_private::DataExtractor &gpregset,
+ llvm::ArrayRef<lldb_private::CoreNote> notes);
~RegisterContextCorePOSIX_arm64() override;
@@ -39,6 +38,12 @@ public:
bool HardwareSingleStep(bool enable) override;
protected:
+ RegisterContextCorePOSIX_arm64(
+ lldb_private::Thread &thread,
+ std::unique_ptr<RegisterInfoPOSIX_arm64> register_info,
+ const lldb_private::DataExtractor &gpregset,
+ llvm::ArrayRef<lldb_private::CoreNote> notes);
+
bool ReadGPR() override;
bool ReadFPR() override;
@@ -48,10 +53,10 @@ protected:
bool WriteFPR() override;
private:
- lldb::DataBufferSP m_gpr_buffer;
- lldb_private::DataExtractor m_gpr;
- lldb_private::DataExtractor m_fpregset;
- lldb_private::DataExtractor m_sveregset;
+ lldb_private::DataExtractor m_gpr_data;
+ lldb_private::DataExtractor m_fpr_data;
+ lldb_private::DataExtractor m_sve_data;
+ lldb_private::DataExtractor m_pac_data;
SVEState m_sve_state;
uint16_t m_sve_vector_length = 0;
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
index b5b83d899a44..5b1eb8b5437d 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
@@ -32,7 +32,7 @@ RegisterContextCorePOSIX_mips64::RegisterContextCorePOSIX_mips64(
m_fpr.SetByteOrder(fpregset.GetByteOrder());
}
-RegisterContextCorePOSIX_mips64::~RegisterContextCorePOSIX_mips64() {}
+RegisterContextCorePOSIX_mips64::~RegisterContextCorePOSIX_mips64() = default;
bool RegisterContextCorePOSIX_mips64::ReadGPR() { return true; }
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
index e15cd47cd7da..8380731692a3 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
@@ -39,7 +39,7 @@ RegisterContextCorePOSIX_powerpc::RegisterContextCorePOSIX_powerpc(
m_vec.SetByteOrder(vregset.GetByteOrder());
}
-RegisterContextCorePOSIX_powerpc::~RegisterContextCorePOSIX_powerpc() {}
+RegisterContextCorePOSIX_powerpc::~RegisterContextCorePOSIX_powerpc() = default;
bool RegisterContextCorePOSIX_powerpc::ReadGPR() { return true; }
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp
index c3aa92c9f86c..f1cd6897616d 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp
@@ -33,7 +33,7 @@ RegisterContextCorePOSIX_s390x::RegisterContextCorePOSIX_s390x(
m_fpr.SetByteOrder(fpregset.GetByteOrder());
}
-RegisterContextCorePOSIX_s390x::~RegisterContextCorePOSIX_s390x() {}
+RegisterContextCorePOSIX_s390x::~RegisterContextCorePOSIX_s390x() = default;
bool RegisterContextCorePOSIX_s390x::ReadGPR() { return true; }
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h b/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
index 25abd7ed54b7..f6a2fbdcc938 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
+++ b/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
@@ -55,6 +55,10 @@ namespace AMD64 {
enum { NT_REGS = 33, NT_FPREGS = 35 };
}
+namespace I386 {
+enum { NT_REGS = 33, NT_FPREGS = 35 };
+}
+
} // namespace NETBSD
namespace OPENBSD {
@@ -96,6 +100,9 @@ DataExtractor getRegset(llvm::ArrayRef<CoreNote> Notes,
llvm::ArrayRef<RegsetDesc> RegsetDescs);
constexpr RegsetDesc FPR_Desc[] = {
+ // FreeBSD/i386 core NT_FPREGSET is x87 FSAVE result but the XSAVE dump
+ // starts with FXSAVE struct, so use that instead if available.
+ {llvm::Triple::FreeBSD, llvm::Triple::x86, llvm::ELF::NT_X86_XSTATE},
{llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, llvm::ELF::NT_FPREGSET},
// In a i386 core file NT_FPREGSET is present, but it's not the result
// of the FXSAVE instruction like in 64 bit files.
@@ -103,6 +110,7 @@ constexpr RegsetDesc FPR_Desc[] = {
{llvm::Triple::Linux, llvm::Triple::x86, llvm::ELF::NT_PRXFPREG},
{llvm::Triple::Linux, llvm::Triple::UnknownArch, llvm::ELF::NT_FPREGSET},
{llvm::Triple::NetBSD, llvm::Triple::aarch64, NETBSD::AARCH64::NT_FPREGS},
+ {llvm::Triple::NetBSD, llvm::Triple::x86, NETBSD::I386::NT_FPREGS},
{llvm::Triple::NetBSD, llvm::Triple::x86_64, NETBSD::AMD64::NT_FPREGS},
{llvm::Triple::OpenBSD, llvm::Triple::UnknownArch, OPENBSD::NT_FPREGS},
};
@@ -111,6 +119,10 @@ constexpr RegsetDesc AARCH64_SVE_Desc[] = {
{llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_SVE},
};
+constexpr RegsetDesc AARCH64_PAC_Desc[] = {
+ {llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_PAC_MASK},
+};
+
constexpr RegsetDesc PPC_VMX_Desc[] = {
{llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX},
{llvm::Triple::Linux, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX},
diff --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
index 76c0c2843e6d..937d074869a2 100644
--- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
@@ -18,10 +18,9 @@
#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
-#include "Plugins/Process/Utility/RegisterContextLinux_mips.h"
-#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h"
#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h"
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
+#include "Plugins/Process/Utility/RegisterContextNetBSD_i386.h"
#include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h"
#include "Plugins/Process/Utility/RegisterContextOpenBSD_i386.h"
#include "Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h"
@@ -109,6 +108,9 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
switch (arch.GetMachine()) {
case llvm::Triple::aarch64:
break;
+ case llvm::Triple::x86:
+ reg_interface = new RegisterContextNetBSD_i386(arch);
+ break;
case llvm::Triple::x86_64:
reg_interface = new RegisterContextNetBSD_x86_64(arch);
break;
@@ -122,14 +124,6 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
switch (arch.GetMachine()) {
case llvm::Triple::aarch64:
break;
- case llvm::Triple::mipsel:
- case llvm::Triple::mips:
- reg_interface = new RegisterContextLinux_mips(arch);
- break;
- case llvm::Triple::mips64el:
- case llvm::Triple::mips64:
- reg_interface = new RegisterContextLinux_mips64(arch);
- break;
case llvm::Triple::ppc64le:
reg_interface = new RegisterInfoPOSIX_ppc64le(arch);
break;
@@ -177,9 +171,8 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
switch (arch.GetMachine()) {
case llvm::Triple::aarch64:
- m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm64>(
- *this, std::make_unique<RegisterInfoPOSIX_arm64>(arch),
- m_gpregset_data, m_notes);
+ m_thread_reg_ctx_sp = RegisterContextCorePOSIX_arm64::Create(
+ *this, arch, m_gpregset_data, m_notes);
break;
case llvm::Triple::arm:
m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm>(
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
index fdaa60e2df41..a4c71e864a76 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
@@ -20,7 +20,10 @@ using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
using namespace std::chrono;
-static const seconds kInterruptTimeout(5);
+// When we've sent a continue packet and are waiting for the target to stop,
+// we wake up the wait with this interval to make sure the stub hasn't gone
+// away while we were waiting.
+static const seconds kWakeupInterval(5);
/////////////////////////
// GDBRemoteClientBase //
@@ -35,7 +38,8 @@ GDBRemoteClientBase::GDBRemoteClientBase(const char *comm_name,
StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
ContinueDelegate &delegate, const UnixSignals &signals,
- llvm::StringRef payload, StringExtractorGDBRemote &response) {
+ llvm::StringRef payload, std::chrono::seconds interrupt_timeout,
+ StringExtractorGDBRemote &response) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
response.Clear();
@@ -48,16 +52,37 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
if (!cont_lock)
return eStateInvalid;
OnRunPacketSent(true);
-
+ // The main ReadPacket loop wakes up at computed_timeout intervals, just to
+ // check that the connection hasn't dropped. When we wake up we also check
+ // whether there is an interrupt request that has reached its endpoint.
+ // If we want a shorter interrupt timeout that kWakeupInterval, we need to
+ // choose the shorter interval for the wake up as well.
+ std::chrono::seconds computed_timeout = std::min(interrupt_timeout,
+ kWakeupInterval);
for (;;) {
- PacketResult read_result = ReadPacket(response, kInterruptTimeout, false);
+ PacketResult read_result = ReadPacket(response, computed_timeout, false);
+ // Reset the computed_timeout to the default value in case we are going
+ // round again.
+ computed_timeout = std::min(interrupt_timeout, kWakeupInterval);
switch (read_result) {
case PacketResult::ErrorReplyTimeout: {
std::lock_guard<std::mutex> lock(m_mutex);
- if (m_async_count == 0)
+ if (m_async_count == 0) {
continue;
- if (steady_clock::now() >= m_interrupt_time + kInterruptTimeout)
+ }
+ auto cur_time = steady_clock::now();
+ if (cur_time >= m_interrupt_endpoint)
return eStateInvalid;
+ else {
+ // We woke up and found an interrupt is in flight, but we haven't
+ // exceeded the interrupt wait time. So reset the wait time to the
+ // time left till the interrupt timeout. But don't wait longer
+ // than our wakeup timeout.
+ auto new_wait = m_interrupt_endpoint - cur_time;
+ computed_timeout = std::min(kWakeupInterval,
+ std::chrono::duration_cast<std::chrono::seconds>(new_wait));
+ continue;
+ }
break;
}
case PacketResult::Success:
@@ -133,8 +158,9 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
}
}
-bool GDBRemoteClientBase::SendAsyncSignal(int signo) {
- Lock lock(*this, true);
+bool GDBRemoteClientBase::SendAsyncSignal(
+ int signo, std::chrono::seconds interrupt_timeout) {
+ Lock lock(*this, interrupt_timeout);
if (!lock || !lock.DidInterrupt())
return false;
@@ -144,25 +170,26 @@ bool GDBRemoteClientBase::SendAsyncSignal(int signo) {
return true;
}
-bool GDBRemoteClientBase::Interrupt() {
- Lock lock(*this, true);
+bool GDBRemoteClientBase::Interrupt(std::chrono::seconds interrupt_timeout) {
+ Lock lock(*this, interrupt_timeout);
if (!lock.DidInterrupt())
return false;
m_should_stop = true;
return true;
}
+
GDBRemoteCommunication::PacketResult
GDBRemoteClientBase::SendPacketAndWaitForResponse(
llvm::StringRef payload, StringExtractorGDBRemote &response,
- bool send_async) {
- Lock lock(*this, send_async);
+ std::chrono::seconds interrupt_timeout) {
+ Lock lock(*this, interrupt_timeout);
if (!lock) {
if (Log *log =
ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS))
LLDB_LOGF(log,
"GDBRemoteClientBase::%s failed to get mutex, not sending "
- "packet '%.*s' (send_async=%d)",
- __FUNCTION__, int(payload.size()), payload.data(), send_async);
+ "packet '%.*s'",
+ __FUNCTION__, int(payload.size()), payload.data());
return PacketResult::ErrorSendFailed;
}
@@ -172,16 +199,16 @@ GDBRemoteClientBase::SendPacketAndWaitForResponse(
GDBRemoteCommunication::PacketResult
GDBRemoteClientBase::SendPacketAndReceiveResponseWithOutputSupport(
llvm::StringRef payload, StringExtractorGDBRemote &response,
- bool send_async,
+ std::chrono::seconds interrupt_timeout,
llvm::function_ref<void(llvm::StringRef)> output_callback) {
- Lock lock(*this, send_async);
+ Lock lock(*this, interrupt_timeout);
if (!lock) {
if (Log *log =
ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS))
LLDB_LOGF(log,
"GDBRemoteClientBase::%s failed to get mutex, not sending "
- "packet '%.*s' (send_async=%d)",
- __FUNCTION__, int(payload.size()), payload.data(), send_async);
+ "packet '%.*s'",
+ __FUNCTION__, int(payload.size()), payload.data());
return PacketResult::ErrorSendFailed;
}
@@ -222,13 +249,14 @@ GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock(
return packet_result;
}
-bool GDBRemoteClientBase::SendvContPacket(llvm::StringRef payload,
- StringExtractorGDBRemote &response) {
+bool GDBRemoteClientBase::SendvContPacket(
+ llvm::StringRef payload, std::chrono::seconds interrupt_timeout,
+ StringExtractorGDBRemote &response) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s ()", __FUNCTION__);
// we want to lock down packet sending while we continue
- Lock lock(*this, true);
+ Lock lock(*this, interrupt_timeout);
LLDB_LOGF(log,
"GDBRemoteCommunicationClient::%s () sending vCont packet: %.*s",
@@ -336,18 +364,20 @@ GDBRemoteClientBase::ContinueLock::lock() {
// GDBRemoteClientBase::Lock //
///////////////////////////////
-GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm, bool interrupt)
+GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm,
+ std::chrono::seconds interrupt_timeout)
: m_async_lock(comm.m_async_mutex, std::defer_lock), m_comm(comm),
- m_acquired(false), m_did_interrupt(false) {
- SyncWithContinueThread(interrupt);
+ m_interrupt_timeout(interrupt_timeout), m_acquired(false),
+ m_did_interrupt(false) {
+ SyncWithContinueThread();
if (m_acquired)
m_async_lock.lock();
}
-void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) {
+void GDBRemoteClientBase::Lock::SyncWithContinueThread() {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
std::unique_lock<std::mutex> lock(m_comm.m_mutex);
- if (m_comm.m_is_running && !interrupt)
+ if (m_comm.m_is_running && m_interrupt_timeout == std::chrono::seconds(0))
return; // We were asked to avoid interrupting the sender. Lock is not
// acquired.
@@ -365,9 +395,9 @@ void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) {
"interrupt packet");
return;
}
+ m_comm.m_interrupt_endpoint = steady_clock::now() + m_interrupt_timeout;
if (log)
log->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03");
- m_comm.m_interrupt_time = steady_clock::now();
}
m_comm.m_cv.wait(lock, [this] { return !m_comm.m_is_running; });
m_did_interrupt = true;
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
index cd9f6ebd7642..518b81318b6c 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
@@ -33,29 +33,46 @@ public:
GDBRemoteClientBase(const char *comm_name, const char *listener_name);
- bool SendAsyncSignal(int signo);
+ bool SendAsyncSignal(int signo, std::chrono::seconds interrupt_timeout);
- bool Interrupt();
+ bool Interrupt(std::chrono::seconds interrupt_timeout);
lldb::StateType SendContinuePacketAndWaitForResponse(
ContinueDelegate &delegate, const UnixSignals &signals,
- llvm::StringRef payload, StringExtractorGDBRemote &response);
+ llvm::StringRef payload, std::chrono::seconds interrupt_timeout,
+ StringExtractorGDBRemote &response);
- PacketResult SendPacketAndWaitForResponse(llvm::StringRef payload,
- StringExtractorGDBRemote &response,
- bool send_async);
+ // If interrupt_timeout == 0 seconds, don't interrupt the target.
+ // Only send the packet if the target is stopped.
+ // If you want to use this mode, use the fact that the timeout is defaulted
+ // so it's clear from the call-site that you are using no-interrupt.
+ // If it is non-zero, interrupt the target if it is running, and
+ // send the packet.
+ // It the target doesn't respond within the given timeout, it returns
+ // ErrorReplyTimeout.
+ PacketResult SendPacketAndWaitForResponse(
+ llvm::StringRef payload, StringExtractorGDBRemote &response,
+ std::chrono::seconds interrupt_timeout = std::chrono::seconds(0));
PacketResult SendPacketAndReceiveResponseWithOutputSupport(
llvm::StringRef payload, StringExtractorGDBRemote &response,
- bool send_async,
+ std::chrono::seconds interrupt_timeout,
llvm::function_ref<void(llvm::StringRef)> output_callback);
bool SendvContPacket(llvm::StringRef payload,
+ std::chrono::seconds interrupt_timeout,
StringExtractorGDBRemote &response);
class Lock {
public:
- Lock(GDBRemoteClientBase &comm, bool interrupt);
+ // If interrupt_timeout == 0 seconds, only take the lock if the target is
+ // not running. If using this option, use the fact that the
+ // interrupt_timeout is defaulted so it will be obvious at the call site
+ // that you are choosing this mode. If it is non-zero, interrupt the target
+ // if it is running, waiting for the given timeout for the interrupt to
+ // succeed.
+ Lock(GDBRemoteClientBase &comm,
+ std::chrono::seconds interrupt_timeout = std::chrono::seconds(0));
~Lock();
explicit operator bool() { return m_acquired; }
@@ -67,10 +84,11 @@ public:
private:
std::unique_lock<std::recursive_mutex> m_async_lock;
GDBRemoteClientBase &m_comm;
+ std::chrono::seconds m_interrupt_timeout;
bool m_acquired;
bool m_did_interrupt;
- void SyncWithContinueThread(bool interrupt);
+ void SyncWithContinueThread();
};
protected:
@@ -109,7 +127,7 @@ private:
/// When was the interrupt packet sent. Used to make sure we time out if the
/// stub does not respond to interrupt requests.
- std::chrono::time_point<std::chrono::steady_clock> m_interrupt_time;
+ std::chrono::time_point<std::chrono::steady_clock> m_interrupt_endpoint;
/// Number of threads interested in sending.
uint32_t m_async_count;
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 4981345d6a18..013d407c0fc1 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -8,9 +8,9 @@
#include "GDBRemoteCommunication.h"
+#include <climits>
+#include <cstring>
#include <future>
-#include <limits.h>
-#include <string.h>
#include <sys/stat.h>
#include "lldb/Core/StreamFile.h"
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index d375a312ae2c..b16aed4f5c90 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -8,7 +8,7 @@
#include "GDBRemoteCommunicationClient.h"
-#include <math.h>
+#include <cmath>
#include <sys/stat.h>
#include <numeric>
@@ -16,6 +16,7 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/StringConvert.h"
#include "lldb/Host/XML.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/MemoryRegionInfo.h"
@@ -55,40 +56,7 @@ llvm::raw_ostream &process_gdb_remote::operator<<(llvm::raw_ostream &os,
// GDBRemoteCommunicationClient constructor
GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
: GDBRemoteClientBase("gdb-remote.client", "gdb-remote.client.rx_packet"),
- m_supports_not_sending_acks(eLazyBoolCalculate),
- m_supports_thread_suffix(eLazyBoolCalculate),
- m_supports_threads_in_stop_reply(eLazyBoolCalculate),
- m_supports_vCont_all(eLazyBoolCalculate),
- m_supports_vCont_any(eLazyBoolCalculate),
- m_supports_vCont_c(eLazyBoolCalculate),
- m_supports_vCont_C(eLazyBoolCalculate),
- m_supports_vCont_s(eLazyBoolCalculate),
- m_supports_vCont_S(eLazyBoolCalculate),
- m_qHostInfo_is_valid(eLazyBoolCalculate),
- m_curr_pid_is_valid(eLazyBoolCalculate),
- m_qProcessInfo_is_valid(eLazyBoolCalculate),
- m_qGDBServerVersion_is_valid(eLazyBoolCalculate),
- m_supports_alloc_dealloc_memory(eLazyBoolCalculate),
- m_supports_memory_region_info(eLazyBoolCalculate),
- m_supports_watchpoint_support_info(eLazyBoolCalculate),
- m_supports_detach_stay_stopped(eLazyBoolCalculate),
- m_watchpoints_trigger_after_instruction(eLazyBoolCalculate),
- m_attach_or_wait_reply(eLazyBoolCalculate),
- m_prepare_for_reg_writing_reply(eLazyBoolCalculate),
- m_supports_p(eLazyBoolCalculate), m_supports_x(eLazyBoolCalculate),
- m_avoid_g_packets(eLazyBoolCalculate),
- m_supports_QSaveRegisterState(eLazyBoolCalculate),
- m_supports_qXfer_auxv_read(eLazyBoolCalculate),
- m_supports_qXfer_libraries_read(eLazyBoolCalculate),
- m_supports_qXfer_libraries_svr4_read(eLazyBoolCalculate),
- m_supports_qXfer_features_read(eLazyBoolCalculate),
- m_supports_qXfer_memory_map_read(eLazyBoolCalculate),
- m_supports_augmented_libraries_svr4_read(eLazyBoolCalculate),
- m_supports_jThreadExtendedInfo(eLazyBoolCalculate),
- m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate),
- m_supports_jGetSharedCacheInfo(eLazyBoolCalculate),
- m_supports_QPassSignals(eLazyBoolCalculate),
- m_supports_error_string_reply(eLazyBoolCalculate),
+
m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true),
m_supports_qUserName(true), m_supports_qGroupName(true),
m_supports_qThreadStopInfo(true), m_supports_z0(true),
@@ -97,15 +65,11 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
m_supports_QEnvironmentHexEncoded(true), m_supports_qSymbol(true),
m_qSymbol_requests_done(false), m_supports_qModuleInfo(true),
m_supports_jThreadsInfo(true), m_supports_jModulesInfo(true),
- m_curr_pid(LLDB_INVALID_PROCESS_ID), m_curr_tid(LLDB_INVALID_THREAD_ID),
- m_curr_tid_run(LLDB_INVALID_THREAD_ID),
- m_num_supported_hardware_watchpoints(0), m_host_arch(), m_process_arch(),
- m_os_build(), m_os_kernel(), m_hostname(), m_gdb_server_name(),
- m_gdb_server_version(UINT32_MAX), m_default_packet_timeout(0),
- m_max_packet_size(0), m_qSupported_response(),
- m_supported_async_json_packets_is_valid(false),
- m_supported_async_json_packets_sp(), m_qXfer_memory_map(),
- m_qXfer_memory_map_loaded(false) {}
+
+ m_host_arch(), m_process_arch(), m_os_build(), m_os_kernel(),
+ m_hostname(), m_gdb_server_name(), m_default_packet_timeout(0),
+ m_qSupported_response(), m_supported_async_json_packets_sp(),
+ m_qXfer_memory_map() {}
// Destructor
GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient() {
@@ -218,7 +182,7 @@ bool GDBRemoteCommunicationClient::QueryNoAckModeSupported() {
ScopedTimeout timeout(*this, std::max(GetPacketTimeout(), seconds(6)));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false) ==
+ if (SendPacketAndWaitForResponse("QStartNoAckMode", response) ==
PacketResult::Success) {
if (response.IsOKResponse()) {
m_send_acks = false;
@@ -235,8 +199,8 @@ void GDBRemoteCommunicationClient::GetListThreadsInStopReplySupported() {
m_supports_threads_in_stop_reply = eLazyBoolNo;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response,
- false) == PacketResult::Success) {
+ if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response) ==
+ PacketResult::Success) {
if (response.IsOKResponse())
m_supports_threads_in_stop_reply = eLazyBoolYes;
}
@@ -248,8 +212,8 @@ bool GDBRemoteCommunicationClient::GetVAttachOrWaitSupported() {
m_attach_or_wait_reply = eLazyBoolNo;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response,
- false) == PacketResult::Success) {
+ if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response) ==
+ PacketResult::Success) {
if (response.IsOKResponse())
m_attach_or_wait_reply = eLazyBoolYes;
}
@@ -262,8 +226,8 @@ bool GDBRemoteCommunicationClient::GetSyncThreadStateSupported() {
m_prepare_for_reg_writing_reply = eLazyBoolNo;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response,
- false) == PacketResult::Success) {
+ if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response) ==
+ PacketResult::Success) {
if (response.IsOKResponse())
m_prepare_for_reg_writing_reply = eLazyBoolYes;
}
@@ -292,6 +256,7 @@ void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
m_prepare_for_reg_writing_reply = eLazyBoolCalculate;
m_attach_or_wait_reply = eLazyBoolCalculate;
m_avoid_g_packets = eLazyBoolCalculate;
+ m_supports_multiprocess = eLazyBoolCalculate;
m_supports_qXfer_auxv_read = eLazyBoolCalculate;
m_supports_qXfer_libraries_read = eLazyBoolCalculate;
m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
@@ -321,6 +286,7 @@ void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
m_gdb_server_name.clear();
m_gdb_server_version = UINT32_MAX;
m_default_packet_timeout = seconds(0);
+ m_target_vm_page_size = 0;
m_max_packet_size = 0;
m_qSupported_response.clear();
m_supported_async_json_packets_is_valid = false;
@@ -342,11 +308,17 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
m_supports_augmented_libraries_svr4_read = eLazyBoolNo;
m_supports_qXfer_features_read = eLazyBoolNo;
m_supports_qXfer_memory_map_read = eLazyBoolNo;
+ m_supports_multiprocess = eLazyBoolNo;
+ m_supports_qEcho = eLazyBoolNo;
+ m_supports_QPassSignals = eLazyBoolNo;
+ m_supports_memory_tagging = eLazyBoolNo;
+
m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if
// not, we assume no limit
// build the qSupported packet
- std::vector<std::string> features = {"xmlRegisters=i386,arm,mips,arc"};
+ std::vector<std::string> features = {"xmlRegisters=i386,arm,mips,arc",
+ "multiprocess+"};
StreamString packet;
packet.PutCString("qSupported");
for (uint32_t i = 0; i < features.size(); ++i) {
@@ -355,97 +327,57 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
}
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response,
- /*send_async=*/false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
- const char *response_cstr = response.GetStringRef().data();
-
// Hang on to the qSupported packet, so that platforms can do custom
// configuration of the transport before attaching/launching the process.
- m_qSupported_response = response_cstr;
+ m_qSupported_response = response.GetStringRef().str();
- if (::strstr(response_cstr, "qXfer:auxv:read+"))
- m_supports_qXfer_auxv_read = eLazyBoolYes;
- if (::strstr(response_cstr, "qXfer:libraries-svr4:read+"))
- m_supports_qXfer_libraries_svr4_read = eLazyBoolYes;
- if (::strstr(response_cstr, "augmented-libraries-svr4-read")) {
- m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; // implied
- m_supports_augmented_libraries_svr4_read = eLazyBoolYes;
- }
- if (::strstr(response_cstr, "qXfer:libraries:read+"))
- m_supports_qXfer_libraries_read = eLazyBoolYes;
- if (::strstr(response_cstr, "qXfer:features:read+"))
- m_supports_qXfer_features_read = eLazyBoolYes;
- if (::strstr(response_cstr, "qXfer:memory-map:read+"))
- m_supports_qXfer_memory_map_read = eLazyBoolYes;
-
- // Look for a list of compressions in the features list e.g.
- // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-
- // deflate,lzma
- const char *features_list = ::strstr(response_cstr, "qXfer:features:");
- if (features_list) {
- const char *compressions =
- ::strstr(features_list, "SupportedCompressions=");
- if (compressions) {
- std::vector<std::string> supported_compressions;
- compressions += sizeof("SupportedCompressions=") - 1;
- const char *end_of_compressions = strchr(compressions, ';');
- if (end_of_compressions == nullptr) {
- end_of_compressions = strchr(compressions, '\0');
- }
- const char *current_compression = compressions;
- while (current_compression < end_of_compressions) {
- const char *next_compression_name = strchr(current_compression, ',');
- const char *end_of_this_word = next_compression_name;
- if (next_compression_name == nullptr ||
- end_of_compressions < next_compression_name) {
- end_of_this_word = end_of_compressions;
- }
+ llvm::SmallVector<llvm::StringRef, 16> server_features;
+ response.GetStringRef().split(server_features, ';');
- if (end_of_this_word) {
- if (end_of_this_word == current_compression) {
- current_compression++;
- } else {
- std::string this_compression(
- current_compression, end_of_this_word - current_compression);
- supported_compressions.push_back(this_compression);
- current_compression = end_of_this_word + 1;
- }
- } else {
- supported_compressions.push_back(current_compression);
- current_compression = end_of_compressions;
- }
- }
-
- if (supported_compressions.size() > 0) {
- MaybeEnableCompression(supported_compressions);
+ for (llvm::StringRef x : server_features) {
+ if (x == "qXfer:auxv:read+")
+ m_supports_qXfer_auxv_read = eLazyBoolYes;
+ else if (x == "qXfer:libraries-svr4:read+")
+ m_supports_qXfer_libraries_svr4_read = eLazyBoolYes;
+ else if (x == "augmented-libraries-svr4-read") {
+ m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; // implied
+ m_supports_augmented_libraries_svr4_read = eLazyBoolYes;
+ } else if (x == "qXfer:libraries:read+")
+ m_supports_qXfer_libraries_read = eLazyBoolYes;
+ else if (x == "qXfer:features:read+")
+ m_supports_qXfer_features_read = eLazyBoolYes;
+ else if (x == "qXfer:memory-map:read+")
+ m_supports_qXfer_memory_map_read = eLazyBoolYes;
+ else if (x == "qEcho")
+ m_supports_qEcho = eLazyBoolYes;
+ else if (x == "QPassSignals+")
+ m_supports_QPassSignals = eLazyBoolYes;
+ else if (x == "multiprocess+")
+ m_supports_multiprocess = eLazyBoolYes;
+ else if (x == "memory-tagging+")
+ m_supports_memory_tagging = eLazyBoolYes;
+ // Look for a list of compressions in the features list e.g.
+ // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-
+ // deflate,lzma
+ else if (x.consume_front("SupportedCompressions=")) {
+ llvm::SmallVector<llvm::StringRef, 4> compressions;
+ x.split(compressions, ',');
+ if (!compressions.empty())
+ MaybeEnableCompression(compressions);
+ } else if (x.consume_front("PacketSize=")) {
+ StringExtractorGDBRemote packet_response(x);
+ m_max_packet_size =
+ packet_response.GetHexMaxU64(/*little_endian=*/false, UINT64_MAX);
+ if (m_max_packet_size == 0) {
+ m_max_packet_size = UINT64_MAX; // Must have been a garbled response
+ Log *log(
+ ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ LLDB_LOGF(log, "Garbled PacketSize spec in qSupported response");
}
}
}
-
- if (::strstr(response_cstr, "qEcho"))
- m_supports_qEcho = eLazyBoolYes;
- else
- m_supports_qEcho = eLazyBoolNo;
-
- if (::strstr(response_cstr, "QPassSignals+"))
- m_supports_QPassSignals = eLazyBoolYes;
- else
- m_supports_QPassSignals = eLazyBoolNo;
-
- const char *packet_size_str = ::strstr(response_cstr, "PacketSize=");
- if (packet_size_str) {
- StringExtractorGDBRemote packet_response(packet_size_str +
- strlen("PacketSize="));
- m_max_packet_size =
- packet_response.GetHexMaxU64(/*little_endian=*/false, UINT64_MAX);
- if (m_max_packet_size == 0) {
- m_max_packet_size = UINT64_MAX; // Must have been a garbled response
- Log *log(
- ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- LLDB_LOGF(log, "Garbled PacketSize spec in qSupported response");
- }
- }
}
}
@@ -453,8 +385,8 @@ bool GDBRemoteCommunicationClient::GetThreadSuffixSupported() {
if (m_supports_thread_suffix == eLazyBoolCalculate) {
StringExtractorGDBRemote response;
m_supports_thread_suffix = eLazyBoolNo;
- if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response,
- false) == PacketResult::Success) {
+ if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response) ==
+ PacketResult::Success) {
if (response.IsOKResponse())
m_supports_thread_suffix = eLazyBoolYes;
}
@@ -470,7 +402,7 @@ bool GDBRemoteCommunicationClient::GetVContSupported(char flavor) {
m_supports_vCont_C = eLazyBoolNo;
m_supports_vCont_s = eLazyBoolNo;
m_supports_vCont_S = eLazyBoolNo;
- if (SendPacketAndWaitForResponse("vCont?", response, false) ==
+ if (SendPacketAndWaitForResponse("vCont?", response) ==
PacketResult::Success) {
const char *response_cstr = response.GetStringRef().data();
if (::strstr(response_cstr, ";c"))
@@ -522,9 +454,9 @@ bool GDBRemoteCommunicationClient::GetVContSupported(char flavor) {
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse(
- lldb::tid_t tid, StreamString &&payload, StringExtractorGDBRemote &response,
- bool send_async) {
- Lock lock(*this, send_async);
+ lldb::tid_t tid, StreamString &&payload,
+ StringExtractorGDBRemote &response) {
+ Lock lock(*this);
if (!lock) {
if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(
GDBR_LOG_PROCESS | GDBR_LOG_PACKETS))
@@ -561,7 +493,7 @@ LazyBool GDBRemoteCommunicationClient::GetThreadPacketSupported(
payload.PutCString(packetStr);
StringExtractorGDBRemote response;
if (SendThreadSpecificPacketAndWaitForResponse(
- tid, std::move(payload), response, false) == PacketResult::Success &&
+ tid, std::move(payload), response) == PacketResult::Success &&
response.IsNormalResponse()) {
return eLazyBoolYes;
}
@@ -575,7 +507,7 @@ StructuredData::ObjectSP GDBRemoteCommunicationClient::GetThreadsInfo() {
if (m_supports_jThreadsInfo) {
StringExtractorGDBRemote response;
response.SetResponseValidatorToJSON();
- if (SendPacketAndWaitForResponse("jThreadsInfo", response, false) ==
+ if (SendPacketAndWaitForResponse("jThreadsInfo", response) ==
PacketResult::Success) {
if (response.IsUnsupportedResponse()) {
m_supports_jThreadsInfo = false;
@@ -592,7 +524,7 @@ bool GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported() {
if (m_supports_jThreadExtendedInfo == eLazyBoolCalculate) {
StringExtractorGDBRemote response;
m_supports_jThreadExtendedInfo = eLazyBoolNo;
- if (SendPacketAndWaitForResponse("jThreadExtendedInfo:", response, false) ==
+ if (SendPacketAndWaitForResponse("jThreadExtendedInfo:", response) ==
PacketResult::Success) {
if (response.IsOKResponse()) {
m_supports_jThreadExtendedInfo = eLazyBoolYes;
@@ -608,7 +540,7 @@ void GDBRemoteCommunicationClient::EnableErrorStringInPacket() {
// We try to enable error strings in remote packets but if we fail, we just
// work in the older way.
m_supports_error_string_reply = eLazyBoolNo;
- if (SendPacketAndWaitForResponse("QEnableErrorStrings", response, false) ==
+ if (SendPacketAndWaitForResponse("QEnableErrorStrings", response) ==
PacketResult::Success) {
if (response.IsOKResponse()) {
m_supports_error_string_reply = eLazyBoolYes;
@@ -622,8 +554,7 @@ bool GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported() {
StringExtractorGDBRemote response;
m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolNo;
if (SendPacketAndWaitForResponse("jGetLoadedDynamicLibrariesInfos:",
- response,
- false) == PacketResult::Success) {
+ response) == PacketResult::Success) {
if (response.IsOKResponse()) {
m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolYes;
}
@@ -636,7 +567,7 @@ bool GDBRemoteCommunicationClient::GetSharedCacheInfoSupported() {
if (m_supports_jGetSharedCacheInfo == eLazyBoolCalculate) {
StringExtractorGDBRemote response;
m_supports_jGetSharedCacheInfo = eLazyBoolNo;
- if (SendPacketAndWaitForResponse("jGetSharedCacheInfo:", response, false) ==
+ if (SendPacketAndWaitForResponse("jGetSharedCacheInfo:", response) ==
PacketResult::Success) {
if (response.IsOKResponse()) {
m_supports_jGetSharedCacheInfo = eLazyBoolYes;
@@ -646,13 +577,82 @@ bool GDBRemoteCommunicationClient::GetSharedCacheInfoSupported() {
return m_supports_jGetSharedCacheInfo;
}
+bool GDBRemoteCommunicationClient::GetMemoryTaggingSupported() {
+ if (m_supports_memory_tagging == eLazyBoolCalculate) {
+ GetRemoteQSupported();
+ }
+ return m_supports_memory_tagging == eLazyBoolYes;
+}
+
+DataBufferSP GDBRemoteCommunicationClient::ReadMemoryTags(lldb::addr_t addr,
+ size_t len,
+ int32_t type) {
+ StreamString packet;
+ packet.Printf("qMemTags:%" PRIx64 ",%zx:%" PRIx32, addr, len, type);
+ StringExtractorGDBRemote response;
+
+ Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_MEMORY);
+
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
+ PacketResult::Success ||
+ !response.IsNormalResponse()) {
+ LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s: qMemTags packet failed",
+ __FUNCTION__);
+ return nullptr;
+ }
+
+ // We are expecting
+ // m<hex encoded bytes>
+
+ if (response.GetChar() != 'm') {
+ LLDB_LOGF(log,
+ "GDBRemoteCommunicationClient::%s: qMemTags response did not "
+ "begin with \"m\"",
+ __FUNCTION__);
+ return nullptr;
+ }
+
+ size_t expected_bytes = response.GetBytesLeft() / 2;
+ DataBufferSP buffer_sp(new DataBufferHeap(expected_bytes, 0));
+ size_t got_bytes = response.GetHexBytesAvail(buffer_sp->GetData());
+ // Check both because in some situations chars are consumed even
+ // if the decoding fails.
+ if (response.GetBytesLeft() || (expected_bytes != got_bytes)) {
+ LLDB_LOGF(
+ log,
+ "GDBRemoteCommunicationClient::%s: Invalid data in qMemTags response",
+ __FUNCTION__);
+ return nullptr;
+ }
+
+ return buffer_sp;
+}
+
+Status GDBRemoteCommunicationClient::WriteMemoryTags(
+ lldb::addr_t addr, size_t len, int32_t type,
+ const std::vector<uint8_t> &tags) {
+ // Format QMemTags:address,length:type:tags
+ StreamString packet;
+ packet.Printf("QMemTags:%" PRIx64 ",%zx:%" PRIx32 ":", addr, len, type);
+ packet.PutBytesAsRawHex8(tags.data(), tags.size());
+
+ Status status;
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
+ PacketResult::Success ||
+ !response.IsOKResponse()) {
+ status.SetErrorString("QMemTags packet failed");
+ }
+ return status;
+}
+
bool GDBRemoteCommunicationClient::GetxPacketSupported() {
if (m_supports_x == eLazyBoolCalculate) {
StringExtractorGDBRemote response;
m_supports_x = eLazyBoolNo;
char packet[256];
snprintf(packet, sizeof(packet), "x0,0");
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success) {
if (response.IsOKResponse())
m_supports_x = eLazyBoolYes;
@@ -664,7 +664,7 @@ bool GDBRemoteCommunicationClient::GetxPacketSupported() {
GDBRemoteCommunicationClient::PacketResult
GDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses(
const char *payload_prefix, std::string &response_string) {
- Lock lock(*this, false);
+ Lock lock(*this);
if (!lock) {
Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS |
GDBR_LOG_PACKETS));
@@ -725,11 +725,11 @@ lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) {
// the thread id, which newer debugserver and lldb-gdbserver stubs return
// correctly.
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qC", response, false) ==
- PacketResult::Success) {
+ if (SendPacketAndWaitForResponse("qC", response) == PacketResult::Success) {
if (response.GetChar() == 'Q') {
if (response.GetChar() == 'C') {
- m_curr_pid = response.GetHexMaxU32(false, LLDB_INVALID_PROCESS_ID);
+ m_curr_pid_run = m_curr_pid =
+ response.GetHexMaxU64(false, LLDB_INVALID_PROCESS_ID);
if (m_curr_pid != LLDB_INVALID_PROCESS_ID) {
m_curr_pid_is_valid = eLazyBoolYes;
return m_curr_pid;
@@ -741,12 +741,14 @@ lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) {
// If we don't get a response for $qC, check if $qfThreadID gives us a
// result.
if (m_curr_pid == LLDB_INVALID_PROCESS_ID) {
- std::vector<lldb::tid_t> thread_ids;
bool sequence_mutex_unavailable;
- size_t size;
- size = GetCurrentThreadIDs(thread_ids, sequence_mutex_unavailable);
- if (size && !sequence_mutex_unavailable) {
- m_curr_pid = thread_ids.front();
+ auto ids = GetCurrentProcessAndThreadIDs(sequence_mutex_unavailable);
+ if (!ids.empty() && !sequence_mutex_unavailable) {
+ // If server returned an explicit PID, use that.
+ m_curr_pid_run = m_curr_pid = ids.front().first;
+ // Otherwise, use the TID of the first thread (Linux hack).
+ if (m_curr_pid == LLDB_INVALID_PROCESS_ID)
+ m_curr_pid_run = m_curr_pid = ids.front().second;
m_curr_pid_is_valid = eLazyBoolYes;
return m_curr_pid;
}
@@ -759,7 +761,7 @@ lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) {
bool GDBRemoteCommunicationClient::GetLaunchSuccess(std::string &error_str) {
error_str.clear();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qLaunchSuccess", response, false) ==
+ if (SendPacketAndWaitForResponse("qLaunchSuccess", response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return true;
@@ -813,7 +815,7 @@ int GDBRemoteCommunicationClient::SendArgumentsPacket(
}
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return 0;
@@ -863,7 +865,7 @@ int GDBRemoteCommunicationClient::SendEnvironmentPacket(
if (m_supports_QEnvironmentHexEncoded) {
packet.PutCString("QEnvironmentHexEncoded:");
packet.PutBytesAsRawHex8(name_equal_value, strlen(name_equal_value));
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return 0;
@@ -877,7 +879,7 @@ int GDBRemoteCommunicationClient::SendEnvironmentPacket(
} else if (m_supports_QEnvironment) {
packet.Printf("QEnvironment:%s", name_equal_value);
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return 0;
@@ -897,7 +899,7 @@ int GDBRemoteCommunicationClient::SendLaunchArchPacket(char const *arch) {
StreamString packet;
packet.Printf("QLaunchArch:%s", arch);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return 0;
@@ -915,7 +917,7 @@ int GDBRemoteCommunicationClient::SendLaunchEventDataPacket(
StreamString packet;
packet.Printf("QSetProcessEvent:%s", data);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse()) {
if (was_supported)
@@ -1000,7 +1002,7 @@ bool GDBRemoteCommunicationClient::GetGDBServerVersion() {
m_qGDBServerVersion_is_valid = eLazyBoolNo;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qGDBServerVersion", response, false) ==
+ if (SendPacketAndWaitForResponse("qGDBServerVersion", response) ==
PacketResult::Success) {
if (response.IsNormalResponse()) {
llvm::StringRef name, value;
@@ -1025,9 +1027,9 @@ bool GDBRemoteCommunicationClient::GetGDBServerVersion() {
}
void GDBRemoteCommunicationClient::MaybeEnableCompression(
- std::vector<std::string> supported_compressions) {
+ llvm::ArrayRef<llvm::StringRef> supported_compressions) {
CompressionType avail_type = CompressionType::None;
- std::string avail_name;
+ llvm::StringRef avail_name;
#if defined(HAVE_LIBCOMPRESSION)
if (avail_type == CompressionType::None) {
@@ -1091,8 +1093,8 @@ void GDBRemoteCommunicationClient::MaybeEnableCompression(
if (avail_type != CompressionType::None) {
StringExtractorGDBRemote response;
- std::string packet = "QEnableCompression:type:" + avail_name + ";";
- if (SendPacketAndWaitForResponse(packet, response, false) !=
+ llvm::Twine packet = "QEnableCompression:type:" + avail_name + ";";
+ if (SendPacketAndWaitForResponse(packet.str(), response) !=
PacketResult::Success)
return;
@@ -1118,15 +1120,29 @@ uint32_t GDBRemoteCommunicationClient::GetGDBServerProgramVersion() {
bool GDBRemoteCommunicationClient::GetDefaultThreadId(lldb::tid_t &tid) {
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qC", response, false) !=
- PacketResult::Success)
+ if (SendPacketAndWaitForResponse("qC", response) != PacketResult::Success)
return false;
if (!response.IsNormalResponse())
return false;
- if (response.GetChar() == 'Q' && response.GetChar() == 'C')
- tid = response.GetHexMaxU32(true, -1);
+ if (response.GetChar() == 'Q' && response.GetChar() == 'C') {
+ auto pid_tid = response.GetPidTid(0);
+ if (!pid_tid)
+ return false;
+
+ lldb::pid_t pid = pid_tid->first;
+ // invalid
+ if (pid == StringExtractorGDBRemote::AllProcesses)
+ return false;
+
+ // if we get pid as well, update m_curr_pid
+ if (pid != 0) {
+ m_curr_pid_run = m_curr_pid = pid;
+ m_curr_pid_is_valid = eLazyBoolYes;
+ }
+ tid = pid_tid->second;
+ }
return true;
}
@@ -1154,7 +1170,7 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) {
ScopedTimeout timeout(*this, seconds(10));
m_qHostInfo_is_valid = eLazyBoolNo;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qHostInfo", response, false) ==
+ if (SendPacketAndWaitForResponse("qHostInfo", response) ==
PacketResult::Success) {
if (response.IsNormalResponse()) {
llvm::StringRef name;
@@ -1219,11 +1235,13 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) {
} else if (name.equals("ptrsize")) {
if (!value.getAsInteger(0, pointer_byte_size))
++num_keys_decoded;
+ } else if (name.equals("addressing_bits")) {
+ if (!value.getAsInteger(0, m_addressing_bits))
+ ++num_keys_decoded;
} else if (name.equals("os_version") ||
- name.equals(
- "version")) // Older debugserver binaries used the
- // "version" key instead of
- // "os_version"...
+ name.equals("version")) // Older debugserver binaries used
+ // the "version" key instead of
+ // "os_version"...
{
if (!m_os_version.tryParse(value))
++num_keys_decoded;
@@ -1245,6 +1263,12 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) {
SetPacketTimeout(m_default_packet_timeout);
++num_keys_decoded;
}
+ } else if (name.equals("vm-page-size")) {
+ int page_size;
+ if (!value.getAsInteger(0, page_size)) {
+ m_target_vm_page_size = page_size;
+ ++num_keys_decoded;
+ }
}
}
@@ -1344,7 +1368,7 @@ int GDBRemoteCommunicationClient::SendAttach(
::snprintf(packet, sizeof(packet), "vAttach;%" PRIx64, pid);
UNUSED_IF_ASSERT_DISABLED(packet_len);
assert(packet_len < (int)sizeof(packet));
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success) {
if (response.IsErrorResponse())
return response.GetError();
@@ -1360,7 +1384,7 @@ int GDBRemoteCommunicationClient::SendStdinNotification(const char *data,
packet.PutCString("I");
packet.PutBytesAsRawHex8(data, data_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
return 0;
}
@@ -1374,6 +1398,11 @@ GDBRemoteCommunicationClient::GetHostArchitecture() {
return m_host_arch;
}
+uint32_t GDBRemoteCommunicationClient::GetAddressingBits() {
+ if (m_qHostInfo_is_valid == eLazyBoolCalculate)
+ GetHostInfo();
+ return m_addressing_bits;
+}
seconds GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout() {
if (m_qHostInfo_is_valid == eLazyBoolCalculate)
GetHostInfo();
@@ -1393,7 +1422,7 @@ addr_t GDBRemoteCommunicationClient::AllocateMemory(size_t size,
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success) {
if (response.IsUnsupportedResponse())
m_supports_alloc_dealloc_memory = eLazyBoolNo;
@@ -1415,7 +1444,7 @@ bool GDBRemoteCommunicationClient::DeallocateMemory(addr_t addr) {
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success) {
if (response.IsUnsupportedResponse())
m_supports_alloc_dealloc_memory = eLazyBoolNo;
@@ -1439,7 +1468,7 @@ Status GDBRemoteCommunicationClient::Detach(bool keep_stopped) {
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success &&
response.IsOKResponse()) {
m_supports_detach_stay_stopped = eLazyBoolYes;
@@ -1453,15 +1482,13 @@ Status GDBRemoteCommunicationClient::Detach(bool keep_stopped) {
return error;
} else {
StringExtractorGDBRemote response;
- PacketResult packet_result =
- SendPacketAndWaitForResponse("D1", response, false);
+ PacketResult packet_result = SendPacketAndWaitForResponse("D1", response);
if (packet_result != PacketResult::Success)
error.SetErrorString("Sending extended disconnect packet failed.");
}
} else {
StringExtractorGDBRemote response;
- PacketResult packet_result =
- SendPacketAndWaitForResponse("D", response, false);
+ PacketResult packet_result = SendPacketAndWaitForResponse("D", response);
if (packet_result != PacketResult::Success)
error.SetErrorString("Sending disconnect packet failed.");
}
@@ -1481,7 +1508,7 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success &&
response.GetResponseType() == StringExtractorGDBRemote::eResponse) {
llvm::StringRef name;
@@ -1551,9 +1578,30 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
// Now convert the HEX bytes into a string value
error_extractor.GetHexByteString(error_string);
error.SetErrorString(error_string.c_str());
+ } else if (name.equals("dirty-pages")) {
+ std::vector<addr_t> dirty_page_list;
+ std::string comma_sep_str = value.str();
+ size_t comma_pos;
+ addr_t page;
+ while ((comma_pos = comma_sep_str.find(',')) != std::string::npos) {
+ comma_sep_str[comma_pos] = '\0';
+ page = StringConvert::ToUInt64(comma_sep_str.c_str(),
+ LLDB_INVALID_ADDRESS, 16);
+ if (page != LLDB_INVALID_ADDRESS)
+ dirty_page_list.push_back(page);
+ comma_sep_str.erase(0, comma_pos + 1);
+ }
+ page = StringConvert::ToUInt64(comma_sep_str.c_str(),
+ LLDB_INVALID_ADDRESS, 16);
+ if (page != LLDB_INVALID_ADDRESS)
+ dirty_page_list.push_back(page);
+ region_info.SetDirtyPageList(dirty_page_list);
}
}
+ if (m_target_vm_page_size != 0)
+ region_info.SetPageSize(m_target_vm_page_size);
+
if (region_info.GetRange().IsValid()) {
// We got a valid address range back but no permissions -- which means
// this is an unmapped page
@@ -1718,8 +1766,8 @@ Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo(uint32_t &num) {
num = 0;
if (m_supports_watchpoint_support_info != eLazyBoolNo) {
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qWatchpointSupportInfo:", response,
- false) == PacketResult::Success) {
+ if (SendPacketAndWaitForResponse("qWatchpointSupportInfo:", response) ==
+ PacketResult::Success) {
m_supports_watchpoint_support_info = eLazyBoolYes;
llvm::StringRef name;
llvm::StringRef value;
@@ -1787,7 +1835,7 @@ int GDBRemoteCommunicationClient::SetSTDIN(const FileSpec &file_spec) {
packet.PutStringAsRawHex8(path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return 0;
@@ -1807,7 +1855,7 @@ int GDBRemoteCommunicationClient::SetSTDOUT(const FileSpec &file_spec) {
packet.PutStringAsRawHex8(path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return 0;
@@ -1827,7 +1875,7 @@ int GDBRemoteCommunicationClient::SetSTDERR(const FileSpec &file_spec) {
packet.PutStringAsRawHex8(path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return 0;
@@ -1841,7 +1889,7 @@ int GDBRemoteCommunicationClient::SetSTDERR(const FileSpec &file_spec) {
bool GDBRemoteCommunicationClient::GetWorkingDir(FileSpec &working_dir) {
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qGetWorkingDir", response, false) ==
+ if (SendPacketAndWaitForResponse("qGetWorkingDir", response) ==
PacketResult::Success) {
if (response.IsUnsupportedResponse())
return false;
@@ -1863,7 +1911,7 @@ int GDBRemoteCommunicationClient::SetWorkingDir(const FileSpec &working_dir) {
packet.PutStringAsRawHex8(path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return 0;
@@ -1882,8 +1930,7 @@ int GDBRemoteCommunicationClient::SetDisableASLR(bool enable) {
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
- PacketResult::Success) {
+ if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) {
if (response.IsOKResponse())
return 0;
uint8_t error = response.GetError();
@@ -1900,8 +1947,7 @@ int GDBRemoteCommunicationClient::SetDetachOnError(bool enable) {
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
- PacketResult::Success) {
+ if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) {
if (response.IsOKResponse())
return 0;
uint8_t error = response.GetError();
@@ -2019,7 +2065,7 @@ bool GDBRemoteCommunicationClient::GetProcessInfo(
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success) {
return DecodeProcessInfoResponse(response, process_info);
} else {
@@ -2044,7 +2090,7 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) {
GetHostInfo();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qProcessInfo", response, false) ==
+ if (SendPacketAndWaitForResponse("qProcessInfo", response) ==
PacketResult::Success) {
if (response.IsNormalResponse()) {
llvm::StringRef name;
@@ -2102,7 +2148,7 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) {
m_qProcessInfo_is_valid = eLazyBoolYes;
if (pid != LLDB_INVALID_PROCESS_ID) {
m_curr_pid_is_valid = eLazyBoolYes;
- m_curr_pid = pid;
+ m_curr_pid_run = m_curr_pid = pid;
}
// Set the ArchSpec from the triple if we have it.
@@ -2240,7 +2286,7 @@ uint32_t GDBRemoteCommunicationClient::FindProcesses(
// Increase timeout as the first qfProcessInfo packet takes a long time on
// Android. The value of 1min was arrived at empirically.
ScopedTimeout timeout(*this, minutes(1));
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
do {
ProcessInstanceInfo process_info;
@@ -2248,7 +2294,7 @@ uint32_t GDBRemoteCommunicationClient::FindProcesses(
break;
process_infos.push_back(process_info);
response = StringExtractorGDBRemote();
- } while (SendPacketAndWaitForResponse("qsProcessInfo", response, false) ==
+ } while (SendPacketAndWaitForResponse("qsProcessInfo", response) ==
PacketResult::Success);
} else {
m_supports_qfProcessInfo = false;
@@ -2267,7 +2313,7 @@ bool GDBRemoteCommunicationClient::GetUserName(uint32_t uid,
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success) {
if (response.IsNormalResponse()) {
// Make sure we parsed the right number of characters. The response is
@@ -2294,7 +2340,7 @@ bool GDBRemoteCommunicationClient::GetGroupName(uint32_t gid,
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success) {
if (response.IsNormalResponse()) {
// Make sure we parsed the right number of characters. The response is
@@ -2322,8 +2368,7 @@ bool GDBRemoteCommunicationClient::SetNonStopMode(const bool enable) {
StringExtractorGDBRemote response;
// Send to target
- if (SendPacketAndWaitForResponse(packet, response, false) ==
- PacketResult::Success)
+ if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success)
if (response.IsOKResponse())
return true;
@@ -2395,7 +2440,7 @@ void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets,
for (i = 0; i < num_packets; ++i) {
const auto packet_start_time = steady_clock::now();
StringExtractorGDBRemote response;
- SendPacketAndWaitForResponse(packet.GetString(), response, false);
+ SendPacketAndWaitForResponse(packet.GetString(), response);
const auto packet_end_time = steady_clock::now();
packet_times.push_back(packet_end_time - packet_start_time);
}
@@ -2449,7 +2494,7 @@ void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets,
uint32_t packet_count = 0;
while (bytes_read < recv_amount) {
StringExtractorGDBRemote response;
- SendPacketAndWaitForResponse(packet.GetString(), response, false);
+ SendPacketAndWaitForResponse(packet.GetString(), response);
bytes_read += recv_size;
++packet_count;
}
@@ -2503,7 +2548,7 @@ bool GDBRemoteCommunicationClient::SendSpeedTestPacket(uint32_t send_size,
}
StringExtractorGDBRemote response;
- return SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ return SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success;
}
@@ -2533,7 +2578,7 @@ bool GDBRemoteCommunicationClient::LaunchGDBServer(
// give the process a few seconds to startup
ScopedTimeout timeout(*this, seconds(10));
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
llvm::StringRef name;
llvm::StringRef value;
@@ -2557,7 +2602,7 @@ size_t GDBRemoteCommunicationClient::QueryGDBServer(
connection_urls.clear();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qQueryGDBServer", response, false) !=
+ if (SendPacketAndWaitForResponse("qQueryGDBServer", response) !=
PacketResult::Success)
return 0;
@@ -2596,7 +2641,7 @@ bool GDBRemoteCommunicationClient::KillSpawnedProcess(lldb::pid_t pid) {
stream.Printf("qKillSpawnedProcess:%" PRId64, pid);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return true;
@@ -2604,25 +2649,27 @@ bool GDBRemoteCommunicationClient::KillSpawnedProcess(lldb::pid_t pid) {
return false;
}
-bool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid) {
- if (m_curr_tid == tid)
- return true;
+llvm::Optional<PidTid>
+GDBRemoteCommunicationClient::SendSetCurrentThreadPacket(uint64_t tid,
+ uint64_t pid,
+ char op) {
+ lldb_private::StreamString packet;
+ packet.PutChar('H');
+ packet.PutChar(op);
+
+ if (pid != LLDB_INVALID_PROCESS_ID)
+ packet.Printf("p%" PRIx64 ".", pid);
- char packet[32];
- int packet_len;
if (tid == UINT64_MAX)
- packet_len = ::snprintf(packet, sizeof(packet), "Hg-1");
+ packet.PutCString("-1");
else
- packet_len = ::snprintf(packet, sizeof(packet), "Hg%" PRIx64, tid);
- assert(packet_len + 1 < (int)sizeof(packet));
- UNUSED_IF_ASSERT_DISABLED(packet_len);
+ packet.Printf("%" PRIx64, tid);
+
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
- PacketResult::Success) {
- if (response.IsOKResponse()) {
- m_curr_tid = tid;
- return true;
- }
+ if (SendPacketAndWaitForResponse(packet.GetString(), response)
+ == PacketResult::Success) {
+ if (response.IsOKResponse())
+ return {{pid, tid}};
/*
* Connected bare-iron target (like YAMON gdb-stub) may not have support for
@@ -2630,55 +2677,46 @@ bool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid) {
* The reply from '?' packet could be as simple as 'S05'. There is no packet
* which can
* give us pid and/or tid. Assume pid=tid=1 in such cases.
- */
- if (response.IsUnsupportedResponse() && IsConnected()) {
- m_curr_tid = 1;
- return true;
- }
+ */
+ if (response.IsUnsupportedResponse() && IsConnected())
+ return {{1, 1}};
}
- return false;
+ return llvm::None;
}
-bool GDBRemoteCommunicationClient::SetCurrentThreadForRun(uint64_t tid) {
- if (m_curr_tid_run == tid)
+bool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid,
+ uint64_t pid) {
+ if (m_curr_tid == tid &&
+ (m_curr_pid == pid || LLDB_INVALID_PROCESS_ID == pid))
return true;
- char packet[32];
- int packet_len;
- if (tid == UINT64_MAX)
- packet_len = ::snprintf(packet, sizeof(packet), "Hc-1");
- else
- packet_len = ::snprintf(packet, sizeof(packet), "Hc%" PRIx64, tid);
+ llvm::Optional<PidTid> ret = SendSetCurrentThreadPacket(tid, pid, 'g');
+ if (ret.hasValue()) {
+ if (ret->pid != LLDB_INVALID_PROCESS_ID)
+ m_curr_pid = ret->pid;
+ m_curr_tid = ret->tid;
+ }
+ return ret.hasValue();
+}
- assert(packet_len + 1 < (int)sizeof(packet));
- UNUSED_IF_ASSERT_DISABLED(packet_len);
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
- PacketResult::Success) {
- if (response.IsOKResponse()) {
- m_curr_tid_run = tid;
- return true;
- }
+bool GDBRemoteCommunicationClient::SetCurrentThreadForRun(uint64_t tid,
+ uint64_t pid) {
+ if (m_curr_tid_run == tid &&
+ (m_curr_pid_run == pid || LLDB_INVALID_PROCESS_ID == pid))
+ return true;
- /*
- * Connected bare-iron target (like YAMON gdb-stub) may not have support for
- * Hc packet.
- * The reply from '?' packet could be as simple as 'S05'. There is no packet
- * which can
- * give us pid and/or tid. Assume pid=tid=1 in such cases.
- */
- if (response.IsUnsupportedResponse() && IsConnected()) {
- m_curr_tid_run = 1;
- return true;
- }
+ llvm::Optional<PidTid> ret = SendSetCurrentThreadPacket(tid, pid, 'c');
+ if (ret.hasValue()) {
+ if (ret->pid != LLDB_INVALID_PROCESS_ID)
+ m_curr_pid_run = ret->pid;
+ m_curr_tid_run = ret->tid;
}
- return false;
+ return ret.hasValue();
}
bool GDBRemoteCommunicationClient::GetStopReply(
StringExtractorGDBRemote &response) {
- if (SendPacketAndWaitForResponse("?", response, false) ==
- PacketResult::Success)
+ if (SendPacketAndWaitForResponse("?", response) == PacketResult::Success)
return response.IsNormalResponse();
return false;
}
@@ -2691,7 +2729,7 @@ bool GDBRemoteCommunicationClient::GetThreadStopInfo(
::snprintf(packet, sizeof(packet), "qThreadStopInfo%" PRIx64, tid);
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success) {
if (response.IsUnsupportedResponse())
m_supports_qThreadStopInfo = false;
@@ -2707,7 +2745,8 @@ bool GDBRemoteCommunicationClient::GetThreadStopInfo(
}
uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket(
- GDBStoppointType type, bool insert, addr_t addr, uint32_t length) {
+ GDBStoppointType type, bool insert, addr_t addr, uint32_t length,
+ std::chrono::seconds timeout) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64,
__FUNCTION__, insert ? "add" : "remove", addr);
@@ -2728,7 +2767,7 @@ uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket(
// or "" (unsupported)
response.SetResponseValidatorToOKErrorNotSupported();
// Try to send the breakpoint packet, and check that it was correctly sent
- if (SendPacketAndWaitForResponse(packet, response, true) ==
+ if (SendPacketAndWaitForResponse(packet, response, timeout) ==
PacketResult::Success) {
// Receive and OK packet when the breakpoint successfully placed
if (response.IsOKResponse())
@@ -2766,11 +2805,12 @@ uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket(
return UINT8_MAX;
}
-size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs(
- std::vector<lldb::tid_t> &thread_ids, bool &sequence_mutex_unavailable) {
- thread_ids.clear();
+std::vector<std::pair<lldb::pid_t, lldb::tid_t>>
+GDBRemoteCommunicationClient::GetCurrentProcessAndThreadIDs(
+ bool &sequence_mutex_unavailable) {
+ std::vector<std::pair<lldb::pid_t, lldb::tid_t>> ids;
- Lock lock(*this, false);
+ Lock lock(*this);
if (lock) {
sequence_mutex_unavailable = false;
StringExtractorGDBRemote response;
@@ -2786,11 +2826,11 @@ size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs(
break;
if (ch == 'm') {
do {
- tid_t tid = response.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID);
+ auto pid_tid = response.GetPidTid(LLDB_INVALID_PROCESS_ID);
+ if (!pid_tid)
+ return {};
- if (tid != LLDB_INVALID_THREAD_ID) {
- thread_ids.push_back(tid);
- }
+ ids.push_back(pid_tid.getValue());
ch = response.GetChar(); // Skip the command separator
} while (ch == ','); // Make sure we got a comma separator
}
@@ -2803,10 +2843,10 @@ size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs(
* be as simple as 'S05'. There is no packet which can give us pid and/or
* tid.
* Assume pid=tid=1 in such cases.
- */
+ */
if ((response.IsUnsupportedResponse() || response.IsNormalResponse()) &&
- thread_ids.size() == 0 && IsConnected()) {
- thread_ids.push_back(1);
+ ids.size() == 0 && IsConnected()) {
+ ids.emplace_back(1, 1);
}
} else {
Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS |
@@ -2815,12 +2855,34 @@ size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs(
"packet 'qfThreadInfo'");
sequence_mutex_unavailable = true;
}
+
+ return ids;
+}
+
+size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs(
+ std::vector<lldb::tid_t> &thread_ids, bool &sequence_mutex_unavailable) {
+ lldb::pid_t pid = GetCurrentProcessID();
+ thread_ids.clear();
+
+ auto ids = GetCurrentProcessAndThreadIDs(sequence_mutex_unavailable);
+ if (ids.empty() || sequence_mutex_unavailable)
+ return 0;
+
+ for (auto id : ids) {
+ // skip threads that do not belong to the current process
+ if (id.first != LLDB_INVALID_PROCESS_ID && id.first != pid)
+ continue;
+ if (id.second != LLDB_INVALID_THREAD_ID &&
+ id.second != StringExtractorGDBRemote::AllThreads)
+ thread_ids.push_back(id.second);
+ }
+
return thread_ids.size();
}
lldb::addr_t GDBRemoteCommunicationClient::GetShlibInfoAddr() {
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qShlibInfoAddr", response, false) !=
+ if (SendPacketAndWaitForResponse("qShlibInfoAddr", response) !=
PacketResult::Success ||
!response.IsNormalResponse())
return LLDB_INVALID_ADDRESS;
@@ -2853,7 +2915,7 @@ lldb_private::Status GDBRemoteCommunicationClient::RunShellCommand(
stream.PutStringAsRawHex8(path);
}
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() != 'F')
return Status("malformed reply");
@@ -2891,8 +2953,7 @@ Status GDBRemoteCommunicationClient::MakeDirectory(const FileSpec &file_spec,
llvm::StringRef packet = stream.GetString();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) !=
- PacketResult::Success)
+ if (SendPacketAndWaitForResponse(packet, response) != PacketResult::Success)
return Status("failed to send '%s' packet", packet.str().c_str());
if (response.GetChar() != 'F')
@@ -2913,8 +2974,7 @@ GDBRemoteCommunicationClient::SetFilePermissions(const FileSpec &file_spec,
llvm::StringRef packet = stream.GetString();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) !=
- PacketResult::Success)
+ if (SendPacketAndWaitForResponse(packet, response) != PacketResult::Success)
return Status("failed to send '%s' packet", stream.GetData());
if (response.GetChar() != 'F')
@@ -2956,7 +3016,7 @@ GDBRemoteCommunicationClient::OpenFile(const lldb_private::FileSpec &file_spec,
stream.PutChar(',');
stream.PutHex32(mode);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
return ParseHostIOPacketResponse(response, UINT64_MAX, error);
}
@@ -2968,7 +3028,7 @@ bool GDBRemoteCommunicationClient::CloseFile(lldb::user_id_t fd,
lldb_private::StreamString stream;
stream.Printf("vFile:close:%i", (int)fd);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
return ParseHostIOPacketResponse(response, -1, error) == 0;
}
@@ -2983,7 +3043,7 @@ lldb::user_id_t GDBRemoteCommunicationClient::GetFileSize(
stream.PutCString("vFile:size:");
stream.PutStringAsRawHex8(path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() != 'F')
return UINT64_MAX;
@@ -3001,7 +3061,7 @@ void GDBRemoteCommunicationClient::AutoCompleteDiskFileOrDirectory(
stream.PutChar(',');
stream.PutStringAsRawHex8(request.GetCursorArgumentPrefix());
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
StreamString strm;
char ch = response.GetChar();
@@ -3027,7 +3087,7 @@ GDBRemoteCommunicationClient::GetFilePermissions(const FileSpec &file_spec,
stream.PutCString("vFile:mode:");
stream.PutStringAsRawHex8(path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() != 'F') {
error.SetErrorStringWithFormat("invalid response to '%s' packet",
@@ -3062,7 +3122,7 @@ uint64_t GDBRemoteCommunicationClient::ReadFile(lldb::user_id_t fd,
stream.Printf("vFile:pread:%i,%" PRId64 ",%" PRId64, (int)fd, dst_len,
offset);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() != 'F')
return 0;
@@ -3096,7 +3156,7 @@ uint64_t GDBRemoteCommunicationClient::WriteFile(lldb::user_id_t fd,
stream.Printf("vFile:pwrite:%i,%" PRId64 ",", (int)fd, offset);
stream.PutEscapedBytes(src, src_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() != 'F') {
error.SetErrorStringWithFormat("write file failed");
@@ -3131,7 +3191,7 @@ Status GDBRemoteCommunicationClient::CreateSymlink(const FileSpec &src,
stream.PutChar(',');
stream.PutStringAsRawHex8(src_path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() == 'F') {
uint32_t result = response.GetU32(UINT32_MAX);
@@ -3162,7 +3222,7 @@ Status GDBRemoteCommunicationClient::Unlink(const FileSpec &file_spec) {
// so we follow suit here
stream.PutStringAsRawHex8(path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() == 'F') {
uint32_t result = response.GetU32(UINT32_MAX);
@@ -3192,7 +3252,7 @@ bool GDBRemoteCommunicationClient::GetFileExists(
stream.PutCString("vFile:exists:");
stream.PutStringAsRawHex8(path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() != 'F')
return false;
@@ -3211,7 +3271,7 @@ bool GDBRemoteCommunicationClient::CalculateMD5(
stream.PutCString("vFile:MD5:");
stream.PutStringAsRawHex8(path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() != 'F')
return false;
@@ -3258,7 +3318,7 @@ DataBufferSP GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid,
payload.Printf("p%x", reg);
StringExtractorGDBRemote response;
if (SendThreadSpecificPacketAndWaitForResponse(
- tid, std::move(payload), response, false) != PacketResult::Success ||
+ tid, std::move(payload), response) != PacketResult::Success ||
!response.IsNormalResponse())
return nullptr;
@@ -3273,7 +3333,7 @@ DataBufferSP GDBRemoteCommunicationClient::ReadAllRegisters(lldb::tid_t tid) {
payload.PutChar('g');
StringExtractorGDBRemote response;
if (SendThreadSpecificPacketAndWaitForResponse(
- tid, std::move(payload), response, false) != PacketResult::Success ||
+ tid, std::move(payload), response) != PacketResult::Success ||
!response.IsNormalResponse())
return nullptr;
@@ -3292,9 +3352,8 @@ bool GDBRemoteCommunicationClient::WriteRegister(lldb::tid_t tid,
endian::InlHostByteOrder(),
endian::InlHostByteOrder());
StringExtractorGDBRemote response;
- return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload),
- response, false) ==
- PacketResult::Success &&
+ return SendThreadSpecificPacketAndWaitForResponse(
+ tid, std::move(payload), response) == PacketResult::Success &&
response.IsOKResponse();
}
@@ -3306,9 +3365,8 @@ bool GDBRemoteCommunicationClient::WriteAllRegisters(
endian::InlHostByteOrder(),
endian::InlHostByteOrder());
StringExtractorGDBRemote response;
- return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload),
- response, false) ==
- PacketResult::Success &&
+ return SendThreadSpecificPacketAndWaitForResponse(
+ tid, std::move(payload), response) == PacketResult::Success &&
response.IsOKResponse();
}
@@ -3323,7 +3381,7 @@ bool GDBRemoteCommunicationClient::SaveRegisterState(lldb::tid_t tid,
payload.PutCString("QSaveRegisterState");
StringExtractorGDBRemote response;
if (SendThreadSpecificPacketAndWaitForResponse(
- tid, std::move(payload), response, false) != PacketResult::Success)
+ tid, std::move(payload), response) != PacketResult::Success)
return false;
if (response.IsUnsupportedResponse())
@@ -3349,7 +3407,7 @@ bool GDBRemoteCommunicationClient::RestoreRegisterState(lldb::tid_t tid,
payload.Printf("QRestoreRegisterState:%u", save_id);
StringExtractorGDBRemote response;
if (SendThreadSpecificPacketAndWaitForResponse(
- tid, std::move(payload), response, false) != PacketResult::Success)
+ tid, std::move(payload), response) != PacketResult::Success)
return false;
if (response.IsOKResponse())
@@ -3367,251 +3425,179 @@ bool GDBRemoteCommunicationClient::SyncThreadState(lldb::tid_t tid) {
StreamString packet;
StringExtractorGDBRemote response;
packet.Printf("QSyncThreadState:%4.4" PRIx64 ";", tid);
- return SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ return SendPacketAndWaitForResponse(packet.GetString(), response) ==
GDBRemoteCommunication::PacketResult::Success &&
response.IsOKResponse();
}
-lldb::user_id_t
-GDBRemoteCommunicationClient::SendStartTracePacket(const TraceOptions &options,
- Status &error) {
+llvm::Expected<TraceSupportedResponse>
+GDBRemoteCommunicationClient::SendTraceSupported(std::chrono::seconds timeout) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- lldb::user_id_t ret_uid = LLDB_INVALID_UID;
StreamGDBRemote escaped_packet;
- escaped_packet.PutCString("jTraceStart:");
-
- StructuredData::Dictionary json_packet;
- json_packet.AddIntegerItem("type", options.getType());
- json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize());
- json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize());
-
- if (options.getThreadID() != LLDB_INVALID_THREAD_ID)
- json_packet.AddIntegerItem("threadid", options.getThreadID());
-
- StructuredData::DictionarySP custom_params = options.getTraceParams();
- if (custom_params)
- json_packet.AddItem("params", custom_params);
-
- StreamString json_string;
- json_packet.Dump(json_string, false);
- escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
+ escaped_packet.PutCString("jLLDBTraceSupported");
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
- true) ==
+ timeout) ==
GDBRemoteCommunication::PacketResult::Success) {
- if (!response.IsNormalResponse()) {
- error = response.GetStatus();
- LLDB_LOG(log, "Target does not support Tracing , error {0}", error);
- } else {
- ret_uid = response.GetHexMaxU64(false, LLDB_INVALID_UID);
- }
- } else {
- LLDB_LOG(log, "failed to send packet");
- error.SetErrorStringWithFormat("failed to send packet: '%s'",
- escaped_packet.GetData());
+ if (response.IsErrorResponse())
+ return response.GetStatus().ToError();
+ if (response.IsUnsupportedResponse())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "jLLDBTraceSupported is unsupported");
+
+ return llvm::json::parse<TraceSupportedResponse>(response.Peek(),
+ "TraceSupportedResponse");
}
- return ret_uid;
+ LLDB_LOG(log, "failed to send packet: jLLDBTraceSupported");
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "failed to send packet: jLLDBTraceSupported");
}
-Status
-GDBRemoteCommunicationClient::SendStopTracePacket(lldb::user_id_t uid,
- lldb::tid_t thread_id) {
+llvm::Error
+GDBRemoteCommunicationClient::SendTraceStop(const TraceStopRequest &request,
+ std::chrono::seconds timeout) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- StringExtractorGDBRemote response;
- Status error;
- StructuredData::Dictionary json_packet;
StreamGDBRemote escaped_packet;
- StreamString json_string;
- escaped_packet.PutCString("jTraceStop:");
+ escaped_packet.PutCString("jLLDBTraceStop:");
- json_packet.AddIntegerItem("traceid", uid);
+ std::string json_string;
+ llvm::raw_string_ostream os(json_string);
+ os << toJSON(request);
+ os.flush();
- if (thread_id != LLDB_INVALID_THREAD_ID)
- json_packet.AddIntegerItem("threadid", thread_id);
-
- json_packet.Dump(json_string, false);
-
- escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
+ escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
+ StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
- true) ==
+ timeout) ==
GDBRemoteCommunication::PacketResult::Success) {
- if (!response.IsOKResponse()) {
- error = response.GetStatus();
- LLDB_LOG(log, "stop tracing failed");
- }
- } else {
- LLDB_LOG(log, "failed to send packet");
- error.SetErrorStringWithFormat(
- "failed to send packet: '%s' with error '%d'", escaped_packet.GetData(),
- response.GetError());
+ if (response.IsErrorResponse())
+ return response.GetStatus().ToError();
+ if (response.IsUnsupportedResponse())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "jLLDBTraceStop is unsupported");
+ if (response.IsOKResponse())
+ return llvm::Error::success();
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Invalid jLLDBTraceStart response");
}
- return error;
-}
-
-Status GDBRemoteCommunicationClient::SendGetDataPacket(
- lldb::user_id_t uid, lldb::tid_t thread_id,
- llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) {
-
- StreamGDBRemote escaped_packet;
- escaped_packet.PutCString("jTraceBufferRead:");
- return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset);
+ LLDB_LOG(log, "failed to send packet: jLLDBTraceStop");
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "failed to send packet: jLLDBTraceStop '%s'",
+ escaped_packet.GetData());
}
-Status GDBRemoteCommunicationClient::SendGetMetaDataPacket(
- lldb::user_id_t uid, lldb::tid_t thread_id,
- llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) {
+llvm::Error
+GDBRemoteCommunicationClient::SendTraceStart(const llvm::json::Value &params,
+ std::chrono::seconds timeout) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
StreamGDBRemote escaped_packet;
- escaped_packet.PutCString("jTraceMetaRead:");
- return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset);
-}
+ escaped_packet.PutCString("jLLDBTraceStart:");
-llvm::Expected<TraceTypeInfo>
-GDBRemoteCommunicationClient::SendGetSupportedTraceType() {
- Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ std::string json_string;
+ llvm::raw_string_ostream os(json_string);
+ os << params;
+ os.flush();
- StreamGDBRemote escaped_packet;
- escaped_packet.PutCString("jLLDBTraceSupportedType");
+ escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
- true) ==
+ timeout) ==
GDBRemoteCommunication::PacketResult::Success) {
if (response.IsErrorResponse())
return response.GetStatus().ToError();
if (response.IsUnsupportedResponse())
return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "jLLDBTraceSupportedType is unsupported");
-
- if (llvm::Expected<TraceTypeInfo> type =
- llvm::json::parse<TraceTypeInfo>(response.Peek()))
- return *type;
- else
- return type.takeError();
+ "jLLDBTraceStart is unsupported");
+ if (response.IsOKResponse())
+ return llvm::Error::success();
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Invalid jLLDBTraceStart response");
}
- LLDB_LOG(log, "failed to send packet: jLLDBTraceSupportedType");
- return llvm::createStringError(
- llvm::inconvertibleErrorCode(),
- "failed to send packet: jLLDBTraceSupportedType");
+ LLDB_LOG(log, "failed to send packet: jLLDBTraceStart");
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "failed to send packet: jLLDBTraceStart '%s'",
+ escaped_packet.GetData());
}
-Status
-GDBRemoteCommunicationClient::SendGetTraceConfigPacket(lldb::user_id_t uid,
- TraceOptions &options) {
+llvm::Expected<std::string>
+GDBRemoteCommunicationClient::SendTraceGetState(llvm::StringRef type,
+ std::chrono::seconds timeout) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- StringExtractorGDBRemote response;
- Status error;
- StreamString json_string;
StreamGDBRemote escaped_packet;
- escaped_packet.PutCString("jTraceConfigRead:");
+ escaped_packet.PutCString("jLLDBTraceGetState:");
- StructuredData::Dictionary json_packet;
- json_packet.AddIntegerItem("traceid", uid);
+ std::string json_string;
+ llvm::raw_string_ostream os(json_string);
+ os << toJSON(TraceGetStateRequest{type.str()});
+ os.flush();
- if (options.getThreadID() != LLDB_INVALID_THREAD_ID)
- json_packet.AddIntegerItem("threadid", options.getThreadID());
-
- json_packet.Dump(json_string, false);
- escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
+ escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
+ StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
- true) ==
+ timeout) ==
GDBRemoteCommunication::PacketResult::Success) {
- if (response.IsNormalResponse()) {
- uint64_t type = std::numeric_limits<uint64_t>::max();
- uint64_t buffersize = std::numeric_limits<uint64_t>::max();
- uint64_t metabuffersize = std::numeric_limits<uint64_t>::max();
-
- auto json_object = StructuredData::ParseJSON(response.Peek());
-
- if (!json_object ||
- json_object->GetType() != lldb::eStructuredDataTypeDictionary) {
- error.SetErrorString("Invalid Configuration obtained");
- return error;
- }
-
- auto json_dict = json_object->GetAsDictionary();
-
- json_dict->GetValueForKeyAsInteger<uint64_t>("metabuffersize",
- metabuffersize);
- options.setMetaDataBufferSize(metabuffersize);
-
- json_dict->GetValueForKeyAsInteger<uint64_t>("buffersize", buffersize);
- options.setTraceBufferSize(buffersize);
-
- json_dict->GetValueForKeyAsInteger<uint64_t>("type", type);
- options.setType(static_cast<lldb::TraceType>(type));
-
- StructuredData::ObjectSP custom_params_sp =
- json_dict->GetValueForKey("params");
- if (custom_params_sp) {
- if (custom_params_sp->GetType() !=
- lldb::eStructuredDataTypeDictionary) {
- error.SetErrorString("Invalid Configuration obtained");
- return error;
- } else
- options.setTraceParams(
- std::static_pointer_cast<StructuredData::Dictionary>(
- custom_params_sp));
- }
- } else {
- error = response.GetStatus();
- }
- } else {
- LLDB_LOG(log, "failed to send packet");
- error.SetErrorStringWithFormat("failed to send packet: '%s'",
- escaped_packet.GetData());
+ if (response.IsErrorResponse())
+ return response.GetStatus().ToError();
+ if (response.IsUnsupportedResponse())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "jLLDBTraceGetState is unsupported");
+ return std::string(response.Peek());
}
- return error;
+
+ LLDB_LOG(log, "failed to send packet: jLLDBTraceGetState");
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "failed to send packet: jLLDBTraceGetState '%s'",
+ escaped_packet.GetData());
}
-Status GDBRemoteCommunicationClient::SendGetTraceDataPacket(
- StreamGDBRemote &packet, lldb::user_id_t uid, lldb::tid_t thread_id,
- llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) {
+llvm::Expected<std::vector<uint8_t>>
+GDBRemoteCommunicationClient::SendTraceGetBinaryData(
+ const TraceGetBinaryDataRequest &request, std::chrono::seconds timeout) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- Status error;
- StructuredData::Dictionary json_packet;
-
- json_packet.AddIntegerItem("traceid", uid);
- json_packet.AddIntegerItem("offset", offset);
- json_packet.AddIntegerItem("buffersize", buffer.size());
+ StreamGDBRemote escaped_packet;
+ escaped_packet.PutCString("jLLDBTraceGetBinaryData:");
- if (thread_id != LLDB_INVALID_THREAD_ID)
- json_packet.AddIntegerItem("threadid", thread_id);
+ std::string json_string;
+ llvm::raw_string_ostream os(json_string);
+ os << toJSON(request);
+ os.flush();
- StreamString json_string;
- json_packet.Dump(json_string, false);
+ escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
- packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, true) ==
+ if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
+ timeout) ==
GDBRemoteCommunication::PacketResult::Success) {
- if (response.IsNormalResponse()) {
- size_t filled_size = response.GetHexBytesAvail(buffer);
- buffer = llvm::MutableArrayRef<uint8_t>(buffer.data(), filled_size);
- } else {
- error = response.GetStatus();
- buffer = buffer.slice(buffer.size());
- }
- } else {
- LLDB_LOG(log, "failed to send packet");
- error.SetErrorStringWithFormat("failed to send packet: '%s'",
- packet.GetData());
- buffer = buffer.slice(buffer.size());
+ if (response.IsErrorResponse())
+ return response.GetStatus().ToError();
+ if (response.IsUnsupportedResponse())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "jLLDBTraceGetBinaryData is unsupported");
+ std::string data;
+ response.GetEscapedBinaryData(data);
+ return std::vector<uint8_t>(data.begin(), data.end());
}
- return error;
+ LLDB_LOG(log, "failed to send packet: jLLDBTraceGetBinaryData");
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "failed to send packet: jLLDBTraceGetBinaryData '%s'",
+ escaped_packet.GetData());
}
llvm::Optional<QOffsets> GDBRemoteCommunicationClient::GetQOffsets() {
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(
- "qOffsets", response, /*send_async=*/false) != PacketResult::Success)
+ if (SendPacketAndWaitForResponse("qOffsets", response) !=
+ PacketResult::Success)
return llvm::None;
if (!response.IsNormalResponse())
return llvm::None;
@@ -3666,7 +3652,7 @@ bool GDBRemoteCommunicationClient::GetModuleInfo(
packet.PutStringAsRawHex8(triple);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) !=
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
PacketResult::Success)
return false;
@@ -3773,7 +3759,7 @@ GDBRemoteCommunicationClient::GetModulesInfo(
ScopedTimeout timeout(*this, std::chrono::seconds(10));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(payload.GetString(), response, false) !=
+ if (SendPacketAndWaitForResponse(payload.GetString(), response) !=
PacketResult::Success ||
response.IsErrorResponse())
return llvm::None;
@@ -3832,7 +3818,7 @@ bool GDBRemoteCommunicationClient::ReadExtFeature(
<< "," << std::hex << size;
GDBRemoteCommunication::PacketResult res =
- SendPacketAndWaitForResponse(packet.str(), chunk, false);
+ SendPacketAndWaitForResponse(packet.str(), chunk);
if (res != GDBRemoteCommunication::PacketResult::Success) {
err.SetErrorString("Error sending $qXfer packet");
@@ -3921,7 +3907,7 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups(
bool first_qsymbol_query = true;
if (m_supports_qSymbol && !m_qSymbol_requests_done) {
- Lock lock(*this, false);
+ Lock lock(*this);
if (lock) {
StreamString packet;
packet.PutCString("qSymbol::");
@@ -4049,9 +4035,8 @@ GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() {
// Poll it now.
StringExtractorGDBRemote response;
- const bool send_async = false;
- if (SendPacketAndWaitForResponse("qStructuredDataPlugins", response,
- send_async) == PacketResult::Success) {
+ if (SendPacketAndWaitForResponse("qStructuredDataPlugins", response) ==
+ PacketResult::Success) {
m_supported_async_json_packets_sp =
StructuredData::ParseJSON(std::string(response.GetStringRef()));
if (m_supported_async_json_packets_sp &&
@@ -4095,7 +4080,7 @@ Status GDBRemoteCommunicationClient::SendSignalsToIgnore(
std::string packet = formatv("QPassSignals:{0:$[;]@(x-2)}", range).str();
StringExtractorGDBRemote response;
- auto send_status = SendPacketAndWaitForResponse(packet, response, false);
+ auto send_status = SendPacketAndWaitForResponse(packet, response);
if (send_status != GDBRemoteCommunication::PacketResult::Success)
return Status("Sending QPassSignals packet failed");
@@ -4134,10 +4119,8 @@ Status GDBRemoteCommunicationClient::ConfigureRemoteStructuredData(
stream.Flush();
// Send the packet.
- const bool send_async = false;
StringExtractorGDBRemote response;
- auto result =
- SendPacketAndWaitForResponse(stream.GetString(), response, send_async);
+ auto result = SendPacketAndWaitForResponse(stream.GetString(), response);
if (result == PacketResult::Success) {
// We failed if the config result comes back other than OK.
if (strcmp(response.GetStringRef().data(), "OK") == 0) {
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index af3755fce774..1e1797c10dfc 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -22,7 +22,7 @@
#include "lldb/Utility/GDBRemote.h"
#include "lldb/Utility/ProcessInfo.h"
#include "lldb/Utility/StructuredData.h"
-#include "lldb/Utility/TraceOptions.h"
+#include "lldb/Utility/TraceGDBRemotePackets.h"
#if defined(_WIN32)
#include "lldb/Host/windows/PosixApi.h"
#endif
@@ -49,6 +49,12 @@ inline bool operator==(const QOffsets &a, const QOffsets &b) {
}
llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const QOffsets &offsets);
+// A trivial struct used to return a pair of PID and TID.
+struct PidTid {
+ uint64_t pid;
+ uint64_t tid;
+};
+
class GDBRemoteCommunicationClient : public GDBRemoteClientBase {
public:
GDBRemoteCommunicationClient();
@@ -275,6 +281,8 @@ public:
ArchSpec GetSystemArchitecture();
+ uint32_t GetAddressingBits();
+
bool GetHostname(std::string &s);
lldb::addr_t GetShlibInfoAddr();
@@ -319,7 +327,8 @@ public:
GDBStoppointType type, // Type of breakpoint or watchpoint
bool insert, // Insert or remove?
lldb::addr_t addr, // Address of breakpoint or watchpoint
- uint32_t length); // Byte Size of breakpoint or watchpoint
+ uint32_t length, // Byte Size of breakpoint or watchpoint
+ std::chrono::seconds interrupt_timeout); // Time to wait for an interrupt
bool SetNonStopMode(const bool enable);
@@ -334,9 +343,14 @@ public:
// and response times.
bool SendSpeedTestPacket(uint32_t send_size, uint32_t recv_size);
- bool SetCurrentThread(uint64_t tid);
+ llvm::Optional<PidTid>
+ SendSetCurrentThreadPacket(uint64_t tid, uint64_t pid, char op);
- bool SetCurrentThreadForRun(uint64_t tid);
+ bool SetCurrentThread(uint64_t tid,
+ lldb::pid_t pid = LLDB_INVALID_PROCESS_ID);
+
+ bool SetCurrentThreadForRun(uint64_t tid,
+ lldb::pid_t pid = LLDB_INVALID_PROCESS_ID);
bool GetQXferAuxvReadSupported();
@@ -366,6 +380,9 @@ public:
return m_supports_alloc_dealloc_memory;
}
+ std::vector<std::pair<lldb::pid_t, lldb::tid_t>>
+ GetCurrentProcessAndThreadIDs(bool &sequence_mutex_unavailable);
+
size_t GetCurrentThreadIDs(std::vector<lldb::tid_t> &thread_ids,
bool &sequence_mutex_unavailable);
@@ -446,6 +463,14 @@ public:
bool GetSharedCacheInfoSupported();
+ bool GetMemoryTaggingSupported();
+
+ lldb::DataBufferSP ReadMemoryTags(lldb::addr_t addr, size_t len,
+ int32_t type);
+
+ Status WriteMemoryTags(lldb::addr_t addr, size_t len, int32_t type,
+ const std::vector<uint8_t> &tags);
+
/// Use qOffsets to query the offset used when relocating the target
/// executable. If successful, the returned structure will contain at least
/// one value in the offsets field.
@@ -505,59 +530,61 @@ public:
ConfigureRemoteStructuredData(ConstString type_name,
const StructuredData::ObjectSP &config_sp);
- lldb::user_id_t SendStartTracePacket(const TraceOptions &options,
- Status &error);
+ llvm::Expected<TraceSupportedResponse>
+ SendTraceSupported(std::chrono::seconds interrupt_timeout);
- Status SendStopTracePacket(lldb::user_id_t uid, lldb::tid_t thread_id);
+ llvm::Error SendTraceStart(const llvm::json::Value &request,
+ std::chrono::seconds interrupt_timeout);
- Status SendGetDataPacket(lldb::user_id_t uid, lldb::tid_t thread_id,
- llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset = 0);
+ llvm::Error SendTraceStop(const TraceStopRequest &request,
+ std::chrono::seconds interrupt_timeout);
- Status SendGetMetaDataPacket(lldb::user_id_t uid, lldb::tid_t thread_id,
- llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset = 0);
+ llvm::Expected<std::string>
+ SendTraceGetState(llvm::StringRef type,
+ std::chrono::seconds interrupt_timeout);
- Status SendGetTraceConfigPacket(lldb::user_id_t uid, TraceOptions &options);
-
- llvm::Expected<TraceTypeInfo> SendGetSupportedTraceType();
+ llvm::Expected<std::vector<uint8_t>>
+ SendTraceGetBinaryData(const TraceGetBinaryDataRequest &request,
+ std::chrono::seconds interrupt_timeout);
protected:
- LazyBool m_supports_not_sending_acks;
- LazyBool m_supports_thread_suffix;
- LazyBool m_supports_threads_in_stop_reply;
- LazyBool m_supports_vCont_all;
- LazyBool m_supports_vCont_any;
- LazyBool m_supports_vCont_c;
- LazyBool m_supports_vCont_C;
- LazyBool m_supports_vCont_s;
- LazyBool m_supports_vCont_S;
- LazyBool m_qHostInfo_is_valid;
- LazyBool m_curr_pid_is_valid;
- LazyBool m_qProcessInfo_is_valid;
- LazyBool m_qGDBServerVersion_is_valid;
- LazyBool m_supports_alloc_dealloc_memory;
- LazyBool m_supports_memory_region_info;
- LazyBool m_supports_watchpoint_support_info;
- LazyBool m_supports_detach_stay_stopped;
- LazyBool m_watchpoints_trigger_after_instruction;
- LazyBool m_attach_or_wait_reply;
- LazyBool m_prepare_for_reg_writing_reply;
- LazyBool m_supports_p;
- LazyBool m_supports_x;
- LazyBool m_avoid_g_packets;
- LazyBool m_supports_QSaveRegisterState;
- LazyBool m_supports_qXfer_auxv_read;
- LazyBool m_supports_qXfer_libraries_read;
- LazyBool m_supports_qXfer_libraries_svr4_read;
- LazyBool m_supports_qXfer_features_read;
- LazyBool m_supports_qXfer_memory_map_read;
- LazyBool m_supports_augmented_libraries_svr4_read;
- LazyBool m_supports_jThreadExtendedInfo;
- LazyBool m_supports_jLoadedDynamicLibrariesInfos;
- LazyBool m_supports_jGetSharedCacheInfo;
- LazyBool m_supports_QPassSignals;
- LazyBool m_supports_error_string_reply;
+ LazyBool m_supports_not_sending_acks = eLazyBoolCalculate;
+ LazyBool m_supports_thread_suffix = eLazyBoolCalculate;
+ LazyBool m_supports_threads_in_stop_reply = eLazyBoolCalculate;
+ LazyBool m_supports_vCont_all = eLazyBoolCalculate;
+ LazyBool m_supports_vCont_any = eLazyBoolCalculate;
+ LazyBool m_supports_vCont_c = eLazyBoolCalculate;
+ LazyBool m_supports_vCont_C = eLazyBoolCalculate;
+ LazyBool m_supports_vCont_s = eLazyBoolCalculate;
+ LazyBool m_supports_vCont_S = eLazyBoolCalculate;
+ LazyBool m_qHostInfo_is_valid = eLazyBoolCalculate;
+ LazyBool m_curr_pid_is_valid = eLazyBoolCalculate;
+ LazyBool m_qProcessInfo_is_valid = eLazyBoolCalculate;
+ LazyBool m_qGDBServerVersion_is_valid = eLazyBoolCalculate;
+ LazyBool m_supports_alloc_dealloc_memory = eLazyBoolCalculate;
+ LazyBool m_supports_memory_region_info = eLazyBoolCalculate;
+ LazyBool m_supports_watchpoint_support_info = eLazyBoolCalculate;
+ LazyBool m_supports_detach_stay_stopped = eLazyBoolCalculate;
+ LazyBool m_watchpoints_trigger_after_instruction = eLazyBoolCalculate;
+ LazyBool m_attach_or_wait_reply = eLazyBoolCalculate;
+ LazyBool m_prepare_for_reg_writing_reply = eLazyBoolCalculate;
+ LazyBool m_supports_p = eLazyBoolCalculate;
+ LazyBool m_supports_x = eLazyBoolCalculate;
+ LazyBool m_avoid_g_packets = eLazyBoolCalculate;
+ LazyBool m_supports_QSaveRegisterState = eLazyBoolCalculate;
+ LazyBool m_supports_qXfer_auxv_read = eLazyBoolCalculate;
+ LazyBool m_supports_qXfer_libraries_read = eLazyBoolCalculate;
+ LazyBool m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
+ LazyBool m_supports_qXfer_features_read = eLazyBoolCalculate;
+ LazyBool m_supports_qXfer_memory_map_read = eLazyBoolCalculate;
+ LazyBool m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
+ LazyBool m_supports_jThreadExtendedInfo = eLazyBoolCalculate;
+ LazyBool m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolCalculate;
+ LazyBool m_supports_jGetSharedCacheInfo = eLazyBoolCalculate;
+ LazyBool m_supports_QPassSignals = eLazyBoolCalculate;
+ LazyBool m_supports_error_string_reply = eLazyBoolCalculate;
+ LazyBool m_supports_multiprocess = eLazyBoolCalculate;
+ LazyBool m_supports_memory_tagging = eLazyBoolCalculate;
bool m_supports_qProcessInfoPID : 1, m_supports_qfProcessInfo : 1,
m_supports_qUserName : 1, m_supports_qGroupName : 1,
@@ -568,13 +595,17 @@ protected:
m_supports_qModuleInfo : 1, m_supports_jThreadsInfo : 1,
m_supports_jModulesInfo : 1;
- lldb::pid_t m_curr_pid;
- lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all
- // other operations
- lldb::tid_t m_curr_tid_run; // Current gdb remote protocol thread index for
- // continue, step, etc
+ /// Current gdb remote protocol process identifier for all other operations
+ lldb::pid_t m_curr_pid = LLDB_INVALID_PROCESS_ID;
+ /// Current gdb remote protocol process identifier for continue, step, etc
+ lldb::pid_t m_curr_pid_run = LLDB_INVALID_PROCESS_ID;
+ /// Current gdb remote protocol thread identifier for all other operations
+ lldb::tid_t m_curr_tid = LLDB_INVALID_THREAD_ID;
+ /// Current gdb remote protocol thread identifier for continue, step, etc
+ lldb::tid_t m_curr_tid_run = LLDB_INVALID_THREAD_ID;
- uint32_t m_num_supported_hardware_watchpoints;
+ uint32_t m_num_supported_hardware_watchpoints = 0;
+ uint32_t m_addressing_bits = 0;
ArchSpec m_host_arch;
ArchSpec m_process_arch;
@@ -585,17 +616,19 @@ protected:
std::string m_hostname;
std::string m_gdb_server_name; // from reply to qGDBServerVersion, empty if
// qGDBServerVersion is not supported
- uint32_t m_gdb_server_version; // from reply to qGDBServerVersion, zero if
- // qGDBServerVersion is not supported
+ uint32_t m_gdb_server_version =
+ UINT32_MAX; // from reply to qGDBServerVersion, zero if
+ // qGDBServerVersion is not supported
std::chrono::seconds m_default_packet_timeout;
- uint64_t m_max_packet_size; // as returned by qSupported
+ int m_target_vm_page_size = 0; // target system VM page size; 0 unspecified
+ uint64_t m_max_packet_size = 0; // as returned by qSupported
std::string m_qSupported_response; // the complete response to qSupported
- bool m_supported_async_json_packets_is_valid;
+ bool m_supported_async_json_packets_is_valid = false;
lldb_private::StructuredData::ObjectSP m_supported_async_json_packets_sp;
std::vector<MemoryRegionInfo> m_qXfer_memory_map;
- bool m_qXfer_memory_map_loaded;
+ bool m_qXfer_memory_map_loaded = false;
bool GetCurrentProcessInfo(bool allow_lazy_pid = true);
@@ -603,7 +636,8 @@ protected:
// Given the list of compression types that the remote debug stub can support,
// possibly enable compression if we find an encoding we can handle.
- void MaybeEnableCompression(std::vector<std::string> supported_compressions);
+ void MaybeEnableCompression(
+ llvm::ArrayRef<llvm::StringRef> supported_compressions);
bool DecodeProcessInfoResponse(StringExtractorGDBRemote &response,
ProcessInstanceInfo &process_info);
@@ -612,7 +646,7 @@ protected:
PacketResult SendThreadSpecificPacketAndWaitForResponse(
lldb::tid_t tid, StreamString &&payload,
- StringExtractorGDBRemote &response, bool send_async);
+ StringExtractorGDBRemote &response);
Status SendGetTraceDataPacket(StreamGDBRemote &packet, lldb::user_id_t uid,
lldb::tid_t thread_id,
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
index 3984a45c3da1..d92c97e81659 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
@@ -19,13 +19,12 @@ using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
GDBRemoteCommunicationHistory::GDBRemoteCommunicationHistory(uint32_t size)
- : m_packets(), m_curr_idx(0), m_total_packet_count(0),
- m_dumped_to_log(false) {
+ : m_packets() {
if (size)
m_packets.resize(size);
}
-GDBRemoteCommunicationHistory::~GDBRemoteCommunicationHistory() {}
+GDBRemoteCommunicationHistory::~GDBRemoteCommunicationHistory() = default;
void GDBRemoteCommunicationHistory::AddPacket(char packet_char,
GDBRemotePacket::Type type,
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
index e783e59c3455..eda464a758e4 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
@@ -74,9 +74,9 @@ private:
}
std::vector<GDBRemotePacket> m_packets;
- uint32_t m_curr_idx;
- uint32_t m_total_packet_count;
- mutable bool m_dumped_to_log;
+ uint32_t m_curr_idx = 0;
+ uint32_t m_total_packet_count = 0;
+ mutable bool m_dumped_to_log = false;
repro::PacketRecorder *m_recorder = nullptr;
};
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
index 920327e7d0ab..c91d7cb5ac30 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <errno.h>
+#include <cerrno>
#include "lldb/Host/Config.h"
#include "llvm/ADT/ScopeExit.h"
@@ -74,7 +74,7 @@ GDBRemoteCommunicationReplayServer::GDBRemoteCommunicationReplayServer()
m_async_broadcaster(nullptr, "lldb.gdb-replay.async-broadcaster"),
m_async_listener_sp(
Listener::MakeListener("lldb.gdb-replay.async-listener")),
- m_async_thread_state_mutex(), m_skip_acks(false) {
+ m_async_thread_state_mutex() {
m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue,
"async thread continue");
m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit,
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h
index c13e5ee0bf92..2f8770d0accf 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h
@@ -73,7 +73,7 @@ protected:
HostThread m_async_thread;
std::recursive_mutex m_async_thread_state_mutex;
- bool m_skip_acks;
+ bool m_skip_acks = false;
private:
GDBRemoteCommunicationReplayServer(
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index 60548efc0f33..11cac9fa3a4d 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <errno.h>
+#include <cerrno>
#include "lldb/Host/Config.h"
@@ -16,11 +16,13 @@
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StringExtractorGDBRemote.h"
#include "lldb/Utility/UnimplementedError.h"
+#include "llvm/Support/JSON.h"
#include <cstring>
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
+using namespace llvm;
GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(
const char *comm_name, const char *listener_name)
@@ -31,7 +33,7 @@ GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(
bool &quit) { return this->Handle_QErrorStringEnable(packet); });
}
-GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() {}
+GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() = default;
void GDBRemoteCommunicationServer::RegisterPacketHandler(
StringExtractorGDBRemote::ServerPacketType packet_type,
@@ -151,3 +153,21 @@ GDBRemoteCommunicationServer::SendOKResponse() {
bool GDBRemoteCommunicationServer::HandshakeWithClient() {
return GetAck() == PacketResult::Success;
}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::SendJSONResponse(const json::Value &value) {
+ std::string json_string;
+ raw_string_ostream os(json_string);
+ os << value;
+ os.flush();
+ StreamGDBRemote escaped_response;
+ escaped_response.PutEscapedBytes(json_string.c_str(), json_string.size());
+ return SendPacketNoLock(escaped_response.GetString());
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::SendJSONResponse(Expected<json::Value> value) {
+ if (!value)
+ return SendErrorResponse(value.takeError());
+ return SendJSONResponse(*value);
+}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index a1cf70f9cd1a..68448eae2b9f 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -72,6 +72,13 @@ protected:
PacketResult SendOKResponse();
+ /// Serialize and send a JSON object response.
+ PacketResult SendJSONResponse(const llvm::json::Value &value);
+
+ /// Serialize and send a JSON object response, or respond with an error if the
+ /// input object is an \a llvm::Error.
+ PacketResult SendJSONResponse(llvm::Expected<llvm::json::Value> value);
+
private:
GDBRemoteCommunicationServer(const GDBRemoteCommunicationServer &) = delete;
const GDBRemoteCommunicationServer &
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index 1ca0290eda13..b2b802552720 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -8,7 +8,7 @@
#include "GDBRemoteCommunicationServerCommon.h"
-#include <errno.h>
+#include <cerrno>
#ifdef __APPLE__
#include <TargetConditionals.h>
@@ -60,8 +60,7 @@ GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon(
const char *comm_name, const char *listener_name)
: GDBRemoteCommunicationServer(comm_name, listener_name),
m_process_launch_info(), m_process_launch_error(), m_proc_infos(),
- m_proc_infos_index(0), m_thread_suffix_supported(false),
- m_list_threads_in_stop_reply(false) {
+ m_proc_infos_index(0) {
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_A,
&GDBRemoteCommunicationServerCommon::Handle_A);
RegisterMemberFunctionHandler(
@@ -86,9 +85,6 @@ GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon(
StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess,
&GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply,
- &GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply);
- RegisterMemberFunctionHandler(
StringExtractorGDBRemote::eServerPacketType_qEcho,
&GDBRemoteCommunicationServerCommon::Handle_qEcho);
RegisterMemberFunctionHandler(
@@ -134,9 +130,6 @@ GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon(
StringExtractorGDBRemote::eServerPacketType_qSupported,
&GDBRemoteCommunicationServerCommon::Handle_qSupported);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported,
- &GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported);
- RegisterMemberFunctionHandler(
StringExtractorGDBRemote::eServerPacketType_qUserName,
&GDBRemoteCommunicationServerCommon::Handle_qUserName);
RegisterMemberFunctionHandler(
@@ -175,7 +168,8 @@ GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon(
}
// Destructor
-GDBRemoteCommunicationServerCommon::~GDBRemoteCommunicationServerCommon() {}
+GDBRemoteCommunicationServerCommon::~GDBRemoteCommunicationServerCommon() =
+ default;
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_qHostInfo(
@@ -831,39 +825,10 @@ GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_qSupported(
StringExtractorGDBRemote &packet) {
- StreamGDBRemote response;
-
- // Features common to lldb-platform and llgs.
- uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet
- // size--debugger can always use less
- response.Printf("PacketSize=%x", max_packet_size);
-
- response.PutCString(";QStartNoAckMode+");
- response.PutCString(";QThreadSuffixSupported+");
- response.PutCString(";QListThreadsInStopReply+");
- response.PutCString(";qEcho+");
- response.PutCString(";qXfer:features:read+");
-#if defined(__linux__) || defined(__NetBSD__) || defined(__FreeBSD__)
- response.PutCString(";QPassSignals+");
- response.PutCString(";qXfer:auxv:read+");
- response.PutCString(";qXfer:libraries-svr4:read+");
-#endif
-
- return SendPacketNoLock(response.GetString());
-}
-
-GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported(
- StringExtractorGDBRemote &packet) {
- m_thread_suffix_supported = true;
- return SendOKResponse();
-}
-
-GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply(
- StringExtractorGDBRemote &packet) {
- m_list_threads_in_stop_reply = true;
- return SendOKResponse();
+ // Parse client-indicated features.
+ llvm::SmallVector<llvm::StringRef, 4> client_features;
+ packet.GetStringRef().split(client_features, ';');
+ return SendPacketNoLock(llvm::join(HandleFeatures(client_features), ";"));
}
GDBRemoteCommunication::PacketResult
@@ -1311,3 +1276,16 @@ GDBRemoteCommunicationServerCommon::GetModuleInfo(llvm::StringRef module_path,
return matched_module_spec;
}
+
+std::vector<std::string> GDBRemoteCommunicationServerCommon::HandleFeatures(
+ const llvm::ArrayRef<llvm::StringRef> client_features) {
+ // 128KBytes is a reasonable max packet size--debugger can always use less.
+ constexpr uint32_t max_packet_size = 128 * 1024;
+
+ // Features common to platform server and llgs.
+ return {
+ llvm::formatv("PacketSize={0}", max_packet_size),
+ "QStartNoAckMode+",
+ "qEcho+",
+ };
+}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
index 0f933c09cbd4..ecd80923fcf0 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
@@ -36,8 +36,6 @@ protected:
Status m_process_launch_error;
ProcessInstanceInfoList m_proc_infos;
uint32_t m_proc_infos_index;
- bool m_thread_suffix_supported;
- bool m_list_threads_in_stop_reply;
PacketResult Handle_A(StringExtractorGDBRemote &packet);
@@ -91,10 +89,6 @@ protected:
PacketResult Handle_qSupported(StringExtractorGDBRemote &packet);
- PacketResult Handle_QThreadSuffixSupported(StringExtractorGDBRemote &packet);
-
- PacketResult Handle_QListThreadsInStopReply(StringExtractorGDBRemote &packet);
-
PacketResult Handle_QSetDetachOnError(StringExtractorGDBRemote &packet);
PacketResult Handle_QStartNoAckMode(StringExtractorGDBRemote &packet);
@@ -145,6 +139,11 @@ protected:
virtual FileSpec FindModuleFile(const std::string &module_path,
const ArchSpec &arch);
+ // Process client_features (qSupported) and return an array of server features
+ // to be returned in response.
+ virtual std::vector<std::string>
+ HandleFeatures(llvm::ArrayRef<llvm::StringRef> client_features);
+
private:
ModuleSpec GetModuleInfo(llvm::StringRef module_path, llvm::StringRef triple);
};
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 62a09a2a432c..5e69b5793f9f 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -6,13 +6,14 @@
//
//===----------------------------------------------------------------------===//
-#include <errno.h>
+#include <cerrno>
#include "lldb/Host/Config.h"
#include <chrono>
#include <cstring>
+#include <limits>
#include <thread>
#include "GDBRemoteCommunicationServerLLGS.h"
@@ -70,6 +71,7 @@ GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS(
: GDBRemoteCommunicationServerCommon("gdb-remote.server",
"gdb-remote.server.rx_packet"),
m_mainloop(mainloop), m_process_factory(process_factory),
+ m_current_process(nullptr), m_continue_process(nullptr),
m_stdio_communication("process.stdio") {
RegisterPacketHandlers();
}
@@ -113,6 +115,12 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
&GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir);
RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported,
+ &GDBRemoteCommunicationServerLLGS::Handle_QThreadSuffixSupported);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply,
+ &GDBRemoteCommunicationServerLLGS::Handle_QListThreadsInStopReply);
+ RegisterMemberFunctionHandler(
StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfo,
&GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo);
RegisterMemberFunctionHandler(
@@ -186,27 +194,32 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
&GDBRemoteCommunicationServerLLGS::Handle_QPassSignals);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_jTraceStart,
- &GDBRemoteCommunicationServerLLGS::Handle_jTraceStart);
+ StringExtractorGDBRemote::eServerPacketType_jLLDBTraceSupported,
+ &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupported);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_jTraceBufferRead,
- &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead);
+ StringExtractorGDBRemote::eServerPacketType_jLLDBTraceStart,
+ &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStart);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_jTraceMetaRead,
- &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead);
+ StringExtractorGDBRemote::eServerPacketType_jLLDBTraceStop,
+ &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStop);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_jTraceStop,
- &GDBRemoteCommunicationServerLLGS::Handle_jTraceStop);
+ StringExtractorGDBRemote::eServerPacketType_jLLDBTraceGetState,
+ &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetState);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_jTraceConfigRead,
- &GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead);
- RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_jLLDBTraceSupportedType,
- &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupportedType);
+ StringExtractorGDBRemote::eServerPacketType_jLLDBTraceGetBinaryData,
+ &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetBinaryData);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_g,
&GDBRemoteCommunicationServerLLGS::Handle_g);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qMemTags,
+ &GDBRemoteCommunicationServerLLGS::Handle_qMemTags);
+
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QMemTags,
+ &GDBRemoteCommunicationServerLLGS::Handle_QMemTags);
+
RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k,
[this](StringExtractorGDBRemote packet, Status &error,
bool &interrupt, bool &quit) {
@@ -245,15 +258,18 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
{
std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex);
- assert(!m_debugged_process_up && "lldb-server creating debugged "
- "process but one already exists");
+ assert(m_debugged_processes.empty() && "lldb-server creating debugged "
+ "process but one already exists");
auto process_or =
m_process_factory.Launch(m_process_launch_info, *this, m_mainloop);
if (!process_or)
return Status(process_or.takeError());
- m_debugged_process_up = std::move(*process_or);
+ m_continue_process = m_current_process = process_or->get();
+ m_debugged_processes[m_current_process->GetID()] = std::move(*process_or);
}
+ SetEnabledExtensions(*m_current_process);
+
// Handle mirroring of inferior stdout/stderr over the gdb-remote protocol as
// needed. llgs local-process debugging may specify PTY paths, which will
// make these file actions non-null process launch -i/e/o will also make
@@ -266,10 +282,10 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
LLDB_LOG(log,
"pid = {0}: setting up stdout/stderr redirection via $O "
"gdb-remote commands",
- m_debugged_process_up->GetID());
+ m_current_process->GetID());
// Setup stdout/stderr mapping from inferior to $O
- auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor();
+ auto terminal_fd = m_current_process->GetTerminalFileDescriptor();
if (terminal_fd >= 0) {
LLDB_LOGF(log,
"ProcessGDBRemoteCommunicationServerLLGS::%s setting "
@@ -288,12 +304,12 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
LLDB_LOG(log,
"pid = {0} skipping stdout/stderr redirection via $O: inferior "
"will communicate over client-provided file descriptors",
- m_debugged_process_up->GetID());
+ m_current_process->GetID());
}
printf("Launched '%s' as process %" PRIu64 "...\n",
m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
- m_debugged_process_up->GetID());
+ m_current_process->GetID());
return Status();
}
@@ -305,12 +321,11 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
// Before we try to attach, make sure we aren't already monitoring something
// else.
- if (m_debugged_process_up &&
- m_debugged_process_up->GetID() != LLDB_INVALID_PROCESS_ID)
+ if (!m_debugged_processes.empty())
return Status("cannot attach to process %" PRIu64
" when another process with pid %" PRIu64
" is being debugged.",
- pid, m_debugged_process_up->GetID());
+ pid, m_current_process->GetID());
// Try to attach.
auto process_or = m_process_factory.Attach(pid, *this, m_mainloop);
@@ -320,10 +335,12 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
status);
return status;
}
- m_debugged_process_up = std::move(*process_or);
+ m_continue_process = m_current_process = process_or->get();
+ m_debugged_processes[m_current_process->GetID()] = std::move(*process_or);
+ SetEnabledExtensions(*m_current_process);
// Setup stdout/stderr mapping from inferior.
- auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor();
+ auto terminal_fd = m_current_process->GetTerminalFileDescriptor();
if (terminal_fd >= 0) {
LLDB_LOGF(log,
"ProcessGDBRemoteCommunicationServerLLGS::%s setting "
@@ -648,6 +665,14 @@ static const char *GetStopReasonString(StopReason stop_reason) {
return "exception";
case eStopReasonExec:
return "exec";
+ case eStopReasonProcessorTrace:
+ return "processor trace";
+ case eStopReasonFork:
+ return "fork";
+ case eStopReasonVFork:
+ return "vfork";
+ case eStopReasonVForkDone:
+ return "vforkdone";
case eStopReasonInstrumentation:
case eStopReasonInvalid:
case eStopReasonPlanComplete:
@@ -736,15 +761,15 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
// Ensure we have a debugged process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(50);
LLDB_LOG(log, "preparing packet for pid {0} tid {1}",
- m_debugged_process_up->GetID(), tid);
+ m_current_process->GetID(), tid);
// Ensure we can get info on the given thread.
- NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid);
+ NativeThreadProtocol *thread = m_current_process->GetThreadByID(tid);
if (!thread)
return SendErrorResponse(51);
@@ -767,7 +792,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
LLDB_LOG(
log,
"pid {0}, tid {1}, got signal signo = {2}, reason = {3}, exc_type = {4}",
- m_debugged_process_up->GetID(), tid, signum, int(tid_stop_info.reason),
+ m_current_process->GetID(), tid, signum, int(tid_stop_info.reason),
tid_stop_info.details.exception.type);
// Print the signal number.
@@ -805,9 +830,9 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
uint32_t thread_index = 0;
NativeThreadProtocol *listed_thread;
- for (listed_thread = m_debugged_process_up->GetThreadAtIndex(thread_index);
+ for (listed_thread = m_current_process->GetThreadAtIndex(thread_index);
listed_thread; ++thread_index,
- listed_thread = m_debugged_process_up->GetThreadAtIndex(thread_index)) {
+ listed_thread = m_current_process->GetThreadAtIndex(thread_index)) {
if (thread_index > 0)
response.PutChar(',');
response.Printf("%" PRIx64, listed_thread->GetID());
@@ -822,7 +847,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
if (thread_index > 1) {
const bool threads_with_valid_stop_info_only = true;
llvm::Expected<json::Array> threads_info = GetJSONThreadsInfo(
- *m_debugged_process_up, threads_with_valid_stop_info_only);
+ *m_current_process, threads_with_valid_stop_info_only);
if (threads_info) {
response.PutCString("jstopinfo:");
StreamString unescaped_response;
@@ -832,7 +857,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
} else {
LLDB_LOG_ERROR(log, threads_info.takeError(),
"failed to prepare a jstopinfo field for pid {1}: {0}",
- m_debugged_process_up->GetID());
+ m_current_process->GetID());
}
}
@@ -840,8 +865,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
response.PutCString("thread-pcs");
char delimiter = ':';
for (NativeThreadProtocol *thread;
- (thread = m_debugged_process_up->GetThreadAtIndex(i)) != nullptr;
- ++i) {
+ (thread = m_current_process->GetThreadAtIndex(i)) != nullptr; ++i) {
NativeRegisterContext& reg_ctx = thread->GetRegisterContext();
uint32_t reg_to_read = reg_ctx.ConvertRegisterKindToRegisterNumber(
@@ -924,6 +948,22 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
}
}
+ // Include child process PID/TID for forks.
+ if (tid_stop_info.reason == eStopReasonFork ||
+ tid_stop_info.reason == eStopReasonVFork) {
+ assert(bool(m_extensions_supported &
+ NativeProcessProtocol::Extension::multiprocess));
+ if (tid_stop_info.reason == eStopReasonFork)
+ assert(bool(m_extensions_supported &
+ NativeProcessProtocol::Extension::fork));
+ if (tid_stop_info.reason == eStopReasonVFork)
+ assert(bool(m_extensions_supported &
+ NativeProcessProtocol::Extension::vfork));
+ response.Printf("%s:p%" PRIx64 ".%" PRIx64 ";", reason_str,
+ tid_stop_info.details.fork.child_pid,
+ tid_stop_info.details.fork.child_tid);
+ }
+
return SendPacketNoLock(response.GetString());
}
@@ -1028,6 +1068,15 @@ void GDBRemoteCommunicationServerLLGS::DidExec(NativeProcessProtocol *process) {
ClearProcessSpecificData();
}
+void GDBRemoteCommunicationServerLLGS::NewSubprocess(
+ NativeProcessProtocol *parent_process,
+ std::unique_ptr<NativeProcessProtocol> child_process) {
+ lldb::pid_t child_pid = child_process->GetID();
+ assert(child_pid != LLDB_INVALID_PROCESS_ID);
+ assert(m_debugged_processes.find(child_pid) == m_debugged_processes.end());
+ m_debugged_processes[child_pid] = std::move(child_process);
+}
+
void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() {
Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_COMM));
@@ -1170,266 +1219,110 @@ void GDBRemoteCommunicationServerLLGS::SendProcessOutput() {
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_jTraceStart(
+GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupported(
StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- // Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse(68);
- if (!packet.ConsumeFront("jTraceStart:"))
- return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet ");
-
- TraceOptions options;
- uint64_t type = std::numeric_limits<uint64_t>::max();
- uint64_t buffersize = std::numeric_limits<uint64_t>::max();
- lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
- uint64_t metabuffersize = std::numeric_limits<uint64_t>::max();
-
- auto json_object = StructuredData::ParseJSON(packet.Peek());
-
- if (!json_object ||
- json_object->GetType() != lldb::eStructuredDataTypeDictionary)
- return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet ");
-
- auto json_dict = json_object->GetAsDictionary();
-
- json_dict->GetValueForKeyAsInteger("metabuffersize", metabuffersize);
- options.setMetaDataBufferSize(metabuffersize);
-
- json_dict->GetValueForKeyAsInteger("buffersize", buffersize);
- options.setTraceBufferSize(buffersize);
-
- json_dict->GetValueForKeyAsInteger("type", type);
- options.setType(static_cast<lldb::TraceType>(type));
-
- json_dict->GetValueForKeyAsInteger("threadid", tid);
- options.setThreadID(tid);
-
- StructuredData::ObjectSP custom_params_sp =
- json_dict->GetValueForKey("params");
- if (custom_params_sp &&
- custom_params_sp->GetType() != lldb::eStructuredDataTypeDictionary)
- return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet ");
-
- options.setTraceParams(
- std::static_pointer_cast<StructuredData::Dictionary>(custom_params_sp));
-
- if (buffersize == std::numeric_limits<uint64_t>::max() ||
- type != lldb::TraceType::eTraceTypeProcessorTrace) {
- LLDB_LOG(log, "Ill formed packet buffersize = {0} type = {1}", buffersize,
- type);
- return SendIllFormedResponse(packet, "JTrace:start: Ill formed packet ");
- }
-
- Status error;
- lldb::user_id_t uid = LLDB_INVALID_UID;
- uid = m_debugged_process_up->StartTrace(options, error);
- LLDB_LOG(log, "uid is {0} , error is {1}", uid, error.GetError());
- if (error.Fail())
- return SendErrorResponse(error);
+ // Fail if we don't have a current process.
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(Status("Process not running."));
- StreamGDBRemote response;
- response.Printf("%" PRIx64, uid);
- return SendPacketNoLock(response.GetString());
+ return SendJSONResponse(m_current_process->TraceSupported());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_jTraceStop(
+GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStop(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse(68);
-
- if (!packet.ConsumeFront("jTraceStop:"))
- return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet ");
-
- lldb::user_id_t uid = LLDB_INVALID_UID;
- lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
-
- auto json_object = StructuredData::ParseJSON(packet.Peek());
-
- if (!json_object ||
- json_object->GetType() != lldb::eStructuredDataTypeDictionary)
- return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet ");
-
- auto json_dict = json_object->GetAsDictionary();
-
- if (!json_dict->GetValueForKeyAsInteger("traceid", uid))
- return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet ");
-
- json_dict->GetValueForKeyAsInteger("threadid", tid);
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(Status("Process not running."));
- Status error = m_debugged_process_up->StopTrace(uid, tid);
+ packet.ConsumeFront("jLLDBTraceStop:");
+ Expected<TraceStopRequest> stop_request =
+ json::parse<TraceStopRequest>(packet.Peek(), "TraceStopRequest");
+ if (!stop_request)
+ return SendErrorResponse(stop_request.takeError());
- if (error.Fail())
- return SendErrorResponse(error);
+ if (Error err = m_current_process->TraceStop(*stop_request))
+ return SendErrorResponse(std::move(err));
return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupportedType(
+GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStart(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(Status("Process not running."));
- llvm::Expected<TraceTypeInfo> supported_trace_type =
- m_debugged_process_up->GetSupportedTraceType();
- if (!supported_trace_type)
- return SendErrorResponse(supported_trace_type.takeError());
+ packet.ConsumeFront("jLLDBTraceStart:");
+ Expected<TraceStartRequest> request =
+ json::parse<TraceStartRequest>(packet.Peek(), "TraceStartRequest");
+ if (!request)
+ return SendErrorResponse(request.takeError());
- StreamGDBRemote escaped_response;
- StructuredData::Dictionary json_packet;
+ if (Error err = m_current_process->TraceStart(packet.Peek(), request->type))
+ return SendErrorResponse(std::move(err));
- json_packet.AddStringItem("name", supported_trace_type->name);
- json_packet.AddStringItem("description", supported_trace_type->description);
-
- StreamString json_string;
- json_packet.Dump(json_string, false);
- escaped_response.PutEscapedBytes(json_string.GetData(),
- json_string.GetSize());
- return SendPacketNoLock(escaped_response.GetString());
+ return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead(
+GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetState(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse(68);
-
- if (!packet.ConsumeFront("jTraceConfigRead:"))
- return SendIllFormedResponse(packet,
- "jTraceConfigRead: Ill formed packet ");
-
- lldb::user_id_t uid = LLDB_INVALID_UID;
- lldb::tid_t threadid = LLDB_INVALID_THREAD_ID;
-
- auto json_object = StructuredData::ParseJSON(packet.Peek());
-
- if (!json_object ||
- json_object->GetType() != lldb::eStructuredDataTypeDictionary)
- return SendIllFormedResponse(packet,
- "jTraceConfigRead: Ill formed packet ");
-
- auto json_dict = json_object->GetAsDictionary();
-
- if (!json_dict->GetValueForKeyAsInteger("traceid", uid))
- return SendIllFormedResponse(packet,
- "jTraceConfigRead: Ill formed packet ");
-
- json_dict->GetValueForKeyAsInteger("threadid", threadid);
-
- TraceOptions options;
- StreamGDBRemote response;
-
- options.setThreadID(threadid);
- Status error = m_debugged_process_up->GetTraceConfig(uid, options);
-
- if (error.Fail())
- return SendErrorResponse(error);
-
- StreamGDBRemote escaped_response;
- StructuredData::Dictionary json_packet;
-
- json_packet.AddIntegerItem("type", options.getType());
- json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize());
- json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize());
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(Status("Process not running."));
- StructuredData::DictionarySP custom_params = options.getTraceParams();
- if (custom_params)
- json_packet.AddItem("params", custom_params);
+ packet.ConsumeFront("jLLDBTraceGetState:");
+ Expected<TraceGetStateRequest> request =
+ json::parse<TraceGetStateRequest>(packet.Peek(), "TraceGetStateRequest");
+ if (!request)
+ return SendErrorResponse(request.takeError());
- StreamString json_string;
- json_packet.Dump(json_string, false);
- escaped_response.PutEscapedBytes(json_string.GetData(),
- json_string.GetSize());
- return SendPacketNoLock(escaped_response.GetString());
+ return SendJSONResponse(m_current_process->TraceGetState(request->type));
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_jTraceRead(
+GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetBinaryData(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse(68);
-
- enum PacketType { MetaData, BufferData };
- PacketType tracetype = MetaData;
-
- if (packet.ConsumeFront("jTraceBufferRead:"))
- tracetype = BufferData;
- else if (packet.ConsumeFront("jTraceMetaRead:"))
- tracetype = MetaData;
- else {
- return SendIllFormedResponse(packet, "jTrace: Ill formed packet ");
- }
-
- lldb::user_id_t uid = LLDB_INVALID_UID;
-
- uint64_t byte_count = std::numeric_limits<uint64_t>::max();
- lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
- uint64_t offset = std::numeric_limits<uint64_t>::max();
-
- auto json_object = StructuredData::ParseJSON(packet.Peek());
-
- if (!json_object ||
- json_object->GetType() != lldb::eStructuredDataTypeDictionary)
- return SendIllFormedResponse(packet, "jTrace: Ill formed packet ");
-
- auto json_dict = json_object->GetAsDictionary();
-
- if (!json_dict->GetValueForKeyAsInteger("traceid", uid) ||
- !json_dict->GetValueForKeyAsInteger("offset", offset) ||
- !json_dict->GetValueForKeyAsInteger("buffersize", byte_count))
- return SendIllFormedResponse(packet, "jTrace: Ill formed packet ");
-
- json_dict->GetValueForKeyAsInteger("threadid", tid);
-
- // Allocate the response buffer.
- std::unique_ptr<uint8_t[]> buffer (new (std::nothrow) uint8_t[byte_count]);
- if (!buffer)
- return SendErrorResponse(0x78);
-
- StreamGDBRemote response;
- Status error;
- llvm::MutableArrayRef<uint8_t> buf(buffer.get(), byte_count);
-
- if (tracetype == BufferData)
- error = m_debugged_process_up->GetData(uid, tid, buf, offset);
- else if (tracetype == MetaData)
- error = m_debugged_process_up->GetMetaData(uid, tid, buf, offset);
-
- if (error.Fail())
- return SendErrorResponse(error);
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(Status("Process not running."));
- for (auto i : buf)
- response.PutHex8(i);
+ packet.ConsumeFront("jLLDBTraceGetBinaryData:");
+ llvm::Expected<TraceGetBinaryDataRequest> request =
+ llvm::json::parse<TraceGetBinaryDataRequest>(packet.Peek(),
+ "TraceGetBinaryDataRequest");
+ if (!request)
+ return SendErrorResponse(Status(request.takeError()));
- StreamGDBRemote escaped_response;
- escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
- return SendPacketNoLock(escaped_response.GetString());
+ if (Expected<std::vector<uint8_t>> bytes =
+ m_current_process->TraceGetBinaryData(*request)) {
+ StreamGDBRemote response;
+ response.PutEscapedBytes(bytes->data(), bytes->size());
+ return SendPacketNoLock(response.GetString());
+ } else
+ return SendErrorResponse(bytes.takeError());
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(68);
- lldb::pid_t pid = m_debugged_process_up->GetID();
+ lldb::pid_t pid = m_current_process->GetID();
if (pid == LLDB_INVALID_PROCESS_ID)
return SendErrorResponse(1);
@@ -1446,16 +1339,16 @@ GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(68);
// Make sure we set the current thread so g and p packets return the data the
// gdb will expect.
- lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID();
+ lldb::tid_t tid = m_current_process->GetCurrentThreadID();
SetCurrentThreadID(tid);
- NativeThreadProtocol *thread = m_debugged_process_up->GetCurrentThread();
+ NativeThreadProtocol *thread = m_current_process->GetCurrentThread();
if (!thread)
return SendErrorResponse(69);
@@ -1471,15 +1364,15 @@ GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) {
StopSTDIOForwarding();
- if (!m_debugged_process_up) {
+ if (!m_current_process) {
LLDB_LOG(log, "No debugged process found.");
return PacketResult::Success;
}
- Status error = m_debugged_process_up->Kill();
+ Status error = m_current_process->Kill();
if (error.Fail())
LLDB_LOG(log, "Failed to kill debugged process {0}: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
// No OK response for kill packet.
// return SendOKResponse ();
@@ -1521,12 +1414,26 @@ GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir(
}
GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_QThreadSuffixSupported(
+ StringExtractorGDBRemote &packet) {
+ m_thread_suffix_supported = true;
+ return SendOKResponse();
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_QListThreadsInStopReply(
+ StringExtractorGDBRemote &packet) {
+ m_list_threads_in_stop_reply = true;
+ return SendOKResponse();
+}
+
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
// Ensure we have a native process.
- if (!m_debugged_process_up) {
+ if (!m_continue_process) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s no debugged process "
"shared pointer",
@@ -1579,20 +1486,20 @@ GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) {
} else {
// Send the signal to the process since we weren't targeting a specific
// continue thread with the signal.
- error = m_debugged_process_up->Signal(signo);
+ error = m_continue_process->Signal(signo);
if (error.Fail()) {
LLDB_LOG(log, "failed to send signal for process {0}: {1}",
- m_debugged_process_up->GetID(), error);
+ m_continue_process->GetID(), error);
return SendErrorResponse(0x52);
}
}
// Resume the threads.
- error = m_debugged_process_up->Resume(resume_actions);
+ error = m_continue_process->Resume(resume_actions);
if (error.Fail()) {
LLDB_LOG(log, "failed to resume threads for process {0}: {1}",
- m_debugged_process_up->GetID(), error);
+ m_continue_process->GetID(), error);
return SendErrorResponse(0x38);
}
@@ -1617,7 +1524,7 @@ GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) {
}
// Ensure we have a native process.
- if (!m_debugged_process_up) {
+ if (!m_continue_process) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s no debugged process "
"shared pointer",
@@ -1629,14 +1536,14 @@ GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) {
ResumeActionList actions(StateType::eStateRunning,
LLDB_INVALID_SIGNAL_NUMBER);
- Status error = m_debugged_process_up->Resume(actions);
+ Status error = m_continue_process->Resume(actions);
if (error.Fail()) {
- LLDB_LOG(log, "c failed for process {0}: {1}",
- m_debugged_process_up->GetID(), error);
+ LLDB_LOG(log, "c failed for process {0}: {1}", m_continue_process->GetID(),
+ error);
return SendErrorResponse(GDBRemoteServerError::eErrorResume);
}
- LLDB_LOG(log, "continued process {0}", m_debugged_process_up->GetID());
+ LLDB_LOG(log, "continued process {0}", m_continue_process->GetID());
// No response required from continue.
return PacketResult::Success;
}
@@ -1679,7 +1586,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont(
}
// Ensure we have a native process.
- if (!m_debugged_process_up) {
+ if (!m_continue_process) {
LLDB_LOG(log, "no debugged process");
return SendErrorResponse(0x36);
}
@@ -1732,23 +1639,27 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont(
// Consume the separator.
packet.GetChar();
- thread_action.tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID);
- if (thread_action.tid == LLDB_INVALID_THREAD_ID)
- return SendIllFormedResponse(
- packet, "Could not parse thread number in vCont packet");
+ llvm::Expected<lldb::tid_t> tid_ret =
+ ReadTid(packet, /*allow_all=*/true, m_continue_process->GetID());
+ if (!tid_ret)
+ return SendErrorResponse(tid_ret.takeError());
+
+ thread_action.tid = tid_ret.get();
+ if (thread_action.tid == StringExtractorGDBRemote::AllThreads)
+ thread_action.tid = LLDB_INVALID_THREAD_ID;
}
thread_actions.Append(thread_action);
}
- Status error = m_debugged_process_up->Resume(thread_actions);
+ Status error = m_continue_process->Resume(thread_actions);
if (error.Fail()) {
LLDB_LOG(log, "vCont failed for process {0}: {1}",
- m_debugged_process_up->GetID(), error);
+ m_continue_process->GetID(), error);
return SendErrorResponse(GDBRemoteServerError::eErrorResume);
}
- LLDB_LOG(log, "continued process {0}", m_debugged_process_up->GetID());
+ LLDB_LOG(log, "continued process {0}", m_continue_process->GetID());
// No response required from vCont.
return PacketResult::Success;
}
@@ -1758,8 +1669,8 @@ void GDBRemoteCommunicationServerLLGS::SetCurrentThreadID(lldb::tid_t tid) {
LLDB_LOG(log, "setting current thread id to {0}", tid);
m_current_tid = tid;
- if (m_debugged_process_up)
- m_debugged_process_up->SetCurrentThreadID(m_current_tid);
+ if (m_current_process)
+ m_current_process->SetCurrentThreadID(m_current_tid);
}
void GDBRemoteCommunicationServerLLGS::SetContinueThreadID(lldb::tid_t tid) {
@@ -1775,10 +1686,10 @@ GDBRemoteCommunicationServerLLGS::Handle_stop_reason(
// Handle the $? gdbremote command.
// If no process, indicate error
- if (!m_debugged_process_up)
+ if (!m_current_process)
return SendErrorResponse(02);
- return SendStopReasonForState(m_debugged_process_up->GetState());
+ return SendStopReasonForState(m_current_process->GetState());
}
GDBRemoteCommunication::PacketResult
@@ -1799,8 +1710,8 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState(
case eStateSuspended:
case eStateStopped:
case eStateCrashed: {
- assert(m_debugged_process_up != nullptr);
- lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID();
+ assert(m_current_process != nullptr);
+ lldb::tid_t tid = m_current_process->GetCurrentThreadID();
// Make sure we set the current thread so g and p packets return the data
// the gdb will expect.
SetCurrentThreadID(tid);
@@ -1810,11 +1721,11 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState(
case eStateInvalid:
case eStateUnloaded:
case eStateExited:
- return SendWResponse(m_debugged_process_up.get());
+ return SendWResponse(m_current_process);
default:
LLDB_LOG(log, "pid {0}, current state reporting not handled: {1}",
- m_debugged_process_up->GetID(), process_state);
+ m_current_process->GetID(), process_state);
break;
}
@@ -1825,12 +1736,12 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(68);
// Ensure we have a thread.
- NativeThreadProtocol *thread = m_debugged_process_up->GetThreadAtIndex(0);
+ NativeThreadProtocol *thread = m_current_process->GetThreadAtIndex(0);
if (!thread)
return SendErrorResponse(69);
@@ -1925,11 +1836,11 @@ GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo(
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOG(log, "no process ({0}), returning OK",
- m_debugged_process_up ? "invalid process id"
- : "null m_debugged_process_up");
+ m_current_process ? "invalid process id"
+ : "null m_current_process");
return SendOKResponse();
}
@@ -1940,9 +1851,9 @@ GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo(
NativeThreadProtocol *thread;
uint32_t thread_index;
for (thread_index = 0,
- thread = m_debugged_process_up->GetThreadAtIndex(thread_index);
+ thread = m_current_process->GetThreadAtIndex(thread_index);
thread; ++thread_index,
- thread = m_debugged_process_up->GetThreadAtIndex(thread_index)) {
+ thread = m_current_process->GetThreadAtIndex(thread_index)) {
LLDB_LOG(log, "iterated thread {0}(tid={2})", thread_index,
thread->GetID());
if (thread_index > 0)
@@ -2163,9 +2074,8 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) {
// Build the reginfos response.
StreamGDBRemote response;
- RegisterValue reg_value(
- makeArrayRef(reg_bytes, reg_size),
- m_debugged_process_up->GetArchitecture().GetByteOrder());
+ RegisterValue reg_value(makeArrayRef(reg_bytes, reg_size),
+ m_current_process->GetArchitecture().GetByteOrder());
Status error = reg_context.WriteRegister(reg_info, reg_value);
if (error.Fail()) {
LLDB_LOGF(log,
@@ -2182,16 +2092,6 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
- // Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
- LLDB_LOGF(
- log,
- "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
- __FUNCTION__);
- return SendErrorResponse(0x15);
- }
-
// Parse out which variant of $H is requested.
packet.SetFilePos(strlen("H"));
if (packet.GetBytesLeft() < 1) {
@@ -2203,11 +2103,14 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
}
const char h_variant = packet.GetChar();
+ NativeProcessProtocol *default_process;
switch (h_variant) {
case 'g':
+ default_process = m_current_process;
break;
case 'c':
+ default_process = m_continue_process;
break;
default:
@@ -2220,14 +2123,32 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
}
// Parse out the thread number.
- // FIXME return a parse success/fail value. All values are valid here.
- const lldb::tid_t tid =
- packet.GetHexMaxU64(false, std::numeric_limits<lldb::tid_t>::max());
+ auto pid_tid = packet.GetPidTid(default_process ? default_process->GetID()
+ : LLDB_INVALID_PROCESS_ID);
+ if (!pid_tid)
+ return SendErrorResponse(llvm::make_error<StringError>(
+ inconvertibleErrorCode(), "Malformed thread-id"));
+
+ lldb::pid_t pid = pid_tid->first;
+ lldb::tid_t tid = pid_tid->second;
+
+ if (pid == StringExtractorGDBRemote::AllProcesses)
+ return SendUnimplementedResponse("Selecting all processes not supported");
+ if (pid == LLDB_INVALID_PROCESS_ID)
+ return SendErrorResponse(llvm::make_error<StringError>(
+ inconvertibleErrorCode(), "No current process and no PID provided"));
+
+ // Check the process ID and find respective process instance.
+ auto new_process_it = m_debugged_processes.find(pid);
+ if (new_process_it == m_debugged_processes.end())
+ return SendErrorResponse(llvm::make_error<StringError>(
+ inconvertibleErrorCode(),
+ llvm::formatv("No process with PID {0} debugged", pid)));
// Ensure we have the given thread when not specifying -1 (all threads) or 0
// (any thread).
if (tid != LLDB_INVALID_THREAD_ID && tid != 0) {
- NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid);
+ NativeThreadProtocol *thread = new_process_it->second->GetThreadByID(tid);
if (!thread) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64
@@ -2237,13 +2158,15 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
}
}
- // Now switch the given thread type.
+ // Now switch the given process and thread type.
switch (h_variant) {
case 'g':
+ m_current_process = new_process_it->second.get();
SetCurrentThreadID(tid);
break;
case 'c':
+ m_continue_process = new_process_it->second.get();
SetContinueThreadID(tid);
break;
@@ -2261,8 +2184,8 @@ GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2297,21 +2220,21 @@ GDBRemoteCommunicationServerLLGS::Handle_interrupt(
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOG(log, "failed, no process available");
return SendErrorResponse(0x15);
}
// Interrupt the process.
- Status error = m_debugged_process_up->Interrupt();
+ Status error = m_current_process->Interrupt();
if (error.Fail()) {
- LLDB_LOG(log, "failed for process {0}: {1}", m_debugged_process_up->GetID(),
+ LLDB_LOG(log, "failed for process {0}: {1}", m_current_process->GetID(),
error);
return SendErrorResponse(GDBRemoteServerError::eErrorResume);
}
- LLDB_LOG(log, "stopped process {0}", m_debugged_process_up->GetID());
+ LLDB_LOG(log, "stopped process {0}", m_current_process->GetID());
// No response required from stop all.
return PacketResult::Success;
@@ -2322,8 +2245,8 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read(
StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2365,13 +2288,13 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read(
// Retrieve the process memory.
size_t bytes_read = 0;
- Status error = m_debugged_process_up->ReadMemoryWithoutTrap(
+ Status error = m_current_process->ReadMemoryWithoutTrap(
read_addr, &buf[0], byte_count, bytes_read);
if (error.Fail()) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
" mem 0x%" PRIx64 ": failed to read. Error: %s",
- __FUNCTION__, m_debugged_process_up->GetID(), read_addr,
+ __FUNCTION__, m_current_process->GetID(), read_addr,
error.AsCString());
return SendErrorResponse(0x08);
}
@@ -2380,8 +2303,7 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read(
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
" mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes",
- __FUNCTION__, m_debugged_process_up->GetID(), read_addr,
- byte_count);
+ __FUNCTION__, m_current_process->GetID(), read_addr, byte_count);
return SendErrorResponse(0x08);
}
@@ -2403,8 +2325,8 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle__M(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2439,8 +2361,7 @@ GDBRemoteCommunicationServerLLGS::Handle__M(StringExtractorGDBRemote &packet) {
}
}
- llvm::Expected<addr_t> addr =
- m_debugged_process_up->AllocateMemory(size, perms);
+ llvm::Expected<addr_t> addr = m_current_process->AllocateMemory(size, perms);
if (!addr)
return SendErrorResponse(addr.takeError());
@@ -2453,8 +2374,8 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle__m(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2471,7 +2392,7 @@ GDBRemoteCommunicationServerLLGS::Handle__m(StringExtractorGDBRemote &packet) {
if (addr == LLDB_INVALID_ADDRESS)
return SendIllFormedResponse(packet, "Address not valid");
- if (llvm::Error Err = m_debugged_process_up->DeallocateMemory(addr))
+ if (llvm::Error Err = m_current_process->DeallocateMemory(addr))
return SendErrorResponse(std::move(Err));
return SendOKResponse();
@@ -2481,8 +2402,8 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2531,8 +2452,7 @@ GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) {
LLDB_LOG(log,
"pid {0} mem {1:x}: asked to write {2} bytes, but only found {3} "
"to convert.",
- m_debugged_process_up->GetID(), write_addr, byte_count,
- convert_count);
+ m_current_process->GetID(), write_addr, byte_count, convert_count);
return SendIllFormedResponse(packet, "M content byte length specified did "
"not match hex-encoded content "
"length");
@@ -2540,17 +2460,17 @@ GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) {
// Write the process memory.
size_t bytes_written = 0;
- Status error = m_debugged_process_up->WriteMemory(write_addr, &buf[0],
- byte_count, bytes_written);
+ Status error = m_current_process->WriteMemory(write_addr, &buf[0], byte_count,
+ bytes_written);
if (error.Fail()) {
LLDB_LOG(log, "pid {0} mem {1:x}: failed to write. Error: {2}",
- m_debugged_process_up->GetID(), write_addr, error);
+ m_current_process->GetID(), write_addr, error);
return SendErrorResponse(0x09);
}
if (bytes_written == 0) {
LLDB_LOG(log, "pid {0} mem {1:x}: wrote 0 of {2} requested bytes",
- m_debugged_process_up->GetID(), write_addr, byte_count);
+ m_current_process->GetID(), write_addr, byte_count);
return SendErrorResponse(0x09);
}
@@ -2569,8 +2489,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported(
// Ensure we have a process running; otherwise, we can't figure this out
// since we won't have a NativeProcessProtocol.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2580,8 +2500,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported(
// Test if we can get any region back when asking for the region around NULL.
MemoryRegionInfo region_info;
- const Status error =
- m_debugged_process_up->GetMemoryRegionInfo(0, region_info);
+ const Status error = m_current_process->GetMemoryRegionInfo(0, region_info);
if (error.Fail()) {
// We don't support memory region info collection for this
// NativeProcessProtocol.
@@ -2597,8 +2516,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo(
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
// Ensure we have a process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2619,7 +2538,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo(
// Get the memory region info for the target address.
MemoryRegionInfo region_info;
const Status error =
- m_debugged_process_up->GetMemoryRegionInfo(read_addr, region_info);
+ m_current_process->GetMemoryRegionInfo(read_addr, region_info);
if (error.Fail()) {
// Return the error message.
@@ -2674,8 +2593,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
// Ensure we have a process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
LLDB_LOG(log, "failed, no process available");
return SendErrorResponse(0x15);
@@ -2745,22 +2664,22 @@ GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
if (want_breakpoint) {
// Try to set the breakpoint.
const Status error =
- m_debugged_process_up->SetBreakpoint(addr, size, want_hardware);
+ m_current_process->SetBreakpoint(addr, size, want_hardware);
if (error.Success())
return SendOKResponse();
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
LLDB_LOG(log, "pid {0} failed to set breakpoint: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
return SendErrorResponse(0x09);
} else {
// Try to set the watchpoint.
- const Status error = m_debugged_process_up->SetWatchpoint(
+ const Status error = m_current_process->SetWatchpoint(
addr, size, watch_flags, want_hardware);
if (error.Success())
return SendOKResponse();
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
LLDB_LOG(log, "pid {0} failed to set watchpoint: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
return SendErrorResponse(0x09);
}
}
@@ -2768,8 +2687,8 @@ GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
// Ensure we have a process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
LLDB_LOG(log, "failed, no process available");
return SendErrorResponse(0x15);
@@ -2833,21 +2752,21 @@ GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
if (want_breakpoint) {
// Try to clear the breakpoint.
const Status error =
- m_debugged_process_up->RemoveBreakpoint(addr, want_hardware);
+ m_current_process->RemoveBreakpoint(addr, want_hardware);
if (error.Success())
return SendOKResponse();
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
LLDB_LOG(log, "pid {0} failed to remove breakpoint: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
return SendErrorResponse(0x09);
} else {
// Try to clear the watchpoint.
- const Status error = m_debugged_process_up->RemoveWatchpoint(addr);
+ const Status error = m_current_process->RemoveWatchpoint(addr);
if (error.Success())
return SendOKResponse();
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
LLDB_LOG(log, "pid {0} failed to remove watchpoint: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
return SendErrorResponse(0x09);
}
}
@@ -2857,8 +2776,8 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
// Ensure we have a process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_continue_process ||
+ (m_continue_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2876,7 +2795,7 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
// Double check that we have such a thread.
// TODO investigate: on MacOSX we might need to do an UpdateThreads () here.
- NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid);
+ NativeThreadProtocol *thread = m_continue_process->GetThreadByID(tid);
if (!thread)
return SendErrorResponse(0x33);
@@ -2889,12 +2808,12 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
// All other threads stop while we're single stepping a thread.
actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
- Status error = m_debugged_process_up->Resume(actions);
+ Status error = m_continue_process->Resume(actions);
if (error.Fail()) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
" tid %" PRIu64 " Resume() failed with error: %s",
- __FUNCTION__, m_debugged_process_up->GetID(), tid,
+ __FUNCTION__, m_continue_process->GetID(), tid,
error.AsCString());
return SendErrorResponse(0x49);
}
@@ -2906,7 +2825,7 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
GDBRemoteCommunicationServerLLGS::BuildTargetXml() {
// Ensure we have a thread.
- NativeThreadProtocol *thread = m_debugged_process_up->GetThreadAtIndex(0);
+ NativeThreadProtocol *thread = m_current_process->GetThreadAtIndex(0);
if (!thread)
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"No thread available");
@@ -2921,7 +2840,7 @@ GDBRemoteCommunicationServerLLGS::BuildTargetXml() {
response.Printf("<target version=\"1.0\">");
response.Printf("<architecture>%s</architecture>",
- m_debugged_process_up->GetArchitecture()
+ m_current_process->GetArchitecture()
.GetTriple()
.getArchName()
.str()
@@ -3010,22 +2929,22 @@ llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
GDBRemoteCommunicationServerLLGS::ReadXferObject(llvm::StringRef object,
llvm::StringRef annex) {
// Make sure we have a valid process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"No process available");
}
if (object == "auxv") {
// Grab the auxv data.
- auto buffer_or_error = m_debugged_process_up->GetAuxvData();
+ auto buffer_or_error = m_current_process->GetAuxvData();
if (!buffer_or_error)
return llvm::errorCodeToError(buffer_or_error.getError());
return std::move(*buffer_or_error);
}
if (object == "libraries-svr4") {
- auto library_list = m_debugged_process_up->GetLoadedSVR4Libraries();
+ auto library_list = m_current_process->GetLoadedSVR4Libraries();
if (!library_list)
return library_list.takeError();
@@ -3148,7 +3067,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState(
Status error = reg_context.ReadAllRegisterValues(register_data_sp);
if (error.Fail()) {
LLDB_LOG(log, "pid {0} failed to save all register values: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
return SendErrorResponse(0x75);
}
@@ -3211,7 +3130,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState(
if (it == m_saved_registers_map.end()) {
LLDB_LOG(log,
"pid {0} does not have a register set save buffer for id {1}",
- m_debugged_process_up->GetID(), save_id);
+ m_current_process->GetID(), save_id);
return SendErrorResponse(0x77);
}
register_data_sp = it->second;
@@ -3223,7 +3142,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState(
Status error = reg_context.WriteAllRegisterValues(register_data_sp);
if (error.Fail()) {
LLDB_LOG(log, "pid {0} failed to restore all register values: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
return SendErrorResponse(0x77);
}
@@ -3263,7 +3182,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttach(
}
// Notify we attached by sending a stop packet.
- return SendStopReasonForState(m_debugged_process_up->GetState());
+ return SendStopReasonForState(m_current_process->GetState());
}
GDBRemoteCommunication::PacketResult
@@ -3293,7 +3212,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttachWait(
}
// Notify we attached by sending a stop packet.
- return SendStopReasonForState(m_debugged_process_up->GetState());
+ return SendStopReasonForState(m_current_process->GetState());
}
GDBRemoteCommunication::PacketResult
@@ -3329,25 +3248,13 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttachOrWait(
}
// Notify we attached by sending a stop packet.
- return SendStopReasonForState(m_debugged_process_up->GetState());
+ return SendStopReasonForState(m_current_process->GetState());
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
-
StopSTDIOForwarding();
- // Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
- LLDB_LOGF(
- log,
- "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
- __FUNCTION__);
- return SendErrorResponse(0x15);
- }
-
lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
// Consume the ';' after D.
@@ -3362,19 +3269,32 @@ GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) {
return SendIllFormedResponse(packet, "D failed to parse the process id");
}
- if (pid != LLDB_INVALID_PROCESS_ID && m_debugged_process_up->GetID() != pid) {
- return SendIllFormedResponse(packet, "Invalid pid");
- }
-
- const Status error = m_debugged_process_up->Detach();
- if (error.Fail()) {
- LLDB_LOGF(log,
- "GDBRemoteCommunicationServerLLGS::%s failed to detach from "
- "pid %" PRIu64 ": %s\n",
- __FUNCTION__, m_debugged_process_up->GetID(), error.AsCString());
- return SendErrorResponse(0x01);
+ // Detach forked children if their PID was specified *or* no PID was requested
+ // (i.e. detach-all packet).
+ llvm::Error detach_error = llvm::Error::success();
+ bool detached = false;
+ for (auto it = m_debugged_processes.begin();
+ it != m_debugged_processes.end();) {
+ if (pid == LLDB_INVALID_PROCESS_ID || pid == it->first) {
+ if (llvm::Error e = it->second->Detach().ToError())
+ detach_error = llvm::joinErrors(std::move(detach_error), std::move(e));
+ else {
+ if (it->second.get() == m_current_process)
+ m_current_process = nullptr;
+ if (it->second.get() == m_continue_process)
+ m_continue_process = nullptr;
+ it = m_debugged_processes.erase(it);
+ detached = true;
+ continue;
+ }
+ }
+ ++it;
}
+ if (detach_error)
+ return SendErrorResponse(std::move(detach_error));
+ if (!detached)
+ return SendErrorResponse(Status("PID %" PRIu64 " not traced", pid));
return SendOKResponse();
}
@@ -3384,7 +3304,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo(
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
packet.SetFilePos(strlen("qThreadStopInfo"));
- const lldb::tid_t tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID);
+ const lldb::tid_t tid = packet.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID);
if (tid == LLDB_INVALID_THREAD_ID) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s failed, could not "
@@ -3401,19 +3321,19 @@ GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo(
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
// Ensure we have a debugged process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(50);
- LLDB_LOG(log, "preparing packet for pid {0}", m_debugged_process_up->GetID());
+ LLDB_LOG(log, "preparing packet for pid {0}", m_current_process->GetID());
StreamString response;
const bool threads_with_valid_stop_info_only = false;
- llvm::Expected<json::Value> threads_info = GetJSONThreadsInfo(
- *m_debugged_process_up, threads_with_valid_stop_info_only);
+ llvm::Expected<json::Value> threads_info =
+ GetJSONThreadsInfo(*m_current_process, threads_with_valid_stop_info_only);
if (!threads_info) {
LLDB_LOG_ERROR(log, threads_info.takeError(),
"failed to prepare a packet for pid {1}: {0}",
- m_debugged_process_up->GetID());
+ m_current_process->GetID());
return SendErrorResponse(52);
}
@@ -3427,8 +3347,8 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)
+ if (!m_current_process ||
+ m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)
return SendErrorResponse(68);
packet.SetFilePos(strlen("qWatchpointSupportInfo"));
@@ -3437,7 +3357,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo(
if (packet.GetChar() != ':')
return SendErrorResponse(67);
- auto hw_debug_cap = m_debugged_process_up->GetHardwareDebugSupportInfo();
+ auto hw_debug_cap = m_current_process->GetHardwareDebugSupportInfo();
StreamGDBRemote response;
if (hw_debug_cap == llvm::None)
@@ -3452,8 +3372,8 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)
+ if (!m_current_process ||
+ m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)
return SendErrorResponse(67);
packet.SetFilePos(strlen("qFileLoadAddress:"));
@@ -3465,7 +3385,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress(
lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS;
Status error =
- m_debugged_process_up->GetFileLoadAddress(file_name, file_load_address);
+ m_current_process->GetFileLoadAddress(file_name, file_load_address);
if (error.Fail())
return SendErrorResponse(69);
@@ -3501,16 +3421,169 @@ GDBRemoteCommunicationServerLLGS::Handle_QPassSignals(
}
// Fail if we don't have a current process.
- if (!m_debugged_process_up)
+ if (!m_current_process)
return SendErrorResponse(68);
- Status error = m_debugged_process_up->IgnoreSignals(signals);
+ Status error = m_current_process->IgnoreSignals(signals);
if (error.Fail())
return SendErrorResponse(69);
return SendOKResponse();
}
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_qMemTags(
+ StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // Ensure we have a process.
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ LLDB_LOGF(
+ log,
+ "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
+ __FUNCTION__);
+ return SendErrorResponse(1);
+ }
+
+ // We are expecting
+ // qMemTags:<hex address>,<hex length>:<hex type>
+
+ // Address
+ packet.SetFilePos(strlen("qMemTags:"));
+ const char *current_char = packet.Peek();
+ if (!current_char || *current_char == ',')
+ return SendIllFormedResponse(packet, "Missing address in qMemTags packet");
+ const lldb::addr_t addr = packet.GetHexMaxU64(/*little_endian=*/false, 0);
+
+ // Length
+ char previous_char = packet.GetChar();
+ current_char = packet.Peek();
+ // If we don't have a separator or the length field is empty
+ if (previous_char != ',' || (current_char && *current_char == ':'))
+ return SendIllFormedResponse(packet,
+ "Invalid addr,length pair in qMemTags packet");
+
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(
+ packet, "Too short qMemtags: packet (looking for length)");
+ const size_t length = packet.GetHexMaxU64(/*little_endian=*/false, 0);
+
+ // Type
+ const char *invalid_type_err = "Invalid type field in qMemTags: packet";
+ if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
+ return SendIllFormedResponse(packet, invalid_type_err);
+
+ int32_t type =
+ packet.GetS32(std::numeric_limits<int32_t>::max(), /*base=*/16);
+ if (type == std::numeric_limits<int32_t>::max() ||
+ // To catch inputs like "123aardvark" that will parse but clearly aren't
+ // valid in this case.
+ packet.GetBytesLeft()) {
+ return SendIllFormedResponse(packet, invalid_type_err);
+ }
+
+ StreamGDBRemote response;
+ std::vector<uint8_t> tags;
+ Status error = m_current_process->ReadMemoryTags(type, addr, length, tags);
+ if (error.Fail())
+ return SendErrorResponse(1);
+
+ // This m is here in case we want to support multi part replies in the future.
+ // In the same manner as qfThreadInfo/qsThreadInfo.
+ response.PutChar('m');
+ response.PutBytesAsRawHex8(tags.data(), tags.size());
+ return SendPacketNoLock(response.GetString());
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_QMemTags(
+ StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // Ensure we have a process.
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ LLDB_LOGF(
+ log,
+ "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
+ __FUNCTION__);
+ return SendErrorResponse(1);
+ }
+
+ // We are expecting
+ // QMemTags:<hex address>,<hex length>:<hex type>:<tags as hex bytes>
+
+ // Address
+ packet.SetFilePos(strlen("QMemTags:"));
+ const char *current_char = packet.Peek();
+ if (!current_char || *current_char == ',')
+ return SendIllFormedResponse(packet, "Missing address in QMemTags packet");
+ const lldb::addr_t addr = packet.GetHexMaxU64(/*little_endian=*/false, 0);
+
+ // Length
+ char previous_char = packet.GetChar();
+ current_char = packet.Peek();
+ // If we don't have a separator or the length field is empty
+ if (previous_char != ',' || (current_char && *current_char == ':'))
+ return SendIllFormedResponse(packet,
+ "Invalid addr,length pair in QMemTags packet");
+
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(
+ packet, "Too short QMemtags: packet (looking for length)");
+ const size_t length = packet.GetHexMaxU64(/*little_endian=*/false, 0);
+
+ // Type
+ const char *invalid_type_err = "Invalid type field in QMemTags: packet";
+ if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
+ return SendIllFormedResponse(packet, invalid_type_err);
+
+ // Our GetU64 uses strtoull which allows leading +/-, we don't want that.
+ const char *first_type_char = packet.Peek();
+ if (first_type_char && (*first_type_char == '+' || *first_type_char == '-'))
+ return SendIllFormedResponse(packet, invalid_type_err);
+
+ // The type is a signed integer but is in the packet as its raw bytes.
+ // So parse first as unsigned then cast to signed later.
+ // We extract to 64 bit, even though we only expect 32, so that we've
+ // got some invalid value we can check for.
+ uint64_t raw_type =
+ packet.GetU64(std::numeric_limits<uint64_t>::max(), /*base=*/16);
+ if (raw_type > std::numeric_limits<uint32_t>::max())
+ return SendIllFormedResponse(packet, invalid_type_err);
+ int32_t type = static_cast<int32_t>(raw_type);
+
+ // Tag data
+ if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
+ return SendIllFormedResponse(packet,
+ "Missing tag data in QMemTags: packet");
+
+ // Must be 2 chars per byte
+ const char *invalid_data_err = "Invalid tag data in QMemTags: packet";
+ if (packet.GetBytesLeft() % 2)
+ return SendIllFormedResponse(packet, invalid_data_err);
+
+ // This is bytes here and is unpacked into target specific tags later
+ // We cannot assume that number of bytes == length here because the server
+ // can repeat tags to fill a given range.
+ std::vector<uint8_t> tag_data;
+ // Zero length writes will not have any tag data
+ // (but we pass them on because it will still check that tagging is enabled)
+ if (packet.GetBytesLeft()) {
+ size_t byte_count = packet.GetBytesLeft() / 2;
+ tag_data.resize(byte_count);
+ size_t converted_bytes = packet.GetHexBytes(tag_data, 0);
+ if (converted_bytes != byte_count) {
+ return SendIllFormedResponse(packet, invalid_data_err);
+ }
+ }
+
+ Status status =
+ m_current_process->WriteMemoryTags(type, addr, length, tag_data);
+ return status.Success() ? SendOKResponse() : SendErrorResponse(1);
+}
+
void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
@@ -3539,8 +3612,8 @@ void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() {
NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
StringExtractorGDBRemote &packet) {
// We have no thread if we don't have a process.
- if (!m_debugged_process_up ||
- m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)
+ if (!m_current_process ||
+ m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)
return nullptr;
// If the client hasn't asked for thread suffix support, there will not be a
@@ -3551,9 +3624,9 @@ NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
return nullptr;
else if (current_tid == 0) {
// Pick a thread.
- return m_debugged_process_up->GetThreadAtIndex(0);
+ return m_current_process->GetThreadAtIndex(0);
} else
- return m_debugged_process_up->GetThreadByID(current_tid);
+ return m_current_process->GetThreadByID(current_tid);
}
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
@@ -3583,7 +3656,7 @@ NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
packet.SetFilePos(packet.GetFilePos() + strlen("thread:"));
const lldb::tid_t tid = packet.GetHexMaxU64(false, 0);
if (tid != 0)
- return m_debugged_process_up->GetThreadByID(tid);
+ return m_current_process->GetThreadByID(tid);
return nullptr;
}
@@ -3593,9 +3666,9 @@ lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const {
// Use whatever the debug process says is the current thread id since the
// protocol either didn't specify or specified we want any/all threads
// marked as the current thread.
- if (!m_debugged_process_up)
+ if (!m_current_process)
return LLDB_INVALID_THREAD_ID;
- return m_debugged_process_up->GetCurrentThreadID();
+ return m_current_process->GetCurrentThreadID();
}
// Use the specific current thread id set by the gdb remote protocol.
return m_current_tid;
@@ -3616,9 +3689,9 @@ void GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData() {
FileSpec
GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path,
const ArchSpec &arch) {
- if (m_debugged_process_up) {
+ if (m_current_process) {
FileSpec file_spec;
- if (m_debugged_process_up
+ if (m_current_process
->GetLoadedModuleFileSpec(module_path.c_str(), file_spec)
.Success()) {
if (FileSystem::Instance().Exists(file_spec))
@@ -3653,3 +3726,93 @@ std::string GDBRemoteCommunicationServerLLGS::XMLEncodeAttributeValue(
}
return result;
}
+
+llvm::Expected<lldb::tid_t> GDBRemoteCommunicationServerLLGS::ReadTid(
+ StringExtractorGDBRemote &packet, bool allow_all, lldb::pid_t default_pid) {
+ assert(m_current_process);
+ assert(m_current_process->GetID() != LLDB_INVALID_PROCESS_ID);
+
+ auto pid_tid = packet.GetPidTid(default_pid);
+ if (!pid_tid)
+ return llvm::make_error<StringError>(inconvertibleErrorCode(),
+ "Malformed thread-id");
+
+ lldb::pid_t pid = pid_tid->first;
+ lldb::tid_t tid = pid_tid->second;
+
+ if (!allow_all && pid == StringExtractorGDBRemote::AllProcesses)
+ return llvm::make_error<StringError>(
+ inconvertibleErrorCode(),
+ llvm::formatv("PID value {0} not allowed", pid == 0 ? 0 : -1));
+
+ if (!allow_all && tid == StringExtractorGDBRemote::AllThreads)
+ return llvm::make_error<StringError>(
+ inconvertibleErrorCode(),
+ llvm::formatv("TID value {0} not allowed", tid == 0 ? 0 : -1));
+
+ if (pid != StringExtractorGDBRemote::AllProcesses) {
+ if (pid != m_current_process->GetID())
+ return llvm::make_error<StringError>(
+ inconvertibleErrorCode(), llvm::formatv("PID {0} not debugged", pid));
+ }
+
+ return tid;
+}
+
+std::vector<std::string> GDBRemoteCommunicationServerLLGS::HandleFeatures(
+ const llvm::ArrayRef<llvm::StringRef> client_features) {
+ std::vector<std::string> ret =
+ GDBRemoteCommunicationServerCommon::HandleFeatures(client_features);
+ ret.insert(ret.end(), {
+ "QThreadSuffixSupported+",
+ "QListThreadsInStopReply+",
+ "qXfer:features:read+",
+ });
+
+ // report server-only features
+ using Extension = NativeProcessProtocol::Extension;
+ Extension plugin_features = m_process_factory.GetSupportedExtensions();
+ if (bool(plugin_features & Extension::pass_signals))
+ ret.push_back("QPassSignals+");
+ if (bool(plugin_features & Extension::auxv))
+ ret.push_back("qXfer:auxv:read+");
+ if (bool(plugin_features & Extension::libraries_svr4))
+ ret.push_back("qXfer:libraries-svr4:read+");
+ if (bool(plugin_features & Extension::memory_tagging))
+ ret.push_back("memory-tagging+");
+
+ // check for client features
+ m_extensions_supported = {};
+ for (llvm::StringRef x : client_features)
+ m_extensions_supported |=
+ llvm::StringSwitch<Extension>(x)
+ .Case("multiprocess+", Extension::multiprocess)
+ .Case("fork-events+", Extension::fork)
+ .Case("vfork-events+", Extension::vfork)
+ .Default({});
+
+ m_extensions_supported &= plugin_features;
+
+ // fork & vfork require multiprocess
+ if (!bool(m_extensions_supported & Extension::multiprocess))
+ m_extensions_supported &= ~(Extension::fork | Extension::vfork);
+
+ // report only if actually supported
+ if (bool(m_extensions_supported & Extension::multiprocess))
+ ret.push_back("multiprocess+");
+ if (bool(m_extensions_supported & Extension::fork))
+ ret.push_back("fork-events+");
+ if (bool(m_extensions_supported & Extension::vfork))
+ ret.push_back("vfork-events+");
+
+ for (auto &x : m_debugged_processes)
+ SetEnabledExtensions(*x.second);
+ return ret;
+}
+
+void GDBRemoteCommunicationServerLLGS::SetEnabledExtensions(
+ NativeProcessProtocol &process) {
+ NativeProcessProtocol::Extension flags = m_extensions_supported;
+ assert(!bool(flags & ~m_process_factory.GetSupportedExtensions()));
+ process.SetEnabledExtensions(flags);
+}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
index c51139924559..04d0605fe420 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -78,6 +78,10 @@ public:
void DidExec(NativeProcessProtocol *process) override;
+ void
+ NewSubprocess(NativeProcessProtocol *parent_process,
+ std::unique_ptr<NativeProcessProtocol> child_process) override;
+
Status InitializeConnection(std::unique_ptr<Connection> connection);
protected:
@@ -86,8 +90,11 @@ protected:
const NativeProcessProtocol::Factory &m_process_factory;
lldb::tid_t m_current_tid = LLDB_INVALID_THREAD_ID;
lldb::tid_t m_continue_tid = LLDB_INVALID_THREAD_ID;
+ NativeProcessProtocol *m_current_process;
+ NativeProcessProtocol *m_continue_process;
std::recursive_mutex m_debugged_process_mutex;
- std::unique_ptr<NativeProcessProtocol> m_debugged_process_up;
+ std::unordered_map<lldb::pid_t, std::unique_ptr<NativeProcessProtocol>>
+ m_debugged_processes;
Communication m_stdio_communication;
MainLoop::ReadHandleUP m_stdio_handle_up;
@@ -98,6 +105,10 @@ protected:
std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map;
uint32_t m_next_saved_registers_id = 1;
bool m_handshake_completed = false;
+ bool m_thread_suffix_supported = false;
+ bool m_list_threads_in_stop_reply = false;
+
+ NativeProcessProtocol::Extension m_extensions_supported = {};
PacketResult SendONotification(const char *buffer, uint32_t len);
@@ -119,6 +130,10 @@ protected:
PacketResult Handle_qGetWorkingDir(StringExtractorGDBRemote &packet);
+ PacketResult Handle_QThreadSuffixSupported(StringExtractorGDBRemote &packet);
+
+ PacketResult Handle_QListThreadsInStopReply(StringExtractorGDBRemote &packet);
+
PacketResult Handle_C(StringExtractorGDBRemote &packet);
PacketResult Handle_c(StringExtractorGDBRemote &packet);
@@ -167,15 +182,15 @@ protected:
PacketResult Handle_QSaveRegisterState(StringExtractorGDBRemote &packet);
- PacketResult Handle_jTraceStart(StringExtractorGDBRemote &packet);
+ PacketResult Handle_jLLDBTraceSupported(StringExtractorGDBRemote &packet);
- PacketResult Handle_jTraceRead(StringExtractorGDBRemote &packet);
+ PacketResult Handle_jLLDBTraceStart(StringExtractorGDBRemote &packet);
- PacketResult Handle_jTraceStop(StringExtractorGDBRemote &packet);
+ PacketResult Handle_jLLDBTraceStop(StringExtractorGDBRemote &packet);
- PacketResult Handle_jTraceConfigRead(StringExtractorGDBRemote &packet);
+ PacketResult Handle_jLLDBTraceGetState(StringExtractorGDBRemote &packet);
- PacketResult Handle_jLLDBTraceSupportedType(StringExtractorGDBRemote &packet);
+ PacketResult Handle_jLLDBTraceGetBinaryData(StringExtractorGDBRemote &packet);
PacketResult Handle_QRestoreRegisterState(StringExtractorGDBRemote &packet);
@@ -201,6 +216,10 @@ protected:
PacketResult Handle_g(StringExtractorGDBRemote &packet);
+ PacketResult Handle_qMemTags(StringExtractorGDBRemote &packet);
+
+ PacketResult Handle_QMemTags(StringExtractorGDBRemote &packet);
+
void SetCurrentThreadID(lldb::tid_t tid);
lldb::tid_t GetCurrentThreadID() const;
@@ -219,6 +238,9 @@ protected:
static std::string XMLEncodeAttributeValue(llvm::StringRef value);
+ virtual std::vector<std::string> HandleFeatures(
+ const llvm::ArrayRef<llvm::StringRef> client_features) override;
+
private:
llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> BuildTargetXml();
@@ -244,6 +266,18 @@ private:
void StopSTDIOForwarding();
+ // Read thread-id from packet. If the thread-id is correct, returns it.
+ // Otherwise, returns the error.
+ //
+ // If allow_all is true, then the pid/tid value of -1 ('all') will be allowed.
+ // In any case, the function assumes that exactly one inferior is being
+ // debugged and rejects pid values that do no match that inferior.
+ llvm::Expected<lldb::tid_t> ReadTid(StringExtractorGDBRemote &packet,
+ bool allow_all, lldb::pid_t default_pid);
+
+ // Call SetEnabledExtensions() with appropriate flags on the process.
+ void SetEnabledExtensions(NativeProcessProtocol &process);
+
// For GDBRemoteCommunicationServerLLGS only
GDBRemoteCommunicationServerLLGS(const GDBRemoteCommunicationServerLLGS &) =
delete;
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
index 3462fb7ec8b9..7c2f80dc76b8 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
@@ -8,7 +8,7 @@
#include "GDBRemoteCommunicationServerPlatform.h"
-#include <errno.h>
+#include <cerrno>
#include <chrono>
#include <csignal>
@@ -153,7 +153,8 @@ GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(
}
// Destructor
-GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() {}
+GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() =
+ default;
Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid,
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index 10006616b0c6..65cf9fb2a834 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -36,7 +36,7 @@ GDBRemoteRegisterContext::GDBRemoteRegisterContext(
: RegisterContext(thread, concrete_frame_idx),
m_reg_info_sp(std::move(reg_info_sp)), m_reg_valid(), m_reg_data(),
m_read_all_at_once(read_all_at_once),
- m_write_all_at_once(write_all_at_once) {
+ m_write_all_at_once(write_all_at_once), m_gpacket_cached(false) {
// 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.
@@ -50,13 +50,14 @@ GDBRemoteRegisterContext::GDBRemoteRegisterContext(
}
// Destructor
-GDBRemoteRegisterContext::~GDBRemoteRegisterContext() {}
+GDBRemoteRegisterContext::~GDBRemoteRegisterContext() = default;
void GDBRemoteRegisterContext::InvalidateAllRegisters() {
SetAllRegisterValid(false);
}
void GDBRemoteRegisterContext::SetAllRegisterValid(bool b) {
+ m_gpacket_cached = b;
std::vector<bool>::iterator pos, end = m_reg_valid.end();
for (pos = m_reg_valid.begin(); pos != end; ++pos)
*pos = b;
@@ -200,7 +201,7 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
if (!GetRegisterIsValid(reg)) {
- if (m_read_all_at_once) {
+ if (m_read_all_at_once && !m_gpacket_cached) {
if (DataBufferSP buffer_sp =
gdb_comm.ReadAllRegisters(m_thread.GetProtocolID())) {
memcpy(const_cast<uint8_t *>(m_reg_data.GetDataStart()),
@@ -221,7 +222,10 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
m_reg_valid[i] = false;
}
}
- return true;
+
+ m_gpacket_cached = true;
+ if (GetRegisterIsValid(reg))
+ return true;
} else {
Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_THREAD |
GDBR_LOG_PACKETS));
@@ -233,9 +237,9 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
" bytes "
"but only got %" PRId64 " bytes.",
m_reg_data.GetByteSize(), buffer_sp->GetByteSize());
+ return false;
}
}
- return false;
}
if (reg_info->value_regs) {
// Process this composite register request by delegating to the
@@ -249,7 +253,8 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
break;
// We have a valid primordial register as our constituent. Grab the
// corresponding register info.
- const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg);
+ const RegisterInfo *prim_reg_info =
+ GetRegisterInfo(eRegisterKindProcessPlugin, prim_reg);
if (prim_reg_info == nullptr)
success = false;
else {
@@ -359,7 +364,7 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
reg_info->byte_size, // dst length
m_reg_data.GetByteOrder())) // dst byte order
{
- GDBRemoteClientBase::Lock lock(gdb_comm, false);
+ GDBRemoteClientBase::Lock lock(gdb_comm);
if (lock) {
if (m_write_all_at_once) {
// Invalidate all register values
@@ -395,7 +400,8 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
break;
// We have a valid primordial register as our constituent. Grab the
// corresponding register info.
- const RegisterInfo *value_reg_info = GetRegisterInfoAtIndex(reg);
+ const RegisterInfo *value_reg_info =
+ GetRegisterInfo(eRegisterKindProcessPlugin, reg);
if (value_reg_info == nullptr)
success = false;
else
@@ -414,9 +420,10 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
if (reg_info->invalidate_regs) {
for (uint32_t idx = 0, reg = reg_info->invalidate_regs[0];
reg != LLDB_INVALID_REGNUM;
- reg = reg_info->invalidate_regs[++idx]) {
- SetRegisterIsValid(reg, false);
- }
+ reg = reg_info->invalidate_regs[++idx])
+ SetRegisterIsValid(ConvertRegisterKindToRegisterNumber(
+ eRegisterKindProcessPlugin, reg),
+ false);
}
return success;
@@ -501,7 +508,7 @@ bool GDBRemoteRegisterContext::ReadAllRegisterValues(
const bool use_g_packet =
!gdb_comm.AvoidGPackets((ProcessGDBRemote *)process);
- GDBRemoteClientBase::Lock lock(gdb_comm, false);
+ GDBRemoteClientBase::Lock lock(gdb_comm);
if (lock) {
if (gdb_comm.SyncThreadState(m_thread.GetProtocolID()))
InvalidateAllRegisters();
@@ -567,7 +574,7 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues(
const bool use_g_packet =
!gdb_comm.AvoidGPackets((ProcessGDBRemote *)process);
- GDBRemoteClientBase::Lock lock(gdb_comm, false);
+ GDBRemoteClientBase::Lock lock(gdb_comm);
if (lock) {
// The data_sp contains the G response packet.
if (use_g_packet) {
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 252d7b359ee8..18fcb73b9815 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -118,6 +118,7 @@ protected:
DataExtractor m_reg_data;
bool m_read_all_at_once;
bool m_write_all_at_once;
+ bool m_gpacket_cached;
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 aba870c42e55..6914b37348ea 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -8,8 +8,8 @@
#include "lldb/Host/Config.h"
-#include <errno.h>
-#include <stdlib.h>
+#include <cerrno>
+#include <cstdlib>
#if LLDB_ENABLE_POSIX
#include <netinet/in.h>
#include <sys/mman.h>
@@ -20,8 +20,8 @@
#if defined(__APPLE__)
#include <sys/sysctl.h>
#endif
+#include <ctime>
#include <sys/types.h>
-#include <time.h>
#include <algorithm>
#include <csignal>
@@ -135,7 +135,7 @@ public:
m_collection_sp->Initialize(g_processgdbremote_properties);
}
- ~PluginProperties() override {}
+ ~PluginProperties() override = default;
uint64_t GetPacketTimeout() {
const uint32_t idx = ePropertyPacketTimeout;
@@ -213,6 +213,10 @@ ProcessGDBRemote::CreateInstance(lldb::TargetSP target_sp,
return process_sp;
}
+std::chrono::seconds ProcessGDBRemote::GetPacketTimeout() {
+ return std::chrono::seconds(GetGlobalPluginProperties()->GetPacketTimeout());
+}
+
bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp,
bool plugin_specified_by_name) {
if (plugin_specified_by_name)
@@ -461,7 +465,7 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, false) ==
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response) ==
GDBRemoteCommunication::PacketResult::Success) {
response_type = response.GetResponseType();
if (response_type == StringExtractorGDBRemote::eResponse) {
@@ -1011,7 +1015,7 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) {
for (size_t idx = 0; idx < num_cmds; idx++) {
StringExtractorGDBRemote response;
m_gdb_comm.SendPacketAndWaitForResponse(
- GetExtraStartupCommands().GetArgumentAtIndex(idx), response, false);
+ GetExtraStartupCommands().GetArgumentAtIndex(idx), response);
}
return error;
}
@@ -1038,6 +1042,12 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
process_arch.GetTriple().getTriple());
}
+ if (int addresssable_bits = m_gdb_comm.GetAddressingBits()) {
+ lldb::addr_t address_mask = ~((1ULL << addresssable_bits) - 1);
+ SetCodeAddressMask(address_mask);
+ SetDataAddressMask(address_mask);
+ }
+
if (process_arch.IsValid()) {
const ArchSpec &target_arch = GetTarget().GetArchitecture();
if (target_arch.IsValid()) {
@@ -1199,34 +1209,26 @@ Status ProcessGDBRemote::DoAttachToProcessWithName(
return error;
}
-lldb::user_id_t ProcessGDBRemote::StartTrace(const TraceOptions &options,
- Status &error) {
- return m_gdb_comm.SendStartTracePacket(options, error);
-}
-
-Status ProcessGDBRemote::StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) {
- return m_gdb_comm.SendStopTracePacket(uid, thread_id);
+llvm::Expected<TraceSupportedResponse> ProcessGDBRemote::TraceSupported() {
+ return m_gdb_comm.SendTraceSupported(GetInterruptTimeout());
}
-Status ProcessGDBRemote::GetData(lldb::user_id_t uid, lldb::tid_t thread_id,
- llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset) {
- return m_gdb_comm.SendGetDataPacket(uid, thread_id, buffer, offset);
+llvm::Error ProcessGDBRemote::TraceStop(const TraceStopRequest &request) {
+ return m_gdb_comm.SendTraceStop(request, GetInterruptTimeout());
}
-Status ProcessGDBRemote::GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id,
- llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset) {
- return m_gdb_comm.SendGetMetaDataPacket(uid, thread_id, buffer, offset);
+llvm::Error ProcessGDBRemote::TraceStart(const llvm::json::Value &request) {
+ return m_gdb_comm.SendTraceStart(request, GetInterruptTimeout());
}
-Status ProcessGDBRemote::GetTraceConfig(lldb::user_id_t uid,
- TraceOptions &options) {
- return m_gdb_comm.SendGetTraceConfigPacket(uid, options);
+llvm::Expected<std::string>
+ProcessGDBRemote::TraceGetState(llvm::StringRef type) {
+ return m_gdb_comm.SendTraceGetState(type, GetInterruptTimeout());
}
-llvm::Expected<TraceTypeInfo> ProcessGDBRemote::GetSupportedTraceType() {
- return m_gdb_comm.SendGetSupportedTraceType();
+llvm::Expected<std::vector<uint8_t>>
+ProcessGDBRemote::TraceGetBinaryData(const TraceGetBinaryDataRequest &request) {
+ return m_gdb_comm.SendTraceGetBinaryData(request, GetInterruptTimeout());
}
void ProcessGDBRemote::DidExit() {
@@ -1471,7 +1473,7 @@ void ProcessGDBRemote::HandleStopReplySequence() {
while (true) {
// Send vStopped
StringExtractorGDBRemote response;
- m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response, false);
+ m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response);
// OK represents end of signal list
if (response.IsOKResponse())
@@ -1491,22 +1493,22 @@ void ProcessGDBRemote::ClearThreadIDList() {
m_thread_pcs.clear();
}
-size_t
-ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue(std::string &value) {
+size_t ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue(
+ llvm::StringRef value) {
m_thread_ids.clear();
- size_t comma_pos;
- lldb::tid_t tid;
- while ((comma_pos = value.find(',')) != std::string::npos) {
- value[comma_pos] = '\0';
- // thread in big endian hex
- tid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_THREAD_ID, 16);
- if (tid != LLDB_INVALID_THREAD_ID)
- m_thread_ids.push_back(tid);
- value.erase(0, comma_pos + 1);
- }
- tid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_THREAD_ID, 16);
- if (tid != LLDB_INVALID_THREAD_ID)
- m_thread_ids.push_back(tid);
+ lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
+ StringExtractorGDBRemote thread_ids{value};
+
+ do {
+ auto pid_tid = thread_ids.GetPidTid(pid);
+ if (pid_tid && pid_tid->first == pid) {
+ lldb::tid_t tid = pid_tid->second;
+ if (tid != LLDB_INVALID_THREAD_ID &&
+ tid != StringExtractorGDBRemote::AllProcesses)
+ m_thread_ids.push_back(tid);
+ }
+ } while (thread_ids.GetChar() == ',');
+
return m_thread_ids.size();
}
@@ -1523,7 +1525,7 @@ ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue(std::string &value) {
value.erase(0, comma_pos + 1);
}
pc = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16);
- if (pc != LLDB_INVALID_THREAD_ID)
+ if (pc != LLDB_INVALID_ADDRESS)
m_thread_pcs.push_back(pc);
return m_thread_pcs.size();
}
@@ -1748,7 +1750,9 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
if (thread_sp) {
ThreadGDBRemote *gdb_thread =
static_cast<ThreadGDBRemote *>(thread_sp.get());
- gdb_thread->GetRegisterContext()->InvalidateIfNeeded(true);
+ RegisterContextSP gdb_reg_ctx_sp(gdb_thread->GetRegisterContext());
+
+ gdb_reg_ctx_sp->InvalidateIfNeeded(true);
auto iter = std::find(m_thread_ids.begin(), m_thread_ids.end(), tid);
if (iter != m_thread_ids.end()) {
@@ -1760,7 +1764,10 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
DataBufferSP buffer_sp(new DataBufferHeap(
reg_value_extractor.GetStringRef().size() / 2, 0));
reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc');
- gdb_thread->PrivateSetRegisterValue(pair.first, buffer_sp->GetData());
+ uint32_t lldb_regnum =
+ gdb_reg_ctx_sp->ConvertRegisterKindToRegisterNumber(
+ eRegisterKindProcessPlugin, pair.first);
+ gdb_thread->PrivateSetRegisterValue(lldb_regnum, buffer_sp->GetData());
}
// AArch64 SVE specific code below calls AArch64SVEReconfigure to update
@@ -1825,8 +1832,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
// If the current pc is a breakpoint site then the StopInfo
// should be set to Breakpoint Otherwise, it will be set to
// Trace.
- if (bp_site_sp &&
- bp_site_sp->ValidForThisThread(thread_sp.get())) {
+ if (bp_site_sp && bp_site_sp->ValidForThisThread(*thread_sp)) {
thread_sp->SetStopInfo(
StopInfo::CreateStopReasonWithBreakpointSiteID(
*thread_sp, bp_site_sp->GetID()));
@@ -1846,7 +1852,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
// breakpoint here, that will be taken care of when the thread
// resumes and notices that there's a breakpoint under the pc.
handled = true;
- if (bp_site_sp->ValidForThisThread(thread_sp.get())) {
+ if (bp_site_sp->ValidForThisThread(*thread_sp)) {
thread_sp->SetStopInfo(
StopInfo::CreateStopReasonWithBreakpointSiteID(
*thread_sp, bp_site_sp->GetID()));
@@ -1897,6 +1903,9 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
thread_sp->SetStopInfo(
StopInfo::CreateStopReasonWithExec(*thread_sp));
handled = true;
+ } else if (reason == "processor trace") {
+ thread_sp->SetStopInfo(StopInfo::CreateStopReasonProcessorTrace(
+ *thread_sp, description.c_str()));
}
} else if (!signo) {
addr_t pc = thread_sp->GetRegisterContext()->GetPC();
@@ -1909,7 +1918,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
// as such. This can happen when the thread is involuntarily
// interrupted (e.g. due to stops on other threads) just as it is
// about to execute the breakpoint instruction.
- if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get())) {
+ if (bp_site_sp && bp_site_sp->ValidForThisThread(*thread_sp)) {
thread_sp->SetStopInfo(
StopInfo::CreateStopReasonWithBreakpointSiteID(
*thread_sp, bp_site_sp->GetID()));
@@ -1934,7 +1943,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
// reason. We don't need to worry about stepping over the
// breakpoint here, that will be taken care of when the thread
// resumes and notices that there's a breakpoint under the pc.
- if (bp_site_sp->ValidForThisThread(thread_sp.get())) {
+ if (bp_site_sp->ValidForThisThread(*thread_sp)) {
if (m_breakpoint_pc_offset != 0)
thread_sp->GetRegisterContext()->SetPC(pc);
thread_sp->SetStopInfo(
@@ -2137,6 +2146,7 @@ ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) {
}
StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
+ lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
stop_packet.SetFilePos(0);
const char stop_type = stop_packet.GetChar();
switch (stop_type) {
@@ -2151,14 +2161,12 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
if (stop_id == 0) {
// Our first stop, make sure we have a process ID, and also make sure we
// know about our registers
- if (GetID() == LLDB_INVALID_PROCESS_ID) {
- lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
- if (pid != LLDB_INVALID_PROCESS_ID)
- SetID(pid);
- }
+ if (GetID() == LLDB_INVALID_PROCESS_ID && pid != LLDB_INVALID_PROCESS_ID)
+ SetID(pid);
BuildDynamicRegisterInfo(true);
}
// Stop with signal and thread info
+ lldb::pid_t stop_pid = LLDB_INVALID_PROCESS_ID;
lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
const uint8_t signo = stop_packet.GetHexU8();
llvm::StringRef key;
@@ -2187,24 +2195,18 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
value.getAsInteger(16, x);
exc_data.push_back(x);
} else if (key.compare("thread") == 0) {
- // thread in big endian hex
- if (value.getAsInteger(16, tid))
+ // thread-id
+ StringExtractorGDBRemote thread_id{value};
+ auto pid_tid = thread_id.GetPidTid(pid);
+ if (pid_tid) {
+ stop_pid = pid_tid->first;
+ tid = pid_tid->second;
+ } else
tid = LLDB_INVALID_THREAD_ID;
} else if (key.compare("threads") == 0) {
std::lock_guard<std::recursive_mutex> guard(
m_thread_list_real.GetMutex());
-
- m_thread_ids.clear();
- // A comma separated list of all threads in the current
- // process that includes the thread for this stop reply packet
- lldb::tid_t tid;
- while (!value.empty()) {
- llvm::StringRef tid_str;
- std::tie(tid_str, value) = value.split(',');
- if (tid_str.getAsInteger(16, tid))
- tid = LLDB_INVALID_THREAD_ID;
- m_thread_ids.push_back(tid);
- }
+ UpdateThreadIDsFromStopReplyThreadsValue(value);
} else if (key.compare("thread-pcs") == 0) {
m_thread_pcs.clear();
// A comma separated list of all threads in the current
@@ -2317,6 +2319,14 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
}
}
+ if (stop_pid != LLDB_INVALID_PROCESS_ID && stop_pid != pid) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ LLDB_LOG(log,
+ "Received stop for incorrect PID = {0} (inferior PID = {1})",
+ stop_pid, pid);
+ return eStateInvalid;
+ }
+
if (tid == LLDB_INVALID_THREAD_ID) {
// A thread id may be invalid if the response is old style 'S' packet
// which does not provide the
@@ -2404,7 +2414,7 @@ Status ProcessGDBRemote::DoHalt(bool &caused_stop) {
// file handle and debugserver will go away, and we can be done...
m_gdb_comm.Disconnect();
} else
- caused_stop = m_gdb_comm.Interrupt();
+ caused_stop = m_gdb_comm.Interrupt(GetInterruptTimeout());
return error;
}
@@ -2553,11 +2563,11 @@ Status ProcessGDBRemote::DoDestroy() {
if (m_gdb_comm.IsConnected()) {
if (m_public_state.GetValue() != eStateAttaching) {
StringExtractorGDBRemote response;
- bool send_async = true;
GDBRemoteCommunication::ScopedTimeout(m_gdb_comm,
std::chrono::seconds(3));
- if (m_gdb_comm.SendPacketAndWaitForResponse("k", response, send_async) ==
+ if (m_gdb_comm.SendPacketAndWaitForResponse("k", response,
+ GetInterruptTimeout()) ==
GDBRemoteCommunication::PacketResult::Success) {
char packet_cmd = response.GetChar(0);
@@ -2721,7 +2731,8 @@ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size,
assert(packet_len + 1 < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, true) ==
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response,
+ GetInterruptTimeout()) ==
GDBRemoteCommunication::PacketResult::Success) {
if (response.IsNormalResponse()) {
error.Clear();
@@ -2757,6 +2768,37 @@ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size,
return 0;
}
+bool ProcessGDBRemote::SupportsMemoryTagging() {
+ return m_gdb_comm.GetMemoryTaggingSupported();
+}
+
+llvm::Expected<std::vector<uint8_t>>
+ProcessGDBRemote::DoReadMemoryTags(lldb::addr_t addr, size_t len,
+ int32_t type) {
+ // By this point ReadMemoryTags has validated that tagging is enabled
+ // for this target/process/address.
+ DataBufferSP buffer_sp = m_gdb_comm.ReadMemoryTags(addr, len, type);
+ if (!buffer_sp) {
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Error reading memory tags from remote");
+ }
+
+ // Return the raw tag data
+ llvm::ArrayRef<uint8_t> tag_data = buffer_sp->GetData();
+ std::vector<uint8_t> got;
+ got.reserve(tag_data.size());
+ std::copy(tag_data.begin(), tag_data.end(), std::back_inserter(got));
+ return got;
+}
+
+Status ProcessGDBRemote::DoWriteMemoryTags(lldb::addr_t addr, size_t len,
+ int32_t type,
+ const std::vector<uint8_t> &tags) {
+ // By now WriteMemoryTags should have validated that tagging is enabled
+ // for this target/process.
+ return m_gdb_comm.WriteMemoryTags(addr, len, type, tags);
+}
+
Status ProcessGDBRemote::WriteObjectFile(
std::vector<ObjectFile::LoadableData> entries) {
Status error;
@@ -2847,7 +2889,7 @@ Status ProcessGDBRemote::FlashErase(lldb::addr_t addr, size_t size) {
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
- true) ==
+ GetInterruptTimeout()) ==
GDBRemoteCommunication::PacketResult::Success) {
if (response.IsOKResponse()) {
m_erased_flash_ranges.Insert(range, true);
@@ -2876,7 +2918,8 @@ Status ProcessGDBRemote::FlashDone() {
if (m_erased_flash_ranges.IsEmpty())
return status;
StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse("vFlashDone", response, true) ==
+ if (m_gdb_comm.SendPacketAndWaitForResponse("vFlashDone", response,
+ GetInterruptTimeout()) ==
GDBRemoteCommunication::PacketResult::Success) {
if (response.IsOKResponse()) {
m_erased_flash_ranges.Clear();
@@ -2937,7 +2980,7 @@ size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf,
}
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
- true) ==
+ GetInterruptTimeout()) ==
GDBRemoteCommunication::PacketResult::Success) {
if (response.IsOKResponse()) {
error.Clear();
@@ -3113,7 +3156,7 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) {
(!bp_site->HardwareRequired())) {
// Try to send off a software breakpoint packet ($Z0)
uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(
- eBreakpointSoftware, true, addr, bp_op_size);
+ eBreakpointSoftware, true, addr, bp_op_size, GetInterruptTimeout());
if (error_no == 0) {
// The breakpoint was placed successfully
bp_site->SetEnabled(true);
@@ -3153,7 +3196,7 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) {
if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) {
// Try to send off a hardware breakpoint packet ($Z1)
uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(
- eBreakpointHardware, true, addr, bp_op_size);
+ eBreakpointHardware, true, addr, bp_op_size, GetInterruptTimeout());
if (error_no == 0) {
// The breakpoint was placed successfully
bp_site->SetEnabled(true);
@@ -3217,13 +3260,15 @@ Status ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) {
case BreakpointSite::eHardware:
if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, false,
- addr, bp_op_size))
+ addr, bp_op_size,
+ GetInterruptTimeout()))
error.SetErrorToGenericError();
break;
case BreakpointSite::eExternal: {
if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false,
- addr, bp_op_size))
+ addr, bp_op_size,
+ GetInterruptTimeout()))
error.SetErrorToGenericError();
} break;
}
@@ -3279,7 +3324,8 @@ Status ProcessGDBRemote::EnableWatchpoint(Watchpoint *wp, bool notify) {
// Pass down an appropriate z/Z packet...
if (m_gdb_comm.SupportsGDBStoppointPacket(type)) {
if (m_gdb_comm.SendGDBStoppointTypePacket(type, true, addr,
- wp->GetByteSize()) == 0) {
+ wp->GetByteSize(),
+ GetInterruptTimeout()) == 0) {
wp->SetEnabled(true, notify);
return error;
} else
@@ -3325,7 +3371,8 @@ Status ProcessGDBRemote::DisableWatchpoint(Watchpoint *wp, bool notify) {
GDBStoppointType type = GetGDBStoppointType(wp);
// Pass down an appropriate z/Z packet...
if (m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr,
- wp->GetByteSize()) == 0) {
+ wp->GetByteSize(),
+ GetInterruptTimeout()) == 0) {
wp->SetEnabled(false, notify);
return error;
} else
@@ -3350,7 +3397,7 @@ Status ProcessGDBRemote::DoSignal(int signo) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
LLDB_LOGF(log, "ProcessGDBRemote::DoSignal (signal = %d)", signo);
- if (!m_gdb_comm.SendAsyncSignal(signo))
+ if (!m_gdb_comm.SendAsyncSignal(signo, GetInterruptTimeout()))
error.SetErrorStringWithFormat("failed to send signal %i", signo);
return error;
}
@@ -3678,12 +3725,25 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) {
__FUNCTION__, arg, process->GetID());
EventSP event_sp;
+
+ // We need to ignore any packets that come in after we have
+ // have decided the process has exited. There are some
+ // situations, for instance when we try to interrupt a running
+ // process and the interrupt fails, where another packet might
+ // get delivered after we've decided to give up on the process.
+ // But once we've decided we are done with the process we will
+ // not be in a state to do anything useful with new packets.
+ // So it is safer to simply ignore any remaining packets by
+ // explicitly checking for eStateExited before reentering the
+ // fetch loop.
+
bool done = false;
- while (!done) {
+ while (!done && process->GetPrivateState() != eStateExited) {
LLDB_LOGF(log,
"ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
") listener.WaitForEvent (NULL, event_sp)...",
__FUNCTION__, arg, process->GetID());
+
if (process->m_async_listener_sp->GetEvent(event_sp, llvm::None)) {
const uint32_t event_type = event_sp->GetType();
if (event_sp->BroadcasterIs(&process->m_async_broadcaster)) {
@@ -3715,7 +3775,7 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) {
// send the vCont packet
if (!process->GetGDBRemote().SendvContPacket(
llvm::StringRef(continue_cstr, continue_cstr_len),
- response)) {
+ process->GetInterruptTimeout(), response)) {
// Something went wrong
done = true;
break;
@@ -3727,6 +3787,7 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) {
process->GetGDBRemote().SendContinuePacketAndWaitForResponse(
*process, *process->GetUnixSignals(),
llvm::StringRef(continue_cstr, continue_cstr_len),
+ process->GetInterruptTimeout(),
response);
// We need to immediately clear the thread ID list so we are sure
@@ -3782,6 +3843,7 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) {
} else {
process->SetExitStatus(-1, "lost connection");
}
+ done = true;
break;
}
@@ -4020,8 +4082,7 @@ ProcessGDBRemote::GetExtendedInfoForThread(lldb::tid_t tid) {
StringExtractorGDBRemote response;
response.SetResponseValidatorToJSON();
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
- false) ==
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) ==
GDBRemoteCommunication::PacketResult::Success) {
StringExtractorGDBRemote::ResponseType response_type =
response.GetResponseType();
@@ -4093,8 +4154,7 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender(
StringExtractorGDBRemote response;
response.SetResponseValidatorToJSON();
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
- false) ==
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) ==
GDBRemoteCommunication::PacketResult::Success) {
StringExtractorGDBRemote::ResponseType response_type =
response.GetResponseType();
@@ -4127,8 +4187,7 @@ StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() {
StringExtractorGDBRemote response;
response.SetResponseValidatorToJSON();
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
- false) ==
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) ==
GDBRemoteCommunication::PacketResult::Success) {
StringExtractorGDBRemote::ResponseType response_type =
response.GetResponseType();
@@ -4894,8 +4953,7 @@ Status ProcessGDBRemote::GetFileLoadAddress(const FileSpec &file,
packet.PutStringAsRawHex8(file_path);
StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
- false) !=
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) !=
GDBRemoteCommunication::PacketResult::Success)
return Status("Sending qFileLoadAddress packet failed");
@@ -5131,7 +5189,7 @@ public:
m_option_group.Finalize();
}
- ~CommandObjectProcessGDBRemoteSpeedTest() override {}
+ ~CommandObjectProcessGDBRemoteSpeedTest() override = default;
Options *GetOptions() override { return &m_option_group; }
@@ -5182,7 +5240,7 @@ public:
: CommandObjectParsed(interpreter, "process plugin packet history",
"Dumps the packet history buffer. ", nullptr) {}
- ~CommandObjectProcessGDBRemotePacketHistory() override {}
+ ~CommandObjectProcessGDBRemotePacketHistory() override = default;
bool DoExecute(Args &command, CommandReturnObject &result) override {
const size_t argc = command.GetArgumentCount();
@@ -5213,7 +5271,7 @@ public:
"Maximum size that lldb will try to read/write one one chunk.",
nullptr) {}
- ~CommandObjectProcessGDBRemotePacketXferSize() override {}
+ ~CommandObjectProcessGDBRemotePacketXferSize() override = default;
bool DoExecute(Args &command, CommandReturnObject &result) override {
const size_t argc = command.GetArgumentCount();
@@ -5222,7 +5280,6 @@ public:
"amount to be transferred when "
"reading/writing",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -5255,7 +5312,7 @@ public:
"stripped from the result.",
nullptr) {}
- ~CommandObjectProcessGDBRemotePacketSend() override {}
+ ~CommandObjectProcessGDBRemotePacketSend() override = default;
bool DoExecute(Args &command, CommandReturnObject &result) override {
const size_t argc = command.GetArgumentCount();
@@ -5263,7 +5320,6 @@ public:
result.AppendErrorWithFormat(
"'%s' takes a one or more packet content arguments",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -5272,10 +5328,9 @@ public:
if (process) {
for (size_t i = 0; i < argc; ++i) {
const char *packet_cstr = command.GetArgumentAtIndex(0);
- bool send_async = true;
StringExtractorGDBRemote response;
process->GetGDBRemote().SendPacketAndWaitForResponse(
- packet_cstr, response, send_async);
+ packet_cstr, response, process->GetInterruptTimeout());
result.SetStatus(eReturnStatusSuccessFinishResult);
Stream &output_strm = result.GetOutputStream();
output_strm.Printf(" packet: %s\n", packet_cstr);
@@ -5306,14 +5361,13 @@ public:
"encoded into a valid 'qRcmd' packet, sent and the "
"response will be printed.") {}
- ~CommandObjectProcessGDBRemotePacketMonitor() override {}
+ ~CommandObjectProcessGDBRemotePacketMonitor() override = default;
bool DoExecute(llvm::StringRef command,
CommandReturnObject &result) override {
if (command.empty()) {
result.AppendErrorWithFormat("'%s' takes a command string argument",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -5324,11 +5378,10 @@ public:
packet.PutCString("qRcmd,");
packet.PutBytesAsRawHex8(command.data(), command.size());
- bool send_async = true;
StringExtractorGDBRemote response;
Stream &output_strm = result.GetOutputStream();
process->GetGDBRemote().SendPacketAndReceiveResponseWithOutputSupport(
- packet.GetString(), response, send_async,
+ packet.GetString(), response, process->GetInterruptTimeout(),
[&output_strm](llvm::StringRef output) { output_strm << output; });
result.SetStatus(eReturnStatusSuccessFinishResult);
output_strm.Printf(" packet: %s\n", packet.GetData());
@@ -5370,7 +5423,7 @@ public:
interpreter)));
}
- ~CommandObjectProcessGDBRemotePacket() override {}
+ ~CommandObjectProcessGDBRemotePacket() override = default;
};
class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword {
@@ -5385,7 +5438,7 @@ public:
CommandObjectSP(new CommandObjectProcessGDBRemotePacket(interpreter)));
}
- ~CommandObjectMultiwordProcessGDBRemote() override {}
+ ~CommandObjectMultiwordProcessGDBRemote() override = default;
};
CommandObject *ProcessGDBRemote::GetPluginCommandObject() {
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 0921bf17c4e4..fe04cdddd0f5 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -68,6 +68,8 @@ public:
static const char *GetPluginDescriptionStatic();
+ static std::chrono::seconds GetPacketTimeout();
+
// Check if a given Process
bool CanDebug(lldb::TargetSP target_sp,
bool plugin_specified_by_name) override;
@@ -163,22 +165,16 @@ public:
Status GetWatchpointSupportInfo(uint32_t &num) override;
- lldb::user_id_t StartTrace(const TraceOptions &options,
- Status &error) override;
-
- Status StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) override;
+ llvm::Expected<TraceSupportedResponse> TraceSupported() override;
- Status GetData(lldb::user_id_t uid, lldb::tid_t thread_id,
- llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset = 0) override;
+ llvm::Error TraceStop(const TraceStopRequest &request) override;
- Status GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id,
- llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset = 0) override;
+ llvm::Error TraceStart(const llvm::json::Value &request) override;
- llvm::Expected<TraceTypeInfo> GetSupportedTraceType() override;
+ llvm::Expected<std::string> TraceGetState(llvm::StringRef type) override;
- Status GetTraceConfig(lldb::user_id_t uid, TraceOptions &options) override;
+ llvm::Expected<std::vector<uint8_t>>
+ TraceGetBinaryData(const TraceGetBinaryDataRequest &request) override;
Status GetWatchpointSupportInfo(uint32_t &num, bool &after) override;
@@ -239,6 +235,8 @@ protected:
friend class GDBRemoteCommunicationClient;
friend class GDBRemoteRegisterContext;
+ bool SupportsMemoryTagging() override;
+
/// Broadcaster event bits definitions.
enum {
eBroadcastBitAsyncContinue = (1 << 0),
@@ -339,7 +337,7 @@ protected:
size_t UpdateThreadPCsFromStopReplyThreadsValue(std::string &value);
- size_t UpdateThreadIDsFromStopReplyThreadsValue(std::string &value);
+ size_t UpdateThreadIDsFromStopReplyThreadsValue(llvm::StringRef value);
bool HandleNotifyPacket(StringExtractorGDBRemote &packet);
@@ -410,6 +408,12 @@ protected:
bool HasErased(FlashRange range);
+ llvm::Expected<std::vector<uint8_t>>
+ DoReadMemoryTags(lldb::addr_t addr, size_t len, int32_t type) override;
+
+ Status DoWriteMemoryTags(lldb::addr_t addr, size_t len, int32_t type,
+ const std::vector<uint8_t> &tags) override;
+
private:
// For ProcessGDBRemote only
std::string m_partial_profile_data;
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
index 05a48acc2f7a..385557422758 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -138,10 +138,10 @@ private:
///
/// \param[in] module_sp The module to grab the .text section from.
///
-/// \param[in/out] breakpad_uuid A vector that will receive the calculated
+/// \param[in,out] breakpad_uuid A vector that will receive the calculated
/// breakpad .text hash.
///
-/// \param[in/out] facebook_uuid A vector that will receive the calculated
+/// \param[in,out] facebook_uuid A vector that will receive the calculated
/// facebook .text hash.
///
void HashElfTextSection(ModuleSP module_sp, std::vector<uint8_t> &breakpad_uuid,
@@ -548,7 +548,7 @@ void ProcessMinidump::ReadModuleList() {
// check if the process is wow64 - a 32 bit windows process running on a
// 64 bit windows
- if (llvm::StringRef(name).endswith_lower("wow64.dll")) {
+ if (llvm::StringRef(name).endswith_insensitive("wow64.dll")) {
m_is_wow64 = true;
}
@@ -871,7 +871,7 @@ public:
m_option_group.Finalize();
}
- ~CommandObjectProcessMinidumpDump() override {}
+ ~CommandObjectProcessMinidumpDump() override = default;
Options *GetOptions() override { return &m_option_group; }
@@ -880,7 +880,6 @@ public:
if (argc > 0) {
result.AppendErrorWithFormat("'%s' take no arguments, only options",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
SetDefaultOptionsIfNoneAreSet();
@@ -1001,7 +1000,7 @@ public:
CommandObjectSP(new CommandObjectProcessMinidumpDump(interpreter)));
}
- ~CommandObjectMultiwordProcessMinidump() override {}
+ ~CommandObjectMultiwordProcessMinidump() override = default;
};
CommandObject *ProcessMinidump::GetPluginCommandObject() {
diff --git a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp
index eb48785263fc..7e309e8322a8 100644
--- a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp
+++ b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp
@@ -16,7 +16,7 @@
#include "lldb/lldb-enumerations.h"
// C includes
-#include <assert.h>
+#include <cassert>
// C++ includes
diff --git a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp
index c7809c5f19b6..e2b7c0e362a7 100644
--- a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp
+++ b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp
@@ -14,7 +14,7 @@
#include "lldb/lldb-enumerations.h"
// C includes
-#include <assert.h>
+#include <cassert>
// C++ includes
diff --git a/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp b/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp
index e146a1a1af92..1fbc52815238 100644
--- a/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp
+++ b/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp
@@ -38,7 +38,7 @@ ThreadMinidump::ThreadMinidump(Process &process, const minidump::Thread &td,
: Thread(process, td.ThreadId), m_thread_reg_ctx_sp(),
m_gpregset_data(gpregset_data) {}
-ThreadMinidump::~ThreadMinidump() {}
+ThreadMinidump::~ThreadMinidump() = default;
void ThreadMinidump::RefreshStateAfterStop() {}
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
new file mode 100644
index 000000000000..09e9375b6f66
--- /dev/null
+++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
@@ -0,0 +1,313 @@
+//===-- ScriptedProcess.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 "ScriptedProcess.h"
+
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+
+#include "lldb/Host/OptionParser.h"
+#include "lldb/Host/ThreadLauncher.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/OptionArgParser.h"
+#include "lldb/Interpreter/OptionGroupBoolean.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Target/RegisterContext.h"
+
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Logging.h"
+#include "lldb/Utility/State.h"
+
+#include <mutex>
+
+LLDB_PLUGIN_DEFINE(ScriptedProcess)
+
+using namespace lldb;
+using namespace lldb_private;
+
+ConstString ScriptedProcess::GetPluginNameStatic() {
+ static ConstString g_name("ScriptedProcess");
+ return g_name;
+}
+
+const char *ScriptedProcess::GetPluginDescriptionStatic() {
+ return "Scripted Process plug-in.";
+}
+
+static constexpr lldb::ScriptLanguage g_supported_script_languages[] = {
+ ScriptLanguage::eScriptLanguagePython,
+};
+
+bool ScriptedProcess::IsScriptLanguageSupported(lldb::ScriptLanguage language) {
+ llvm::ArrayRef<lldb::ScriptLanguage> supported_languages =
+ llvm::makeArrayRef(g_supported_script_languages);
+
+ return llvm::is_contained(supported_languages, language);
+}
+
+void ScriptedProcess::CheckInterpreterAndScriptObject() const {
+ lldbassert(m_interpreter && "Invalid Script Interpreter.");
+ lldbassert(m_script_object_sp && "Invalid Script Object.");
+}
+
+lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp,
+ lldb::ListenerSP listener_sp,
+ const FileSpec *file,
+ bool can_connect) {
+ if (!target_sp ||
+ !IsScriptLanguageSupported(target_sp->GetDebugger().GetScriptLanguage()))
+ return nullptr;
+
+ Status error;
+ ScriptedProcess::ScriptedProcessInfo scripted_process_info(
+ target_sp->GetProcessLaunchInfo());
+
+ auto process_sp = std::make_shared<ScriptedProcess>(
+ target_sp, listener_sp, scripted_process_info, error);
+
+ if (error.Fail() || !process_sp || !process_sp->m_script_object_sp ||
+ !process_sp->m_script_object_sp->IsValid()) {
+ LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS), "%s",
+ error.AsCString());
+ return nullptr;
+ }
+
+ return process_sp;
+}
+
+bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) {
+ return true;
+}
+
+ScriptedProcess::ScriptedProcess(
+ lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
+ const ScriptedProcess::ScriptedProcessInfo &scripted_process_info,
+ Status &error)
+ : Process(target_sp, listener_sp),
+ m_scripted_process_info(scripted_process_info) {
+
+ if (!target_sp) {
+ error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
+ __FUNCTION__, "Invalid target");
+ return;
+ }
+
+ m_interpreter = target_sp->GetDebugger().GetScriptInterpreter();
+
+ if (!m_interpreter) {
+ error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
+ __FUNCTION__,
+ "Debugger has no Script Interpreter");
+ return;
+ }
+
+ StructuredData::ObjectSP object_sp = GetInterface().CreatePluginObject(
+ m_scripted_process_info.GetClassName().c_str(), target_sp,
+ m_scripted_process_info.GetDictionarySP());
+
+ if (!object_sp || !object_sp->IsValid()) {
+ error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
+ __FUNCTION__,
+ "Failed to create valid script object");
+ return;
+ }
+
+ m_script_object_sp = object_sp;
+}
+
+ScriptedProcess::~ScriptedProcess() {
+ Clear();
+ // We need to call finalize on the process before destroying ourselves to
+ // make sure all of the broadcaster cleanup goes as planned. If we destruct
+ // this class, then Process::~Process() might have problems trying to fully
+ // destroy the broadcaster.
+ Finalize();
+}
+
+void ScriptedProcess::Initialize() {
+ static llvm::once_flag g_once_flag;
+
+ llvm::call_once(g_once_flag, []() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance);
+ });
+}
+
+void ScriptedProcess::Terminate() {
+ PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance);
+}
+
+ConstString ScriptedProcess::GetPluginName() { return GetPluginNameStatic(); }
+
+uint32_t ScriptedProcess::GetPluginVersion() { return 1; }
+
+Status ScriptedProcess::DoLoadCore() {
+ ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo();
+
+ return DoLaunch(nullptr, launch_info);
+}
+
+Status ScriptedProcess::DoLaunch(Module *exe_module,
+ ProcessLaunchInfo &launch_info) {
+ CheckInterpreterAndScriptObject();
+
+ /* FIXME: This doesn't reflect how lldb actually launches a process.
+ In reality, it attaches to debugserver, then resume the process. */
+ Status error = GetInterface().Launch();
+ SetPrivateState(eStateRunning);
+
+ if (error.Fail())
+ return error;
+
+ // TODO: Fetch next state from stopped event queue then send stop event
+ // const StateType state = SetThreadStopInfo(response);
+ // if (state != eStateInvalid) {
+ // SetPrivateState(state);
+
+ SetPrivateState(eStateStopped);
+
+ UpdateThreadListIfNeeded();
+ GetThreadList();
+
+ return {};
+}
+
+void ScriptedProcess::DidLaunch() {
+ CheckInterpreterAndScriptObject();
+ m_pid = GetInterface().GetProcessID();
+}
+
+Status ScriptedProcess::DoResume() {
+ CheckInterpreterAndScriptObject();
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ // FIXME: Fetch data from thread.
+ const StateType thread_resume_state = eStateRunning;
+ LLDB_LOGF(log, "ScriptedProcess::%s thread_resume_state = %s", __FUNCTION__,
+ StateAsCString(thread_resume_state));
+
+ bool resume = (thread_resume_state == eStateRunning);
+ assert(thread_resume_state == eStateRunning && "invalid thread resume state");
+
+ Status error;
+ if (resume) {
+ LLDB_LOGF(log, "ScriptedProcess::%s sending resume", __FUNCTION__);
+
+ SetPrivateState(eStateRunning);
+ SetPrivateState(eStateStopped);
+ error = GetInterface().Resume();
+ }
+
+ return error;
+}
+
+Status ScriptedProcess::DoStop() {
+ CheckInterpreterAndScriptObject();
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ if (GetInterface().ShouldStop()) {
+ SetPrivateState(eStateStopped);
+ LLDB_LOGF(log, "ScriptedProcess::%s Immediate stop", __FUNCTION__);
+ return {};
+ }
+
+ LLDB_LOGF(log, "ScriptedProcess::%s Delayed stop", __FUNCTION__);
+ return GetInterface().Stop();
+}
+
+Status ScriptedProcess::DoDestroy() { return Status(); }
+
+bool ScriptedProcess::IsAlive() {
+ if (m_interpreter && m_script_object_sp)
+ return GetInterface().IsAlive();
+ return false;
+}
+
+size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ Status &error) {
+
+ auto error_with_message = [&error](llvm::StringRef message) {
+ error.SetErrorString(message);
+ return 0;
+ };
+
+ if (!m_interpreter)
+ return error_with_message("No interpreter.");
+
+ lldb::DataExtractorSP data_extractor_sp =
+ GetInterface().ReadMemoryAtAddress(addr, size, error);
+
+ if (!data_extractor_sp || error.Fail())
+ return 0;
+
+ offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData(
+ 0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder());
+
+ if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET)
+ return error_with_message("Failed to copy read memory to buffer.");
+
+ return size;
+}
+
+ArchSpec ScriptedProcess::GetArchitecture() {
+ return GetTarget().GetArchitecture();
+}
+
+Status ScriptedProcess::GetMemoryRegionInfo(lldb::addr_t load_addr,
+ MemoryRegionInfo &region) {
+ // TODO: Implement
+ return Status();
+}
+
+Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos &region_list) {
+ CheckInterpreterAndScriptObject();
+
+ lldb::addr_t address = 0;
+ lldb::MemoryRegionInfoSP mem_region_sp = nullptr;
+
+ while ((mem_region_sp =
+ GetInterface().GetMemoryRegionContainingAddress(address))) {
+ auto range = mem_region_sp->GetRange();
+ address += range.GetRangeBase() + range.GetByteSize();
+ region_list.push_back(*mem_region_sp.get());
+ }
+
+ return {};
+}
+
+void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); }
+
+bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
+ ThreadList &new_thread_list) {
+ // TODO: Implement
+ // This is supposed to get the current set of threads, if any of them are in
+ // old_thread_list then they get copied to new_thread_list, and then any
+ // actually new threads will get added to new_thread_list.
+ return new_thread_list.GetSize(false) > 0;
+}
+
+bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) {
+ info.Clear();
+ info.SetProcessID(GetID());
+ info.SetArchitecture(GetArchitecture());
+ lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
+ if (module_sp) {
+ const bool add_exe_file_as_first_arg = false;
+ info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
+ add_exe_file_as_first_arg);
+ }
+ return true;
+}
+
+ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
+ return m_interpreter->GetScriptedProcessInterface();
+}
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.h b/lldb/source/Plugins/Process/scripted/ScriptedProcess.h
new file mode 100644
index 000000000000..98c1a1ca4fe9
--- /dev/null
+++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.h
@@ -0,0 +1,119 @@
+//===-- ScriptedProcess.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_SOURCE_PLUGINS_SCRIPTED_PROCESS_H
+#define LLDB_SOURCE_PLUGINS_SCRIPTED_PROCESS_H
+
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Status.h"
+
+#include <mutex>
+
+namespace lldb_private {
+
+class ScriptedProcess : public Process {
+protected:
+ class ScriptedProcessInfo {
+ public:
+ ScriptedProcessInfo(const ProcessLaunchInfo &launch_info) {
+ m_class_name = launch_info.GetScriptedProcessClassName();
+ m_dictionary_sp = launch_info.GetScriptedProcessDictionarySP();
+ }
+
+ std::string GetClassName() const { return m_class_name; }
+ StructuredData::DictionarySP GetDictionarySP() const {
+ return m_dictionary_sp;
+ }
+
+ private:
+ std::string m_class_name;
+ StructuredData::DictionarySP m_dictionary_sp;
+ };
+
+public:
+ static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp,
+ lldb::ListenerSP listener_sp,
+ const FileSpec *crash_file_path,
+ bool can_connect);
+
+ static void Initialize();
+
+ static void Terminate();
+
+ static ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ ScriptedProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
+ const ScriptedProcess::ScriptedProcessInfo &launch_info,
+ Status &error);
+
+ ~ScriptedProcess() override;
+
+ bool CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) override;
+
+ DynamicLoader *GetDynamicLoader() override { return nullptr; }
+
+ ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+ SystemRuntime *GetSystemRuntime() override { return nullptr; }
+
+ Status DoLoadCore() override;
+
+ Status DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) override;
+
+ void DidLaunch() override;
+
+ Status DoResume() override;
+
+ Status DoDestroy() override;
+
+ void RefreshStateAfterStop() override{};
+
+ bool IsAlive() override;
+
+ size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ Status &error) override;
+
+ ArchSpec GetArchitecture();
+
+ Status GetMemoryRegionInfo(lldb::addr_t load_addr,
+ MemoryRegionInfo &range_info) override;
+
+ Status
+ GetMemoryRegions(lldb_private::MemoryRegionInfos &region_list) override;
+
+ bool GetProcessInfo(ProcessInstanceInfo &info) override;
+
+protected:
+ Status DoStop();
+
+ void Clear();
+
+ bool DoUpdateThreadList(ThreadList &old_thread_list,
+ ThreadList &new_thread_list) override;
+
+private:
+ void CheckInterpreterAndScriptObject() const;
+ ScriptedProcessInterface &GetInterface() const;
+ static bool IsScriptLanguageSupported(lldb::ScriptLanguage language);
+
+ // Member variables.
+ const ScriptedProcessInfo m_scripted_process_info;
+ lldb_private::ScriptInterpreter *m_interpreter = nullptr;
+ lldb_private::StructuredData::ObjectSP m_script_object_sp = nullptr;
+ //@}
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_SCRIPTED_PROCESS_H
diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
index f14e2732f6eb..e99b7b88379a 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
@@ -30,6 +30,9 @@ extern "C" llvm::Expected<bool> LLDBSwigLuaBreakpointCallbackFunction(
lua_State *L, lldb::StackFrameSP stop_frame_sp,
lldb::BreakpointLocationSP bp_loc_sp, StructuredDataImpl *extra_args_impl);
+extern "C" llvm::Expected<bool> LLDBSwigLuaWatchpointCallbackFunction(
+ lua_State *L, lldb::StackFrameSP stop_frame_sp, lldb::WatchpointSP wp_sp);
+
#if _MSC_VER
#pragma warning (pop)
#endif
@@ -113,6 +116,32 @@ Lua::CallBreakpointCallback(void *baton, lldb::StackFrameSP stop_frame_sp,
bp_loc_sp, extra_args_impl);
}
+llvm::Error Lua::RegisterWatchpointCallback(void *baton, const char *body) {
+ lua_pushlightuserdata(m_lua_state, baton);
+ const char *fmt_str = "return function(frame, wp, ...) {0} end";
+ std::string func_str = llvm::formatv(fmt_str, body).str();
+ if (luaL_dostring(m_lua_state, func_str.c_str()) != LUA_OK) {
+ llvm::Error e = llvm::make_error<llvm::StringError>(
+ llvm::formatv("{0}", lua_tostring(m_lua_state, -1)),
+ llvm::inconvertibleErrorCode());
+ // Pop error message from the stack.
+ lua_pop(m_lua_state, 2);
+ return e;
+ }
+ lua_settable(m_lua_state, LUA_REGISTRYINDEX);
+ return llvm::Error::success();
+}
+
+llvm::Expected<bool>
+Lua::CallWatchpointCallback(void *baton, lldb::StackFrameSP stop_frame_sp,
+ lldb::WatchpointSP wp_sp) {
+
+ lua_pushlightuserdata(m_lua_state, baton);
+ lua_gettable(m_lua_state, LUA_REGISTRYINDEX);
+ return LLDBSwigLuaWatchpointCallbackFunction(m_lua_state, stop_frame_sp,
+ wp_sp);
+}
+
llvm::Error Lua::CheckSyntax(llvm::StringRef buffer) {
int error =
luaL_loadbuffer(m_lua_state, buffer.data(), buffer.size(), "buffer");
diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h
index 873440f0aab3..5daedf835b9b 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h
@@ -37,6 +37,10 @@ public:
CallBreakpointCallback(void *baton, lldb::StackFrameSP stop_frame_sp,
lldb::BreakpointLocationSP bp_loc_sp,
StructuredData::ObjectSP extra_args_sp);
+ llvm::Error RegisterWatchpointCallback(void *baton, const char *body);
+ llvm::Expected<bool> CallWatchpointCallback(void *baton,
+ lldb::StackFrameSP stop_frame_sp,
+ lldb::WatchpointSP wp_sp);
llvm::Error LoadModule(llvm::StringRef filename);
llvm::Error CheckSyntax(llvm::StringRef buffer);
llvm::Error ChangeIO(FILE *out, FILE *err);
diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
index 920e334f51aa..ef46401c8b46 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
@@ -58,7 +58,13 @@ public:
const char *instructions = nullptr;
switch (m_active_io_handler) {
case eIOHandlerNone:
+ break;
case eIOHandlerWatchpoint:
+ instructions = "Enter your Lua command(s). Type 'quit' to end.\n"
+ "The commands are compiled as the body of the following "
+ "Lua function\n"
+ "function (frame, wp) end\n";
+ SetPrompt(llvm::StringRef("..> "));
break;
case eIOHandlerBreakpoint:
instructions = "Enter your Lua command(s). Type 'quit' to end.\n"
@@ -78,7 +84,8 @@ public:
StringList &lines) override {
size_t last = lines.GetSize() - 1;
if (IsQuitCommand(lines.GetStringAtIndex(last))) {
- if (m_active_io_handler == eIOHandlerBreakpoint)
+ if (m_active_io_handler == eIOHandlerBreakpoint ||
+ m_active_io_handler == eIOHandlerWatchpoint)
lines.DeleteStringAtIndex(last);
return true;
}
@@ -90,17 +97,19 @@ public:
// Lua always errors out to incomplete code with '<eof>'
return error_str.find("<eof>") == std::string::npos;
}
- // The breakpoint handler only exits with a explicit 'quit'
- return m_active_io_handler != eIOHandlerBreakpoint;
+ // The breakpoint and watchpoint handler only exits with a explicit 'quit'
+ return m_active_io_handler != eIOHandlerBreakpoint &&
+ m_active_io_handler != eIOHandlerWatchpoint;
}
void IOHandlerInputComplete(IOHandler &io_handler,
std::string &data) override {
switch (m_active_io_handler) {
case eIOHandlerBreakpoint: {
- auto *bp_options_vec = static_cast<std::vector<BreakpointOptions *> *>(
- io_handler.GetUserData());
- for (auto *bp_options : *bp_options_vec) {
+ auto *bp_options_vec =
+ static_cast<std::vector<std::reference_wrapper<BreakpointOptions>> *>(
+ io_handler.GetUserData());
+ for (BreakpointOptions &bp_options : *bp_options_vec) {
Status error = m_script_interpreter.SetBreakpointCommandCallback(
bp_options, data.c_str());
if (error.Fail())
@@ -108,9 +117,13 @@ public:
}
io_handler.SetIsDone(true);
} break;
- case eIOHandlerWatchpoint:
+ case eIOHandlerWatchpoint: {
+ auto *wp_options =
+ static_cast<WatchpointOptions *>(io_handler.GetUserData());
+ m_script_interpreter.SetWatchpointCommandCallback(wp_options,
+ data.c_str());
io_handler.SetIsDone(true);
- break;
+ } break;
case eIOHandlerNone:
if (IsQuitCommand(data)) {
io_handler.SetIsDone(true);
@@ -133,7 +146,7 @@ ScriptInterpreterLua::ScriptInterpreterLua(Debugger &debugger)
: ScriptInterpreter(debugger, eScriptLanguageLua),
m_lua(std::make_unique<Lua>()) {}
-ScriptInterpreterLua::~ScriptInterpreterLua() {}
+ScriptInterpreterLua::~ScriptInterpreterLua() = default;
bool ScriptInterpreterLua::ExecuteOneLine(llvm::StringRef command,
CommandReturnObject *result,
@@ -194,8 +207,9 @@ void ScriptInterpreterLua::ExecuteInterpreterLoop() {
}
bool ScriptInterpreterLua::LoadScriptingModule(
- const char *filename, bool init_session, lldb_private::Status &error,
- StructuredData::ObjectSP *module_sp, FileSpec extra_search_dir) {
+ const char *filename, const LoadScriptOptions &options,
+ lldb_private::Status &error, StructuredData::ObjectSP *module_sp,
+ FileSpec extra_search_dir) {
FileSystem::Instance().Collect(filename);
if (llvm::Error e = m_lua->LoadModule(filename)) {
@@ -275,8 +289,35 @@ bool ScriptInterpreterLua::BreakpointCallbackFunction(
return *BoolOrErr;
}
+bool ScriptInterpreterLua::WatchpointCallbackFunction(
+ void *baton, StoppointCallbackContext *context, user_id_t watch_id) {
+ assert(context);
+
+ ExecutionContext exe_ctx(context->exe_ctx_ref);
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target == nullptr)
+ return true;
+
+ StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());
+ WatchpointSP wp_sp = target->GetWatchpointList().FindByID(watch_id);
+
+ Debugger &debugger = target->GetDebugger();
+ ScriptInterpreterLua *lua_interpreter = static_cast<ScriptInterpreterLua *>(
+ debugger.GetScriptInterpreter(true, eScriptLanguageLua));
+ Lua &lua = lua_interpreter->GetLua();
+
+ llvm::Expected<bool> BoolOrErr =
+ lua.CallWatchpointCallback(baton, stop_frame_sp, wp_sp);
+ if (llvm::Error E = BoolOrErr.takeError()) {
+ debugger.GetErrorStream() << toString(std::move(E));
+ return true;
+ }
+
+ return *BoolOrErr;
+}
+
void ScriptInterpreterLua::CollectDataForBreakpointCommandCallback(
- std::vector<BreakpointOptions *> &bp_options_vec,
+ std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
CommandReturnObject &result) {
IOHandlerSP io_handler_sp(
new IOHandlerLuaInterpreter(m_debugger, *this, eIOHandlerBreakpoint));
@@ -284,8 +325,16 @@ void ScriptInterpreterLua::CollectDataForBreakpointCommandCallback(
m_debugger.RunIOHandlerAsync(io_handler_sp);
}
+void ScriptInterpreterLua::CollectDataForWatchpointCommandCallback(
+ WatchpointOptions *wp_options, CommandReturnObject &result) {
+ IOHandlerSP io_handler_sp(
+ new IOHandlerLuaInterpreter(m_debugger, *this, eIOHandlerWatchpoint));
+ io_handler_sp->SetUserData(wp_options);
+ m_debugger.RunIOHandlerAsync(io_handler_sp);
+}
+
Status ScriptInterpreterLua::SetBreakpointCommandCallbackFunction(
- BreakpointOptions *bp_options, const char *function_name,
+ BreakpointOptions &bp_options, const char *function_name,
StructuredData::ObjectSP extra_args_sp) {
const char *fmt_str = "return {0}(frame, bp_loc, ...)";
std::string oneliner = llvm::formatv(fmt_str, function_name).str();
@@ -294,12 +343,12 @@ Status ScriptInterpreterLua::SetBreakpointCommandCallbackFunction(
}
Status ScriptInterpreterLua::SetBreakpointCommandCallback(
- BreakpointOptions *bp_options, const char *command_body_text) {
+ BreakpointOptions &bp_options, const char *command_body_text) {
return RegisterBreakpointCallback(bp_options, command_body_text, {});
}
Status ScriptInterpreterLua::RegisterBreakpointCallback(
- BreakpointOptions *bp_options, const char *command_body_text,
+ BreakpointOptions &bp_options, const char *command_body_text,
StructuredData::ObjectSP extra_args_sp) {
Status error;
auto data_up = std::make_unique<CommandDataLua>(extra_args_sp);
@@ -308,7 +357,27 @@ Status ScriptInterpreterLua::RegisterBreakpointCallback(
return error;
auto baton_sp =
std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up));
- bp_options->SetCallback(ScriptInterpreterLua::BreakpointCallbackFunction,
+ bp_options.SetCallback(ScriptInterpreterLua::BreakpointCallbackFunction,
+ baton_sp);
+ return error;
+}
+
+void ScriptInterpreterLua::SetWatchpointCommandCallback(
+ WatchpointOptions *wp_options, const char *command_body_text) {
+ RegisterWatchpointCallback(wp_options, command_body_text, {});
+}
+
+Status ScriptInterpreterLua::RegisterWatchpointCallback(
+ WatchpointOptions *wp_options, const char *command_body_text,
+ StructuredData::ObjectSP extra_args_sp) {
+ Status error;
+ auto data_up = std::make_unique<WatchpointOptions::CommandData>();
+ error = m_lua->RegisterWatchpointCallback(data_up.get(), command_body_text);
+ if (error.Fail())
+ return error;
+ auto baton_sp =
+ std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up));
+ wp_options->SetCallback(ScriptInterpreterLua::WatchpointCallbackFunction,
baton_sp);
return error;
}
diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
index 1130ceee3c20..808000b833ec 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
@@ -9,6 +9,9 @@
#ifndef liblldb_ScriptInterpreterLua_h_
#define liblldb_ScriptInterpreterLua_h_
+#include <vector>
+
+#include "lldb/Breakpoint/WatchpointOptions.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Utility/Status.h"
@@ -40,7 +43,8 @@ public:
void ExecuteInterpreterLoop() override;
- bool LoadScriptingModule(const char *filename, bool init_session,
+ bool LoadScriptingModule(const char *filename,
+ const LoadScriptOptions &options,
lldb_private::Status &error,
StructuredData::ObjectSP *module_sp = nullptr,
FileSpec extra_search_dir = {}) override;
@@ -61,6 +65,10 @@ public:
lldb::user_id_t break_id,
lldb::user_id_t break_loc_id);
+ static bool WatchpointCallbackFunction(void *baton,
+ StoppointCallbackContext *context,
+ lldb::user_id_t watch_id);
+
// PluginInterface protocol
lldb_private::ConstString GetPluginName() override;
@@ -72,21 +80,32 @@ public:
llvm::Error LeaveSession();
void CollectDataForBreakpointCommandCallback(
- std::vector<BreakpointOptions *> &bp_options_vec,
+ std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
CommandReturnObject &result) override;
- Status SetBreakpointCommandCallback(BreakpointOptions *bp_options,
+ void
+ CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options,
+ CommandReturnObject &result) override;
+
+ Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
const char *command_body_text) override;
+ void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
+ const char *command_body_text) override;
+
Status SetBreakpointCommandCallbackFunction(
- BreakpointOptions *bp_options, const char *function_name,
+ BreakpointOptions &bp_options, const char *function_name,
StructuredData::ObjectSP extra_args_sp) override;
private:
std::unique_ptr<Lua> m_lua;
bool m_session_is_active = false;
- Status RegisterBreakpointCallback(BreakpointOptions *bp_options,
+ Status RegisterBreakpointCallback(BreakpointOptions &bp_options,
+ const char *command_body_text,
+ StructuredData::ObjectSP extra_args_sp);
+
+ Status RegisterWatchpointCallback(WatchpointOptions *wp_options,
const char *command_body_text,
StructuredData::ObjectSP extra_args_sp);
};
diff --git a/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp b/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
index d9c32cc132d4..f8a385240bd9 100644
--- a/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
@@ -25,7 +25,7 @@ LLDB_PLUGIN_DEFINE(ScriptInterpreterNone)
ScriptInterpreterNone::ScriptInterpreterNone(Debugger &debugger)
: ScriptInterpreter(debugger, eScriptLanguageNone) {}
-ScriptInterpreterNone::~ScriptInterpreterNone() {}
+ScriptInterpreterNone::~ScriptInterpreterNone() = default;
bool ScriptInterpreterNone::ExecuteOneLine(llvm::StringRef command,
CommandReturnObject *,
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
index 7c49502f1b57..f51d9b3a796c 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
@@ -24,7 +24,7 @@
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Errno.h"
-#include <stdio.h>
+#include <cstdio>
using namespace lldb_private;
using namespace lldb;
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
index 22f6c67eb7a5..4577253227cd 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
@@ -229,7 +229,7 @@ struct PythonFormat<
class PythonObject {
public:
- PythonObject() : m_py_obj(nullptr) {}
+ PythonObject() = default;
PythonObject(PyRefType type, PyObject *py_obj) {
m_py_obj = py_obj;
@@ -378,7 +378,7 @@ public:
}
protected:
- PyObject *m_py_obj;
+ PyObject *m_py_obj = nullptr;
};
@@ -421,7 +421,7 @@ public:
Py_DECREF(py_obj);
}
- TypedPythonObject() {}
+ TypedPythonObject() = default;
};
class PythonBytes : public TypedPythonObject<PythonBytes> {
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
index 5f6429f5cd0e..95a3365ed983 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
@@ -2,7 +2,7 @@
#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
-#include <stdio.h>
+#include <cstdio>
#include <editline/readline.h>
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp
new file mode 100644
index 000000000000..7c7c5d73680a
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp
@@ -0,0 +1,48 @@
+//===-- SWIGPythonBridge.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 "lldb/Host/Config.h"
+#include "lldb/lldb-enumerations.h"
+
+#if LLDB_ENABLE_PYTHON
+
+// LLDB Python header must be included first
+#include "lldb-python.h"
+
+#include "SWIGPythonBridge.h"
+
+using namespace lldb;
+
+namespace lldb_private {
+
+template <typename T> const char *GetPythonValueFormatString(T t);
+template <> const char *GetPythonValueFormatString(char *) { return "s"; }
+template <> const char *GetPythonValueFormatString(char) { return "b"; }
+template <> const char *GetPythonValueFormatString(unsigned char) {
+ return "B";
+}
+template <> const char *GetPythonValueFormatString(short) { return "h"; }
+template <> const char *GetPythonValueFormatString(unsigned short) {
+ return "H";
+}
+template <> const char *GetPythonValueFormatString(int) { return "i"; }
+template <> const char *GetPythonValueFormatString(unsigned int) { return "I"; }
+template <> const char *GetPythonValueFormatString(long) { return "l"; }
+template <> const char *GetPythonValueFormatString(unsigned long) {
+ return "k";
+}
+template <> const char *GetPythonValueFormatString(long long) { return "L"; }
+template <> const char *GetPythonValueFormatString(unsigned long long) {
+ return "K";
+}
+template <> const char *GetPythonValueFormatString(float) { return "f"; }
+template <> const char *GetPythonValueFormatString(double) { return "d"; }
+
+} // namespace lldb_private
+
+#endif // LLDB_ENABLE_PYTHON
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
new file mode 100644
index 000000000000..1ef792bcf303
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
@@ -0,0 +1,56 @@
+//===-- ScriptInterpreterPython.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_SWIGPYTHONBRIDGE_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SWIGPYTHONBRIDGE_H
+
+#include <string>
+
+#include "lldb/Host/Config.h"
+
+#if LLDB_ENABLE_PYTHON
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
+
+namespace lldb_private {
+
+// GetPythonValueFormatString provides a system independent type safe way to
+// convert a variable's type into a python value format. Python value formats
+// are defined in terms of builtin C types and could change from system to as
+// the underlying typedef for uint* types, size_t, off_t and other values
+// change.
+
+template <typename T> const char *GetPythonValueFormatString(T t);
+template <> const char *GetPythonValueFormatString(char *);
+template <> const char *GetPythonValueFormatString(char);
+template <> const char *GetPythonValueFormatString(unsigned char);
+template <> const char *GetPythonValueFormatString(short);
+template <> const char *GetPythonValueFormatString(unsigned short);
+template <> const char *GetPythonValueFormatString(int);
+template <> const char *GetPythonValueFormatString(unsigned int);
+template <> const char *GetPythonValueFormatString(long);
+template <> const char *GetPythonValueFormatString(unsigned long);
+template <> const char *GetPythonValueFormatString(long long);
+template <> const char *GetPythonValueFormatString(unsigned long long);
+template <> const char *GetPythonValueFormatString(float t);
+template <> const char *GetPythonValueFormatString(double t);
+
+extern "C" void *LLDBSwigPythonCreateScriptedProcess(
+ const char *python_class_name, const char *session_dictionary_name,
+ const lldb::TargetSP &target_sp, StructuredDataImpl *args_impl,
+ std::string &error_string);
+
+extern "C" void *LLDBSWIGPython_CastPyObjectToSBData(void *data);
+extern "C" void *LLDBSWIGPython_CastPyObjectToSBError(void *data);
+extern "C" void *LLDBSWIGPython_CastPyObjectToSBValue(void *data);
+
+} // namespace lldb_private
+
+#endif // LLDB_ENABLE_PYTHON
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SWIGPYTHONBRIDGE_H
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index 6b53bd3a2edc..7ad63722c31c 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -16,7 +16,11 @@
#include "PythonDataObjects.h"
#include "PythonReadline.h"
+#include "SWIGPythonBridge.h"
#include "ScriptInterpreterPythonImpl.h"
+#include "ScriptedProcessPythonInterface.h"
+
+#include "lldb/API/SBError.h"
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBValue.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
@@ -41,10 +45,10 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatAdapters.h"
+#include <cstdio>
+#include <cstdlib>
#include <memory>
#include <mutex>
-#include <stdio.h>
-#include <stdlib.h>
#include <string>
using namespace lldb;
@@ -148,8 +152,6 @@ extern "C" void *LLDBSwigPython_GetChildAtIndex(void *implementor,
extern "C" int LLDBSwigPython_GetIndexOfChildWithName(void *implementor,
const char *child_name);
-extern "C" void *LLDBSWIGPython_CastPyObjectToSBValue(void *data);
-
extern lldb::ValueObjectSP
LLDBSWIGPython_GetValueObjectSPFromSBValue(void *data);
@@ -234,8 +236,7 @@ namespace {
// save off initial state at the beginning, and restore it at the end
struct InitializePythonRAII {
public:
- InitializePythonRAII()
- : m_gil_state(PyGILState_UNLOCKED), m_was_already_initialized(false) {
+ InitializePythonRAII() {
InitializePythonHome();
#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
@@ -355,8 +356,8 @@ private:
}
TerminalState m_stdin_tty_state;
- PyGILState_STATE m_gil_state;
- bool m_was_already_initialized;
+ PyGILState_STATE m_gil_state = PyGILState_UNLOCKED;
+ bool m_was_already_initialized = false;
};
} // namespace
@@ -410,6 +411,32 @@ FileSpec ScriptInterpreterPython::GetPythonDir() {
return g_spec;
}
+void ScriptInterpreterPython::SharedLibraryDirectoryHelper(
+ FileSpec &this_file) {
+ // When we're loaded from python, this_file will point to the file inside the
+ // python package directory. Replace it with the one in the lib directory.
+#ifdef _WIN32
+ // On windows, we need to manually back out of the python tree, and go into
+ // the bin directory. This is pretty much the inverse of what ComputePythonDir
+ // does.
+ if (this_file.GetFileNameExtension() == ConstString(".pyd")) {
+ this_file.RemoveLastPathComponent(); // _lldb.pyd or _lldb_d.pyd
+ this_file.RemoveLastPathComponent(); // lldb
+ llvm::StringRef libdir = LLDB_PYTHON_RELATIVE_LIBDIR;
+ for (auto it = llvm::sys::path::begin(libdir),
+ end = llvm::sys::path::end(libdir);
+ it != end; ++it)
+ this_file.RemoveLastPathComponent();
+ this_file.AppendPathComponent("bin");
+ this_file.AppendPathComponent("liblldb.dll");
+ }
+#else
+ // The python file is a symlink, so we can find the real library by resolving
+ // it. We can do this unconditionally.
+ FileSystem::Instance().ResolveSymbolicLink(this_file, this_file);
+#endif
+}
+
lldb_private::ConstString ScriptInterpreterPython::GetPluginNameStatic() {
static ConstString g_name("script-python");
return g_name;
@@ -506,6 +533,9 @@ ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger)
m_command_thread_state(nullptr) {
InitializePrivate();
+ m_scripted_process_interface_up =
+ std::make_unique<ScriptedProcessPythonInterface>(*this);
+
m_dictionary_name.append("_dict");
StreamString run_string;
run_string.Printf("%s = dict()", m_dictionary_name.c_str());
@@ -605,11 +635,10 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler,
case eIOHandlerNone:
break;
case eIOHandlerBreakpoint: {
- std::vector<BreakpointOptions *> *bp_options_vec =
- (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
- for (auto bp_options : *bp_options_vec) {
- if (!bp_options)
- continue;
+ std::vector<std::reference_wrapper<BreakpointOptions>> *bp_options_vec =
+ (std::vector<std::reference_wrapper<BreakpointOptions>> *)
+ io_handler.GetUserData();
+ for (BreakpointOptions &bp_options : *bp_options_vec) {
auto data_up = std::make_unique<CommandDataPython>();
if (!data_up)
@@ -623,7 +652,7 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler,
.Success()) {
auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>(
std::move(data_up));
- bp_options->SetCallback(
+ bp_options.SetCallback(
ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);
} else if (!batch_mode) {
StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
@@ -1048,11 +1077,24 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn(
llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type,
void *ret_value, const ExecuteScriptOptions &options) {
+ llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
+ io_redirect_or_error = ScriptInterpreterIORedirect::Create(
+ options.GetEnableIO(), m_debugger, /*result=*/nullptr);
+
+ if (!io_redirect_or_error) {
+ llvm::consumeError(io_redirect_or_error.takeError());
+ return false;
+ }
+
+ ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;
+
Locker locker(this,
Locker::AcquireLock | Locker::InitSession |
(options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
Locker::NoSTDIN,
- Locker::FreeAcquiredLock | Locker::TearDownSession);
+ Locker::FreeAcquiredLock | Locker::TearDownSession,
+ io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
+ io_redirect.GetErrorFile());
PythonModule &main_module = GetMainModule();
PythonDictionary globals = main_module.GetDictionary();
@@ -1161,11 +1203,22 @@ Status ScriptInterpreterPythonImpl::ExecuteMultipleLines(
if (in_string == nullptr)
return Status();
+ llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
+ io_redirect_or_error = ScriptInterpreterIORedirect::Create(
+ options.GetEnableIO(), m_debugger, /*result=*/nullptr);
+
+ if (!io_redirect_or_error)
+ return Status(io_redirect_or_error.takeError());
+
+ ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;
+
Locker locker(this,
Locker::AcquireLock | Locker::InitSession |
(options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
Locker::NoSTDIN,
- Locker::FreeAcquiredLock | Locker::TearDownSession);
+ Locker::FreeAcquiredLock | Locker::TearDownSession,
+ io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
+ io_redirect.GetErrorFile());
PythonModule &main_module = GetMainModule();
PythonDictionary globals = main_module.GetDictionary();
@@ -1196,7 +1249,7 @@ Status ScriptInterpreterPythonImpl::ExecuteMultipleLines(
}
void ScriptInterpreterPythonImpl::CollectDataForBreakpointCommandCallback(
- std::vector<BreakpointOptions *> &bp_options_vec,
+ std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
CommandReturnObject &result) {
m_active_io_handler = eIOHandlerBreakpoint;
m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(
@@ -1211,7 +1264,7 @@ void ScriptInterpreterPythonImpl::CollectDataForWatchpointCommandCallback(
}
Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction(
- BreakpointOptions *bp_options, const char *function_name,
+ 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.
@@ -1253,7 +1306,7 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction(
}
Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
- BreakpointOptions *bp_options,
+ BreakpointOptions &bp_options,
std::unique_ptr<BreakpointOptions::CommandData> &cmd_data_up) {
Status error;
error = GenerateBreakpointCommandCallbackData(cmd_data_up->user_source,
@@ -1264,21 +1317,20 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
}
auto baton_sp =
std::make_shared<BreakpointOptions::CommandBaton>(std::move(cmd_data_up));
- bp_options->SetCallback(
+ bp_options.SetCallback(
ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);
return error;
}
Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
- BreakpointOptions *bp_options, const char *command_body_text) {
+ BreakpointOptions &bp_options, const char *command_body_text) {
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) {
+ 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
@@ -1292,7 +1344,7 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
if (error.Success()) {
auto baton_sp =
std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up));
- bp_options->SetCallback(
+ bp_options.SetCallback(
ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);
return error;
}
@@ -1330,7 +1382,7 @@ Status ScriptInterpreterPythonImpl::ExportFunctionDefinitionToInterpreter(
Status error = ExecuteMultipleLines(
function_def_string.c_str(),
- ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false));
+ ExecuteScriptOptions().SetEnableIO(false));
return error;
}
@@ -1678,35 +1730,6 @@ StructuredData::ArraySP ScriptInterpreterPythonImpl::OSPlugin_ThreadsInfo(
return StructuredData::ArraySP();
}
-// GetPythonValueFormatString provides a system independent type safe way to
-// convert a variable's type into a python value format. Python value formats
-// are defined in terms of builtin C types and could change from system to as
-// the underlying typedef for uint* types, size_t, off_t and other values
-// change.
-
-template <typename T> const char *GetPythonValueFormatString(T t);
-template <> const char *GetPythonValueFormatString(char *) { return "s"; }
-template <> const char *GetPythonValueFormatString(char) { return "b"; }
-template <> const char *GetPythonValueFormatString(unsigned char) {
- return "B";
-}
-template <> const char *GetPythonValueFormatString(short) { return "h"; }
-template <> const char *GetPythonValueFormatString(unsigned short) {
- return "H";
-}
-template <> const char *GetPythonValueFormatString(int) { return "i"; }
-template <> const char *GetPythonValueFormatString(unsigned int) { return "I"; }
-template <> const char *GetPythonValueFormatString(long) { return "l"; }
-template <> const char *GetPythonValueFormatString(unsigned long) {
- return "k";
-}
-template <> const char *GetPythonValueFormatString(long long) { return "L"; }
-template <> const char *GetPythonValueFormatString(unsigned long long) {
- return "K";
-}
-template <> const char *GetPythonValueFormatString(float t) { return "f"; }
-template <> const char *GetPythonValueFormatString(double t) { return "d"; }
-
StructuredData::StringSP
ScriptInterpreterPythonImpl::OSPlugin_RegisterContextData(
StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid) {
@@ -2058,7 +2081,10 @@ ScriptInterpreterPythonImpl::LoadPluginModule(const FileSpec &file_spec,
StructuredData::ObjectSP module_sp;
- if (LoadScriptingModule(file_spec.GetPath().c_str(), true, error, &module_sp))
+ LoadScriptOptions load_script_options =
+ LoadScriptOptions().SetInitSession(true).SetSilent(false);
+ if (LoadScriptingModule(file_spec.GetPath().c_str(), load_script_options,
+ error, &module_sp))
return module_sp;
return StructuredData::ObjectSP();
@@ -2733,26 +2759,44 @@ uint64_t replace_all(std::string &str, const std::string &oldStr,
}
bool ScriptInterpreterPythonImpl::LoadScriptingModule(
- const char *pathname, bool init_session, lldb_private::Status &error,
- StructuredData::ObjectSP *module_sp, FileSpec extra_search_dir) {
+ const char *pathname, const LoadScriptOptions &options,
+ lldb_private::Status &error, StructuredData::ObjectSP *module_sp,
+ FileSpec extra_search_dir) {
namespace fs = llvm::sys::fs;
namespace path = llvm::sys::path;
+ ExecuteScriptOptions exc_options = ExecuteScriptOptions()
+ .SetEnableIO(!options.GetSilent())
+ .SetSetLLDBGlobals(false);
+
if (!pathname || !pathname[0]) {
error.SetErrorString("invalid pathname");
return false;
}
+ llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
+ io_redirect_or_error = ScriptInterpreterIORedirect::Create(
+ exc_options.GetEnableIO(), m_debugger, /*result=*/nullptr);
+
+ if (!io_redirect_or_error) {
+ error = io_redirect_or_error.takeError();
+ return false;
+ }
+
+ ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;
lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();
// Before executing Python code, lock the GIL.
Locker py_lock(this,
Locker::AcquireLock |
- (init_session ? Locker::InitSession : 0) | Locker::NoSTDIN,
+ (options.GetInitSession() ? Locker::InitSession : 0) |
+ Locker::NoSTDIN,
Locker::FreeAcquiredLock |
- (init_session ? Locker::TearDownSession : 0));
+ (options.GetInitSession() ? Locker::TearDownSession : 0),
+ io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
+ io_redirect.GetErrorFile());
- auto ExtendSysPath = [this](std::string directory) -> llvm::Error {
+ auto ExtendSysPath = [&](std::string directory) -> llvm::Error {
if (directory.empty()) {
return llvm::make_error<llvm::StringError>(
"invalid directory name", llvm::inconvertibleErrorCode());
@@ -2767,11 +2811,7 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule(
"sys.path.insert(1,'%s');\n\n",
directory.c_str(), directory.c_str());
bool syspath_retval =
- ExecuteMultipleLines(command_stream.GetData(),
- ScriptInterpreter::ExecuteScriptOptions()
- .SetEnableIO(false)
- .SetSetLLDBGlobals(false))
- .Success();
+ ExecuteMultipleLines(command_stream.GetData(), exc_options).Success();
if (!syspath_retval) {
return llvm::make_error<llvm::StringError>(
"Python sys.path handling failed", llvm::inconvertibleErrorCode());
@@ -2781,6 +2821,7 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule(
};
std::string module_name(pathname);
+ bool possible_package = false;
if (extra_search_dir) {
if (llvm::Error e = ExtendSysPath(extra_search_dir.GetPath())) {
@@ -2805,6 +2846,7 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule(
return false;
}
// Not a filename, probably a package of some sort, let it go through.
+ possible_package = true;
} else if (is_directory(st) || is_regular_file(st)) {
if (module_file.GetDirectory().IsEmpty()) {
error.SetErrorString("invalid directory name");
@@ -2831,35 +2873,39 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule(
module_name.resize(module_name.length() - 4);
}
- // check if the module is already import-ed
+ if (!possible_package && module_name.find('.') != llvm::StringRef::npos) {
+ error.SetErrorStringWithFormat(
+ "Python does not allow dots in module names: %s", module_name.c_str());
+ return false;
+ }
+
+ if (module_name.find('-') != llvm::StringRef::npos) {
+ error.SetErrorStringWithFormat(
+ "Python discourages dashes in module names: %s", module_name.c_str());
+ return false;
+ }
+
+ // Check if the module is already imported.
StreamString command_stream;
command_stream.Clear();
command_stream.Printf("sys.modules.__contains__('%s')", module_name.c_str());
bool does_contain = false;
- // this call will succeed if the module was ever imported in any Debugger
- // in the lifetime of the process in which this LLDB framework is living
- bool was_imported_globally =
- (ExecuteOneLineWithReturn(
- command_stream.GetData(),
- ScriptInterpreterPythonImpl::eScriptReturnTypeBool, &does_contain,
- ScriptInterpreter::ExecuteScriptOptions()
- .SetEnableIO(false)
- .SetSetLLDBGlobals(false)) &&
- does_contain);
- // this call will fail if the module was not imported in this Debugger
- // before
- command_stream.Clear();
- command_stream.Printf("sys.getrefcount(%s)", module_name.c_str());
- bool was_imported_locally = GetSessionDictionary()
- .GetItemForKey(PythonString(module_name))
- .IsAllocated();
+ // This call will succeed if the module was ever imported in any Debugger in
+ // the lifetime of the process in which this LLDB framework is living.
+ const bool does_contain_executed = ExecuteOneLineWithReturn(
+ command_stream.GetData(),
+ ScriptInterpreterPythonImpl::eScriptReturnTypeBool, &does_contain, exc_options);
- bool was_imported = (was_imported_globally || was_imported_locally);
+ const bool was_imported_globally = does_contain_executed && does_contain;
+ const bool was_imported_locally =
+ GetSessionDictionary()
+ .GetItemForKey(PythonString(module_name))
+ .IsAllocated();
// now actually do the import
command_stream.Clear();
- if (was_imported) {
+ if (was_imported_globally || was_imported_locally) {
if (!was_imported_locally)
command_stream.Printf("import %s ; reload_module(%s)",
module_name.c_str(), module_name.c_str());
@@ -2868,10 +2914,7 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule(
} else
command_stream.Printf("import %s", module_name.c_str());
- error = ExecuteMultipleLines(command_stream.GetData(),
- ScriptInterpreter::ExecuteScriptOptions()
- .SetEnableIO(false)
- .SetSetLLDBGlobals(false));
+ error = ExecuteMultipleLines(command_stream.GetData(), exc_options);
if (error.Fail())
return false;
@@ -2890,7 +2933,8 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule(
void *module_pyobj = nullptr;
if (ExecuteOneLineWithReturn(
command_stream.GetData(),
- ScriptInterpreter::eScriptReturnTypeOpaqueObject, &module_pyobj) &&
+ ScriptInterpreter::eScriptReturnTypeOpaqueObject, &module_pyobj,
+ exc_options) &&
module_pyobj)
*module_sp = std::make_shared<StructuredPythonObject>(module_pyobj);
}
@@ -3047,7 +3091,7 @@ bool ScriptInterpreterPythonImpl::GetDocumentationForItem(const char *item,
if (ExecuteOneLineWithReturn(
command, ScriptInterpreter::eScriptReturnTypeCharStrOrNone,
&result_ptr,
- ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false))) {
+ ExecuteScriptOptions().SetEnableIO(false))) {
if (result_ptr)
dest.assign(result_ptr);
return true;
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
index e59fedbd0971..b8b978118218 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
@@ -13,6 +13,8 @@
#if LLDB_ENABLE_PYTHON
+#include "ScriptedProcessPythonInterface.h"
+
#include "lldb/Breakpoint/BreakpointOptions.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Core/StructuredDataImpl.h"
@@ -51,6 +53,7 @@ public:
static lldb_private::ConstString GetPluginNameStatic();
static const char *GetPluginDescriptionStatic();
static FileSpec GetPythonDir();
+ static void SharedLibraryDirectoryHelper(FileSpec &this_file);
protected:
static void ComputePythonDirForApple(llvm::SmallVectorImpl<char> &path);
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
index 45dad4217005..d1b0b3fda1ef 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
@@ -6,6 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
+
#include "lldb/Host/Config.h"
#if LLDB_ENABLE_PYTHON
@@ -231,7 +234,8 @@ public:
bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value,
std::string &output, Status &error) override;
- bool LoadScriptingModule(const char *filename, bool init_session,
+ bool LoadScriptingModule(const char *filename,
+ const LoadScriptOptions &options,
lldb_private::Status &error,
StructuredData::ObjectSP *module_sp = nullptr,
FileSpec extra_search_dir = {}) override;
@@ -241,7 +245,7 @@ public:
std::unique_ptr<ScriptInterpreterLocker> AcquireInterpreterLock() override;
void CollectDataForBreakpointCommandCallback(
- std::vector<BreakpointOptions *> &bp_options_vec,
+ std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
CommandReturnObject &result) override;
void
@@ -249,20 +253,19 @@ public:
CommandReturnObject &result) override;
/// Set the callback body text into the callback for the breakpoint.
- Status SetBreakpointCommandCallback(BreakpointOptions *bp_options,
+ Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
const char *callback_body) override;
Status SetBreakpointCommandCallbackFunction(
- BreakpointOptions *bp_options,
- const char *function_name,
+ BreakpointOptions &bp_options, const char *function_name,
StructuredData::ObjectSP extra_args_sp) override;
/// This one is for deserialization:
Status SetBreakpointCommandCallback(
- BreakpointOptions *bp_options,
+ BreakpointOptions &bp_options,
std::unique_ptr<BreakpointOptions::CommandData> &data_up) override;
- Status SetBreakpointCommandCallback(BreakpointOptions *bp_options,
+ Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
const char *command_body_text,
StructuredData::ObjectSP extra_args_sp,
bool uses_extra_args);
@@ -416,7 +419,7 @@ public:
: IOHandler(debugger, IOHandler::Type::PythonInterpreter),
m_python(python) {}
- ~IOHandlerPythonInterpreter() override {}
+ ~IOHandlerPythonInterpreter() override = default;
ConstString GetControlSequence(char ch) override {
if (ch == 'd')
@@ -483,4 +486,5 @@ protected:
} // namespace lldb_private
-#endif
+#endif // LLDB_ENABLE_PYTHON
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
new file mode 100644
index 000000000000..ce262c930f8b
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
@@ -0,0 +1,306 @@
+//===-- ScriptedProcessPythonInterface.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 "lldb/Host/Config.h"
+#include "lldb/lldb-enumerations.h"
+
+#if LLDB_ENABLE_PYTHON
+
+// LLDB Python header must be included first
+#include "lldb-python.h"
+
+#include "SWIGPythonBridge.h"
+#include "ScriptInterpreterPythonImpl.h"
+#include "ScriptedProcessPythonInterface.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::python;
+using Locker = ScriptInterpreterPythonImpl::Locker;
+
+StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject(
+ const llvm::StringRef class_name, lldb::TargetSP target_sp,
+ StructuredData::DictionarySP args_sp) {
+ if (class_name.empty())
+ return {};
+
+ std::string error_string;
+ StructuredDataImpl *args_impl = nullptr;
+ if (args_sp) {
+ args_impl = new StructuredDataImpl();
+ args_impl->SetObjectSP(args_sp);
+ }
+
+ void *ret_val;
+
+ {
+
+ Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+
+ ret_val = LLDBSwigPythonCreateScriptedProcess(
+ class_name.str().c_str(), m_interpreter.GetDictionaryName(), target_sp,
+ args_impl, error_string);
+ }
+
+ m_object_instance_sp =
+ StructuredData::GenericSP(new StructuredPythonObject(ret_val));
+
+ return m_object_instance_sp;
+}
+
+Status ScriptedProcessPythonInterface::Launch() {
+ return GetStatusFromMethod("launch");
+}
+
+Status ScriptedProcessPythonInterface::Resume() {
+ return GetStatusFromMethod("resume");
+}
+
+bool ScriptedProcessPythonInterface::ShouldStop() {
+ llvm::Optional<unsigned long long> should_stop =
+ GetGenericInteger("should_stop");
+
+ if (!should_stop)
+ return false;
+
+ return static_cast<bool>(*should_stop);
+}
+
+Status ScriptedProcessPythonInterface::Stop() {
+ return GetStatusFromMethod("stop");
+}
+
+Status ScriptedProcessPythonInterface::GetStatusFromMethod(
+ llvm::StringRef method_name) {
+ Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+
+ if (!m_object_instance_sp)
+ return Status("Python object ill-formed.");
+
+ if (!m_object_instance_sp)
+ return Status("Cannot convert Python object to StructuredData::Generic.");
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)m_object_instance_sp->GetValue());
+
+ if (!implementor.IsAllocated())
+ return Status("Python implementor not allocated.");
+
+ PythonObject pmeth(
+ PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), method_name.str().c_str()));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return Status("Python method not allocated.");
+
+ if (PyCallable_Check(pmeth.get()) == 0) {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ return Status("Python method not callable.");
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ PythonObject py_return(PyRefType::Owned,
+ PyObject_CallMethod(implementor.get(),
+ method_name.str().c_str(),
+ nullptr));
+
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ return Status("Python method could not be called.");
+ }
+
+ if (PyObject *py_ret_ptr = py_return.get()) {
+ lldb::SBError *sb_error =
+ (lldb::SBError *)LLDBSWIGPython_CastPyObjectToSBError(py_ret_ptr);
+
+ if (!sb_error)
+ return Status("Couldn't cast lldb::SBError to lldb::Status.");
+
+ Status status = m_interpreter.GetStatusFromSBError(*sb_error);
+
+ if (status.Fail())
+ return Status("error: %s", status.AsCString());
+
+ return status;
+ }
+
+ return Status("Returned object is null.");
+}
+
+llvm::Optional<unsigned long long>
+ScriptedProcessPythonInterface::GetGenericInteger(llvm::StringRef method_name) {
+ Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+
+ if (!m_object_instance_sp)
+ return llvm::None;
+
+ if (!m_object_instance_sp)
+ return llvm::None;
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)m_object_instance_sp->GetValue());
+
+ if (!implementor.IsAllocated())
+ return llvm::None;
+
+ PythonObject pmeth(
+ PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), method_name.str().c_str()));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return llvm::None;
+
+ if (PyCallable_Check(pmeth.get()) == 0) {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ return llvm::None;
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ PythonObject py_return(PyRefType::Owned,
+ PyObject_CallMethod(implementor.get(),
+ method_name.str().c_str(),
+ nullptr));
+
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ if (!py_return.get())
+ return llvm::None;
+
+ llvm::Expected<unsigned long long> size = py_return.AsUnsignedLongLong();
+ // FIXME: Handle error.
+ if (!size)
+ return llvm::None;
+
+ return *size;
+}
+
+lldb::MemoryRegionInfoSP
+ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress(
+ lldb::addr_t address) {
+ // TODO: Implement
+ return nullptr;
+}
+
+StructuredData::DictionarySP
+ScriptedProcessPythonInterface::GetThreadWithID(lldb::tid_t tid) {
+ // TODO: Implement
+ return nullptr;
+}
+
+StructuredData::DictionarySP
+ScriptedProcessPythonInterface::GetRegistersForThread(lldb::tid_t tid) {
+ // TODO: Implement
+ return nullptr;
+}
+
+lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress(
+ lldb::addr_t address, size_t size, Status &error) {
+ Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+
+ auto error_with_message = [&error](llvm::StringRef message) {
+ error.SetErrorString(message);
+ return nullptr;
+ };
+
+ static char callee_name[] = "read_memory_at_address";
+ std::string param_format = GetPythonValueFormatString(address);
+ param_format += GetPythonValueFormatString(size);
+
+ if (!m_object_instance_sp)
+ return error_with_message("Python object ill-formed.");
+
+ if (!m_object_instance_sp)
+ return error_with_message("Python method not callable.");
+
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)m_object_instance_sp->GetValue());
+
+ if (!implementor.IsAllocated())
+ return error_with_message("Python implementor not allocated.");
+
+ PythonObject pmeth(PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), callee_name));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return error_with_message("Python method not allocated.");
+
+ if (PyCallable_Check(pmeth.get()) == 0) {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ return error_with_message("Python method not callable.");
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ PythonObject py_return(PyRefType::Owned,
+ PyObject_CallMethod(implementor.get(), callee_name,
+ param_format.c_str(), address,
+ size));
+
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ return error_with_message("Python method could not be called.");
+ }
+
+ if (PyObject *py_ret_ptr = py_return.get()) {
+ lldb::SBData *sb_data =
+ (lldb::SBData *)LLDBSWIGPython_CastPyObjectToSBData(py_ret_ptr);
+
+ if (!sb_data)
+ return error_with_message(
+ "Couldn't cast lldb::SBData to lldb::DataExtractor.");
+
+ return m_interpreter.GetDataExtractorFromSBData(*sb_data);
+ }
+
+ return error_with_message("Returned object is null.");
+}
+
+StructuredData::DictionarySP ScriptedProcessPythonInterface::GetLoadedImages() {
+ // TODO: Implement
+ return nullptr;
+}
+
+lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() {
+ llvm::Optional<unsigned long long> pid = GetGenericInteger("get_process_id");
+ return (!pid) ? LLDB_INVALID_PROCESS_ID : *pid;
+}
+
+bool ScriptedProcessPythonInterface::IsAlive() {
+ llvm::Optional<unsigned long long> is_alive = GetGenericInteger("is_alive");
+
+ if (!is_alive)
+ return false;
+
+ return static_cast<bool>(*is_alive);
+}
+
+#endif
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h
new file mode 100644
index 000000000000..30cb5a882af2
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h
@@ -0,0 +1,66 @@
+//===-- ScriptedProcessPythonInterface.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_SCRIPTEDPROCESSPYTHONINTERFACE_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H
+
+#include "lldb/Host/Config.h"
+
+#if LLDB_ENABLE_PYTHON
+
+#include "lldb/Interpreter/ScriptedProcessInterface.h"
+
+namespace lldb_private {
+class ScriptInterpreterPythonImpl;
+class ScriptedProcessPythonInterface : public ScriptedProcessInterface {
+public:
+ ScriptedProcessPythonInterface(ScriptInterpreterPythonImpl &interpreter)
+ : ScriptedProcessInterface(), m_interpreter(interpreter) {}
+
+ StructuredData::GenericSP
+ CreatePluginObject(const llvm::StringRef class_name, lldb::TargetSP target_sp,
+ StructuredData::DictionarySP args_sp) override;
+
+ Status Launch() override;
+
+ Status Resume() override;
+
+ bool ShouldStop() override;
+
+ Status Stop() override;
+
+ lldb::MemoryRegionInfoSP
+ GetMemoryRegionContainingAddress(lldb::addr_t address) override;
+
+ StructuredData::DictionarySP GetThreadWithID(lldb::tid_t tid) override;
+
+ StructuredData::DictionarySP GetRegistersForThread(lldb::tid_t tid) override;
+
+ lldb::DataExtractorSP ReadMemoryAtAddress(lldb::addr_t address, size_t size,
+ Status &error) override;
+
+ StructuredData::DictionarySP GetLoadedImages() override;
+
+ lldb::pid_t GetProcessID() override;
+
+ bool IsAlive() override;
+
+protected:
+ llvm::Optional<unsigned long long>
+ GetGenericInteger(llvm::StringRef method_name);
+ Status GetStatusFromMethod(llvm::StringRef method_name);
+
+private:
+ // The lifetime is managed by the ScriptInterpreter
+ ScriptInterpreterPythonImpl &m_interpreter;
+ StructuredData::GenericSP m_object_instance_sp;
+};
+} // namespace lldb_private
+
+#endif // LLDB_ENABLE_PYTHON
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H
diff --git a/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp b/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
index f669e5873d2d..87edf7789f0d 100644
--- a/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
+++ b/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
@@ -8,7 +8,7 @@
#include "StructuredDataDarwinLog.h"
-#include <string.h>
+#include <cstring>
#include <memory>
#include <sstream>
@@ -126,7 +126,7 @@ public:
m_collection_sp->Initialize(g_darwinlog_properties);
}
- ~StructuredDataDarwinLogProperties() override {}
+ ~StructuredDataDarwinLogProperties() override = default;
bool GetEnableOnStartup() const {
const uint32_t idx = ePropertyEnableOnStartup;
@@ -181,7 +181,7 @@ using FilterRuleSP = std::shared_ptr<FilterRule>;
class FilterRule {
public:
- virtual ~FilterRule() {}
+ virtual ~FilterRule() = default;
using OperationCreationFunc =
std::function<FilterRuleSP(bool accept, size_t attribute_index,
@@ -473,13 +473,9 @@ static constexpr OptionDefinition g_enable_option_table[] = {
class EnableOptions : public Options {
public:
EnableOptions()
- : Options(), m_include_debug_level(false), m_include_info_level(false),
- m_include_any_process(false),
+ : Options(),
m_filter_fall_through_accepts(DEFAULT_FILTER_FALLTHROUGH_ACCEPTS),
- m_echo_to_stderr(false), m_display_timestamp_relative(false),
- m_display_subsystem(false), m_display_category(false),
- m_display_activity_chain(false), m_broadcast_events(true),
- m_live_stream(true), m_filter_rules() {}
+ m_filter_rules() {}
void OptionParsingStarting(ExecutionContext *execution_context) override {
m_include_debug_level = false;
@@ -728,17 +724,17 @@ private:
return -1;
}
- bool m_include_debug_level;
- bool m_include_info_level;
- bool m_include_any_process;
+ bool m_include_debug_level = false;
+ bool m_include_info_level = false;
+ bool m_include_any_process = false;
bool m_filter_fall_through_accepts;
- bool m_echo_to_stderr;
- bool m_display_timestamp_relative;
- bool m_display_subsystem;
- bool m_display_category;
- bool m_display_activity_chain;
- bool m_broadcast_events;
- bool m_live_stream;
+ bool m_echo_to_stderr = false;
+ bool m_display_timestamp_relative = false;
+ bool m_display_subsystem = false;
+ bool m_display_category = false;
+ bool m_display_activity_chain = false;
+ bool m_broadcast_events = true;
+ bool m_live_stream = true;
FilterRules m_filter_rules;
};
@@ -813,7 +809,6 @@ protected:
StructuredDataDarwinLog::GetStaticPluginName())) {
result.AppendError("failed to get StructuredDataPlugin for "
"the process");
- result.SetStatus(eReturnStatusFailed);
}
StructuredDataDarwinLog &plugin =
*static_cast<StructuredDataDarwinLog *>(plugin_sp.get());
@@ -837,7 +832,6 @@ protected:
// Report results.
if (!error.Success()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
// Our configuration failed, so we're definitely disabled.
plugin.SetEnabled(false);
} else {
diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
index 07e5b284eab8..b815ebb3c07a 100644
--- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
+++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
@@ -278,7 +278,7 @@ SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr,
}
uint32_t SymbolFileBreakpad::ResolveSymbolContext(
- const FileSpec &file_spec, uint32_t line, bool check_inlines,
+ const SourceLocationSpec &src_location_spec,
lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
if (!(resolve_scope & eSymbolContextCompUnit))
@@ -287,8 +287,7 @@ uint32_t SymbolFileBreakpad::ResolveSymbolContext(
uint32_t old_size = sc_list.GetSize();
for (size_t i = 0, size = GetNumCompileUnits(); i < size; ++i) {
CompileUnit &cu = *GetCompileUnitAtIndex(i);
- cu.ResolveSymbolContext(file_spec, line, check_inlines,
- /*exact*/ false, resolve_scope, sc_list);
+ cu.ResolveSymbolContext(src_location_spec, resolve_scope, sc_list);
}
return sc_list.GetSize() - old_size;
}
@@ -716,10 +715,10 @@ void SymbolFileBreakpad::ParseLineTableAndSupportFiles(CompileUnit &cu,
llvm::Optional<addr_t> next_addr;
auto finish_sequence = [&]() {
LineTable::AppendLineEntryToSequence(
- line_seq_up.get(), *next_addr, /*line*/ 0, /*column*/ 0,
- /*file_idx*/ 0, /*is_start_of_statement*/ false,
- /*is_start_of_basic_block*/ false, /*is_prologue_end*/ false,
- /*is_epilogue_begin*/ false, /*is_terminal_entry*/ true);
+ line_seq_up.get(), *next_addr, /*line=*/0, /*column=*/0,
+ /*file_idx=*/0, /*is_start_of_statement=*/false,
+ /*is_start_of_basic_block=*/false, /*is_prologue_end=*/false,
+ /*is_epilogue_begin=*/false, /*is_terminal_entry=*/true);
sequences.push_back(std::move(line_seq_up));
line_seq_up = LineTable::CreateLineSequenceContainer();
};
@@ -739,10 +738,10 @@ void SymbolFileBreakpad::ParseLineTableAndSupportFiles(CompileUnit &cu,
finish_sequence();
}
LineTable::AppendLineEntryToSequence(
- line_seq_up.get(), record->Address, record->LineNum, /*column*/ 0,
- map[record->FileNum], /*is_start_of_statement*/ true,
- /*is_start_of_basic_block*/ false, /*is_prologue_end*/ false,
- /*is_epilogue_begin*/ false, /*is_terminal_entry*/ false);
+ line_seq_up.get(), record->Address, record->LineNum, /*column=*/0,
+ map[record->FileNum], /*is_start_of_statement=*/true,
+ /*is_start_of_basic_block=*/false, /*is_prologue_end=*/false,
+ /*is_epilogue_begin=*/false, /*is_terminal_entry=*/false);
next_addr = record->Address + record->Size;
}
if (next_addr)
diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
index 90dbcc77627a..b0a35fa11de4 100644
--- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
+++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
@@ -51,7 +51,7 @@ public:
SymbolFileBreakpad(lldb::ObjectFileSP objfile_sp)
: SymbolFile(std::move(objfile_sp)) {}
- ~SymbolFileBreakpad() override {}
+ ~SymbolFileBreakpad() override = default;
uint32_t CalculateAbilities() override;
@@ -101,8 +101,7 @@ public:
lldb::SymbolContextItem resolve_scope,
SymbolContext &sc) override;
- uint32_t ResolveSymbolContext(const FileSpec &file_spec, uint32_t line,
- bool check_inlines,
+ uint32_t ResolveSymbolContext(const SourceLocationSpec &src_location_spec,
lldb::SymbolContextItem resolve_scope,
SymbolContextList &sc_list) override;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
index 2e0a7fd3ecd3..ffe24836955f 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
@@ -24,7 +24,7 @@ class SymbolFileDWARF;
class DWARFASTParser {
public:
- virtual ~DWARFASTParser() {}
+ virtual ~DWARFASTParser() = default;
virtual lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
const DWARFDIE &die,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 188a667ca564..46015f7b43b1 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <stdlib.h>
+#include <cstdlib>
#include "DWARFASTParserClang.h"
#include "DWARFDebugInfo.h"
@@ -49,7 +49,7 @@
//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
#ifdef ENABLE_DEBUG_PRINTF
-#include <stdio.h>
+#include <cstdio>
#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
#else
#define DEBUG_PRINTF(fmt, ...)
@@ -60,7 +60,7 @@ using namespace lldb_private;
DWARFASTParserClang::DWARFASTParserClang(TypeSystemClang &ast)
: m_ast(ast), m_die_to_decl_ctx(), m_decl_ctx_to_die() {}
-DWARFASTParserClang::~DWARFASTParserClang() {}
+DWARFASTParserClang::~DWARFASTParserClang() = default;
static AccessType DW_ACCESS_to_AccessType(uint32_t dwarf_accessibility) {
switch (dwarf_accessibility) {
@@ -157,7 +157,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
// The type in the Clang module must have the same language as the current CU.
LanguageSet languages;
- languages.Insert(SymbolFileDWARF::GetLanguage(*die.GetCU()));
+ languages.Insert(SymbolFileDWARF::GetLanguageFamily(*die.GetCU()));
llvm::DenseSet<SymbolFile *> searched_symbol_files;
clang_module_sp->GetSymbolFile()->FindTypes(decl_context, languages,
searched_symbol_files, pcm_types);
@@ -666,8 +666,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
// 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()) {
+ for (DWARFDIE child_die : target_die.children()) {
if (!strcmp(child_die.GetAttributeValueAsString(DW_AT_name, ""),
"__FuncPtr")) {
DWARFDIE function_pointer_type =
@@ -1226,6 +1225,7 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
}
if (!function_decl) {
+ char *name_buf = nullptr;
llvm::StringRef name = attrs.name.GetStringRef();
// We currently generate function templates with template parameters in
@@ -1233,8 +1233,10 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
// we want to strip these from the name when creating the AST.
if (attrs.mangled_name) {
llvm::ItaniumPartialDemangler D;
- if (!D.partialDemangle(attrs.mangled_name))
- name = D.getFunctionBaseName(nullptr, nullptr);
+ if (!D.partialDemangle(attrs.mangled_name)) {
+ name_buf = D.getFunctionBaseName(nullptr, nullptr);
+ name = name_buf;
+ }
}
// We just have a function that isn't part of a class
@@ -1243,6 +1245,7 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
: containing_decl_ctx,
GetOwningClangModule(die), name, clang_type, attrs.storage,
attrs.is_inline);
+ std::free(name_buf);
if (has_template_params) {
TypeSystemClang::TemplateParameterInfos template_param_infos;
@@ -1266,13 +1269,10 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
LinkDeclContextToDIE(function_decl, die);
if (!function_param_decls.empty()) {
- m_ast.SetFunctionParameters(function_decl,
- &function_param_decls.front(),
- function_param_decls.size());
+ m_ast.SetFunctionParameters(function_decl, function_param_decls);
if (template_function_decl)
m_ast.SetFunctionParameters(template_function_decl,
- &function_param_decls.front(),
- function_param_decls.size());
+ function_param_decls);
}
ClangASTMetadata metadata;
@@ -1357,7 +1357,7 @@ TypeSP DWARFASTParserClang::ParsePointerToMemberType(
dwarf->ResolveTypeUID(attrs.containing_type.Reference(), true);
CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType();
- CompilerType class_clang_type = class_type->GetLayoutCompilerType();
+ CompilerType class_clang_type = class_type->GetForwardCompilerType();
CompilerType clang_type = TypeSystemClang::CreateMemberPointerType(
class_clang_type, pointee_clang_type);
@@ -1684,14 +1684,18 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
die.GetOffset(), attrs.name.GetCString());
}
- if (tag == DW_TAG_structure_type) // this only applies in C
- {
+ // If the byte size of the record is specified then overwrite the size
+ // that would be computed by Clang. This is only needed as LLDB's
+ // TypeSystemClang is always in C++ mode, but some compilers such as
+ // GCC and Clang give empty structs a size of 0 in C mode (in contrast to
+ // the size of 1 for empty structs that would be computed in C++ mode).
+ if (attrs.byte_size) {
clang::RecordDecl *record_decl =
TypeSystemClang::GetAsRecordDecl(clang_type);
-
if (record_decl) {
- GetClangASTImporter().SetRecordLayout(
- record_decl, ClangASTImporter::LayoutInfo());
+ ClangASTImporter::LayoutInfo layout;
+ layout.bit_size = *attrs.byte_size * 8;
+ GetClangASTImporter().SetRecordLayout(record_decl, layout);
}
}
} else if (clang_type_was_created) {
@@ -1822,8 +1826,7 @@ bool DWARFASTParserClang::ParseTemplateDIE(
case DW_TAG_GNU_template_parameter_pack: {
template_param_infos.packed_args =
std::make_unique<TypeSystemClang::TemplateParameterInfos>();
- for (DWARFDIE child_die = die.GetFirstChild(); child_die.IsValid();
- child_die = child_die.GetSibling()) {
+ for (DWARFDIE child_die : die.children()) {
if (!ParseTemplateDIE(child_die, *template_param_infos.packed_args))
return false;
}
@@ -1928,8 +1931,7 @@ bool DWARFASTParserClang::ParseTemplateParameterInfos(
if (!parent_die)
return false;
- for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
- die = die.GetSibling()) {
+ for (DWARFDIE die : parent_die.children()) {
const dw_tag_t tag = die.Tag();
switch (tag) {
@@ -1978,15 +1980,12 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,
}
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, bases, member_accessibilities,
- member_function_dies, delayed_properties,
- default_accessibility, is_a_class, layout_info);
+ ParseChildMembers(die, clang_type, bases, member_function_dies,
+ delayed_properties, default_accessibility, layout_info);
// Now parse any methods if there were any...
for (const DWARFDIE &die : member_function_dies)
@@ -2007,31 +2006,6 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,
}
}
- // 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 (!type_is_objc_object_or_interface) {
- 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
@@ -2131,8 +2105,7 @@ void DWARFASTParserClang::EnsureAllDIEsInDeclContextHaveBeenParsed(
for (auto it = m_decl_ctx_to_die.find(opaque_decl_ctx);
it != m_decl_ctx_to_die.end() && it->first == opaque_decl_ctx;
it = m_decl_ctx_to_die.erase(it))
- for (DWARFDIE decl = it->second.GetFirstChild(); decl;
- decl = decl.GetSibling())
+ for (DWARFDIE decl : it->second.children())
GetClangDeclForDIE(decl);
}
@@ -2168,8 +2141,7 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
size_t enumerators_added = 0;
- for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
- die = die.GetSibling()) {
+ for (DWARFDIE die : parent_die.children()) {
const dw_tag_t tag = die.Tag();
if (tag == DW_TAG_enumerator) {
DWARFAttributes attributes;
@@ -2201,7 +2173,8 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
case DW_AT_description:
default:
case DW_AT_decl_file:
- decl.SetFile(die.GetCU()->GetFile(form_value.Unsigned()));
+ decl.SetFile(attributes.CompileUnitAtIndex(i)->GetFile(
+ form_value.Unsigned()));
break;
case DW_AT_decl_line:
decl.SetLine(form_value.Unsigned());
@@ -2343,7 +2316,6 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit,
void DWARFASTParserClang::ParseSingleMember(
const DWARFDIE &die, const DWARFDIE &parent_die,
const lldb_private::CompilerType &class_clang_type,
- std::vector<int> &member_accessibilities,
lldb::AccessType default_accessibility,
DelayedPropertyList &delayed_properties,
lldb_private::ClangASTImporter::LayoutInfo &layout_info,
@@ -2533,7 +2505,7 @@ void DWARFASTParserClang::ParseSingleMember(
if (accessibility == eAccessNone)
accessibility = eAccessPublic;
TypeSystemClang::AddVariableToRecordType(
- class_clang_type, name, var_type->GetLayoutCompilerType(),
+ class_clang_type, name, var_type->GetForwardCompilerType(),
accessibility);
}
return;
@@ -2551,7 +2523,6 @@ void DWARFASTParserClang::ParseSingleMember(
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));
@@ -2666,7 +2637,7 @@ void DWARFASTParserClang::ParseSingleMember(
last_field_info.bit_offset = field_bit_offset;
if (llvm::Optional<uint64_t> clang_type_size =
- member_clang_type.GetByteSize(nullptr)) {
+ member_type->GetByteSize(nullptr)) {
last_field_info.bit_size = *clang_type_size * character_width;
}
@@ -2761,10 +2732,9 @@ void DWARFASTParserClang::ParseSingleMember(
bool DWARFASTParserClang::ParseChildMembers(
const DWARFDIE &parent_die, CompilerType &class_clang_type,
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) {
+ ClangASTImporter::LayoutInfo &layout_info) {
if (!parent_die)
return false;
@@ -2776,16 +2746,15 @@ bool DWARFASTParserClang::ParseChildMembers(
if (ast == nullptr)
return false;
- for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
- die = die.GetSibling()) {
+ for (DWARFDIE die : parent_die.children()) {
dw_tag_t tag = die.Tag();
switch (tag) {
case DW_TAG_member:
case DW_TAG_APPLE_property:
ParseSingleMember(die, parent_die, class_clang_type,
- member_accessibilities, default_accessibility,
- delayed_properties, layout_info, last_field_info);
+ default_accessibility, delayed_properties, layout_info,
+ last_field_info);
break;
case DW_TAG_subprogram:
@@ -2794,9 +2763,6 @@ bool DWARFASTParserClang::ParseChildMembers(
break;
case DW_TAG_inheritance: {
- is_a_class = true;
- if (default_accessibility == eAccessNone)
- default_accessibility = eAccessPrivate;
// TODO: implement DW_TAG_inheritance type parsing
DWARFAttributes attributes;
const size_t num_attributes = die.GetAttributes(attributes);
@@ -2926,8 +2892,7 @@ size_t DWARFASTParserClang::ParseChildParameters(
return 0;
size_t arg_idx = 0;
- for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
- die = die.GetSibling()) {
+ for (DWARFDIE die : parent_die.children()) {
const dw_tag_t tag = die.Tag();
switch (tag) {
case DW_TAG_formal_parameter: {
@@ -3046,8 +3011,7 @@ DWARFASTParser::ParseChildArrayInfo(const DWARFDIE &parent_die,
if (!parent_die)
return llvm::None;
- for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
- die = die.GetSibling()) {
+ for (DWARFDIE die : parent_die.children()) {
const dw_tag_t tag = die.Tag();
if (tag != DW_TAG_subrange_type)
continue;
@@ -3349,8 +3313,7 @@ static DWARFDIE GetContainingFunctionWithAbstractOrigin(const DWARFDIE &die) {
}
static DWARFDIE FindAnyChildWithAbstractOrigin(const DWARFDIE &context) {
- for (DWARFDIE candidate = context.GetFirstChild(); candidate.IsValid();
- candidate = candidate.GetSibling()) {
+ for (DWARFDIE candidate : context.children()) {
if (candidate.GetReferencedDIE(DW_AT_abstract_origin)) {
return candidate;
}
@@ -3514,8 +3477,7 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes(
UniqueCStringMap<DWARFDIE> dst_name_to_die;
UniqueCStringMap<DWARFDIE> src_name_to_die_artificial;
UniqueCStringMap<DWARFDIE> dst_name_to_die_artificial;
- for (src_die = src_class_die.GetFirstChild(); src_die.IsValid();
- src_die = src_die.GetSibling()) {
+ for (DWARFDIE src_die : src_class_die.children()) {
if (src_die.Tag() == DW_TAG_subprogram) {
// Make sure this is a declaration and not a concrete instance by looking
// for DW_AT_declaration set to 1. Sometimes concrete function instances
@@ -3533,8 +3495,7 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes(
}
}
}
- for (dst_die = dst_class_die.GetFirstChild(); dst_die.IsValid();
- dst_die = dst_die.GetSibling()) {
+ for (DWARFDIE dst_die : dst_class_die.children()) {
if (dst_die.Tag() == DW_TAG_subprogram) {
// Make sure this is a declaration and not a concrete instance by looking
// for DW_AT_declaration set to 1. Sometimes concrete function instances
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index e13716b95c1c..9bf6240b7554 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -111,10 +111,9 @@ protected:
bool ParseChildMembers(
const DWARFDIE &die, lldb_private::CompilerType &class_compiler_type,
std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,
- std::vector<int> &member_accessibilities,
std::vector<DWARFDIE> &member_function_dies,
DelayedPropertyList &delayed_properties,
- lldb::AccessType &default_accessibility, bool &is_a_class,
+ lldb::AccessType &default_accessibility,
lldb_private::ClangASTImporter::LayoutInfo &layout_info);
size_t
@@ -194,7 +193,6 @@ private:
void
ParseSingleMember(const DWARFDIE &die, const DWARFDIE &parent_die,
const lldb_private::CompilerType &class_clang_type,
- std::vector<int> &member_accessibilities,
lldb::AccessType default_accessibility,
DelayedPropertyList &delayed_properties,
lldb_private::ClangASTImporter::LayoutInfo &layout_info,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
index 0e9370be15fb..2f6b36c79b80 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
@@ -17,9 +17,7 @@
using namespace lldb_private;
-DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration()
- : m_code(InvalidCode), m_tag(llvm::dwarf::DW_TAG_null), m_has_children(0),
- m_attributes() {}
+DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() : m_attributes() {}
DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration(dw_tag_t tag,
uint8_t has_children)
@@ -58,7 +56,7 @@ DWARFAbbreviationDeclaration::extract(const DWARFDataExtractor &data,
DWARFFormValue::ValueType val;
if (form == DW_FORM_implicit_const)
- val.value.sval = data.GetULEB128(offset_ptr);
+ val.value.sval = data.GetSLEB128(offset_ptr);
m_attributes.push_back(DWARFAttribute(attr, form, val));
}
@@ -82,9 +80,3 @@ DWARFAbbreviationDeclaration::FindAttributeIndex(dw_attr_t attr) const {
}
return DW_INVALID_INDEX;
}
-
-bool DWARFAbbreviationDeclaration::
-operator==(const DWARFAbbreviationDeclaration &rhs) const {
- return Tag() == rhs.Tag() && HasChildren() == rhs.HasChildren() &&
- m_attributes == rhs.m_attributes;
-}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
index f70aa71a5958..378ba888f4e0 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
@@ -53,12 +53,11 @@ public:
extract(const lldb_private::DWARFDataExtractor &data,
lldb::offset_t *offset_ptr);
bool IsValid();
- bool operator==(const DWARFAbbreviationDeclaration &rhs) const;
protected:
- dw_uleb128_t m_code;
- dw_tag_t m_tag;
- uint8_t m_has_children;
+ dw_uleb128_t m_code = InvalidCode;
+ dw_tag_t m_tag = llvm::dwarf::DW_TAG_null;
+ uint8_t m_has_children = 0;
DWARFAttribute::collection m_attributes;
};
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
index ef98d7e33a90..134f6b2bd114 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
@@ -12,7 +12,7 @@
DWARFAttributes::DWARFAttributes() : m_infos() {}
-DWARFAttributes::~DWARFAttributes() {}
+DWARFAttributes::~DWARFAttributes() = default;
uint32_t DWARFAttributes::FindAttributeIndex(dw_attr_t attr) const {
collection::const_iterator end = m_infos.end();
@@ -25,10 +25,11 @@ uint32_t DWARFAttributes::FindAttributeIndex(dw_attr_t attr) const {
return UINT32_MAX;
}
-void DWARFAttributes::Append(DWARFUnit *cu, dw_offset_t attr_die_offset,
- dw_attr_t attr, dw_form_t form) {
- AttributeValue attr_value = {
- cu, attr_die_offset, {attr, form, DWARFFormValue::ValueType()}};
+void DWARFAttributes::Append(const DWARFFormValue &form_value,
+ dw_offset_t attr_die_offset, dw_attr_t attr) {
+ AttributeValue attr_value = {const_cast<DWARFUnit *>(form_value.GetUnit()),
+ attr_die_offset,
+ {attr, form_value.Form(), form_value.Value()}};
m_infos.push_back(attr_value);
}
@@ -37,6 +38,10 @@ bool DWARFAttributes::ExtractFormValueAtIndex(
const DWARFUnit *cu = CompileUnitAtIndex(i);
form_value.SetUnit(cu);
form_value.SetForm(FormAtIndex(i));
+ if (form_value.Form() == DW_FORM_implicit_const) {
+ form_value.SetValue(ValueAtIndex(i));
+ return true;
+ }
lldb::offset_t offset = DIEOffsetAtIndex(i);
return form_value.ExtractValue(cu->GetData(), &offset);
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
index 8c21404610d7..a31ee861179c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
@@ -22,21 +22,15 @@ public:
DWARFFormValue::ValueType value)
: m_attr(attr), m_form(form), m_value(value) {}
- void set(dw_attr_t attr, dw_form_t form) {
- m_attr = attr;
- m_form = form;
- }
dw_attr_t get_attr() const { return m_attr; }
dw_form_t get_form() const { return m_form; }
+ DWARFFormValue::ValueType get_value() const { return m_value; }
void get(dw_attr_t &attr, dw_form_t &form,
DWARFFormValue::ValueType &val) const {
attr = m_attr;
form = m_form;
val = m_value;
}
- bool operator==(const DWARFAttribute &rhs) const {
- return m_attr == rhs.m_attr && m_form == rhs.m_form;
- }
typedef std::vector<DWARFAttribute> collection;
typedef collection::iterator iterator;
typedef collection::const_iterator const_iterator;
@@ -52,8 +46,8 @@ public:
DWARFAttributes();
~DWARFAttributes();
- void Append(DWARFUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr,
- dw_form_t form);
+ void Append(const DWARFFormValue &form_value, dw_offset_t attr_die_offset,
+ dw_attr_t attr);
DWARFUnit *CompileUnitAtIndex(uint32_t i) const { return m_infos[i].cu; }
dw_offset_t DIEOffsetAtIndex(uint32_t i) const {
return m_infos[i].die_offset;
@@ -62,6 +56,9 @@ public:
return m_infos[i].attr.get_attr();
}
dw_attr_t FormAtIndex(uint32_t i) const { return m_infos[i].attr.get_form(); }
+ DWARFFormValue::ValueType ValueAtIndex(uint32_t i) const {
+ return m_infos[i].attr.get_value();
+ }
bool ExtractFormValueAtIndex(uint32_t i, DWARFFormValue &form_value) const;
DWARFDIE FormValueAsReferenceAtIndex(uint32_t i) const;
DWARFDIE FormValueAsReference(dw_attr_t attr) const;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
index 059b84864be7..36df980f6ef0 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
@@ -24,7 +24,7 @@ class SymbolFileDWARF;
class DWARFBaseDIE {
public:
- DWARFBaseDIE() : m_cu(nullptr), m_die(nullptr) {}
+ DWARFBaseDIE() = default;
DWARFBaseDIE(DWARFUnit *cu, DWARFDebugInfoEntry *die)
: m_cu(cu), m_die(die) {}
@@ -115,8 +115,8 @@ public:
Recurse recurse = Recurse::yes) const;
protected:
- DWARFUnit *m_cu;
- DWARFDebugInfoEntry *m_die;
+ DWARFUnit *m_cu = nullptr;
+ DWARFDebugInfoEntry *m_die = nullptr;
};
bool operator==(const DWARFBaseDIE &lhs, const DWARFBaseDIE &rhs);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
index 8e995e627978..dda691eecacc 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -54,7 +54,7 @@ public:
explicit ElaboratingDIEIterator(DWARFDIE d) : m_worklist(1, d) {}
/// End marker
- ElaboratingDIEIterator() {}
+ ElaboratingDIEIterator() = default;
const DWARFDIE &operator*() const { return m_worklist.back(); }
ElaboratingDIEIterator &operator++() {
@@ -192,7 +192,7 @@ DWARFDIE::LookupDeepestBlock(lldb::addr_t address) const {
}
if (check_children) {
- for (DWARFDIE child = GetFirstChild(); child; child = child.GetSibling()) {
+ for (DWARFDIE child : children()) {
if (DWARFDIE child_result = child.LookupDeepestBlock(address))
return child_result;
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
index 13737280926c..56154055c44d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -11,9 +11,11 @@
#include "DWARFBaseDIE.h"
#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/iterator_range.h"
class DWARFDIE : public DWARFBaseDIE {
public:
+ class child_iterator;
using DWARFBaseDIE::DWARFBaseDIE;
// Tests
@@ -88,6 +90,47 @@ public:
int &decl_line, int &decl_column, int &call_file,
int &call_line, int &call_column,
lldb_private::DWARFExpression *frame_base) const;
+ /// The range of all the children of this DIE.
+ ///
+ /// This is a template just because child_iterator is not completely defined
+ /// at this point.
+ template <typename T = child_iterator>
+ llvm::iterator_range<T> children() const {
+ return llvm::make_range(T(*this), T());
+ }
+};
+
+class DWARFDIE::child_iterator
+ : public llvm::iterator_facade_base<DWARFDIE::child_iterator,
+ std::forward_iterator_tag, DWARFDIE> {
+ /// The current child or an invalid DWARFDie.
+ DWARFDIE m_die;
+
+public:
+ child_iterator() = default;
+ child_iterator(const DWARFDIE &parent) : m_die(parent.GetFirstChild()) {}
+ bool operator==(const child_iterator &it) const {
+ // DWARFDIE's operator== differentiates between an invalid DWARFDIE that
+ // has a CU but no DIE and one that has neither CU nor DIE. The 'end'
+ // iterator could be default constructed, so explicitly allow
+ // (CU, (DIE)nullptr) == (nullptr, nullptr) -> true
+ if (!m_die.IsValid() && !it.m_die.IsValid())
+ return true;
+ return m_die == it.m_die;
+ }
+ const DWARFDIE &operator*() const {
+ assert(m_die.IsValid() && "Derefencing invalid iterator?");
+ return m_die;
+ }
+ DWARFDIE &operator*() {
+ assert(m_die.IsValid() && "Derefencing invalid iterator?");
+ return m_die;
+ }
+ child_iterator &operator++() {
+ assert(m_die.IsValid() && "Incrementing invalid iterator?");
+ m_die = m_die.GetSibling();
+ return *this;
+ }
};
#endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDIE_H
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h
index 555864f44967..ec6b93ce0e7f 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h
@@ -26,8 +26,7 @@ typedef DWARFAbbreviationDeclarationColl::const_iterator
class DWARFAbbreviationDeclarationSet {
public:
- DWARFAbbreviationDeclarationSet()
- : m_offset(DW_INVALID_OFFSET), m_idx_offset(0), m_decls() {}
+ DWARFAbbreviationDeclarationSet() : m_offset(DW_INVALID_OFFSET), m_decls() {}
DWARFAbbreviationDeclarationSet(dw_offset_t offset, uint32_t idx_offset)
: m_offset(offset), m_idx_offset(idx_offset), m_decls() {}
@@ -51,7 +50,7 @@ public:
/// @}
private:
dw_offset_t m_offset;
- uint32_t m_idx_offset;
+ uint32_t m_idx_offset = 0;
std::vector<DWARFAbbreviationDeclaration> m_decls;
};
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
index 728cefe620a5..ce514381ee39 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
@@ -8,22 +8,18 @@
#include "DWARFDebugArangeSet.h"
#include "DWARFDataExtractor.h"
+#include "LogChannelDWARF.h"
#include "llvm/Object/Error.h"
#include <cassert>
using namespace lldb_private;
DWARFDebugArangeSet::DWARFDebugArangeSet()
- : m_offset(DW_INVALID_OFFSET), m_header(), m_arange_descriptors() {
- m_header.length = 0;
- m_header.version = 0;
- m_header.cu_offset = 0;
- m_header.addr_size = 0;
- m_header.seg_size = 0;
-}
+ : m_offset(DW_INVALID_OFFSET), m_next_offset(DW_INVALID_OFFSET) {}
void DWARFDebugArangeSet::Clear() {
m_offset = DW_INVALID_OFFSET;
+ m_next_offset = DW_INVALID_OFFSET;
m_header.length = 0;
m_header.version = 0;
m_header.cu_offset = 0;
@@ -54,6 +50,12 @@ llvm::Error DWARFDebugArangeSet::extract(const DWARFDataExtractor &data,
// consists of an address and a length, each in the size appropriate for an
// address on the target architecture.
m_header.length = data.GetDWARFInitialLength(offset_ptr);
+ // The length could be 4 bytes or 12 bytes, so use the current offset to
+ // determine the next offset correctly.
+ if (m_header.length > 0)
+ m_next_offset = *offset_ptr + m_header.length;
+ else
+ m_next_offset = DW_INVALID_OFFSET;
m_header.version = data.GetU16(offset_ptr);
m_header.cu_offset = data.GetDWARFOffset(offset_ptr);
m_header.addr_size = data.GetU8(offset_ptr);
@@ -105,17 +107,45 @@ llvm::Error DWARFDebugArangeSet::extract(const DWARFDataExtractor &data,
"DWARFDebugArangeSet::Descriptor.address and "
"DWARFDebugArangeSet::Descriptor.length must have same size");
- while (data.ValidOffset(*offset_ptr)) {
+ const lldb::offset_t next_offset = GetNextOffset();
+ assert(next_offset != DW_INVALID_OFFSET);
+ uint32_t num_terminators = 0;
+ bool last_was_terminator = false;
+ while (*offset_ptr < next_offset) {
arangeDescriptor.address = data.GetMaxU64(offset_ptr, m_header.addr_size);
arangeDescriptor.length = data.GetMaxU64(offset_ptr, m_header.addr_size);
// Each set of tuples is terminated by a 0 for the address and 0 for
- // the length.
- if (!arangeDescriptor.address && !arangeDescriptor.length)
- return llvm::ErrorSuccess();
-
- m_arange_descriptors.push_back(arangeDescriptor);
+ // the length. Some linkers can emit .debug_aranges with multiple
+ // terminator pair entries that are still withing the length of the
+ // DWARFDebugArangeSet. We want to be sure to parse all entries for
+ // this DWARFDebugArangeSet so that we don't stop parsing early and end up
+ // treating addresses as a header of the next DWARFDebugArangeSet. We also
+ // need to make sure we parse all valid address pairs so we don't omit them
+ // from the aranges result, so we can't stop at the first terminator entry
+ // we find.
+ if (arangeDescriptor.address == 0 && arangeDescriptor.length == 0) {
+ ++num_terminators;
+ last_was_terminator = true;
+ } else {
+ last_was_terminator = false;
+ // Only add .debug_aranges address entries that have a non zero size.
+ // Some linkers will zero out the length field for some .debug_aranges
+ // entries if they were stripped. We also could watch out for multiple
+ // entries at address zero and remove those as well.
+ if (arangeDescriptor.length > 0)
+ m_arange_descriptors.push_back(arangeDescriptor);
+ }
+ }
+ if (num_terminators > 1) {
+ Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
+ LLDB_LOG(log,
+ "warning: DWARFDebugArangeSet at %#" PRIx64 " contains %u "
+ "terminator entries",
+ m_offset, num_terminators);
}
+ if (last_was_terminator)
+ return llvm::ErrorSuccess();
return llvm::make_error<llvm::object::GenericBinaryError>(
"arange descriptors not terminated by null entry");
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h
index 6b5b69a70a80..3c8633eaa3cc 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h
@@ -16,18 +16,21 @@
class DWARFDebugArangeSet {
public:
struct Header {
- uint32_t length; // The total length of the entries for that set, not
- // including the length field itself.
- uint16_t version; // The DWARF version number
- uint32_t cu_offset; // The offset from the beginning of the .debug_info
- // section of the compilation unit entry referenced by
- // the table.
- uint8_t addr_size; // The size in bytes of an address on the target
- // architecture. For segmented addressing, this is the
- // size of the offset portion of the address
- uint8_t seg_size; // The size in bytes of a segment descriptor on the target
- // architecture. If the target system uses a flat address
- // space, this value is 0.
+ /// The total length of the entries for that set, not including the length
+ /// field itself.
+ uint32_t length = 0;
+ /// The DWARF version number.
+ uint16_t version = 0;
+ /// The offset from the beginning of the .debug_info section of the
+ /// compilation unit entry referenced by the table.
+ uint32_t cu_offset = 0;
+ /// The size in bytes of an address on the target architecture. For
+ /// segmented addressing, this is the size of the offset portion of the
+ /// address.
+ uint8_t addr_size = 0;
+ /// The size in bytes of a segment descriptor on the target architecture.
+ /// If the target system uses a flat address space, this value is 0.
+ uint8_t seg_size = 0;
};
struct Descriptor {
@@ -44,7 +47,7 @@ public:
dw_offset_t FindAddress(dw_addr_t address) const;
size_t NumDescriptors() const { return m_arange_descriptors.size(); }
const Header &GetHeader() const { return m_header; }
-
+ dw_offset_t GetNextOffset() const { return m_next_offset; }
const Descriptor &GetDescriptorRef(uint32_t i) const {
return m_arange_descriptors[i];
}
@@ -54,7 +57,8 @@ protected:
typedef DescriptorColl::iterator DescriptorIter;
typedef DescriptorColl::const_iterator DescriptorConstIter;
- uint32_t m_offset;
+ dw_offset_t m_offset;
+ dw_offset_t m_next_offset;
Header m_header;
DescriptorColl m_arange_descriptors;
};
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
index 9f190fbcee87..65923cb4ad6b 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
@@ -9,6 +9,7 @@
#include "DWARFDebugAranges.h"
#include "DWARFDebugArangeSet.h"
#include "DWARFUnit.h"
+#include "LogChannelDWARF.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Timer.h"
@@ -31,31 +32,40 @@ public:
};
// Extract
-llvm::Error
-DWARFDebugAranges::extract(const DWARFDataExtractor &debug_aranges_data) {
+void DWARFDebugAranges::extract(const DWARFDataExtractor &debug_aranges_data) {
lldb::offset_t offset = 0;
DWARFDebugArangeSet set;
Range range;
while (debug_aranges_data.ValidOffset(offset)) {
- llvm::Error error = set.extract(debug_aranges_data, &offset);
- if (error)
- return error;
+ const lldb::offset_t set_offset = offset;
+ if (llvm::Error error = set.extract(debug_aranges_data, &offset)) {
+ Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
+ LLDB_LOG_ERROR(log, std::move(error),
+ "DWARFDebugAranges::extract failed to extract "
+ ".debug_aranges set at offset %#" PRIx64,
+ set_offset);
+ } else {
+ const uint32_t num_descriptors = set.NumDescriptors();
+ if (num_descriptors > 0) {
+ const dw_offset_t cu_offset = set.GetHeader().cu_offset;
- const uint32_t num_descriptors = set.NumDescriptors();
- if (num_descriptors > 0) {
- const dw_offset_t cu_offset = set.GetHeader().cu_offset;
-
- for (uint32_t i = 0; i < num_descriptors; ++i) {
- const DWARFDebugArangeSet::Descriptor &descriptor =
- set.GetDescriptorRef(i);
- m_aranges.Append(RangeToDIE::Entry(descriptor.address,
- descriptor.length, cu_offset));
+ for (uint32_t i = 0; i < num_descriptors; ++i) {
+ const DWARFDebugArangeSet::Descriptor &descriptor =
+ set.GetDescriptorRef(i);
+ m_aranges.Append(RangeToDIE::Entry(descriptor.address,
+ descriptor.length, cu_offset));
+ }
}
}
+ // Always use the previous DWARFDebugArangeSet's information to calculate
+ // the offset of the next DWARFDebugArangeSet in case we entouncter an
+ // error in the current DWARFDebugArangeSet and our offset position is
+ // still in the middle of the data. If we do this, we can parse all valid
+ // DWARFDebugArangeSet objects without returning invalid errors.
+ offset = set.GetNextOffset();
set.Clear();
}
- return llvm::ErrorSuccess();
}
void DWARFDebugAranges::Dump(Log *log) const {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
index 96e82619f985..5ff37e400c88 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
@@ -26,8 +26,7 @@ public:
void Clear() { m_aranges.Clear(); }
- llvm::Error
- extract(const lldb_private::DWARFDataExtractor &debug_aranges_data);
+ void extract(const lldb_private::DWARFDataExtractor &debug_aranges_data);
// Use append range multiple times and then call sort
void AppendRange(dw_offset_t cu_offset, dw_addr_t low_pc, dw_addr_t high_pc);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
index 8d393b295443..e43afa104413 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -34,17 +34,18 @@ DWARFDebugInfo::DWARFDebugInfo(SymbolFileDWARF &dwarf,
lldb_private::DWARFContext &context)
: m_dwarf(dwarf), m_context(context), m_units(), m_cu_aranges_up() {}
-llvm::Expected<DWARFDebugAranges &> DWARFDebugInfo::GetCompileUnitAranges() {
+const DWARFDebugAranges &DWARFDebugInfo::GetCompileUnitAranges() {
if (m_cu_aranges_up)
return *m_cu_aranges_up;
m_cu_aranges_up = std::make_unique<DWARFDebugAranges>();
const DWARFDataExtractor &debug_aranges_data =
m_context.getOrLoadArangesData();
- if (llvm::Error error = m_cu_aranges_up->extract(debug_aranges_data))
- return std::move(error);
- // Make a list of all CUs represented by the arange data in the file.
+ // Extract what we can from the .debug_aranges first.
+ m_cu_aranges_up->extract(debug_aranges_data);
+
+ // Make a list of all CUs represented by the .debug_aranges data.
std::set<dw_offset_t> cus_with_data;
for (size_t n = 0; n < m_cu_aranges_up->GetNumRanges(); n++) {
dw_offset_t offset = m_cu_aranges_up->OffsetAtIndex(n);
@@ -52,8 +53,7 @@ llvm::Expected<DWARFDebugAranges &> DWARFDebugInfo::GetCompileUnitAranges() {
cus_with_data.insert(offset);
}
- // Manually build arange data for everything that wasn't in the
- // .debug_aranges table.
+ // Manually build arange data for everything that wasn't in .debug_aranges.
const size_t num_units = GetNumUnits();
for (size_t idx = 0; idx < num_units; ++idx) {
DWARFUnit *cu = GetUnitAtIndex(idx);
@@ -72,16 +72,10 @@ void DWARFDebugInfo::ParseUnitsFor(DIERef::Section section) {
DWARFDataExtractor data = section == DIERef::Section::DebugTypes
? m_context.getOrLoadDebugTypesData()
: m_context.getOrLoadDebugInfoData();
- const llvm::DWARFUnitIndex *index = nullptr;
- if (m_context.isDwo())
- index = &llvm::getDWARFUnitIndex(m_context.GetAsLLVM(),
- section == DIERef::Section::DebugTypes
- ? llvm::DW_SECT_EXT_TYPES
- : llvm::DW_SECT_INFO);
lldb::offset_t offset = 0;
while (data.ValidOffset(offset)) {
llvm::Expected<DWARFUnitSP> unit_sp = DWARFUnit::extract(
- m_dwarf, m_units.size(), data, section, &offset, index);
+ m_dwarf, m_units.size(), data, section, &offset);
if (!unit_sp) {
// FIXME: Propagate this error up.
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
index bdc718a5c2fa..46c04d749c46 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
@@ -54,7 +54,7 @@ public:
(1 << 2) // Show all parent DIEs when dumping single DIEs
};
- llvm::Expected<DWARFDebugAranges &> GetCompileUnitAranges();
+ const DWARFDebugAranges &GetCompileUnitAranges();
protected:
typedef std::vector<DWARFUnitSP> UnitColl;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
index 421298802645..39915aa889ff 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -8,7 +8,7 @@
#include "DWARFDebugInfoEntry.h"
-#include <assert.h>
+#include <cassert>
#include <algorithm>
@@ -49,156 +49,159 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data,
// assert (fixed_form_sizes); // For best performance this should be
// specified!
- if (m_abbr_idx) {
- lldb::offset_t offset = *offset_ptr;
- const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu);
- if (abbrevDecl == nullptr) {
- cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
- "{0x%8.8x}: invalid abbreviation code %u, please file a bug and "
- "attach the file at the start of this error message",
- m_offset, (unsigned)abbr_idx);
- // WE can't parse anymore if the DWARF is borked...
- *offset_ptr = UINT32_MAX;
- return false;
- }
- m_tag = abbrevDecl->Tag();
- m_has_children = abbrevDecl->HasChildren();
- // Skip all data in the .debug_info or .debug_types for the attributes
- const uint32_t numAttributes = abbrevDecl->NumAttributes();
- uint32_t i;
- dw_form_t form;
- for (i = 0; i < numAttributes; ++i) {
- form = abbrevDecl->GetFormByIndexUnchecked(i);
- llvm::Optional<uint8_t> fixed_skip_size =
- DWARFFormValue::GetFixedSize(form, cu);
- if (fixed_skip_size)
- offset += *fixed_skip_size;
- else {
- bool form_is_indirect = false;
- do {
- form_is_indirect = false;
- uint32_t form_size = 0;
- switch (form) {
- // Blocks if inlined data that have a length field and the data bytes
- // inlined in the .debug_info/.debug_types
- case DW_FORM_exprloc:
- case DW_FORM_block:
- form_size = data.GetULEB128(&offset);
- break;
- case DW_FORM_block1:
- form_size = data.GetU8_unchecked(&offset);
- break;
- case DW_FORM_block2:
- form_size = data.GetU16_unchecked(&offset);
- break;
- case DW_FORM_block4:
- form_size = data.GetU32_unchecked(&offset);
- break;
+ if (m_abbr_idx == 0) {
+ m_tag = llvm::dwarf::DW_TAG_null;
+ m_has_children = false;
+ return true; // NULL debug tag entry
+ }
- // Inlined NULL terminated C-strings
- case DW_FORM_string:
- data.GetCStr(&offset);
- break;
+ lldb::offset_t offset = *offset_ptr;
+ const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu);
+ if (abbrevDecl == nullptr) {
+ cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
+ "{0x%8.8x}: invalid abbreviation code %u, please file a bug and "
+ "attach the file at the start of this error message",
+ m_offset, (unsigned)abbr_idx);
+ // WE can't parse anymore if the DWARF is borked...
+ *offset_ptr = UINT32_MAX;
+ return false;
+ }
+ m_tag = abbrevDecl->Tag();
+ m_has_children = abbrevDecl->HasChildren();
+ // Skip all data in the .debug_info or .debug_types for the attributes
+ const uint32_t numAttributes = abbrevDecl->NumAttributes();
+ uint32_t i;
+ dw_form_t form;
+ for (i = 0; i < numAttributes; ++i) {
+ form = abbrevDecl->GetFormByIndexUnchecked(i);
+ llvm::Optional<uint8_t> fixed_skip_size =
+ DWARFFormValue::GetFixedSize(form, cu);
+ if (fixed_skip_size)
+ offset += *fixed_skip_size;
+ else {
+ bool form_is_indirect = false;
+ do {
+ form_is_indirect = false;
+ uint32_t form_size = 0;
+ switch (form) {
+ // Blocks if inlined data that have a length field and the data bytes
+ // inlined in the .debug_info/.debug_types
+ case DW_FORM_exprloc:
+ case DW_FORM_block:
+ form_size = data.GetULEB128(&offset);
+ break;
+ case DW_FORM_block1:
+ form_size = data.GetU8_unchecked(&offset);
+ break;
+ case DW_FORM_block2:
+ form_size = data.GetU16_unchecked(&offset);
+ break;
+ case DW_FORM_block4:
+ form_size = data.GetU32_unchecked(&offset);
+ break;
+
+ // Inlined NULL terminated C-strings
+ case DW_FORM_string:
+ data.GetCStr(&offset);
+ break;
- // Compile unit address sized values
- case DW_FORM_addr:
+ // Compile unit address sized values
+ case DW_FORM_addr:
+ form_size = cu->GetAddressByteSize();
+ break;
+ case DW_FORM_ref_addr:
+ if (cu->GetVersion() <= 2)
form_size = cu->GetAddressByteSize();
- break;
- case DW_FORM_ref_addr:
- if (cu->GetVersion() <= 2)
- form_size = cu->GetAddressByteSize();
- else
- form_size = 4;
- break;
+ else
+ form_size = 4;
+ break;
- // 0 sized form
- case DW_FORM_flag_present:
- form_size = 0;
- break;
+ // 0 sized form
+ case DW_FORM_flag_present:
+ form_size = 0;
+ break;
- // 1 byte values
- case DW_FORM_addrx1:
- case DW_FORM_data1:
- case DW_FORM_flag:
- case DW_FORM_ref1:
- case DW_FORM_strx1:
- form_size = 1;
- break;
+ // 1 byte values
+ case DW_FORM_addrx1:
+ case DW_FORM_data1:
+ case DW_FORM_flag:
+ case DW_FORM_ref1:
+ case DW_FORM_strx1:
+ form_size = 1;
+ break;
- // 2 byte values
- case DW_FORM_addrx2:
- case DW_FORM_data2:
- case DW_FORM_ref2:
- case DW_FORM_strx2:
- form_size = 2;
- break;
+ // 2 byte values
+ case DW_FORM_addrx2:
+ case DW_FORM_data2:
+ case DW_FORM_ref2:
+ case DW_FORM_strx2:
+ form_size = 2;
+ break;
- // 3 byte values
- case DW_FORM_addrx3:
- case DW_FORM_strx3:
- form_size = 3;
- break;
+ // 3 byte values
+ case DW_FORM_addrx3:
+ case DW_FORM_strx3:
+ form_size = 3;
+ break;
- // 4 byte values
- case DW_FORM_addrx4:
- case DW_FORM_data4:
- case DW_FORM_ref4:
- case DW_FORM_strx4:
- form_size = 4;
- break;
+ // 4 byte values
+ case DW_FORM_addrx4:
+ case DW_FORM_data4:
+ case DW_FORM_ref4:
+ case DW_FORM_strx4:
+ form_size = 4;
+ break;
- // 8 byte values
- case DW_FORM_data8:
- case DW_FORM_ref8:
- case DW_FORM_ref_sig8:
- form_size = 8;
- break;
+ // 8 byte values
+ case DW_FORM_data8:
+ case DW_FORM_ref8:
+ case DW_FORM_ref_sig8:
+ form_size = 8;
+ break;
- // 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:
- case DW_FORM_ref_udata:
- case DW_FORM_GNU_addr_index:
- case DW_FORM_GNU_str_index:
- case DW_FORM_strx:
- data.Skip_LEB128(&offset);
- break;
+ // 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:
+ case DW_FORM_ref_udata:
+ case DW_FORM_GNU_addr_index:
+ case DW_FORM_GNU_str_index:
+ case DW_FORM_strx:
+ data.Skip_LEB128(&offset);
+ break;
- case DW_FORM_indirect:
- form_is_indirect = true;
- form = data.GetULEB128(&offset);
- break;
+ case DW_FORM_indirect:
+ form_is_indirect = true;
+ form = data.GetULEB128(&offset);
+ break;
- case DW_FORM_strp:
- case DW_FORM_sec_offset:
- data.GetU32(&offset);
- break;
+ case DW_FORM_strp:
+ case DW_FORM_line_strp:
+ case DW_FORM_sec_offset:
+ data.GetU32(&offset);
+ break;
- case DW_FORM_implicit_const:
- form_size = 0;
- break;
+ case DW_FORM_implicit_const:
+ form_size = 0;
+ break;
- default:
- *offset_ptr = m_offset;
- return false;
- }
- offset += form_size;
+ default:
+ cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
+ "{0x%8.8x}: Unsupported DW_FORM_0x%x, please file a bug and "
+ "attach the file at the start of this error message",
+ m_offset, (unsigned)form);
+ *offset_ptr = m_offset;
+ return false;
+ }
+ offset += form_size;
- } while (form_is_indirect);
- }
+ } while (form_is_indirect);
}
- *offset_ptr = offset;
- return true;
- } else {
- m_tag = llvm::dwarf::DW_TAG_null;
- m_has_children = false;
- return true; // NULL debug tag entry
}
-
- return false;
+ *offset_ptr = offset;
+ return true;
}
static DWARFRangeList GetRangesOrReportError(DWARFUnit &unit,
@@ -211,11 +214,12 @@ static DWARFRangeList GetRangesOrReportError(DWARFUnit &unit,
if (expected_ranges)
return std::move(*expected_ranges);
unit.GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
- "{0x%8.8x}: DIE has DW_AT_ranges(0x%" PRIx64 ") attribute, but "
+ "{0x%8.8x}: DIE has DW_AT_ranges(%s 0x%" PRIx64 ") attribute, but "
"range extraction failed (%s), please file a bug "
"and attach the file at the start of this error message",
- die.GetOffset(), value.Unsigned(),
- toString(expected_ranges.takeError()).c_str());
+ die.GetOffset(),
+ llvm::dwarf::FormEncodingString(value.Form()).str().c_str(),
+ value.Unsigned(), toString(expected_ranges.takeError()).c_str());
return DWARFRangeList();
}
@@ -429,7 +433,7 @@ size_t DWARFDebugInfoEntry::GetAttributes(DWARFUnit *cu,
}
LLVM_FALLTHROUGH;
default:
- attributes.Append(cu, offset, attr, form);
+ attributes.Append(form_value, offset, attr);
break;
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
index 0ba56a0a4161..64e86c71ac09 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
@@ -35,8 +35,7 @@ public:
typedef collection::const_iterator const_iterator;
DWARFDebugInfoEntry()
- : m_offset(DW_INVALID_OFFSET), m_parent_idx(0), m_sibling_idx(0),
- m_has_children(false), m_abbr_idx(0), m_tag(llvm::dwarf::DW_TAG_null) {}
+ : m_offset(DW_INVALID_OFFSET), m_sibling_idx(0), m_has_children(false) {}
explicit operator bool() const { return m_offset != DW_INVALID_OFFSET; }
bool operator==(const DWARFDebugInfoEntry &rhs) const;
@@ -167,14 +166,14 @@ protected:
GetDWARFDeclContextStatic(const DWARFDebugInfoEntry *die, DWARFUnit *cu);
dw_offset_t m_offset; // Offset within the .debug_info/.debug_types
- uint32_t m_parent_idx; // How many to subtract from "this" to get the parent.
- // If zero this die has no parent
+ uint32_t m_parent_idx = 0; // How many to subtract from "this" to get the
+ // parent. If zero this die has no parent
uint32_t m_sibling_idx : 31, // How many to add to "this" to get the sibling.
// If it is zero, then the DIE doesn't have children, or the
// DWARF claimed it had children but the DIE only contained
// a single NULL terminating child.
m_has_children : 1;
- uint16_t m_abbr_idx;
+ uint16_t m_abbr_idx = 0;
/// A copy of the DW_TAG value so we don't have to go through the compile
/// unit abbrev table
dw_tag_t m_tag = llvm::dwarf::DW_TAG_null;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
index 9072b2dc0115..e46694405415 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
@@ -23,7 +23,7 @@
class DWARFDeclContext {
public:
struct Entry {
- Entry() : tag(llvm::dwarf::DW_TAG_null), name(nullptr) {}
+ Entry() = default;
Entry(dw_tag_t t, const char *n) : tag(t), name(n) {}
bool NameMatches(const Entry &rhs) const {
@@ -37,11 +37,11 @@ public:
// Test operator
explicit operator bool() const { return tag != 0; }
- dw_tag_t tag;
- const char *name;
+ dw_tag_t tag = llvm::dwarf::DW_TAG_null;
+ const char *name = nullptr;
};
- DWARFDeclContext() : m_entries(), m_language(lldb::eLanguageTypeUnknown) {}
+ DWARFDeclContext() : m_entries() {}
void AppendDeclContext(dw_tag_t tag, const char *name) {
m_entries.push_back(Entry(tag, name));
@@ -83,7 +83,7 @@ protected:
typedef std::vector<Entry> collection;
collection m_entries;
mutable std::string m_qualified_name;
- lldb::LanguageType m_language;
+ lldb::LanguageType m_language = lldb::eLanguageTypeUnknown;
};
#endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDECLCONTEXT_H
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
index 1b7102cd7e31..2d0d5cad4612 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
@@ -10,7 +10,7 @@
#define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEFINES_H
#include "lldb/Core/dwarf.h"
-#include <stdint.h>
+#include <cstdint>
namespace lldb_private {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index 305f1cbd2826..4c498705da45 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <assert.h>
+#include <cassert>
#include "lldb/Core/Module.h"
#include "lldb/Core/dwarf.h"
@@ -150,40 +150,40 @@ struct FormSize {
uint8_t valid:1, size:7;
};
static FormSize g_form_sizes[] = {
- {0,0}, // 0x00 unused
- {0,0}, // 0x01 DW_FORM_addr
- {0,0}, // 0x02 unused
- {0,0}, // 0x03 DW_FORM_block2
- {0,0}, // 0x04 DW_FORM_block4
- {1,2}, // 0x05 DW_FORM_data2
- {1,4}, // 0x06 DW_FORM_data4
- {1,8}, // 0x07 DW_FORM_data8
- {0,0}, // 0x08 DW_FORM_string
- {0,0}, // 0x09 DW_FORM_block
- {0,0}, // 0x0a DW_FORM_block1
- {1,1}, // 0x0b DW_FORM_data1
- {1,1}, // 0x0c DW_FORM_flag
- {0,0}, // 0x0d DW_FORM_sdata
- {1,4}, // 0x0e DW_FORM_strp
- {0,0}, // 0x0f DW_FORM_udata
- {0,0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for
- // DWARF32, 8 bytes for DWARF32 in DWARF 3 and later
- {1,1}, // 0x11 DW_FORM_ref1
- {1,2}, // 0x12 DW_FORM_ref2
- {1,4}, // 0x13 DW_FORM_ref4
- {1,8}, // 0x14 DW_FORM_ref8
- {0,0}, // 0x15 DW_FORM_ref_udata
- {0,0}, // 0x16 DW_FORM_indirect
- {1,4}, // 0x17 DW_FORM_sec_offset
- {0,0}, // 0x18 DW_FORM_exprloc
- {1,0}, // 0x19 DW_FORM_flag_present
- {0,0}, // 0x1a
- {0,0}, // 0x1b
- {0,0}, // 0x1c
- {0,0}, // 0x1d
- {0,0}, // 0x1e
- {0,0}, // 0x1f
- {1,8}, // 0x20 DW_FORM_ref_sig8
+ {0, 0}, // 0x00 unused
+ {0, 0}, // 0x01 DW_FORM_addr
+ {0, 0}, // 0x02 unused
+ {0, 0}, // 0x03 DW_FORM_block2
+ {0, 0}, // 0x04 DW_FORM_block4
+ {1, 2}, // 0x05 DW_FORM_data2
+ {1, 4}, // 0x06 DW_FORM_data4
+ {1, 8}, // 0x07 DW_FORM_data8
+ {0, 0}, // 0x08 DW_FORM_string
+ {0, 0}, // 0x09 DW_FORM_block
+ {0, 0}, // 0x0a DW_FORM_block1
+ {1, 1}, // 0x0b DW_FORM_data1
+ {1, 1}, // 0x0c DW_FORM_flag
+ {0, 0}, // 0x0d DW_FORM_sdata
+ {1, 4}, // 0x0e DW_FORM_strp
+ {0, 0}, // 0x0f DW_FORM_udata
+ {0, 0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes
+ // for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later
+ {1, 1}, // 0x11 DW_FORM_ref1
+ {1, 2}, // 0x12 DW_FORM_ref2
+ {1, 4}, // 0x13 DW_FORM_ref4
+ {1, 8}, // 0x14 DW_FORM_ref8
+ {0, 0}, // 0x15 DW_FORM_ref_udata
+ {0, 0}, // 0x16 DW_FORM_indirect
+ {1, 4}, // 0x17 DW_FORM_sec_offset
+ {0, 0}, // 0x18 DW_FORM_exprloc
+ {1, 0}, // 0x19 DW_FORM_flag_present
+ {0, 0}, // 0x1a DW_FORM_strx (ULEB128)
+ {0, 0}, // 0x1b DW_FORM_addrx (ULEB128)
+ {1, 4}, // 0x1c DW_FORM_ref_sup4
+ {0, 0}, // 0x1d DW_FORM_strp_sup (4 bytes for DWARF32, 8 bytes for DWARF64)
+ {1, 16}, // 0x1e DW_FORM_data16
+ {1, 4}, // 0x1f DW_FORM_line_strp
+ {1, 8}, // 0x20 DW_FORM_ref_sig8
};
llvm::Optional<uint8_t>
@@ -286,6 +286,7 @@ bool DWARFFormValue::SkipValue(dw_form_t form,
// 32 bit for DWARF 32, 64 for DWARF 64
case DW_FORM_sec_offset:
case DW_FORM_strp:
+ case DW_FORM_line_strp:
*offset_ptr += 4;
return true;
@@ -398,7 +399,8 @@ void DWARFFormValue::Dump(Stream &s) const {
case DW_FORM_udata:
s.PutULEB128(uvalue);
break;
- case DW_FORM_strp: {
+ case DW_FORM_strp:
+ case DW_FORM_line_strp: {
const char *dbg_str = AsCString();
if (dbg_str) {
s.QuotedCString(dbg_str);
@@ -606,6 +608,7 @@ bool DWARFFormValue::FormIsSupported(dw_form_t form) {
case DW_FORM_flag:
case DW_FORM_sdata:
case DW_FORM_strp:
+ case DW_FORM_line_strp:
case DW_FORM_strx:
case DW_FORM_strx1:
case DW_FORM_strx2:
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
index fe6a55520978..9406bcf0c038 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
@@ -10,8 +10,8 @@
#define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFFORMVALUE_H
#include "DWARFDataExtractor.h"
-#include <stddef.h>
#include "llvm/ADT/Optional.h"
+#include <cstddef>
class DWARFUnit;
class SymbolFileDWARF;
@@ -20,14 +20,14 @@ class DWARFDIE;
class DWARFFormValue {
public:
typedef struct ValueTypeTag {
- ValueTypeTag() : value(), data(nullptr) { value.uval = 0; }
+ ValueTypeTag() : value() { value.uval = 0; }
union {
uint64_t uval;
int64_t sval;
const char *cstr;
} value;
- const uint8_t *data;
+ const uint8_t *data = nullptr;
} ValueType;
enum {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index a761dd3daac4..824e43872269 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -236,6 +236,11 @@ void DWARFUnit::ExtractDIEsRWLocked() {
}
if (!m_die_array.empty()) {
+ // The last die cannot have children (if it did, it wouldn't be the last one).
+ // This only makes a difference for malformed dwarf that does not have a
+ // terminating null die.
+ m_die_array.back().SetHasChildren(false);
+
if (m_first_die) {
// Only needed for the assertion.
m_first_die.SetHasChildren(m_die_array.front().HasChildren());
@@ -292,8 +297,7 @@ uint64_t DWARFUnit::GetDWOId() {
// m_die_array_mutex must be already held as read/write.
void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
- llvm::Optional<uint64_t> addr_base, gnu_addr_base, ranges_base,
- gnu_ranges_base;
+ llvm::Optional<uint64_t> addr_base, gnu_addr_base, gnu_ranges_base;
DWARFAttributes attributes;
size_t num_attributes = cu_die.GetAttributes(this, attributes);
@@ -320,8 +324,7 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
SetLoclistsBase(form_value.Unsigned());
break;
case DW_AT_rnglists_base:
- ranges_base = form_value.Unsigned();
- SetRangesBase(*ranges_base);
+ SetRangesBase(form_value.Unsigned());
break;
case DW_AT_str_offsets_base:
SetStrOffsetsBase(form_value.Unsigned());
@@ -482,19 +485,46 @@ DWARFDataExtractor DWARFUnit::GetLocationData() const {
}
void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) {
+ lldbassert(!m_rnglist_table_done);
+
m_ranges_base = ranges_base;
+}
- if (GetVersion() < 5)
- return;
+const llvm::Optional<llvm::DWARFDebugRnglistTable> &
+DWARFUnit::GetRnglistTable() {
+ if (GetVersion() >= 5 && !m_rnglist_table_done) {
+ m_rnglist_table_done = true;
+ if (auto table_or_error =
+ ParseListTableHeader<llvm::DWARFDebugRnglistTable>(
+ m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(),
+ m_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",
+ m_ranges_base, toString(table_or_error.takeError()).c_str());
+ }
+ return m_rnglist_table;
+}
- 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());
+// This function is called only for DW_FORM_rnglistx.
+llvm::Expected<uint64_t> DWARFUnit::GetRnglistOffset(uint32_t Index) {
+ if (!GetRnglistTable())
+ return llvm::createStringError(errc::invalid_argument,
+ "missing or invalid range list table");
+ if (!m_ranges_base)
+ return llvm::createStringError(errc::invalid_argument,
+ "DW_FORM_rnglistx cannot be used without "
+ "DW_AT_rnglists_base for CU at 0x%8.8x",
+ GetOffset());
+ if (llvm::Optional<uint64_t> off = GetRnglistTable()->getOffsetEntry(
+ m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(), Index))
+ return *off + m_ranges_base;
+ return llvm::createStringError(
+ errc::invalid_argument,
+ "invalid range list table index %u; OffsetEntryCount is %u, "
+ "DW_AT_rnglists_base is %" PRIu64,
+ Index, GetRnglistTable()->getOffsetEntryCount(), m_ranges_base);
}
void DWARFUnit::SetStrOffsetsBase(dw_offset_t str_offsets_base) {
@@ -784,12 +814,11 @@ const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() {
llvm::Expected<DWARFUnitHeader>
DWARFUnitHeader::extract(const DWARFDataExtractor &data,
- DIERef::Section section, lldb::offset_t *offset_ptr,
- const llvm::DWARFUnitIndex *index) {
+ DIERef::Section section,
+ lldb_private::DWARFContext &context,
+ lldb::offset_t *offset_ptr) {
DWARFUnitHeader header;
header.m_offset = *offset_ptr;
- if (index)
- header.m_index_entry = index->getFromOffset(*offset_ptr);
header.m_length = data.GetDWARFInitialLength(offset_ptr);
header.m_version = data.GetU16(offset_ptr);
if (header.m_version == 5) {
@@ -806,6 +835,16 @@ DWARFUnitHeader::extract(const DWARFDataExtractor &data,
section == DIERef::Section::DebugTypes ? DW_UT_type : DW_UT_compile;
}
+ if (context.isDwo()) {
+ if (header.IsTypeUnit()) {
+ header.m_index_entry =
+ context.GetAsLLVM().getTUIndex().getFromOffset(header.m_offset);
+ } else {
+ header.m_index_entry =
+ context.GetAsLLVM().getCUIndex().getFromOffset(header.m_offset);
+ }
+ }
+
if (header.m_index_entry) {
if (header.m_abbr_offset) {
return llvm::createStringError(
@@ -856,12 +895,11 @@ DWARFUnitHeader::extract(const DWARFDataExtractor &data,
llvm::Expected<DWARFUnitSP>
DWARFUnit::extract(SymbolFileDWARF &dwarf, user_id_t uid,
const DWARFDataExtractor &debug_info,
- DIERef::Section section, lldb::offset_t *offset_ptr,
- const llvm::DWARFUnitIndex *index) {
+ DIERef::Section section, lldb::offset_t *offset_ptr) {
assert(debug_info.ValidOffset(*offset_ptr));
- auto expected_header =
- DWARFUnitHeader::extract(debug_info, section, offset_ptr, index);
+ auto expected_header = DWARFUnitHeader::extract(
+ debug_info, section, dwarf.GetDWARFContext(), offset_ptr);
if (!expected_header)
return expected_header.takeError();
@@ -930,11 +968,11 @@ DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) {
return ranges;
}
- if (!m_rnglist_table)
+ if (!GetRnglistTable())
return llvm::createStringError(errc::invalid_argument,
"missing or invalid range list table");
- auto range_list_or_error = m_rnglist_table->findList(
+ auto range_list_or_error = GetRnglistTable()->findList(
m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(), offset);
if (!range_list_or_error)
return range_list_or_error.takeError();
@@ -963,12 +1001,8 @@ DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) {
llvm::Expected<DWARFRangeList>
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");
+ llvm::Expected<uint64_t> maybe_offset = GetRnglistOffset(index);
+ if (!maybe_offset)
+ return maybe_offset.takeError();
+ return FindRnglistFromOffset(*maybe_offset);
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index 5739c36bbacb..da79a6aaf64e 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -73,7 +73,8 @@ public:
static llvm::Expected<DWARFUnitHeader>
extract(const lldb_private::DWARFDataExtractor &data, DIERef::Section section,
- lldb::offset_t *offset_ptr, const llvm::DWARFUnitIndex *index);
+ lldb_private::DWARFContext &dwarf_context,
+ lldb::offset_t *offset_ptr);
};
class DWARFUnit : public lldb_private::UserID {
@@ -84,8 +85,7 @@ public:
static llvm::Expected<DWARFUnitSP>
extract(SymbolFileDWARF &dwarf2Data, lldb::user_id_t uid,
const lldb_private::DWARFDataExtractor &debug_info,
- DIERef::Section section, lldb::offset_t *offset_ptr,
- const llvm::DWARFUnitIndex *index);
+ DIERef::Section section, lldb::offset_t *offset_ptr);
virtual ~DWARFUnit();
bool IsDWOUnit() { return m_is_dwo; }
@@ -235,15 +235,7 @@ public:
/// 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(
- m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(),
- Index))
- return *off + m_ranges_base;
- return llvm::None;
- }
+ llvm::Expected<uint64_t> GetRnglistOffset(uint32_t Index);
llvm::Optional<uint64_t> GetLoclistOffset(uint32_t Index) {
if (!m_loclist_table_header)
@@ -291,6 +283,8 @@ protected:
return &m_die_array[0];
}
+ const llvm::Optional<llvm::DWARFDebugRnglistTable> &GetRnglistTable();
+
SymbolFileDWARF &m_dwarf;
std::shared_ptr<DWARFUnit> m_dwo;
DWARFUnitHeader m_header;
@@ -331,6 +325,7 @@ protected:
dw_offset_t m_str_offsets_base = 0; // Value of DW_AT_str_offsets_base.
llvm::Optional<llvm::DWARFDebugRnglistTable> m_rnglist_table;
+ bool m_rnglist_table_done = false;
llvm::Optional<llvm::DWARFListTableHeader> m_loclist_table_header;
const DIERef::Section m_section;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
index d36f2a8bccf7..ce71281db8bd 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
@@ -130,8 +130,7 @@ DWARFMappedHash::DIEInfo::DIEInfo(dw_offset_t o, dw_tag_t t, uint32_t f,
: die_offset(o), tag(t), type_flags(f), qualified_name_hash(h) {}
DWARFMappedHash::Prologue::Prologue(dw_offset_t _die_base_offset)
- : die_base_offset(_die_base_offset), atoms(), atom_mask(0),
- min_hash_data_byte_size(0), hash_data_has_fixed_byte_size(true) {
+ : die_base_offset(_die_base_offset), atoms() {
// Define an array of DIE offsets by first defining an array, and then define
// the atom type for the array, in this case we have an array of DIE offsets.
AppendAtom(eAtomTypeDIEOffset, DW_FORM_data4);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
index ad178fc6a987..efc08e47a280 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
@@ -101,9 +101,9 @@ public:
/// DIE offset base so die offsets in hash_data can be CU relative.
dw_offset_t die_base_offset;
AtomArray atoms;
- uint32_t atom_mask;
- size_t min_hash_data_byte_size;
- bool hash_data_has_fixed_byte_size;
+ uint32_t atom_mask = 0;
+ size_t min_hash_data_byte_size = 0;
+ bool hash_data_has_fixed_byte_size = true;
};
class Header : public MappedHash::Header<Prologue> {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
index dda599baffeb..1f40d880ea34 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -13,9 +13,11 @@
#include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/Progress.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/ThreadPool.h"
using namespace lldb_private;
@@ -56,6 +58,17 @@ void ManualDWARFIndex::Index() {
if (units_to_index.empty())
return;
+ StreamString module_desc;
+ m_module.GetDescription(module_desc.AsRawOstream(),
+ lldb::eDescriptionLevelBrief);
+
+ // Include 2 passes per unit to index for extracting DIEs from the unit and
+ // indexing the unit, and then 8 extra entries for finalizing each index set.
+ const uint64_t total_progress = units_to_index.size() * 2 + 8;
+ Progress progress(
+ llvm::formatv("Manually indexing DWARF for {0}", module_desc.GetData()),
+ total_progress);
+
std::vector<IndexSet> sets(units_to_index.size());
// Keep memory down by clearing DIEs for any units if indexing
@@ -64,10 +77,12 @@ void ManualDWARFIndex::Index() {
units_to_index.size());
auto parser_fn = [&](size_t cu_idx) {
IndexUnit(*units_to_index[cu_idx], dwp_dwarf, sets[cu_idx]);
+ progress.Increment();
};
- auto extract_fn = [&units_to_index, &clear_cu_dies](size_t cu_idx) {
+ auto extract_fn = [&](size_t cu_idx) {
clear_cu_dies[cu_idx] = units_to_index[cu_idx]->ExtractDIEsScoped();
+ progress.Increment();
};
// Share one thread pool across operations to avoid the overhead of
@@ -92,11 +107,12 @@ void ManualDWARFIndex::Index() {
pool.async(parser_fn, i);
pool.wait();
- auto finalize_fn = [this, &sets](NameToDIE(IndexSet::*index)) {
+ auto finalize_fn = [this, &sets, &progress](NameToDIE(IndexSet::*index)) {
NameToDIE &result = m_set.*index;
for (auto &set : sets)
result.Append(set.*index);
result.Finalize();
+ progress.Increment();
};
pool.async(finalize_fn, &IndexSet::function_basenames);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
index 5aa841cf3d10..a6863f6c9549 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
@@ -22,7 +22,7 @@ class NameToDIE {
public:
NameToDIE() : m_map() {}
- ~NameToDIE() {}
+ ~NameToDIE() = default;
void Dump(lldb_private::Stream *s);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 3656c7333f27..ccaf31317d75 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -16,6 +16,7 @@
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Progress.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/Value.h"
@@ -74,18 +75,19 @@
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FormatVariadic.h"
#include <algorithm>
#include <map>
#include <memory>
-#include <ctype.h>
-#include <string.h>
+#include <cctype>
+#include <cstring>
//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
#ifdef ENABLE_DEBUG_PRINTF
-#include <stdio.h>
+#include <cstdio>
#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
#else
#define DEBUG_PRINTF(fmt, ...)
@@ -238,9 +240,12 @@ ParseSupportFilesFromPrologue(const lldb::ModuleSP &module,
const size_t number_of_files = prologue.FileNames.size();
for (size_t idx = first_file; idx <= number_of_files; ++idx) {
std::string remapped_file;
- if (auto file_path = GetFileByIndex(prologue, idx, compile_dir, style))
- if (!module->RemapSourceFile(llvm::StringRef(*file_path), remapped_file))
+ if (auto file_path = GetFileByIndex(prologue, idx, compile_dir, style)) {
+ if (auto remapped = module->RemapSourceFile(llvm::StringRef(*file_path)))
+ remapped_file = *remapped;
+ else
remapped_file = std::move(*file_path);
+ }
// Unconditionally add an entry, so the indices match up.
support_files.EmplaceBack(remapped_file, style);
@@ -358,8 +363,7 @@ void SymbolFileDWARF::GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset,
}
}
- for (DWARFDIE child_die = die.GetFirstChild(); child_die.IsValid();
- child_die = child_die.GetSibling()) {
+ for (DWARFDIE child_die : die.children()) {
GetTypes(child_die, min_die_offset, max_die_offset, type_mask, type_set);
}
}
@@ -435,7 +439,7 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFileSP objfile_sp,
m_fetched_external_modules(false),
m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) {}
-SymbolFileDWARF::~SymbolFileDWARF() {}
+SymbolFileDWARF::~SymbolFileDWARF() = default;
static ConstString GetDWARFMachOSegmentName() {
static ConstString g_dwarf_section_name("__DWARF");
@@ -467,22 +471,32 @@ void SymbolFileDWARF::InitializeObject() {
Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
if (!GetGlobalPluginProperties()->IgnoreFileIndexes()) {
+ StreamString module_desc;
+ GetObjectFile()->GetModule()->GetDescription(module_desc.AsRawOstream(),
+ lldb::eDescriptionLevelBrief);
DWARFDataExtractor apple_names, apple_namespaces, apple_types, apple_objc;
LoadSectionData(eSectionTypeDWARFAppleNames, apple_names);
LoadSectionData(eSectionTypeDWARFAppleNamespaces, apple_namespaces);
LoadSectionData(eSectionTypeDWARFAppleTypes, apple_types);
LoadSectionData(eSectionTypeDWARFAppleObjC, apple_objc);
- m_index = AppleDWARFIndex::Create(
- *GetObjectFile()->GetModule(), apple_names, apple_namespaces,
- apple_types, apple_objc, m_context.getOrLoadStrData());
+ if (apple_names.GetByteSize() > 0 || apple_namespaces.GetByteSize() > 0 ||
+ apple_types.GetByteSize() > 0 || apple_objc.GetByteSize() > 0) {
+ Progress progress(llvm::formatv("Loading Apple DWARF index for {0}",
+ module_desc.GetData()));
+ m_index = AppleDWARFIndex::Create(
+ *GetObjectFile()->GetModule(), apple_names, apple_namespaces,
+ apple_types, apple_objc, m_context.getOrLoadStrData());
- if (m_index)
- return;
+ if (m_index)
+ return;
+ }
DWARFDataExtractor debug_names;
LoadSectionData(eSectionTypeDWARFDebugNames, debug_names);
if (debug_names.GetByteSize() > 0) {
+ Progress progress(
+ llvm::formatv("Loading DWARF5 index for {0}", module_desc.GetData()));
llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> index_or =
DebugNamesDWARFIndex::Create(*GetObjectFile()->GetModule(),
debug_names,
@@ -669,9 +683,8 @@ static void MakeAbsoluteAndRemap(FileSpec &file_spec, DWARFUnit &dwarf_cu,
// files are NFS mounted.
file_spec.MakeAbsolute(dwarf_cu.GetCompilationDirectory());
- std::string remapped_file;
- if (module_sp->RemapSourceFile(file_spec.GetPath(), remapped_file))
- file_spec.SetFile(remapped_file, FileSpec::Style::native);
+ if (auto remapped_file = module_sp->RemapSourceFile(file_spec.GetPath()))
+ file_spec.SetFile(*remapped_file, FileSpec::Style::native);
}
lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
@@ -973,8 +986,7 @@ bool SymbolFileDWARF::ParseImportedModules(
if (!die)
return false;
- for (DWARFDIE child_die = die.GetFirstChild(); child_die;
- child_die = child_die.GetSibling()) {
+ for (DWARFDIE child_die : die.children()) {
if (child_die.Tag() != DW_TAG_imported_declaration)
continue;
@@ -1233,8 +1245,7 @@ size_t SymbolFileDWARF::ParseBlocksRecursive(
bool SymbolFileDWARF::ClassOrStructIsVirtual(const DWARFDIE &parent_die) {
if (parent_die) {
- for (DWARFDIE die = parent_die.GetFirstChild(); die;
- die = die.GetSibling()) {
+ for (DWARFDIE die : parent_die.children()) {
dw_tag_t tag = die.Tag();
bool check_virtuality = false;
switch (tag) {
@@ -1639,6 +1650,13 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
return nullptr;
dwo_file.SetFile(comp_dir, FileSpec::Style::native);
+ if (dwo_file.IsRelative()) {
+ // if DW_AT_comp_dir is relative, it should be relative to the location
+ // of the executable, not to the location from which the debugger was
+ // launched.
+ dwo_file.PrependPathComponent(
+ m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef());
+ }
FileSystem::Instance().Resolve(dwo_file);
dwo_file.AppendPathComponent(dwo_name);
}
@@ -1784,7 +1802,7 @@ SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() {
if (location.Evaluate(nullptr, LLDB_INVALID_ADDRESS, nullptr,
nullptr, location_result, &error)) {
if (location_result.GetValueType() ==
- Value::eValueTypeFileAddress) {
+ Value::ValueType::FileAddress) {
lldb::addr_t file_addr =
location_result.GetScalar().ULongLong();
lldb::addr_t byte_size = 1;
@@ -1850,17 +1868,8 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,
lldb::addr_t file_vm_addr = so_addr.GetFileAddress();
DWARFDebugInfo &debug_info = DebugInfo();
- llvm::Expected<DWARFDebugAranges &> aranges =
- debug_info.GetCompileUnitAranges();
- if (!aranges) {
- Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
- LLDB_LOG_ERROR(log, aranges.takeError(),
- "SymbolFileDWARF::ResolveSymbolContext failed to get cu "
- "aranges. {0}");
- return 0;
- }
-
- const dw_offset_t cu_offset = aranges->FindAddress(file_vm_addr);
+ const DWARFDebugAranges &aranges = debug_info.GetCompileUnitAranges();
+ const dw_offset_t cu_offset = aranges.FindAddress(file_vm_addr);
if (cu_offset == DW_INVALID_OFFSET) {
// Global variables are not in the compile unit address ranges. The only
// way to currently find global variables is to iterate over the
@@ -1949,12 +1958,11 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,
return resolved;
}
-uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
- uint32_t line,
- bool check_inlines,
- SymbolContextItem resolve_scope,
- SymbolContextList &sc_list) {
+uint32_t SymbolFileDWARF::ResolveSymbolContext(
+ const SourceLocationSpec &src_location_spec,
+ SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
+ const bool check_inlines = src_location_spec.GetCheckInlines();
const uint32_t prev_size = sc_list.GetSize();
if (resolve_scope & eSymbolContextCompUnit) {
for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus;
@@ -1963,69 +1971,10 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
if (!dc_cu)
continue;
- bool file_spec_matches_cu_file_spec =
- FileSpec::Match(file_spec, dc_cu->GetPrimaryFile());
+ bool file_spec_matches_cu_file_spec = FileSpec::Match(
+ src_location_spec.GetFileSpec(), dc_cu->GetPrimaryFile());
if (check_inlines || file_spec_matches_cu_file_spec) {
- SymbolContext sc(m_objfile_sp->GetModule());
- sc.comp_unit = dc_cu;
- uint32_t file_idx = UINT32_MAX;
-
- // If we are looking for inline functions only and we don't find it
- // in the support files, we are done.
- if (check_inlines) {
- file_idx =
- sc.comp_unit->GetSupportFiles().FindFileIndex(1, file_spec, true);
- if (file_idx == UINT32_MAX)
- continue;
- }
-
- if (line != 0) {
- LineTable *line_table = sc.comp_unit->GetLineTable();
-
- if (line_table != nullptr && line != 0) {
- // We will have already looked up the file index if we are
- // searching for inline entries.
- if (!check_inlines)
- file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex(
- 1, file_spec, true);
-
- if (file_idx != UINT32_MAX) {
- uint32_t found_line;
- uint32_t line_idx = line_table->FindLineEntryIndexByFileIndex(
- 0, file_idx, line, false, &sc.line_entry);
- found_line = sc.line_entry.line;
-
- while (line_idx != UINT32_MAX) {
- sc.function = nullptr;
- sc.block = nullptr;
- if (resolve_scope &
- (eSymbolContextFunction | eSymbolContextBlock)) {
- const lldb::addr_t file_vm_addr =
- sc.line_entry.range.GetBaseAddress().GetFileAddress();
- if (file_vm_addr != LLDB_INVALID_ADDRESS) {
- ResolveFunctionAndBlock(
- file_vm_addr, resolve_scope & eSymbolContextBlock, sc);
- }
- }
-
- sc_list.Append(sc);
- line_idx = line_table->FindLineEntryIndexByFileIndex(
- line_idx + 1, file_idx, found_line, true, &sc.line_entry);
- }
- }
- } 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
- 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
- sc_list.Append(sc);
- }
-
+ dc_cu->ResolveSymbolContext(src_location_spec, resolve_scope, sc_list);
if (!check_inlines)
break;
}
@@ -2462,7 +2411,7 @@ void SymbolFileDWARF::FindTypes(
return;
m_index->GetTypes(name, [&](DWARFDIE die) {
- if (!languages[GetLanguage(*die.GetCU())])
+ if (!languages[GetLanguageFamily(*die.GetCU())])
return true;
llvm::SmallVector<CompilerContext, 4> die_context;
@@ -3126,8 +3075,8 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
continue;
switch (attr) {
case DW_AT_decl_file:
- decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(
- form_value.Unsigned()));
+ decl.SetFile(
+ attributes.CompileUnitAtIndex(i)->GetFile(form_value.Unsigned()));
break;
case DW_AT_decl_line:
decl.SetLine(form_value.Unsigned());
@@ -3469,8 +3418,7 @@ SymbolFileDWARF::FindBlockContainingSpecification(
// Give the concrete function die specified by "func_die_offset", find the
// concrete block whose DW_AT_specification or DW_AT_abstract_origin points
// to "spec_block_die_offset"
- for (DWARFDIE child_die = die.GetFirstChild(); child_die;
- child_die = child_die.GetSibling()) {
+ for (DWARFDIE child_die : die.children()) {
DWARFDIE result_die =
FindBlockContainingSpecification(child_die, spec_block_die_offset);
if (result_die)
@@ -3599,8 +3547,7 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc,
static CallSiteParameterArray
CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) {
CallSiteParameterArray parameters;
- for (DWARFDIE child = call_site_die.GetFirstChild(); child.IsValid();
- child = child.GetSibling()) {
+ for (DWARFDIE child : call_site_die.children()) {
if (child.Tag() != DW_TAG_call_site_parameter &&
child.Tag() != DW_TAG_GNU_call_site_parameter)
continue;
@@ -3665,8 +3612,7 @@ SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
// 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<std::unique_ptr<CallEdge>> call_edges;
- for (DWARFDIE child = function_die.GetFirstChild(); child.IsValid();
- child = child.GetSibling()) {
+ for (DWARFDIE child : function_die.children()) {
if (child.Tag() != DW_TAG_call_site && child.Tag() != DW_TAG_GNU_call_site)
continue;
@@ -3842,7 +3788,7 @@ void SymbolFileDWARF::DumpClangAST(Stream &s) {
}
SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() {
- if (m_debug_map_symfile == nullptr && !m_debug_map_module_wp.expired()) {
+ if (m_debug_map_symfile == nullptr) {
lldb::ModuleSP module_sp(m_debug_map_module_wp.lock());
if (module_sp) {
m_debug_map_symfile =
@@ -3936,3 +3882,10 @@ LanguageType SymbolFileDWARF::LanguageTypeFromDWARF(uint64_t val) {
LanguageType SymbolFileDWARF::GetLanguage(DWARFUnit &unit) {
return LanguageTypeFromDWARF(unit.GetDWARFLanguageType());
}
+
+LanguageType SymbolFileDWARF::GetLanguageFamily(DWARFUnit &unit) {
+ auto lang = (llvm::dwarf::SourceLanguage)unit.GetDWARFLanguageType();
+ if (llvm::dwarf::isCPlusPlus(lang))
+ lang = DW_LANG_C_plus_plus;
+ return LanguageTypeFromDWARF(lang);
+}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 019f76c67c63..d9feeef549ed 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -161,11 +161,10 @@ public:
lldb::SymbolContextItem resolve_scope,
lldb_private::SymbolContext &sc) override;
- uint32_t
- ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line,
- bool check_inlines,
- lldb::SymbolContextItem resolve_scope,
- lldb_private::SymbolContextList &sc_list) override;
+ uint32_t ResolveSymbolContext(
+ const lldb_private::SourceLocationSpec &src_location_spec,
+ lldb::SymbolContextItem resolve_scope,
+ lldb_private::SymbolContextList &sc_list) override;
void
FindGlobalVariables(lldb_private::ConstString name,
@@ -318,6 +317,8 @@ public:
static lldb::LanguageType LanguageTypeFromDWARF(uint64_t val);
static lldb::LanguageType GetLanguage(DWARFUnit &unit);
+ /// Same as GetLanguage() but reports all C++ versions as C++ (no version).
+ static lldb::LanguageType GetLanguageFamily(DWARFUnit &unit);
protected:
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *>
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index fa24f975b073..4e2e5e16637b 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -16,7 +16,6 @@
#include "lldb/Host/FileSystem.h"
#include "lldb/Utility/RangeMap.h"
#include "lldb/Utility/RegularExpression.h"
-#include "lldb/Utility/Timer.h"
//#define DEBUG_OSO_DMAP // DO NOT CHECKIN WITH THIS NOT COMMENTED OUT
#if defined(DEBUG_OSO_DMAP)
@@ -34,6 +33,9 @@
#include "LogChannelDWARF.h"
#include "SymbolFileDWARF.h"
+// Work around the fact that Timer.h pulls in the system Mach-O headers.
+#include "lldb/Utility/Timer.h"
+
#include <memory>
using namespace lldb;
@@ -246,7 +248,7 @@ SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap(ObjectFileSP objfile_sp)
m_func_indexes(), m_glob_indexes(),
m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) {}
-SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap() {}
+SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap() = default;
void SymbolFileDWARFDebugMap::InitializeObject() {}
@@ -806,7 +808,7 @@ SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address &exe_so_addr,
}
uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext(
- const FileSpec &file_spec, uint32_t line, bool check_inlines,
+ const SourceLocationSpec &src_location_spec,
SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
const uint32_t initial = sc_list.GetSize();
@@ -815,18 +817,19 @@ uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext(
for (uint32_t i = 0; i < cu_count; ++i) {
// If we are checking for inlines, then we need to look through all compile
// units no matter if "file_spec" matches.
- bool resolve = check_inlines;
+ bool resolve = src_location_spec.GetCheckInlines();
if (!resolve) {
FileSpec so_file_spec;
if (GetFileSpecForSO(i, so_file_spec))
- resolve = FileSpec::Match(file_spec, so_file_spec);
+ resolve =
+ FileSpec::Match(src_location_spec.GetFileSpec(), so_file_spec);
}
if (resolve) {
SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(i);
if (oso_dwarf)
- oso_dwarf->ResolveSymbolContext(file_spec, line, check_inlines,
- resolve_scope, sc_list);
+ oso_dwarf->ResolveSymbolContext(src_location_spec, resolve_scope,
+ sc_list);
}
}
return sc_list.GetSize() - initial;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index 06f0d48c04ca..8b6624e70869 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -97,11 +97,10 @@ public:
uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr,
lldb::SymbolContextItem resolve_scope,
lldb_private::SymbolContext &sc) override;
- uint32_t
- ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line,
- bool check_inlines,
- lldb::SymbolContextItem resolve_scope,
- lldb_private::SymbolContextList &sc_list) override;
+ uint32_t ResolveSymbolContext(
+ const lldb_private::SourceLocationSpec &src_location_spec,
+ lldb::SymbolContextItem resolve_scope,
+ lldb_private::SymbolContextList &sc_list) override;
void
FindGlobalVariables(lldb_private::ConstString name,
const lldb_private::CompilerDeclContext &parent_decl_ctx,
@@ -171,18 +170,17 @@ protected:
llvm::sys::TimePoint<> oso_mod_time;
OSOInfoSP oso_sp;
lldb::CompUnitSP compile_unit_sp;
- uint32_t first_symbol_index;
- uint32_t last_symbol_index;
- uint32_t first_symbol_id;
- uint32_t last_symbol_id;
+ uint32_t first_symbol_index = UINT32_MAX;
+ uint32_t last_symbol_index = UINT32_MAX;
+ uint32_t first_symbol_id = UINT32_MAX;
+ uint32_t last_symbol_id = UINT32_MAX;
FileRangeMap file_range_map;
- bool file_range_map_valid;
+ bool file_range_map_valid = false;
CompileUnitInfo()
: so_file(), oso_path(), oso_mod_time(), oso_sp(), compile_unit_sp(),
- first_symbol_index(UINT32_MAX), last_symbol_index(UINT32_MAX),
- first_symbol_id(UINT32_MAX), last_symbol_id(UINT32_MAX),
- file_range_map(), file_range_map_valid(false) {}
+
+ file_range_map() {}
const FileRangeMap &GetFileRangeMap(SymbolFileDWARFDebugMap *exe_symfile);
};
@@ -280,8 +278,7 @@ protected:
// OSOEntry
class OSOEntry {
public:
- OSOEntry()
- : m_exe_sym_idx(UINT32_MAX), m_oso_file_addr(LLDB_INVALID_ADDRESS) {}
+ OSOEntry() = default;
OSOEntry(uint32_t exe_sym_idx, lldb::addr_t oso_file_addr)
: m_exe_sym_idx(exe_sym_idx), m_oso_file_addr(oso_file_addr) {}
@@ -299,8 +296,8 @@ protected:
}
protected:
- uint32_t m_exe_sym_idx;
- lldb::addr_t m_oso_file_addr;
+ uint32_t m_exe_sym_idx = UINT32_MAX;
+ lldb::addr_t m_oso_file_addr = LLDB_INVALID_ADDRESS;
};
typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, OSOEntry>
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
index 2181989cd37a..34ff23667465 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
@@ -8,7 +8,7 @@
#include "UniqueDWARFASTType.h"
-#include "lldb/Symbol/Declaration.h"
+#include "lldb/Core/Declaration.h"
bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die,
const lldb_private::Declaration &decl,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
index a1b1a3009787..0947d1e581c5 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
@@ -14,16 +14,12 @@
#include "llvm/ADT/DenseMap.h"
#include "DWARFDIE.h"
-#include "lldb/Symbol/Declaration.h"
+#include "lldb/Core/Declaration.h"
class UniqueDWARFASTType {
public:
// Constructors and Destructors
- UniqueDWARFASTType()
- : m_type_sp(), m_die(), m_declaration(),
- m_byte_size(
- -1) // Set to negative value to make sure we have a valid value
- {}
+ UniqueDWARFASTType() : m_type_sp(), m_die(), m_declaration() {}
UniqueDWARFASTType(lldb::TypeSP &type_sp, const DWARFDIE &die,
const lldb_private::Declaration &decl, int32_t byte_size)
@@ -34,7 +30,7 @@ public:
: m_type_sp(rhs.m_type_sp), m_die(rhs.m_die),
m_declaration(rhs.m_declaration), m_byte_size(rhs.m_byte_size) {}
- ~UniqueDWARFASTType() {}
+ ~UniqueDWARFASTType() = default;
UniqueDWARFASTType &operator=(const UniqueDWARFASTType &rhs) {
if (this != &rhs) {
@@ -49,14 +45,14 @@ public:
lldb::TypeSP m_type_sp;
DWARFDIE m_die;
lldb_private::Declaration m_declaration;
- int32_t m_byte_size;
+ int32_t m_byte_size = -1;
};
class UniqueDWARFASTTypeList {
public:
UniqueDWARFASTTypeList() : m_collection() {}
- ~UniqueDWARFASTTypeList() {}
+ ~UniqueDWARFASTTypeList() = default;
uint32_t GetSize() { return (uint32_t)m_collection.size(); }
@@ -76,7 +72,7 @@ class UniqueDWARFASTTypeMap {
public:
UniqueDWARFASTTypeMap() : m_collection() {}
- ~UniqueDWARFASTTypeMap() {}
+ ~UniqueDWARFASTTypeMap() = default;
void Insert(lldb_private::ConstString name,
const UniqueDWARFASTType &entry) {
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp
index f25dc84fb342..9f09c0accc87 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp
@@ -43,7 +43,7 @@ static bool IsMainFile(llvm::StringRef main, llvm::StringRef other) {
llvm::SmallString<64> normalized(other);
llvm::sys::path::native(normalized);
- return main.equals_lower(normalized);
+ return main.equals_insensitive(normalized);
}
static void ParseCompile3(const CVSymbol &sym, CompilandIndexItem &cci) {
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
index 5b4ab78ac219..43cf262016c2 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -1093,7 +1093,7 @@ void PdbAstBuilder::CreateFunctionParameters(PdbCompilandSymId func_id,
}
if (!params.empty())
- m_clang.SetFunctionParameters(&function_decl, params.data(), params.size());
+ m_clang.SetFunctionParameters(&function_decl, params);
}
clang::QualType PdbAstBuilder::CreateEnumType(PdbTypeSymId id,
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
index ecae767e4469..4f570d5e6788 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
@@ -41,7 +41,7 @@ static uint32_t ResolveLLDBRegisterNum(llvm::StringRef reg_name, llvm::Triple::A
auto it = llvm::find_if(
register_names,
[&reg_name](const llvm::EnumEntry<uint16_t> &register_entry) {
- return reg_name.compare_lower(register_entry.Name) == 0;
+ return reg_name.compare_insensitive(register_entry.Name) == 0;
});
if (it == register_names.end())
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 24b4c64a91bc..b9b075d83b6a 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -256,7 +256,7 @@ SymbolFile *SymbolFileNativePDB::CreateInstance(ObjectFileSP objfile_sp) {
SymbolFileNativePDB::SymbolFileNativePDB(ObjectFileSP objfile_sp)
: SymbolFile(std::move(objfile_sp)) {}
-SymbolFileNativePDB::~SymbolFileNativePDB() {}
+SymbolFileNativePDB::~SymbolFileNativePDB() = default;
uint32_t SymbolFileNativePDB::CalculateAbilities() {
uint32_t abilities = 0;
@@ -1001,7 +1001,7 @@ uint32_t SymbolFileNativePDB::ResolveSymbolContext(
}
uint32_t SymbolFileNativePDB::ResolveSymbolContext(
- const FileSpec &file_spec, uint32_t line, bool check_inlines,
+ const SourceLocationSpec &src_location_spec,
lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
return 0;
}
@@ -1039,7 +1039,7 @@ static void TerminateLineSequence(LineTable &table,
table.AppendLineEntryToSequence(seq.get(), base_addr + block.CodeSize,
last_line, 0, file_number, false, false,
false, false, true);
- table.InsertSequence(seq.release());
+ table.InsertSequence(seq.get());
}
bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) {
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
index 61c1d77164b7..def0995065ca 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -120,8 +120,7 @@ public:
uint32_t ResolveSymbolContext(const Address &so_addr,
lldb::SymbolContextItem resolve_scope,
SymbolContext &sc) override;
- uint32_t ResolveSymbolContext(const FileSpec &file_spec, uint32_t line,
- bool check_inlines,
+ uint32_t ResolveSymbolContext(const SourceLocationSpec &src_location_spec,
lldb::SymbolContextItem resolve_scope,
SymbolContextList &sc_list) override;
diff --git a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
index f9c12e634140..78a0d09a681a 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
+++ b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
@@ -17,8 +17,8 @@
#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
+#include "lldb/Core/Declaration.h"
#include "lldb/Core/Module.h"
-#include "lldb/Symbol/Declaration.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/TypeMap.h"
#include "lldb/Symbol/TypeSystem.h"
@@ -326,7 +326,7 @@ GetDeclFromContextByName(const clang::ASTContext &ast,
if (result.empty())
return nullptr;
- return result[0];
+ return *result.begin();
}
static bool IsAnonymousNamespaceName(llvm::StringRef name) {
@@ -355,7 +355,7 @@ static clang::CallingConv TranslateCallingConvention(PDB_CallingConv pdb_cc) {
PDBASTParser::PDBASTParser(lldb_private::TypeSystemClang &ast) : m_ast(ast) {}
-PDBASTParser::~PDBASTParser() {}
+PDBASTParser::~PDBASTParser() = default;
// DebugInfoASTParser interface
@@ -534,8 +534,12 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type);
assert(type_def);
+ SymbolFile *symbol_file = m_ast.GetSymbolFile();
+ if (!symbol_file)
+ return nullptr;
+
lldb_private::Type *target_type =
- m_ast.GetSymbolFile()->ResolveTypeUID(type_def->getTypeId());
+ symbol_file->ResolveTypeUID(type_def->getTypeId());
if (!target_type)
return nullptr;
@@ -609,8 +613,13 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
auto arg = arg_enum->getChildAtIndex(arg_idx);
if (!arg)
break;
+
+ SymbolFile *symbol_file = m_ast.GetSymbolFile();
+ if (!symbol_file)
+ return nullptr;
+
lldb_private::Type *arg_type =
- m_ast.GetSymbolFile()->ResolveTypeUID(arg->getSymIndexId());
+ symbol_file->ResolveTypeUID(arg->getSymIndexId());
// If there's some error looking up one of the dependent types of this
// function signature, bail.
if (!arg_type)
@@ -621,8 +630,12 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
lldbassert(arg_list.size() <= num_args);
auto pdb_return_type = func_sig->getReturnType();
+ SymbolFile *symbol_file = m_ast.GetSymbolFile();
+ if (!symbol_file)
+ return nullptr;
+
lldb_private::Type *return_type =
- m_ast.GetSymbolFile()->ResolveTypeUID(pdb_return_type->getSymIndexId());
+ symbol_file->ResolveTypeUID(pdb_return_type->getSymIndexId());
// If there's some error looking up one of the dependent types of this
// function signature, bail.
if (!return_type)
@@ -654,10 +667,13 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
if (uint64_t size = array_type->getLength())
bytes = size;
+ SymbolFile *symbol_file = m_ast.GetSymbolFile();
+ if (!symbol_file)
+ return nullptr;
+
// If array rank > 0, PDB gives the element type at N=0. So element type
// will parsed in the order N=0, N=1,..., N=rank sequentially.
- lldb_private::Type *element_type =
- m_ast.GetSymbolFile()->ResolveTypeUID(element_uid);
+ lldb_private::Type *element_type = symbol_file->ResolveTypeUID(element_uid);
if (!element_type)
return nullptr;
@@ -711,7 +727,12 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
case PDB_SymType::PointerType: {
auto *pointer_type = llvm::dyn_cast<PDBSymbolTypePointer>(&type);
assert(pointer_type);
- Type *pointee_type = m_ast.GetSymbolFile()->ResolveTypeUID(
+
+ SymbolFile *symbol_file = m_ast.GetSymbolFile();
+ if (!symbol_file)
+ return nullptr;
+
+ Type *pointee_type = symbol_file->ResolveTypeUID(
pointer_type->getPointeeType()->getSymIndexId());
if (!pointee_type)
return nullptr;
@@ -719,8 +740,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
if (pointer_type->isPointerToDataMember() ||
pointer_type->isPointerToMemberFunction()) {
auto class_parent_uid = pointer_type->getRawSymbol().getClassParentId();
- auto class_parent_type =
- m_ast.GetSymbolFile()->ResolveTypeUID(class_parent_uid);
+ auto class_parent_type = symbol_file->ResolveTypeUID(class_parent_uid);
assert(class_parent_type);
CompilerType pointer_ast_type;
@@ -950,7 +970,7 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) {
}
}
if (params.size())
- m_ast.SetFunctionParameters(decl, params.data(), params.size());
+ m_ast.SetFunctionParameters(decl, params);
m_uid_to_decl[sym_id] = decl;
diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
index befc08158cea..6b30ad26dca7 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -84,8 +84,10 @@ bool ShouldAddLine(uint32_t requested_line, uint32_t actual_line,
static bool ShouldUseNativeReader() {
#if defined(_WIN32)
llvm::StringRef use_native = ::getenv("LLDB_USE_NATIVE_PDB_READER");
- return use_native.equals_lower("on") || use_native.equals_lower("yes") ||
- use_native.equals_lower("1") || use_native.equals_lower("true");
+ return use_native.equals_insensitive("on") ||
+ use_native.equals_insensitive("yes") ||
+ use_native.equals_insensitive("1") ||
+ use_native.equals_insensitive("true");
#else
return true;
#endif
@@ -128,7 +130,7 @@ SymbolFilePDB::CreateInstance(ObjectFileSP objfile_sp) {
SymbolFilePDB::SymbolFilePDB(lldb::ObjectFileSP objfile_sp)
: SymbolFile(std::move(objfile_sp)), m_session_up(), m_global_scope_up() {}
-SymbolFilePDB::~SymbolFilePDB() {}
+SymbolFilePDB::~SymbolFilePDB() = default;
uint32_t SymbolFilePDB::CalculateAbilities() {
uint32_t abilities = 0;
@@ -784,10 +786,12 @@ SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr,
}
uint32_t SymbolFilePDB::ResolveSymbolContext(
- const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines,
+ const lldb_private::SourceLocationSpec &src_location_spec,
SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
const size_t old_size = sc_list.GetSize();
+ const FileSpec &file_spec = src_location_spec.GetFileSpec();
+ const uint32_t line = src_location_spec.GetLine().getValueOr(0);
if (resolve_scope & lldb::eSymbolContextCompUnit) {
// Locate all compilation units with line numbers referencing the specified
// file. For example, if `file_spec` is <vector>, then this should return
@@ -806,7 +810,7 @@ uint32_t SymbolFilePDB::ResolveSymbolContext(
// this file unless the FileSpec matches. For inline functions, we don't
// have to match the FileSpec since they could be defined in headers
// other than file specified in FileSpec.
- if (!check_inlines) {
+ if (!src_location_spec.GetCheckInlines()) {
std::string source_file = compiland->getSourceFileFullPath();
if (source_file.empty())
continue;
@@ -1813,7 +1817,7 @@ bool SymbolFilePDB::ParseCompileUnitLineTable(CompileUnit &comp_unit,
sequence.get(), prev_addr + prev_length, prev_line, 0,
prev_source_idx, false, false, false, false, true);
- line_table->InsertSequence(sequence.release());
+ line_table->InsertSequence(sequence.get());
sequence = line_table->CreateLineSequenceContainer();
}
diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
index 928cbffc5f63..2171b7f686cc 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
+++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
@@ -104,11 +104,10 @@ public:
lldb::SymbolContextItem resolve_scope,
lldb_private::SymbolContext &sc) override;
- uint32_t
- ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line,
- bool check_inlines,
- lldb::SymbolContextItem resolve_scope,
- lldb_private::SymbolContextList &sc_list) override;
+ uint32_t ResolveSymbolContext(
+ const lldb_private::SourceLocationSpec &src_location_spec,
+ lldb::SymbolContextItem resolve_scope,
+ lldb_private::SymbolContextList &sc_list) override;
void
FindGlobalVariables(lldb_private::ConstString name,
diff --git a/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
index 4df5140bd7e1..9130eed63e43 100644
--- a/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
+++ b/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
@@ -8,7 +8,7 @@
#include "SymbolVendorELF.h"
-#include <string.h>
+#include <cstring>
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
#include "lldb/Core/Module.h"
diff --git a/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp b/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp
index 67a1ef5e4e51..2b2840796579 100644
--- a/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp
+++ b/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp
@@ -8,7 +8,7 @@
#include "SymbolVendorWasm.h"
-#include <string.h>
+#include <cstring>
#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h"
#include "lldb/Core/Module.h"
diff --git a/lldb/source/Target/ThreadTrace.cpp b/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.cpp
index 346f36a737d7..45d6f3b0e098 100644
--- a/lldb/source/Target/ThreadTrace.cpp
+++ b/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.cpp
@@ -1,4 +1,4 @@
-//===-- ThreadTrace.cpp ---------------------------------------------------===//
+//===-- ThreadPostMortemTrace.cpp -----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Target/ThreadTrace.h"
+#include "ThreadPostMortemTrace.h"
#include <memory>
@@ -17,9 +17,9 @@
using namespace lldb;
using namespace lldb_private;
-void ThreadTrace::RefreshStateAfterStop() {}
+void ThreadPostMortemTrace::RefreshStateAfterStop() {}
-RegisterContextSP ThreadTrace::GetRegisterContext() {
+RegisterContextSP ThreadPostMortemTrace::GetRegisterContext() {
if (!m_reg_context_sp)
m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
@@ -27,13 +27,15 @@ RegisterContextSP ThreadTrace::GetRegisterContext() {
}
RegisterContextSP
-ThreadTrace::CreateRegisterContextForFrame(StackFrame *frame) {
+ThreadPostMortemTrace::CreateRegisterContextForFrame(StackFrame *frame) {
// Eventually this will calculate the register context based on the current
// trace position.
return std::make_shared<RegisterContextHistory>(
*this, 0, GetProcess()->GetAddressByteSize(), LLDB_INVALID_ADDRESS);
}
-bool ThreadTrace::CalculateStopInfo() { return false; }
+bool ThreadPostMortemTrace::CalculateStopInfo() { return false; }
-const FileSpec &ThreadTrace::GetTraceFile() const { return m_trace_file; }
+const FileSpec &ThreadPostMortemTrace::GetTraceFile() const {
+ return m_trace_file;
+}
diff --git a/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.h b/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.h
new file mode 100644
index 000000000000..9cfe754ae0e4
--- /dev/null
+++ b/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.h
@@ -0,0 +1,60 @@
+//===-- ThreadPostMortemTrace.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_TARGET_THREADPOSTMORTEMTRACE_H
+#define LLDB_TARGET_THREADPOSTMORTEMTRACE_H
+
+#include "lldb/Target/Thread.h"
+
+namespace lldb_private {
+
+/// \class ThreadPostMortemTrace ThreadPostMortemTrace.h
+///
+/// Thread implementation used for representing threads gotten from trace
+/// session files, which are similar to threads from core files.
+///
+/// See \a TraceSessionFileParser for more information regarding trace session
+/// files.
+class ThreadPostMortemTrace : public Thread {
+public:
+ /// \param[in] process
+ /// The process who owns this thread.
+ ///
+ /// \param[in] tid
+ /// The tid of this thread.
+ ///
+ /// \param[in] trace_file
+ /// The file that contains the list of instructions that were traced when
+ /// this thread was being executed.
+ ThreadPostMortemTrace(Process &process, lldb::tid_t tid,
+ const FileSpec &trace_file)
+ : Thread(process, tid), m_trace_file(trace_file) {}
+
+ void RefreshStateAfterStop() override;
+
+ lldb::RegisterContextSP GetRegisterContext() override;
+
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame(StackFrame *frame) override;
+
+ /// \return
+ /// The trace file of this thread.
+ const FileSpec &GetTraceFile() const;
+
+protected:
+ bool CalculateStopInfo() override;
+
+ lldb::RegisterContextSP m_thread_reg_ctx_sp;
+
+private:
+ FileSpec m_trace_file;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_TARGET_THREADPOSTMORTEMTRACE_H
diff --git a/lldb/source/Target/TraceSessionFileParser.cpp b/lldb/source/Plugins/Trace/common/TraceSessionFileParser.cpp
index 713fadc1eb4f..c88ad9dc6a59 100644
--- a/lldb/source/Target/TraceSessionFileParser.cpp
+++ b/lldb/source/Plugins/Trace/common/TraceSessionFileParser.cpp
@@ -6,7 +6,8 @@
//
//===----------------------------------------------------------------------===/
-#include "lldb/Target/TraceSessionFileParser.h"
+#include "TraceSessionFileParser.h"
+#include "ThreadPostMortemTrace.h"
#include <sstream>
@@ -14,7 +15,6 @@
#include "lldb/Core/Module.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
-#include "lldb/Target/ThreadTrace.h"
using namespace lldb;
using namespace lldb_private;
@@ -96,15 +96,16 @@ std::string TraceSessionFileParser::BuildSchema(StringRef plugin_schema) {
return schema_builder.str();
}
-ThreadTraceSP TraceSessionFileParser::ParseThread(ProcessSP &process_sp,
- const JSONThread &thread) {
+ThreadPostMortemTraceSP
+TraceSessionFileParser::ParseThread(ProcessSP &process_sp,
+ const JSONThread &thread) {
lldb::tid_t tid = static_cast<lldb::tid_t>(thread.tid);
FileSpec trace_file(thread.trace_file);
NormalizePath(trace_file);
- ThreadTraceSP thread_sp =
- std::make_shared<ThreadTrace>(*process_sp, tid, trace_file);
+ ThreadPostMortemTraceSP thread_sp =
+ std::make_shared<ThreadPostMortemTrace>(*process_sp, tid, trace_file);
process_sp->GetThreadList().AddThread(thread_sp);
return thread_sp;
}
diff --git a/lldb/source/Plugins/Trace/common/TraceSessionFileParser.h b/lldb/source/Plugins/Trace/common/TraceSessionFileParser.h
new file mode 100644
index 000000000000..6abaffcecd3a
--- /dev/null
+++ b/lldb/source/Plugins/Trace/common/TraceSessionFileParser.h
@@ -0,0 +1,179 @@
+//===-- TraceSessionFileParser.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_TARGET_TRACESESSIONPARSER_H
+#define LLDB_TARGET_TRACESESSIONPARSER_H
+
+#include "llvm/Support/JSON.h"
+
+#include "ThreadPostMortemTrace.h"
+
+namespace lldb_private {
+
+/// \class TraceSessionFileParser TraceSessionFileParser.h
+///
+/// Base class for parsing the common information of JSON trace session files.
+/// Contains the basic C++ structs that represent the JSON data, which include
+/// \a JSONTraceSession as the root object.
+///
+/// See \a Trace::FindPlugin for more information regarding these JSON files.
+class TraceSessionFileParser {
+public:
+ /// C++ structs representing the JSON trace session.
+ /// \{
+ struct JSONAddress {
+ lldb::addr_t value;
+ };
+
+ struct JSONModule {
+ std::string system_path;
+ llvm::Optional<std::string> file;
+ JSONAddress load_address;
+ llvm::Optional<std::string> uuid;
+ };
+
+ struct JSONThread {
+ int64_t tid;
+ std::string trace_file;
+ };
+
+ struct JSONProcess {
+ int64_t pid;
+ std::string triple;
+ std::vector<JSONThread> threads;
+ std::vector<JSONModule> modules;
+ };
+
+ struct JSONTracePluginSettings {
+ std::string type;
+ };
+
+ struct JSONTraceSessionBase {
+ std::vector<JSONProcess> processes;
+ };
+
+ /// The trace plug-in implementation should provide its own TPluginSettings,
+ /// which corresponds to the "trace" section of the schema.
+ template <class TPluginSettings>
+ struct JSONTraceSession : JSONTraceSessionBase {
+ TPluginSettings trace;
+ };
+ /// \}
+
+ /// Helper struct holding the objects created when parsing a process
+ struct ParsedProcess {
+ lldb::TargetSP target_sp;
+ std::vector<lldb::ThreadPostMortemTraceSP> threads;
+ };
+
+ TraceSessionFileParser(Debugger &debugger, llvm::StringRef session_file_dir,
+ llvm::StringRef schema)
+ : m_debugger(debugger), m_session_file_dir(session_file_dir),
+ m_schema(schema) {}
+
+ /// Build the full schema for a Trace plug-in.
+ ///
+ /// \param[in] plugin_schema
+ /// The subschema that corresponds to the "trace" section of the schema.
+ ///
+ /// \return
+ /// The full schema containing the common attributes and the plug-in
+ /// specific attributes.
+ static std::string BuildSchema(llvm::StringRef plugin_schema);
+
+ /// Parse the fields common to all trace session schemas.
+ ///
+ /// \param[in] session
+ /// The session json objects already deserialized.
+ ///
+ /// \return
+ /// A list of \a ParsedProcess containing all threads and targets created
+ /// during the parsing, or an error in case of failures. In case of
+ /// errors, no side effects are produced.
+ llvm::Expected<std::vector<ParsedProcess>>
+ ParseCommonSessionFile(const JSONTraceSessionBase &session);
+
+protected:
+ /// Resolve non-absolute paths relative to the session file folder. It
+ /// modifies the given file_spec.
+ void NormalizePath(lldb_private::FileSpec &file_spec);
+
+ lldb::ThreadPostMortemTraceSP ParseThread(lldb::ProcessSP &process_sp,
+ const JSONThread &thread);
+
+ llvm::Expected<ParsedProcess> ParseProcess(const JSONProcess &process);
+
+ llvm::Error ParseModule(lldb::TargetSP &target_sp, const JSONModule &module);
+
+ /// Create a user-friendly error message upon a JSON-parsing failure using the
+ /// \a json::ObjectMapper functionality.
+ ///
+ /// \param[in] root
+ /// The \a llvm::json::Path::Root used to parse the JSON \a value.
+ ///
+ /// \param[in] value
+ /// The json value that failed to parse.
+ ///
+ /// \return
+ /// An \a llvm::Error containing the user-friendly error message.
+ llvm::Error CreateJSONError(llvm::json::Path::Root &root,
+ const llvm::json::Value &value);
+
+ Debugger &m_debugger;
+ std::string m_session_file_dir;
+ llvm::StringRef m_schema;
+};
+} // namespace lldb_private
+
+namespace llvm {
+namespace json {
+
+bool fromJSON(const Value &value,
+ lldb_private::TraceSessionFileParser::JSONAddress &address,
+ Path path);
+
+bool fromJSON(const Value &value,
+ lldb_private::TraceSessionFileParser::JSONModule &module,
+ Path path);
+
+bool fromJSON(const Value &value,
+ lldb_private::TraceSessionFileParser::JSONThread &thread,
+ Path path);
+
+bool fromJSON(const Value &value,
+ lldb_private::TraceSessionFileParser::JSONProcess &process,
+ Path path);
+
+bool fromJSON(const Value &value,
+ lldb_private::TraceSessionFileParser::JSONTracePluginSettings
+ &plugin_settings,
+ Path path);
+
+bool fromJSON(
+ const Value &value,
+ lldb_private::TraceSessionFileParser::JSONTraceSessionBase &session,
+ Path path);
+
+template <class TPluginSettings>
+bool fromJSON(
+ const Value &value,
+ lldb_private::TraceSessionFileParser::JSONTraceSession<TPluginSettings>
+ &session,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("trace", session.trace) &&
+ fromJSON(value,
+ (lldb_private::TraceSessionFileParser::JSONTraceSessionBase &)
+ session,
+ path);
+}
+
+} // namespace json
+} // namespace llvm
+
+#endif // LLDB_TARGET_TRACESESSIONPARSER_H
diff --git a/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp b/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
index e1758dfcfc41..5650af657c5e 100644
--- a/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
+++ b/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
@@ -8,7 +8,10 @@
#include "CommandObjectTraceStartIntelPT.h"
+#include "TraceIntelPT.h"
+#include "TraceIntelPTConstants.h"
#include "lldb/Host/OptionParser.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/Trace.h"
using namespace lldb;
@@ -16,10 +19,12 @@ using namespace lldb_private;
using namespace lldb_private::trace_intel_pt;
using namespace llvm;
+// CommandObjectThreadTraceStartIntelPT
+
#define LLDB_OPTIONS_thread_trace_start_intel_pt
#include "TraceIntelPTCommandOptions.inc"
-Status CommandObjectTraceStartIntelPT::CommandOptions::SetOptionValue(
+Status CommandObjectThreadTraceStartIntelPT::CommandOptions::SetOptionValue(
uint32_t option_idx, llvm::StringRef option_arg,
ExecutionContext *execution_context) {
Status error;
@@ -27,23 +32,27 @@ Status CommandObjectTraceStartIntelPT::CommandOptions::SetOptionValue(
switch (short_option) {
case 's': {
- int32_t size_in_kb;
- if (option_arg.empty() || option_arg.getAsInteger(0, size_in_kb) ||
- size_in_kb < 0)
+ int64_t thread_buffer_size;
+ if (option_arg.empty() || option_arg.getAsInteger(0, thread_buffer_size) ||
+ thread_buffer_size < 0)
error.SetErrorStringWithFormat("invalid integer value for option '%s'",
option_arg.str().c_str());
else
- m_size_in_kb = size_in_kb;
+ m_thread_buffer_size = thread_buffer_size;
+ break;
+ }
+ case 't': {
+ m_enable_tsc = true;
break;
}
- case 'c': {
- int32_t custom_config;
- if (option_arg.empty() || option_arg.getAsInteger(0, custom_config) ||
- custom_config < 0)
+ case 'p': {
+ int64_t psb_period;
+ if (option_arg.empty() || option_arg.getAsInteger(0, psb_period) ||
+ psb_period < 0)
error.SetErrorStringWithFormat("invalid integer value for option '%s'",
option_arg.str().c_str());
else
- m_custom_config = custom_config;
+ m_psb_period = psb_period;
break;
}
default:
@@ -52,22 +61,104 @@ Status CommandObjectTraceStartIntelPT::CommandOptions::SetOptionValue(
return error;
}
-void CommandObjectTraceStartIntelPT::CommandOptions::OptionParsingStarting(
- ExecutionContext *execution_context) {
- m_size_in_kb = 4;
- m_custom_config = 0;
+void CommandObjectThreadTraceStartIntelPT::CommandOptions::
+ OptionParsingStarting(ExecutionContext *execution_context) {
+ m_thread_buffer_size = kDefaultThreadBufferSize;
+ m_enable_tsc = kDefaultEnableTscValue;
+ m_psb_period = kDefaultPsbPeriod;
}
llvm::ArrayRef<OptionDefinition>
-CommandObjectTraceStartIntelPT::CommandOptions::GetDefinitions() {
+CommandObjectThreadTraceStartIntelPT::CommandOptions::GetDefinitions() {
return llvm::makeArrayRef(g_thread_trace_start_intel_pt_options);
}
-bool CommandObjectTraceStartIntelPT::HandleOneThread(
- lldb::tid_t tid, CommandReturnObject &result) {
- result.AppendMessageWithFormat(
- "would trace tid %" PRIu64 " with size_in_kb %zu and custom_config %d\n",
- tid, m_options.m_size_in_kb, m_options.m_custom_config);
- result.SetStatus(eReturnStatusSuccessFinishResult);
+bool CommandObjectThreadTraceStartIntelPT::DoExecuteOnThreads(
+ Args &command, CommandReturnObject &result,
+ llvm::ArrayRef<lldb::tid_t> tids) {
+ if (Error err = m_trace.Start(tids, m_options.m_thread_buffer_size,
+ m_options.m_enable_tsc, m_options.m_psb_period))
+ result.SetError(Status(std::move(err)));
+ else
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+
+ return result.Succeeded();
+}
+
+/// CommandObjectProcessTraceStartIntelPT
+
+#define LLDB_OPTIONS_process_trace_start_intel_pt
+#include "TraceIntelPTCommandOptions.inc"
+
+Status CommandObjectProcessTraceStartIntelPT::CommandOptions::SetOptionValue(
+ uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) {
+ Status error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 's': {
+ int64_t thread_buffer_size;
+ if (option_arg.empty() || option_arg.getAsInteger(0, thread_buffer_size) ||
+ thread_buffer_size < 0)
+ error.SetErrorStringWithFormat("invalid integer value for option '%s'",
+ option_arg.str().c_str());
+ else
+ m_thread_buffer_size = thread_buffer_size;
+ break;
+ }
+ case 'l': {
+ int64_t process_buffer_size_limit;
+ if (option_arg.empty() ||
+ option_arg.getAsInteger(0, process_buffer_size_limit) ||
+ process_buffer_size_limit < 0)
+ error.SetErrorStringWithFormat("invalid integer value for option '%s'",
+ option_arg.str().c_str());
+ else
+ m_process_buffer_size_limit = process_buffer_size_limit;
+ break;
+ }
+ case 't': {
+ m_enable_tsc = true;
+ break;
+ }
+ case 'p': {
+ int64_t psb_period;
+ if (option_arg.empty() || option_arg.getAsInteger(0, psb_period) ||
+ psb_period < 0)
+ error.SetErrorStringWithFormat("invalid integer value for option '%s'",
+ option_arg.str().c_str());
+ else
+ m_psb_period = psb_period;
+ break;
+ }
+ default:
+ llvm_unreachable("Unimplemented option");
+ }
+ return error;
+}
+
+void CommandObjectProcessTraceStartIntelPT::CommandOptions::
+ OptionParsingStarting(ExecutionContext *execution_context) {
+ m_thread_buffer_size = kDefaultThreadBufferSize;
+ m_process_buffer_size_limit = kDefaultProcessBufferSizeLimit;
+ m_enable_tsc = kDefaultEnableTscValue;
+ m_psb_period = kDefaultPsbPeriod;
+}
+
+llvm::ArrayRef<OptionDefinition>
+CommandObjectProcessTraceStartIntelPT::CommandOptions::GetDefinitions() {
+ return llvm::makeArrayRef(g_process_trace_start_intel_pt_options);
+}
+
+bool CommandObjectProcessTraceStartIntelPT::DoExecute(
+ Args &command, CommandReturnObject &result) {
+ if (Error err = m_trace.Start(m_options.m_thread_buffer_size,
+ m_options.m_process_buffer_size_limit,
+ m_options.m_enable_tsc, m_options.m_psb_period))
+ result.SetError(Status(std::move(err)));
+ else
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+
return result.Succeeded();
}
diff --git a/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h b/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h
index 265569c553fa..2f3d53a86406 100644
--- a/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h
+++ b/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h
@@ -9,21 +9,21 @@
#ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_COMMANDOBJECTTRACESTARTINTELPT_H
#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_COMMANDOBJECTTRACESTARTINTELPT_H
-#include "../../../../source/Commands/CommandObjectThreadUtil.h"
+#include "../../../../source/Commands/CommandObjectTrace.h"
+#include "TraceIntelPT.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
namespace lldb_private {
namespace trace_intel_pt {
-class CommandObjectTraceStartIntelPT : public CommandObjectIterateOverThreads {
+class CommandObjectThreadTraceStartIntelPT
+ : public CommandObjectMultipleThreads {
public:
class CommandOptions : public Options {
public:
CommandOptions() : Options() { OptionParsingStarting(nullptr); }
- ~CommandOptions() override = default;
-
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
ExecutionContext *execution_context) override;
@@ -31,31 +31,76 @@ public:
llvm::ArrayRef<OptionDefinition> GetDefinitions() override;
- size_t m_size_in_kb;
- uint32_t m_custom_config;
+ size_t m_thread_buffer_size;
+ bool m_enable_tsc;
+ llvm::Optional<size_t> m_psb_period;
};
- CommandObjectTraceStartIntelPT(CommandInterpreter &interpreter)
- : CommandObjectIterateOverThreads(
+ CommandObjectThreadTraceStartIntelPT(TraceIntelPT &trace,
+ CommandInterpreter &interpreter)
+ : CommandObjectMultipleThreads(
interpreter, "thread trace start",
"Start tracing one or more threads with intel-pt. "
"Defaults to the current thread. Thread indices can be "
"specified as arguments.\n Use the thread-index \"all\" to trace "
- "all threads.",
+ "all threads including future threads.",
"thread trace start [<thread-index> <thread-index> ...] "
"[<intel-pt-options>]",
lldb::eCommandRequiresProcess | lldb::eCommandTryTargetAPILock |
lldb::eCommandProcessMustBeLaunched |
lldb::eCommandProcessMustBePaused),
- m_options() {}
+ m_trace(trace), m_options() {}
+
+ Options *GetOptions() override { return &m_options; }
+
+protected:
+ bool DoExecuteOnThreads(Args &command, CommandReturnObject &result,
+ llvm::ArrayRef<lldb::tid_t> tids) override;
+
+ TraceIntelPT &m_trace;
+ CommandOptions m_options;
+};
+
+class CommandObjectProcessTraceStartIntelPT : public CommandObjectParsed {
+public:
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options() { OptionParsingStarting(nullptr); }
- ~CommandObjectTraceStartIntelPT() override = default;
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override;
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override;
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override;
+
+ size_t m_thread_buffer_size;
+ size_t m_process_buffer_size_limit;
+ bool m_enable_tsc;
+ llvm::Optional<size_t> m_psb_period;
+ };
+
+ CommandObjectProcessTraceStartIntelPT(TraceIntelPT &trace,
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "process trace start",
+ "Start tracing this process with intel-pt, including future "
+ "threads. "
+ "This is implemented by tracing each thread independently. "
+ "Threads traced with the \"thread trace start\" command are left "
+ "unaffected ant not retraced.",
+ "process trace start [<intel-pt-options>]",
+ lldb::eCommandRequiresProcess | lldb::eCommandTryTargetAPILock |
+ lldb::eCommandProcessMustBeLaunched |
+ lldb::eCommandProcessMustBePaused),
+ m_trace(trace), m_options() {}
Options *GetOptions() override { return &m_options; }
protected:
- bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override;
+ bool DoExecute(Args &command, CommandReturnObject &result) override;
+ TraceIntelPT &m_trace;
CommandOptions m_options;
};
diff --git a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp
index 6b8b06564052..4822a786c68c 100644
--- a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp
+++ b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp
@@ -8,8 +8,13 @@
#include "DecodedThread.h"
+#include <intel-pt.h>
+#include <memory>
+
+#include "TraceCursorIntelPT.h"
#include "lldb/Utility/StreamString.h"
+using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::trace_intel_pt;
using namespace llvm;
@@ -30,12 +35,21 @@ void IntelPTError::log(llvm::raw_ostream &OS) const {
OS << "error: " << libipt_error_message;
}
+IntelPTInstruction::IntelPTInstruction(llvm::Error err) {
+ llvm::handleAllErrors(std::move(err),
+ [&](std::unique_ptr<llvm::ErrorInfoBase> info) {
+ m_error = std::move(info);
+ });
+ m_pt_insn.ip = LLDB_INVALID_ADDRESS;
+ m_pt_insn.iclass = ptic_error;
+}
+
bool IntelPTInstruction::IsError() const { return (bool)m_error; }
-Expected<lldb::addr_t> IntelPTInstruction::GetLoadAddress() const {
- if (IsError())
- return ToError();
- return m_pt_insn.ip;
+lldb::addr_t IntelPTInstruction::GetLoadAddress() const { return m_pt_insn.ip; }
+
+Optional<uint64_t> IntelPTInstruction::GetTimestampCounter() const {
+ return m_timestamp;
}
Error IntelPTInstruction::ToError() const {
@@ -47,18 +61,58 @@ Error IntelPTInstruction::ToError() const {
return make_error<StringError>(m_error->message(),
m_error->convertToErrorCode());
}
+size_t DecodedThread::GetRawTraceSize() const { return m_raw_trace_size; }
+
+TraceInstructionControlFlowType
+IntelPTInstruction::GetControlFlowType(lldb::addr_t next_load_address) const {
+ if (IsError())
+ return (TraceInstructionControlFlowType)0;
-size_t DecodedThread::GetLastPosition() const {
- return m_instructions.empty() ? 0 : m_instructions.size() - 1;
+ TraceInstructionControlFlowType mask =
+ eTraceInstructionControlFlowTypeInstruction;
+
+ switch (m_pt_insn.iclass) {
+ case ptic_cond_jump:
+ case ptic_jump:
+ case ptic_far_jump:
+ mask |= eTraceInstructionControlFlowTypeBranch;
+ if (m_pt_insn.ip + m_pt_insn.size != next_load_address)
+ mask |= eTraceInstructionControlFlowTypeTakenBranch;
+ break;
+ case ptic_return:
+ case ptic_far_return:
+ mask |= eTraceInstructionControlFlowTypeReturn;
+ break;
+ case ptic_call:
+ case ptic_far_call:
+ mask |= eTraceInstructionControlFlowTypeCall;
+ break;
+ default:
+ break;
+ }
+
+ return mask;
}
ArrayRef<IntelPTInstruction> DecodedThread::GetInstructions() const {
return makeArrayRef(m_instructions);
}
-size_t DecodedThread::GetCursorPosition() const { return m_position; }
+DecodedThread::DecodedThread(ThreadSP thread_sp, Error error)
+ : m_thread_sp(thread_sp) {
+ m_instructions.emplace_back(std::move(error));
+}
+
+DecodedThread::DecodedThread(ThreadSP thread_sp,
+ std::vector<IntelPTInstruction> &&instructions,
+ size_t raw_trace_size)
+ : m_thread_sp(thread_sp), m_instructions(std::move(instructions)),
+ m_raw_trace_size(raw_trace_size) {
+ if (m_instructions.empty())
+ m_instructions.emplace_back(
+ createStringError(inconvertibleErrorCode(), "empty trace"));
+}
-size_t DecodedThread::SetCursorPosition(size_t new_position) {
- m_position = std::min(new_position, GetLastPosition());
- return m_position;
+lldb::TraceCursorUP DecodedThread::GetCursor() {
+ return std::make_unique<TraceCursorIntelPT>(m_thread_sp, shared_from_this());
}
diff --git a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h
index 3c7e030414cb..592c402cd0e5 100644
--- a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h
+++ b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h
@@ -15,6 +15,7 @@
#include "llvm/Support/Error.h"
#include "lldb/Target/Trace.h"
+#include "lldb/Utility/TraceIntelPTGDBRemotePackets.h"
#include "intel-pt.h"
@@ -60,17 +61,15 @@ private:
/// As mentioned, any gap is represented as an error in this class.
class IntelPTInstruction {
public:
+ IntelPTInstruction(const pt_insn &pt_insn, uint64_t timestamp)
+ : m_pt_insn(pt_insn), m_timestamp(timestamp) {}
+
IntelPTInstruction(const pt_insn &pt_insn) : m_pt_insn(pt_insn) {}
/// Error constructor
///
/// libipt errors should use the underlying \a IntelPTError class.
- IntelPTInstruction(llvm::Error err) {
- llvm::handleAllErrors(std::move(err),
- [&](std::unique_ptr<llvm::ErrorInfoBase> info) {
- m_error = std::move(info);
- });
- }
+ IntelPTInstruction(llvm::Error err);
/// Check if this object represents an error (i.e. a gap).
///
@@ -79,15 +78,34 @@ public:
bool IsError() const;
/// \return
- /// The instruction pointer address, or an \a llvm::Error if it is an
- /// error.
- llvm::Expected<lldb::addr_t> GetLoadAddress() const;
+ /// The instruction pointer address, or \a LLDB_INVALID_ADDRESS if it is
+ /// an error.
+ lldb::addr_t GetLoadAddress() const;
/// \return
/// An \a llvm::Error object if this class corresponds to an Error, or an
/// \a llvm::Error::success otherwise.
llvm::Error ToError() const;
+ /// Get the timestamp associated with the current instruction. The timestamp
+ /// is similar to what a rdtsc instruction would return.
+ ///
+ /// \return
+ /// The timestamp or \b llvm::None if not available.
+ llvm::Optional<uint64_t> GetTimestampCounter() const;
+
+ /// Get the \a lldb::TraceInstructionControlFlowType categories of the
+ /// instruction.
+ ///
+ /// \param[in] next_load_address
+ /// The address of the next instruction in the trace or \b
+ /// LLDB_INVALID_ADDRESS if not available.
+ ///
+ /// \return
+ /// The control flow categories, or \b 0 if the instruction is an error.
+ lldb::TraceInstructionControlFlowType
+ GetControlFlowType(lldb::addr_t next_load_address) const;
+
IntelPTInstruction(IntelPTInstruction &&other) = default;
private:
@@ -95,6 +113,7 @@ private:
const IntelPTInstruction &operator=(const IntelPTInstruction &other) = delete;
pt_insn m_pt_insn;
+ llvm::Optional<uint64_t> m_timestamp;
std::unique_ptr<llvm::ErrorInfoBase> m_error;
};
@@ -105,11 +124,15 @@ private:
///
/// Each decoded thread contains a cursor to the current position the user is
/// stopped at. See \a Trace::GetCursorPosition for more information.
-class DecodedThread {
+class DecodedThread : public std::enable_shared_from_this<DecodedThread> {
public:
- DecodedThread(std::vector<IntelPTInstruction> &&instructions)
- : m_instructions(std::move(instructions)), m_position(GetLastPosition()) {
- }
+ DecodedThread(lldb::ThreadSP thread_sp,
+ std::vector<IntelPTInstruction> &&instructions,
+ size_t raw_trace_size);
+
+ /// Constructor with a single error signaling a complete failure of the
+ /// decoding process.
+ DecodedThread(lldb::ThreadSP thread_sp, llvm::Error error);
/// Get the instructions from the decoded trace. Some of them might indicate
/// errors (i.e. gaps) in the trace.
@@ -118,28 +141,23 @@ public:
/// The instructions of the trace.
llvm::ArrayRef<IntelPTInstruction> GetInstructions() const;
- /// \return
- /// The current position of the cursor of this trace, or 0 if there are no
- /// instructions.
- size_t GetCursorPosition() const;
+ /// Get a new cursor for the decoded thread.
+ lldb::TraceCursorUP GetCursor();
- /// Change the position of the cursor of this trace. If this value is to high,
- /// the new position will be set as the last instruction of the trace.
+ /// Get the size in bytes of the corresponding Intel PT raw trace
///
/// \return
- /// The effective new position.
- size_t SetCursorPosition(size_t new_position);
- /// \}
+ /// The size of the trace.
+ size_t GetRawTraceSize() const;
private:
- /// \return
- /// The index of the last element of the trace, or 0 if empty.
- size_t GetLastPosition() const;
-
+ lldb::ThreadSP m_thread_sp;
std::vector<IntelPTInstruction> m_instructions;
- size_t m_position;
+ size_t m_raw_trace_size;
};
+using DecodedThreadSP = std::shared_ptr<DecodedThread>;
+
} // namespace trace_intel_pt
} // namespace lldb_private
diff --git a/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp b/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp
index b6e8ae808632..3827881454c7 100644
--- a/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp
+++ b/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp
@@ -1,5 +1,4 @@
-//===-- IntelPTDecoder.cpp --------------------------------------*- C++ -*-===//
-//
+//===-- IntelPTDecoder.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
@@ -10,10 +9,13 @@
#include "llvm/Support/MemoryBuffer.h"
+#include "../common/ThreadPostMortemTrace.h"
+#include "DecodedThread.h"
+#include "TraceIntelPT.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Target/Target.h"
-#include "lldb/Target/ThreadTrace.h"
+#include "lldb/Utility/StringExtractor.h"
using namespace lldb;
using namespace lldb_private;
@@ -85,7 +87,7 @@ static int ProcessPTEvents(pt_insn_decoder &decoder, int errcode) {
return errcode;
}
return 0;
-};
+}
/// Decode all the instructions from a configured decoder.
/// The decoding flow is based on
@@ -135,7 +137,23 @@ DecodeInstructions(pt_insn_decoder &decoder) {
break;
}
- instructions.emplace_back(insn);
+ uint64_t time;
+ int time_error = pt_insn_time(&decoder, &time, nullptr, nullptr);
+ if (time_error == -pte_invalid) {
+ // This happens if we invoke the pt_insn_time method incorrectly,
+ // but the instruction is good though.
+ instructions.emplace_back(
+ make_error<IntelPTError>(time_error, insn.ip));
+ instructions.emplace_back(insn);
+ break;
+ }
+ if (time_error == -pte_no_time) {
+ // We simply don't have time information, i.e. None of TSC, MTC or CYC
+ // was enabled.
+ instructions.emplace_back(insn);
+ } else {
+ instructions.emplace_back(insn, time);
+ }
}
}
@@ -158,39 +176,26 @@ static int ReadProcessMemory(uint8_t *buffer, size_t size,
return bytes_read;
}
-static std::vector<IntelPTInstruction> makeInstructionListFromError(Error err) {
- std::vector<IntelPTInstruction> instructions;
- instructions.emplace_back(std::move(err));
- return instructions;
-}
-
-static std::vector<IntelPTInstruction>
-CreateDecoderAndDecode(Process &process, const pt_cpu &pt_cpu,
- const FileSpec &trace_file) {
- ErrorOr<std::unique_ptr<MemoryBuffer>> trace_or_error =
- MemoryBuffer::getFile(trace_file.GetPath());
- if (std::error_code err = trace_or_error.getError())
- return makeInstructionListFromError(errorCodeToError(err));
-
- MemoryBuffer &trace = **trace_or_error;
+static Expected<std::vector<IntelPTInstruction>>
+DecodeInMemoryTrace(Process &process, TraceIntelPT &trace_intel_pt,
+ MutableArrayRef<uint8_t> buffer) {
+ Expected<pt_cpu> cpu_info = trace_intel_pt.GetCPUInfo();
+ if (!cpu_info)
+ return cpu_info.takeError();
pt_config config;
pt_config_init(&config);
- config.cpu = pt_cpu;
+ config.cpu = *cpu_info;
if (int errcode = pt_cpu_errata(&config.errata, &config.cpu))
- return makeInstructionListFromError(make_error<IntelPTError>(errcode));
+ return make_error<IntelPTError>(errcode);
- // The libipt library does not modify the trace buffer, hence the following
- // cast is safe.
- config.begin =
- reinterpret_cast<uint8_t *>(const_cast<char *>(trace.getBufferStart()));
- config.end =
- reinterpret_cast<uint8_t *>(const_cast<char *>(trace.getBufferEnd()));
+ config.begin = buffer.data();
+ config.end = buffer.data() + buffer.size();
pt_insn_decoder *decoder = pt_insn_alloc_decoder(&config);
if (!decoder)
- return makeInstructionListFromError(make_error<IntelPTError>(-pte_nomem));
+ return make_error<IntelPTError>(-pte_nomem);
pt_image *image = pt_insn_get_image(decoder);
@@ -204,12 +209,71 @@ CreateDecoderAndDecode(Process &process, const pt_cpu &pt_cpu,
return instructions;
}
-const DecodedThread &ThreadTraceDecoder::Decode() {
- if (!m_decoded_thread.hasValue()) {
- m_decoded_thread = DecodedThread(
- CreateDecoderAndDecode(*m_trace_thread->GetProcess(), m_pt_cpu,
- m_trace_thread->GetTraceFile()));
- }
+static Expected<std::vector<IntelPTInstruction>>
+DecodeTraceFile(Process &process, TraceIntelPT &trace_intel_pt,
+ const FileSpec &trace_file, size_t &raw_trace_size) {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> trace_or_error =
+ MemoryBuffer::getFile(trace_file.GetPath());
+ if (std::error_code err = trace_or_error.getError())
+ return errorCodeToError(err);
+ MemoryBuffer &trace = **trace_or_error;
+ MutableArrayRef<uint8_t> trace_data(
+ // The libipt library does not modify the trace buffer, hence the
+ // following cast is safe.
+ reinterpret_cast<uint8_t *>(const_cast<char *>(trace.getBufferStart())),
+ trace.getBufferSize());
+ raw_trace_size = trace_data.size();
+ return DecodeInMemoryTrace(process, trace_intel_pt, trace_data);
+}
+
+static Expected<std::vector<IntelPTInstruction>>
+DecodeLiveThread(Thread &thread, TraceIntelPT &trace, size_t &raw_trace_size) {
+ Expected<std::vector<uint8_t>> buffer =
+ trace.GetLiveThreadBuffer(thread.GetID());
+ if (!buffer)
+ return buffer.takeError();
+ raw_trace_size = buffer->size();
+ if (Expected<pt_cpu> cpu_info = trace.GetCPUInfo())
+ return DecodeInMemoryTrace(*thread.GetProcess(), trace,
+ MutableArrayRef<uint8_t>(*buffer));
+ else
+ return cpu_info.takeError();
+}
+
+DecodedThreadSP ThreadDecoder::Decode() {
+ if (!m_decoded_thread.hasValue())
+ m_decoded_thread = DoDecode();
return *m_decoded_thread;
}
+
+PostMortemThreadDecoder::PostMortemThreadDecoder(
+ const lldb::ThreadPostMortemTraceSP &trace_thread, TraceIntelPT &trace)
+ : m_trace_thread(trace_thread), m_trace(trace) {}
+
+DecodedThreadSP PostMortemThreadDecoder::DoDecode() {
+ size_t raw_trace_size = 0;
+ if (Expected<std::vector<IntelPTInstruction>> instructions =
+ DecodeTraceFile(*m_trace_thread->GetProcess(), m_trace,
+ m_trace_thread->GetTraceFile(), raw_trace_size))
+ return std::make_shared<DecodedThread>(m_trace_thread->shared_from_this(),
+ std::move(*instructions),
+ raw_trace_size);
+ else
+ return std::make_shared<DecodedThread>(m_trace_thread->shared_from_this(),
+ instructions.takeError());
+}
+
+LiveThreadDecoder::LiveThreadDecoder(Thread &thread, TraceIntelPT &trace)
+ : m_thread_sp(thread.shared_from_this()), m_trace(trace) {}
+
+DecodedThreadSP LiveThreadDecoder::DoDecode() {
+ size_t raw_trace_size = 0;
+ if (Expected<std::vector<IntelPTInstruction>> instructions =
+ DecodeLiveThread(*m_thread_sp, m_trace, raw_trace_size))
+ return std::make_shared<DecodedThread>(
+ m_thread_sp, std::move(*instructions), raw_trace_size);
+ else
+ return std::make_shared<DecodedThread>(m_thread_sp,
+ instructions.takeError());
+}
diff --git a/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.h b/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.h
index 2e67f9bf6da7..e969db579e52 100644
--- a/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.h
+++ b/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.h
@@ -12,38 +12,73 @@
#include "intel-pt.h"
#include "DecodedThread.h"
+#include "forward-declarations.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/FileSpec.h"
namespace lldb_private {
namespace trace_intel_pt {
-/// \a lldb_private::ThreadTrace decoder that stores the output from decoding,
-/// avoiding recomputations, as decoding is expensive.
-class ThreadTraceDecoder {
+/// Base class that handles the decoding of a thread and caches the result.
+class ThreadDecoder {
public:
- /// \param[in] trace_thread
- /// The thread whose trace file will be decoded.
+ virtual ~ThreadDecoder() = default;
+
+ ThreadDecoder() = default;
+
+ /// Decode the thread and store the result internally, to avoid
+ /// recomputations.
///
- /// \param[in] pt_cpu
- /// The libipt cpu used when recording the trace.
- ThreadTraceDecoder(const std::shared_ptr<ThreadTrace> &trace_thread,
- const pt_cpu &pt_cpu)
- : m_trace_thread(trace_thread), m_pt_cpu(pt_cpu), m_decoded_thread() {}
+ /// \return
+ /// A \a DecodedThread instance.
+ DecodedThreadSP Decode();
- /// Decode the thread and store the result internally.
+ ThreadDecoder(const ThreadDecoder &other) = delete;
+ ThreadDecoder &operator=(const ThreadDecoder &other) = delete;
+
+protected:
+ /// Decode the thread.
///
/// \return
/// A \a DecodedThread instance.
- const DecodedThread &Decode();
+ virtual DecodedThreadSP DoDecode() = 0;
+
+ llvm::Optional<DecodedThreadSP> m_decoded_thread;
+};
+
+/// Decoder implementation for \a lldb_private::ThreadPostMortemTrace, which are
+/// non-live processes that come trace session files.
+class PostMortemThreadDecoder : public ThreadDecoder {
+public:
+ /// \param[in] trace_thread
+ /// The thread whose trace file will be decoded.
+ ///
+ /// \param[in] trace
+ /// The main Trace object who owns this decoder and its data.
+ PostMortemThreadDecoder(const lldb::ThreadPostMortemTraceSP &trace_thread,
+ TraceIntelPT &trace);
+
+private:
+ DecodedThreadSP DoDecode() override;
+
+ lldb::ThreadPostMortemTraceSP m_trace_thread;
+ TraceIntelPT &m_trace;
+};
+
+class LiveThreadDecoder : public ThreadDecoder {
+public:
+ /// \param[in] thread
+ /// The thread whose traces will be decoded.
+ ///
+ /// \param[in] trace
+ /// The main Trace object who owns this decoder and its data.
+ LiveThreadDecoder(Thread &thread, TraceIntelPT &trace);
private:
- ThreadTraceDecoder(const ThreadTraceDecoder &other) = delete;
- ThreadTraceDecoder &operator=(const ThreadTraceDecoder &other) = delete;
+ DecodedThreadSP DoDecode() override;
- std::shared_ptr<ThreadTrace> m_trace_thread;
- pt_cpu m_pt_cpu;
- llvm::Optional<DecodedThread> m_decoded_thread;
+ lldb::ThreadSP m_thread_sp;
+ TraceIntelPT &m_trace;
};
} // namespace trace_intel_pt
diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp b/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp
new file mode 100644
index 000000000000..edefdd0d3486
--- /dev/null
+++ b/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp
@@ -0,0 +1,100 @@
+//===-- TraceCursorIntelPT.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 "TraceCursorIntelPT.h"
+#include "DecodedThread.h"
+#include "TraceIntelPT.h"
+
+#include <cstdlib>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::trace_intel_pt;
+using namespace llvm;
+
+TraceCursorIntelPT::TraceCursorIntelPT(ThreadSP thread_sp,
+ DecodedThreadSP decoded_thread_sp)
+ : TraceCursor(thread_sp), m_decoded_thread_sp(decoded_thread_sp) {
+ assert(!m_decoded_thread_sp->GetInstructions().empty() &&
+ "a trace should have at least one instruction or error");
+ m_pos = m_decoded_thread_sp->GetInstructions().size() - 1;
+}
+
+size_t TraceCursorIntelPT::GetInternalInstructionSize() {
+ return m_decoded_thread_sp->GetInstructions().size();
+}
+
+bool TraceCursorIntelPT::Next() {
+ auto canMoveOne = [&]() {
+ if (IsForwards())
+ return m_pos + 1 < GetInternalInstructionSize();
+ return m_pos > 0;
+ };
+
+ size_t initial_pos = m_pos;
+
+ while (canMoveOne()) {
+ m_pos += IsForwards() ? 1 : -1;
+ if (!m_ignore_errors && IsError())
+ return true;
+ if (GetInstructionControlFlowType() & m_granularity)
+ return true;
+ }
+
+ // Didn't find any matching instructions
+ m_pos = initial_pos;
+ return false;
+}
+
+size_t TraceCursorIntelPT::Seek(int64_t offset, SeekType origin) {
+ int64_t last_index = GetInternalInstructionSize() - 1;
+
+ auto fitPosToBounds = [&](int64_t raw_pos) -> int64_t {
+ return std::min(std::max((int64_t)0, raw_pos), last_index);
+ };
+
+ switch (origin) {
+ case TraceCursor::SeekType::Set:
+ m_pos = fitPosToBounds(offset);
+ return m_pos;
+ case TraceCursor::SeekType::End:
+ m_pos = fitPosToBounds(offset + last_index);
+ return last_index - m_pos;
+ case TraceCursor::SeekType::Current:
+ int64_t new_pos = fitPosToBounds(offset + m_pos);
+ int64_t dist = m_pos - new_pos;
+ m_pos = new_pos;
+ return std::abs(dist);
+ }
+}
+
+bool TraceCursorIntelPT::IsError() {
+ return m_decoded_thread_sp->GetInstructions()[m_pos].IsError();
+}
+
+Error TraceCursorIntelPT::GetError() {
+ return m_decoded_thread_sp->GetInstructions()[m_pos].ToError();
+}
+
+lldb::addr_t TraceCursorIntelPT::GetLoadAddress() {
+ return m_decoded_thread_sp->GetInstructions()[m_pos].GetLoadAddress();
+}
+
+Optional<uint64_t> TraceCursorIntelPT::GetTimestampCounter() {
+ return m_decoded_thread_sp->GetInstructions()[m_pos].GetTimestampCounter();
+}
+
+TraceInstructionControlFlowType
+TraceCursorIntelPT::GetInstructionControlFlowType() {
+ lldb::addr_t next_load_address =
+ m_pos + 1 < GetInternalInstructionSize()
+ ? m_decoded_thread_sp->GetInstructions()[m_pos + 1].GetLoadAddress()
+ : LLDB_INVALID_ADDRESS;
+ return m_decoded_thread_sp->GetInstructions()[m_pos].GetControlFlowType(
+ next_load_address);
+}
diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h b/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h
new file mode 100644
index 000000000000..29d3792bb489
--- /dev/null
+++ b/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h
@@ -0,0 +1,50 @@
+//===-- TraceCursorIntelPT.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_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACECURSORINTELPT_H
+#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACECURSORINTELPT_H
+
+#include "IntelPTDecoder.h"
+#include "TraceIntelPTSessionFileParser.h"
+
+namespace lldb_private {
+namespace trace_intel_pt {
+
+class TraceCursorIntelPT : public TraceCursor {
+public:
+ TraceCursorIntelPT(lldb::ThreadSP thread_sp,
+ DecodedThreadSP decoded_thread_sp);
+
+ size_t Seek(int64_t offset, SeekType origin) override;
+
+ virtual bool Next() override;
+
+ llvm::Error GetError() override;
+
+ lldb::addr_t GetLoadAddress() override;
+
+ llvm::Optional<uint64_t> GetTimestampCounter() override;
+
+ lldb::TraceInstructionControlFlowType
+ GetInstructionControlFlowType() override;
+
+ bool IsError() override;
+
+private:
+ size_t GetInternalInstructionSize();
+
+ /// Storage of the actual instructions
+ DecodedThreadSP m_decoded_thread_sp;
+ /// Internal instruction index currently pointing at.
+ size_t m_pos;
+};
+
+} // namespace trace_intel_pt
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACECURSORINTELPT_H
diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
index 63a8b2dff4a7..c12bcd3523e3 100644
--- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
+++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
@@ -8,12 +8,14 @@
#include "TraceIntelPT.h"
+#include "../common/ThreadPostMortemTrace.h"
#include "CommandObjectTraceStartIntelPT.h"
+#include "DecodedThread.h"
+#include "TraceIntelPTConstants.h"
#include "TraceIntelPTSessionFileParser.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
-#include "lldb/Target/ThreadTrace.h"
using namespace lldb;
using namespace lldb_private;
@@ -22,18 +24,27 @@ using namespace llvm;
LLDB_PLUGIN_DEFINE(TraceIntelPT)
-CommandObjectSP GetStartCommand(CommandInterpreter &interpreter) {
- return CommandObjectSP(new CommandObjectTraceStartIntelPT(interpreter));
+lldb::CommandObjectSP
+TraceIntelPT::GetProcessTraceStartCommand(CommandInterpreter &interpreter) {
+ return CommandObjectSP(
+ new CommandObjectProcessTraceStartIntelPT(*this, interpreter));
+}
+
+lldb::CommandObjectSP
+TraceIntelPT::GetThreadTraceStartCommand(CommandInterpreter &interpreter) {
+ return CommandObjectSP(
+ new CommandObjectThreadTraceStartIntelPT(*this, interpreter));
}
void TraceIntelPT::Initialize() {
- PluginManager::RegisterPlugin(
- GetPluginNameStatic(), "Intel Processor Trace", CreateInstance,
- TraceIntelPTSessionFileParser::GetSchema(), GetStartCommand);
+ PluginManager::RegisterPlugin(GetPluginNameStatic(), "Intel Processor Trace",
+ CreateInstanceForSessionFile,
+ CreateInstanceForLiveProcess,
+ TraceIntelPTSessionFileParser::GetSchema());
}
void TraceIntelPT::Terminate() {
- PluginManager::UnregisterPlugin(CreateInstance);
+ PluginManager::UnregisterPlugin(CreateInstanceForSessionFile);
}
ConstString TraceIntelPT::GetPluginNameStatic() {
@@ -55,60 +66,278 @@ uint32_t TraceIntelPT::GetPluginVersion() { return 1; }
void TraceIntelPT::Dump(Stream *s) const {}
-Expected<TraceSP>
-TraceIntelPT::CreateInstance(const json::Value &trace_session_file,
- StringRef session_file_dir, Debugger &debugger) {
+Expected<TraceSP> TraceIntelPT::CreateInstanceForSessionFile(
+ const json::Value &trace_session_file, StringRef session_file_dir,
+ Debugger &debugger) {
return TraceIntelPTSessionFileParser(debugger, trace_session_file,
session_file_dir)
.Parse();
}
+Expected<TraceSP> TraceIntelPT::CreateInstanceForLiveProcess(Process &process) {
+ TraceSP instance(new TraceIntelPT(process));
+ process.GetTarget().SetTrace(instance);
+ return instance;
+}
+
TraceIntelPT::TraceIntelPT(
- const pt_cpu &pt_cpu,
- const std::vector<std::shared_ptr<ThreadTrace>> &traced_threads)
- : m_pt_cpu(pt_cpu) {
- for (const std::shared_ptr<ThreadTrace> &thread : traced_threads)
- m_trace_threads.emplace(
- std::piecewise_construct,
- std::forward_as_tuple(thread->GetProcess()->GetID(), thread->GetID()),
- std::forward_as_tuple(thread, pt_cpu));
+ const pt_cpu &cpu_info,
+ const std::vector<ThreadPostMortemTraceSP> &traced_threads)
+ : m_cpu_info(cpu_info) {
+ for (const ThreadPostMortemTraceSP &thread : traced_threads)
+ m_thread_decoders.emplace(
+ thread.get(), std::make_unique<PostMortemThreadDecoder>(thread, *this));
+}
+
+DecodedThreadSP TraceIntelPT::Decode(Thread &thread) {
+ RefreshLiveProcessState();
+ if (m_live_refresh_error.hasValue())
+ return std::make_shared<DecodedThread>(
+ thread.shared_from_this(),
+ createStringError(inconvertibleErrorCode(), *m_live_refresh_error));
+
+ auto it = m_thread_decoders.find(&thread);
+ if (it == m_thread_decoders.end())
+ return std::make_shared<DecodedThread>(
+ thread.shared_from_this(),
+ createStringError(inconvertibleErrorCode(), "thread not traced"));
+ return it->second->Decode();
+}
+
+lldb::TraceCursorUP TraceIntelPT::GetCursor(Thread &thread) {
+ return Decode(thread)->GetCursor();
+}
+
+void TraceIntelPT::DumpTraceInfo(Thread &thread, Stream &s, bool verbose) {
+ Optional<size_t> raw_size = GetRawTraceSize(thread);
+ s.Printf("\nthread #%u: tid = %" PRIu64, thread.GetIndexID(), thread.GetID());
+ if (!raw_size) {
+ s.Printf(", not traced\n");
+ return;
+ }
+ s.Printf("\n Raw trace size: %zu bytes\n", *raw_size);
+ return;
+}
+
+Optional<size_t> TraceIntelPT::GetRawTraceSize(Thread &thread) {
+ if (IsTraced(thread))
+ return Decode(thread)->GetRawTraceSize();
+ else
+ return None;
}
-const DecodedThread *TraceIntelPT::Decode(const Thread &thread) {
- auto it = m_trace_threads.find(
- std::make_pair(thread.GetProcess()->GetID(), thread.GetID()));
- if (it == m_trace_threads.end())
- return nullptr;
- return &it->second.Decode();
+Expected<pt_cpu> TraceIntelPT::GetCPUInfoForLiveProcess() {
+ Expected<std::vector<uint8_t>> cpu_info = GetLiveProcessBinaryData("cpuInfo");
+ if (!cpu_info)
+ return cpu_info.takeError();
+
+ int64_t cpu_family = -1;
+ int64_t model = -1;
+ int64_t stepping = -1;
+ std::string vendor_id;
+
+ StringRef rest(reinterpret_cast<const char *>(cpu_info->data()),
+ cpu_info->size());
+ while (!rest.empty()) {
+ StringRef line;
+ std::tie(line, rest) = rest.split('\n');
+
+ SmallVector<StringRef, 2> columns;
+ line.split(columns, StringRef(":"), -1, false);
+
+ if (columns.size() < 2)
+ continue; // continue searching
+
+ columns[1] = columns[1].trim(" ");
+ if (columns[0].contains("cpu family") &&
+ columns[1].getAsInteger(10, cpu_family))
+ continue;
+
+ else if (columns[0].contains("model") && columns[1].getAsInteger(10, model))
+ continue;
+
+ else if (columns[0].contains("stepping") &&
+ columns[1].getAsInteger(10, stepping))
+ continue;
+
+ else if (columns[0].contains("vendor_id")) {
+ vendor_id = columns[1].str();
+ if (!vendor_id.empty())
+ continue;
+ }
+
+ if ((cpu_family != -1) && (model != -1) && (stepping != -1) &&
+ (!vendor_id.empty())) {
+ return pt_cpu{vendor_id == "GenuineIntel" ? pcv_intel : pcv_unknown,
+ static_cast<uint16_t>(cpu_family),
+ static_cast<uint8_t>(model),
+ static_cast<uint8_t>(stepping)};
+ }
+ }
+ return createStringError(inconvertibleErrorCode(),
+ "Failed parsing the target's /proc/cpuinfo file");
}
-size_t TraceIntelPT::GetCursorPosition(const Thread &thread) {
- const DecodedThread *decoded_thread = Decode(thread);
- if (!decoded_thread)
- return 0;
- return decoded_thread->GetCursorPosition();
+Expected<pt_cpu> TraceIntelPT::GetCPUInfo() {
+ if (!m_cpu_info) {
+ if (llvm::Expected<pt_cpu> cpu_info = GetCPUInfoForLiveProcess())
+ m_cpu_info = *cpu_info;
+ else
+ return cpu_info.takeError();
+ }
+ return *m_cpu_info;
}
-void TraceIntelPT::TraverseInstructions(
- const Thread &thread, size_t position, TraceDirection direction,
- std::function<bool(size_t index, Expected<lldb::addr_t> load_addr)>
- callback) {
- const DecodedThread *decoded_thread = Decode(thread);
- if (!decoded_thread)
+void TraceIntelPT::DoRefreshLiveProcessState(
+ Expected<TraceGetStateResponse> state) {
+ m_thread_decoders.clear();
+
+ if (!state) {
+ m_live_refresh_error = toString(state.takeError());
return;
+ }
- ArrayRef<IntelPTInstruction> instructions = decoded_thread->GetInstructions();
+ for (const TraceThreadState &thread_state : state->tracedThreads) {
+ Thread &thread =
+ *m_live_process->GetThreadList().FindThreadByID(thread_state.tid);
+ m_thread_decoders.emplace(
+ &thread, std::make_unique<LiveThreadDecoder>(thread, *this));
+ }
+}
- ssize_t delta = direction == TraceDirection::Forwards ? 1 : -1;
- for (ssize_t i = position; i < (ssize_t)instructions.size() && i >= 0;
- i += delta)
- if (!callback(i, instructions[i].GetLoadAddress()))
- break;
+bool TraceIntelPT::IsTraced(const Thread &thread) {
+ RefreshLiveProcessState();
+ return m_thread_decoders.count(&thread);
}
-size_t TraceIntelPT::GetInstructionCount(const Thread &thread) {
- if (const DecodedThread *decoded_thread = Decode(thread))
- return decoded_thread->GetInstructions().size();
- else
- return 0;
+// The information here should match the description of the intel-pt section
+// of the jLLDBTraceStart packet in the lldb/docs/lldb-gdb-remote.txt
+// documentation file. Similarly, it should match the CLI help messages of the
+// TraceIntelPTOptions.td file.
+const char *TraceIntelPT::GetStartConfigurationHelp() {
+ return R"(Parameters:
+
+ Note: If a parameter is not specified, a default value will be used.
+
+ - int threadBufferSize (defaults to 4096 bytes):
+ [process and thread tracing]
+ Trace size in bytes per thread. It must be a power of 2 greater
+ than or equal to 4096 (2^12). The trace is circular keeping the
+ the most recent data.
+
+ - boolean enableTsc (default to false):
+ [process and thread tracing]
+ Whether to use enable TSC timestamps or not. This is supported on
+ all devices that support intel-pt.
+
+ - psbPeriod (defaults to null):
+ [process and thread tracing]
+ This value defines the period in which PSB packets will be generated.
+ A PSB packet is a synchronization packet that contains a TSC
+ timestamp and the current absolute instruction pointer.
+
+ This parameter can only be used if
+
+ /sys/bus/event_source/devices/intel_pt/caps/psb_cyc
+
+ is 1. Otherwise, the PSB period will be defined by the processor.
+
+ If supported, valid values for this period can be found in
+
+ /sys/bus/event_source/devices/intel_pt/caps/psb_periods
+
+ which contains a hexadecimal number, whose bits represent
+ valid values e.g. if bit 2 is set, then value 2 is valid.
+
+ The psb_period value is converted to the approximate number of
+ raw trace bytes between PSB packets as:
+
+ 2 ^ (value + 11)
+
+ e.g. value 3 means 16KiB between PSB packets. Defaults to 0 if
+ supported.
+
+ - int processBufferSizeLimit (defaults to 500 MB):
+ [process tracing only]
+ Maximum total trace size per process in bytes. This limit applies
+ to the sum of the sizes of all thread traces of this process,
+ excluding the ones created explicitly with "thread tracing".
+ Whenever a thread is attempted to be traced due to this command
+ and the limit would be reached, the process is stopped with a
+ "processor trace" reason, so that the user can retrace the process
+ if needed.)";
+}
+
+Error TraceIntelPT::Start(size_t thread_buffer_size,
+ size_t total_buffer_size_limit, bool enable_tsc,
+ Optional<size_t> psb_period) {
+ TraceIntelPTStartRequest request;
+ request.threadBufferSize = thread_buffer_size;
+ request.processBufferSizeLimit = total_buffer_size_limit;
+ request.enableTsc = enable_tsc;
+ request.psbPeriod = psb_period.map([](size_t val) { return (int64_t)val; });
+ request.type = GetPluginName().AsCString();
+ return Trace::Start(toJSON(request));
+}
+
+Error TraceIntelPT::Start(StructuredData::ObjectSP configuration) {
+ size_t thread_buffer_size = kDefaultThreadBufferSize;
+ size_t process_buffer_size_limit = kDefaultProcessBufferSizeLimit;
+ bool enable_tsc = kDefaultEnableTscValue;
+ Optional<size_t> psb_period = kDefaultPsbPeriod;
+
+ if (configuration) {
+ if (StructuredData::Dictionary *dict = configuration->GetAsDictionary()) {
+ dict->GetValueForKeyAsInteger("threadBufferSize", thread_buffer_size);
+ dict->GetValueForKeyAsInteger("processBufferSizeLimit",
+ process_buffer_size_limit);
+ dict->GetValueForKeyAsBoolean("enableTsc", enable_tsc);
+ dict->GetValueForKeyAsInteger("psbPeriod", psb_period);
+ } else {
+ return createStringError(inconvertibleErrorCode(),
+ "configuration object is not a dictionary");
+ }
+ }
+
+ return Start(thread_buffer_size, process_buffer_size_limit, enable_tsc,
+ psb_period);
+}
+
+llvm::Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids,
+ size_t thread_buffer_size, bool enable_tsc,
+ Optional<size_t> psb_period) {
+ TraceIntelPTStartRequest request;
+ request.threadBufferSize = thread_buffer_size;
+ request.enableTsc = enable_tsc;
+ request.psbPeriod = psb_period.map([](size_t val) { return (int64_t)val; });
+ request.type = GetPluginName().AsCString();
+ request.tids.emplace();
+ for (lldb::tid_t tid : tids)
+ request.tids->push_back(tid);
+ return Trace::Start(toJSON(request));
+}
+
+Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids,
+ StructuredData::ObjectSP configuration) {
+ size_t thread_buffer_size = kDefaultThreadBufferSize;
+ bool enable_tsc = kDefaultEnableTscValue;
+ Optional<size_t> psb_period = kDefaultPsbPeriod;
+
+ if (configuration) {
+ if (StructuredData::Dictionary *dict = configuration->GetAsDictionary()) {
+ dict->GetValueForKeyAsInteger("threadBufferSize", thread_buffer_size);
+ dict->GetValueForKeyAsBoolean("enableTsc", enable_tsc);
+ dict->GetValueForKeyAsInteger("psbPeriod", psb_period);
+ } else {
+ return createStringError(inconvertibleErrorCode(),
+ "configuration object is not a dictionary");
+ }
+ }
+
+ return Start(tids, thread_buffer_size, enable_tsc, psb_period);
+}
+
+Expected<std::vector<uint8_t>>
+TraceIntelPT::GetLiveThreadBuffer(lldb::tid_t tid) {
+ return Trace::GetLiveThreadBinaryData(tid, "threadTraceBuffer");
}
diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
index 5058e6fd32f2..e3b247112ae1 100644
--- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
+++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
@@ -45,49 +45,134 @@ public:
/// \return
/// A trace instance or an error in case of failures.
static llvm::Expected<lldb::TraceSP>
- CreateInstance(const llvm::json::Value &trace_session_file,
- llvm::StringRef session_file_dir, Debugger &debugger);
+ CreateInstanceForSessionFile(const llvm::json::Value &trace_session_file,
+ llvm::StringRef session_file_dir,
+ Debugger &debugger);
+
+ static llvm::Expected<lldb::TraceSP>
+ CreateInstanceForLiveProcess(Process &process);
static ConstString GetPluginNameStatic();
uint32_t GetPluginVersion() override;
/// \}
+ lldb::CommandObjectSP
+ GetProcessTraceStartCommand(CommandInterpreter &interpreter) override;
+
+ lldb::CommandObjectSP
+ GetThreadTraceStartCommand(CommandInterpreter &interpreter) override;
+
llvm::StringRef GetSchema() override;
- void TraverseInstructions(
- const Thread &thread, size_t position, TraceDirection direction,
- std::function<bool(size_t index, llvm::Expected<lldb::addr_t> load_addr)>
- callback) override;
+ lldb::TraceCursorUP GetCursor(Thread &thread) override;
+
+ void DumpTraceInfo(Thread &thread, Stream &s, bool verbose) override;
+
+ llvm::Optional<size_t> GetRawTraceSize(Thread &thread);
+
+ void DoRefreshLiveProcessState(
+ llvm::Expected<TraceGetStateResponse> state) override;
+
+ bool IsTraced(const Thread &thread) override;
- size_t GetInstructionCount(const Thread &thread) override;
+ const char *GetStartConfigurationHelp() override;
- size_t GetCursorPosition(const Thread &thread) override;
+ /// Start tracing a live process.
+ ///
+ /// \param[in] thread_buffer_size
+ /// Trace size per thread in bytes.
+ ///
+ /// \param[in] total_buffer_size_limit
+ /// Maximum total trace size per process in bytes.
+ /// More information in TraceIntelPT::GetStartConfigurationHelp().
+ ///
+ /// \param[in] enable_tsc
+ /// Whether to use enable TSC timestamps or not.
+ /// More information in TraceIntelPT::GetStartConfigurationHelp().
+ ///
+ /// \param[in] psb_period
+ ///
+ /// This value defines the period in which PSB packets will be generated.
+ /// More information in TraceIntelPT::GetStartConfigurationHelp();
+ ///
+ /// \return
+ /// \a llvm::Error::success if the operation was successful, or
+ /// \a llvm::Error otherwise.
+ llvm::Error Start(size_t thread_buffer_size, size_t total_buffer_size_limit,
+ bool enable_tsc, llvm::Optional<size_t> psb_period);
+
+ /// \copydoc Trace::Start
+ llvm::Error Start(StructuredData::ObjectSP configuration =
+ StructuredData::ObjectSP()) override;
+
+ /// Start tracing live threads.
+ ///
+ /// \param[in] tids
+ /// Threads to trace.
+ ///
+ /// \param[in] thread_buffer_size
+ /// Trace size per thread in bytes.
+ ///
+ /// \param[in] enable_tsc
+ /// Whether to use enable TSC timestamps or not.
+ /// More information in TraceIntelPT::GetStartConfigurationHelp().
+ ///
+ /// \param[in] psb_period
+ ///
+ /// This value defines the period in which PSB packets will be generated.
+ /// More information in TraceIntelPT::GetStartConfigurationHelp().
+ ///
+ /// \return
+ /// \a llvm::Error::success if the operation was successful, or
+ /// \a llvm::Error otherwise.
+ llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids, size_t thread_buffer_size,
+ bool enable_tsc, llvm::Optional<size_t> psb_period);
+
+ /// \copydoc Trace::Start
+ llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids,
+ StructuredData::ObjectSP configuration =
+ StructuredData::ObjectSP()) override;
+
+ /// Get the thread buffer content for a live thread
+ llvm::Expected<std::vector<uint8_t>> GetLiveThreadBuffer(lldb::tid_t tid);
+
+ llvm::Expected<pt_cpu> GetCPUInfo();
private:
friend class TraceIntelPTSessionFileParser;
+ llvm::Expected<pt_cpu> GetCPUInfoForLiveProcess();
+
/// \param[in] trace_threads
/// ThreadTrace instances, which are not live-processes and whose trace
/// files are fixed.
- TraceIntelPT(const pt_cpu &pt_cpu,
- const std::vector<std::shared_ptr<ThreadTrace>> &traced_threads);
+ TraceIntelPT(
+ const pt_cpu &cpu_info,
+ const std::vector<lldb::ThreadPostMortemTraceSP> &traced_threads);
+
+ /// Constructor for live processes
+ TraceIntelPT(Process &live_process)
+ : Trace(live_process), m_thread_decoders(){};
/// Decode the trace of the given thread that, i.e. recontruct the traced
- /// instructions. That trace must be managed by this class.
+ /// instructions.
///
/// \param[in] thread
/// If \a thread is a \a ThreadTrace, then its internal trace file will be
/// decoded. Live threads are not currently supported.
///
/// \return
- /// A \a DecodedThread instance if decoding was successful, or a \b
- /// nullptr if the thread's trace is not managed by this class.
- const DecodedThread *Decode(const Thread &thread);
+ /// A \a DecodedThread shared pointer with the decoded instructions. Any
+ /// errors are embedded in the instruction list.
+ DecodedThreadSP Decode(Thread &thread);
- pt_cpu m_pt_cpu;
- std::map<std::pair<lldb::pid_t, lldb::tid_t>, ThreadTraceDecoder>
- m_trace_threads;
+ /// It is provided by either a session file or a live process' "cpuInfo"
+ /// binary data.
+ llvm::Optional<pt_cpu> m_cpu_info;
+ std::map<const Thread *, std::unique_ptr<ThreadDecoder>> m_thread_decoders;
+ /// Error gotten after a failed live process update, if any.
+ llvm::Optional<std::string> m_live_refresh_error;
};
} // namespace trace_intel_pt
diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h
new file mode 100644
index 000000000000..c2bc1b57b2bd
--- /dev/null
+++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h
@@ -0,0 +1,27 @@
+//===-- TraceIntelPTConstants.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_SOURCE_PLUGINS_TRACE_INTEL_PT_CONSTANTS_H
+#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_CONSTANTS_H
+
+#include <cstddef>
+
+#include <llvm/ADT/Optional.h>
+
+namespace lldb_private {
+namespace trace_intel_pt {
+
+const size_t kDefaultThreadBufferSize = 4 * 1024; // 4KB
+const size_t kDefaultProcessBufferSizeLimit = 5 * 1024 * 1024; // 500MB
+const bool kDefaultEnableTscValue = false;
+const llvm::Optional<size_t> kDefaultPsbPeriod = llvm::None;
+
+} // namespace trace_intel_pt
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_CONSTANTS_H
diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td
index 6ffe949dbe7b..9e8cab1ee5c4 100644
--- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td
+++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td
@@ -1,16 +1,74 @@
include "../../../../source/Commands/OptionsBase.td"
+// The information of the start commands here should match the description of
+// the intel-pt section of the jLLDBTraceStart packet in the
+// lldb/docs/lldb-gdb-remote.txt documentation file. Similarly, it should match
+// the API help message of TraceIntelPT::GetStartConfigurationHelp().
+
let Command = "thread trace start intel pt" in {
def thread_trace_start_intel_pt_size: Option<"size", "s">,
Group<1>,
Arg<"Value">,
- Desc<"The size of the trace in KB. The kernel rounds it down to the nearest"
- " multiple of 4. Defaults to 4.">;
- def thread_trace_start_intel_pt_custom_config: Option<"custom-config", "c">,
+ Desc<"Trace size in bytes per thread. It must be a power of 2 greater "
+ "than or equal to 4096 (2^12). The trace is circular keeping "
+ "the most recent data. Defaults to 4096 bytes.">;
+ def thread_trace_start_intel_pt_tsc: Option<"tsc", "t">,
+ Group<1>,
+ Desc<"Enable the use of TSC timestamps. This is supported on all devices "
+ "that support intel-pt.">;
+ def thread_trace_start_intel_pt_psb_period: Option<"psb-period", "p">,
+ Group<1>,
+ Arg<"Value">,
+ Desc<"This value defines the period in which PSB packets will be "
+ "generated. A PSB packet is a synchronization packet that contains a "
+ "TSC timestamp and the current absolute instruction pointer. "
+ "This parameter can only be used if "
+ "/sys/bus/event_source/devices/intel_pt/caps/psb_cyc is 1. Otherwise, "
+ "the PSB period will be defined by the processor. If supported, valid "
+ "values for this period can be found in "
+ "/sys/bus/event_source/devices/intel_pt/caps/psb_periods which "
+ "contains a hexadecimal number, whose bits represent valid values "
+ "e.g. if bit 2 is set, then value 2 is valid. The psb_period value is "
+ "converted to the approximate number of raw trace bytes between PSB "
+ "packets as: 2 ^ (value + 11), e.g. value 3 means 16KiB between PSB "
+ "packets. Defaults to 0 if supported.">;
+}
+
+let Command = "process trace start intel pt" in {
+ def process_trace_start_intel_pt_thread_size: Option<"thread-size", "s">,
+ Group<1>,
+ Arg<"Value">,
+ Desc<"Trace size in bytes per thread. It must be a power of 2 greater "
+ "than or equal to 4096 (2^12). The trace is circular keeping "
+ "the most recent data. Defaults to 4096 bytes.">;
+ def process_trace_start_intel_pt_process_size_limit: Option<"total-size-limit", "l">,
+ Group<1>,
+ Arg<"Value">,
+ Desc<"Maximum total trace size per process in bytes. This limit applies to "
+ "the sum of the sizes of all thread traces of this process, excluding "
+ "the ones created with the \"thread trace start\" command. "
+ "Whenever a thread is attempted to be traced due to this command and "
+ "the limit would be reached, the process is stopped with a "
+ "\"processor trace\" reason, so that the user can retrace the process "
+ "if needed. Defaults to 500MB.">;
+ def process_trace_start_intel_pt_tsc: Option<"tsc", "t">,
+ Group<1>,
+ Desc<"Enable the use of TSC timestamps. This is supported on all devices "
+ "that support intel-pt.">;
+ def process_trace_start_intel_pt_psb_period: Option<"psb-period", "p">,
Group<1>,
Arg<"Value">,
- Desc<"Low level bitmask configuration for the kernel based on the values "
- "in `grep -H /sys/bus/event_source/devices/intel_pt/format/*`. "
- "See https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/perf-intel-pt.txt"
- " for more information. Defaults to 0.">;
+ Desc<"This value defines the period in which PSB packets will be "
+ "generated. A PSB packet is a synchronization packet that contains a "
+ "TSC timestamp and the current absolute instruction pointer. "
+ "This parameter can only be used if "
+ "/sys/bus/event_source/devices/intel_pt/caps/psb_cyc is 1. Otherwise, "
+ "the PSB period will be defined by the processor. If supported, valid "
+ "values for this period can be found in "
+ "/sys/bus/event_source/devices/intel_pt/caps/psb_periods which "
+ "contains a hexadecimal number, whose bits represent valid values "
+ "e.g. if bit 2 is set, then value 2 is valid. The psb_period value is "
+ "converted to the approximate number of raw trace bytes between PSB "
+ "packets as: 2 ^ (value + 11), e.g. value 3 means 16KiB between PSB "
+ "packets. Defaults to 0 if supported.">;
}
diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
index beef5c3968ea..5af7c269d0cb 100644
--- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
+++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
@@ -8,11 +8,11 @@
#include "TraceIntelPTSessionFileParser.h"
+#include "../common/ThreadPostMortemTrace.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadList.h"
-#include "lldb/Target/ThreadTrace.h"
using namespace lldb;
using namespace lldb_private;
@@ -24,7 +24,7 @@ StringRef TraceIntelPTSessionFileParser::GetSchema() {
if (schema.empty()) {
schema = TraceSessionFileParser::BuildSchema(R"({
"type": "intel-pt",
- "pt_cpu": {
+ "cpuInfo": {
"vendor": "intel" | "unknown",
"family": integer,
"model": integer,
@@ -35,21 +35,22 @@ StringRef TraceIntelPTSessionFileParser::GetSchema() {
return schema;
}
-pt_cpu TraceIntelPTSessionFileParser::ParsePTCPU(const JSONPTCPU &pt_cpu) {
- return {pt_cpu.vendor.compare("intel") == 0 ? pcv_intel : pcv_unknown,
- static_cast<uint16_t>(pt_cpu.family),
- static_cast<uint8_t>(pt_cpu.model),
- static_cast<uint8_t>(pt_cpu.stepping)};
+pt_cpu TraceIntelPTSessionFileParser::ParsePTCPU(
+ const JSONTraceIntelPTCPUInfo &cpu_info) {
+ return {cpu_info.vendor.compare("intel") == 0 ? pcv_intel : pcv_unknown,
+ static_cast<uint16_t>(cpu_info.family),
+ static_cast<uint8_t>(cpu_info.model),
+ static_cast<uint8_t>(cpu_info.stepping)};
}
TraceSP TraceIntelPTSessionFileParser::CreateTraceIntelPTInstance(
- const pt_cpu &pt_cpu, std::vector<ParsedProcess> &parsed_processes) {
- std::vector<ThreadTraceSP> threads;
+ const pt_cpu &cpu_info, std::vector<ParsedProcess> &parsed_processes) {
+ std::vector<ThreadPostMortemTraceSP> threads;
for (const ParsedProcess &parsed_process : parsed_processes)
threads.insert(threads.end(), parsed_process.threads.begin(),
parsed_process.threads.end());
- TraceSP trace_instance(new TraceIntelPT(pt_cpu, threads));
+ TraceSP trace_instance(new TraceIntelPT(cpu_info, threads));
for (const ParsedProcess &parsed_process : parsed_processes)
parsed_process.target_sp->SetTrace(trace_instance);
@@ -64,7 +65,7 @@ Expected<TraceSP> TraceIntelPTSessionFileParser::Parse() {
if (Expected<std::vector<ParsedProcess>> parsed_processes =
ParseCommonSessionFile(session))
- return CreateTraceIntelPTInstance(ParsePTCPU(session.trace.pt_cpu),
+ return CreateTraceIntelPTInstance(ParsePTCPU(session.trace.cpuInfo),
*parsed_processes);
else
return parsed_processes.takeError();
@@ -73,25 +74,34 @@ Expected<TraceSP> TraceIntelPTSessionFileParser::Parse() {
namespace llvm {
namespace json {
-bool fromJSON(const Value &value,
- TraceIntelPTSessionFileParser::JSONPTCPU &pt_cpu, Path path) {
- ObjectMapper o(value, path);
- return o && o.map("vendor", pt_cpu.vendor) &&
- o.map("family", pt_cpu.family) && o.map("model", pt_cpu.model) &&
- o.map("stepping", pt_cpu.stepping);
-}
-
bool fromJSON(
const Value &value,
TraceIntelPTSessionFileParser::JSONTraceIntelPTSettings &plugin_settings,
Path path) {
ObjectMapper o(value, path);
- return o && o.map("pt_cpu", plugin_settings.pt_cpu) &&
+ return o && o.map("cpuInfo", plugin_settings.cpuInfo) &&
fromJSON(
value,
(TraceSessionFileParser::JSONTracePluginSettings &)plugin_settings,
path);
}
+bool fromJSON(const json::Value &value,
+ TraceIntelPTSessionFileParser::JSONTraceIntelPTCPUInfo &cpu_info,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("vendor", cpu_info.vendor) &&
+ o.map("family", cpu_info.family) && o.map("model", cpu_info.model) &&
+ o.map("stepping", cpu_info.stepping);
+}
+
+Value toJSON(
+ const TraceIntelPTSessionFileParser::JSONTraceIntelPTCPUInfo &cpu_info) {
+ return Value(Object{{"family", cpu_info.family},
+ {"model", cpu_info.model},
+ {"stepping", cpu_info.stepping},
+ {"vendor", cpu_info.vendor}});
+}
+
} // namespace json
} // namespace llvm
diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h
index 6a896de09d00..b2667a882222 100644
--- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h
+++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h
@@ -10,7 +10,8 @@
#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTSESSIONFILEPARSER_H
#include "TraceIntelPT.h"
-#include "lldb/Target/TraceSessionFileParser.h"
+
+#include "../common/TraceSessionFileParser.h"
namespace lldb_private {
namespace trace_intel_pt {
@@ -19,16 +20,16 @@ class TraceIntelPT;
class TraceIntelPTSessionFileParser : public TraceSessionFileParser {
public:
- struct JSONPTCPU {
- std::string vendor;
+ struct JSONTraceIntelPTCPUInfo {
int64_t family;
int64_t model;
int64_t stepping;
+ std::string vendor;
};
struct JSONTraceIntelPTSettings
: TraceSessionFileParser::JSONTracePluginSettings {
- JSONPTCPU pt_cpu;
+ JSONTraceIntelPTCPUInfo cpuInfo;
};
/// See \a TraceSessionFileParser::TraceSessionFileParser for the description
@@ -52,11 +53,11 @@ public:
llvm::Expected<lldb::TraceSP> Parse();
lldb::TraceSP
- CreateTraceIntelPTInstance(const pt_cpu &pt_cpu,
+ CreateTraceIntelPTInstance(const pt_cpu &cpu_info,
std::vector<ParsedProcess> &parsed_processes);
private:
- pt_cpu ParsePTCPU(const JSONPTCPU &pt_cpu);
+ static pt_cpu ParsePTCPU(const JSONTraceIntelPTCPUInfo &cpu_info);
const llvm::json::Value &m_trace_session_file;
};
@@ -67,17 +68,20 @@ private:
namespace llvm {
namespace json {
-bool fromJSON(
- const Value &value,
- lldb_private::trace_intel_pt::TraceIntelPTSessionFileParser::JSONPTCPU
- &pt_cpu,
- Path path);
-
bool fromJSON(const Value &value,
lldb_private::trace_intel_pt::TraceIntelPTSessionFileParser::
JSONTraceIntelPTSettings &plugin_settings,
Path path);
+bool fromJSON(const llvm::json::Value &value,
+ lldb_private::trace_intel_pt::TraceIntelPTSessionFileParser::
+ JSONTraceIntelPTCPUInfo &packet,
+ llvm::json::Path path);
+
+llvm::json::Value
+toJSON(const lldb_private::trace_intel_pt::TraceIntelPTSessionFileParser::
+ JSONTraceIntelPTCPUInfo &packet);
+
} // namespace json
} // namespace llvm
diff --git a/lldb/source/Plugins/Trace/intel-pt/forward-declarations.h b/lldb/source/Plugins/Trace/intel-pt/forward-declarations.h
new file mode 100644
index 000000000000..3c5f811acc10
--- /dev/null
+++ b/lldb/source/Plugins/Trace/intel-pt/forward-declarations.h
@@ -0,0 +1,20 @@
+//===-- forward-declarations.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_SOURCE_PLUGINS_TRACE_INTEL_PT_FORWARD_DECLARATIONS_H
+#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_FORWARD_DECLARATIONS_H
+
+namespace lldb_private {
+namespace trace_intel_pt {
+
+class TraceIntelPT;
+class ThreadDecoder;
+
+} // namespace trace_intel_pt
+} // namespace lldb_private
+#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_FORWARD_DECLARATIONS_H
diff --git a/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp b/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp
new file mode 100644
index 000000000000..3dd4c89e2777
--- /dev/null
+++ b/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp
@@ -0,0 +1,66 @@
+//===-- CommandObjectThreadTraceExportCTF.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 "CommandObjectThreadTraceExportCTF.h"
+
+#include "lldb/Host/OptionParser.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::ctf;
+using namespace llvm;
+
+// CommandObjectThreadTraceExportCTF
+
+#define LLDB_OPTIONS_thread_trace_export_ctf
+#include "TraceExporterCTFCommandOptions.inc"
+
+Status CommandObjectThreadTraceExportCTF::CommandOptions::SetOptionValue(
+ uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) {
+ Status error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 't': {
+ int64_t thread_index;
+ if (option_arg.empty() || option_arg.getAsInteger(0, thread_index) ||
+ thread_index < 0)
+ error.SetErrorStringWithFormat("invalid integer value for option '%s'",
+ option_arg.str().c_str());
+ else
+ m_thread_index = thread_index;
+ break;
+ }
+ default:
+ llvm_unreachable("Unimplemented option");
+ }
+ return error;
+}
+
+void CommandObjectThreadTraceExportCTF::CommandOptions::OptionParsingStarting(
+ ExecutionContext *execution_context) {
+ m_thread_index = None;
+}
+
+llvm::ArrayRef<OptionDefinition>
+CommandObjectThreadTraceExportCTF::CommandOptions::GetDefinitions() {
+ return llvm::makeArrayRef(g_thread_trace_export_ctf_options);
+}
+
+bool CommandObjectThreadTraceExportCTF::DoExecute(Args &command,
+ CommandReturnObject &result) {
+ Stream &s = result.GetOutputStream();
+ // TODO: create an actual instance of the exporter and invoke it
+ if (m_options.m_thread_index)
+ s.Printf("got thread index %d\n", (int)m_options.m_thread_index.getValue());
+ else
+ s.Printf("didn't get a thread index\n");
+
+ return result.Succeeded();
+}
diff --git a/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.h b/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.h
new file mode 100644
index 000000000000..26b068a8f8c5
--- /dev/null
+++ b/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.h
@@ -0,0 +1,56 @@
+//===-- CommandObjectThreadTraceExportCTF.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_SOURCE_PLUGINS_TRACE_INTEL_PT_COMMANDOBJECTTHREADTRACEEXPORTCTF_H
+#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_COMMANDOBJECTTHREADTRACEEXPORTCTF_H
+
+#include "TraceExporterCTF.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+namespace lldb_private {
+namespace ctf {
+
+class CommandObjectThreadTraceExportCTF : public CommandObjectParsed {
+public:
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options() { OptionParsingStarting(nullptr); }
+
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override;
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override;
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override;
+
+ llvm::Optional<size_t> m_thread_index;
+ };
+
+ CommandObjectThreadTraceExportCTF(CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "thread trace export ctf",
+ "Export a given thread's trace to Chrome Trace Format",
+ "thread trace export ctf [<ctf-options>]",
+ lldb::eCommandRequiresProcess | lldb::eCommandTryTargetAPILock |
+ lldb::eCommandProcessMustBeLaunched |
+ lldb::eCommandProcessMustBePaused),
+ m_options() {}
+
+ Options *GetOptions() override { return &m_options; }
+
+protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override;
+
+ CommandOptions m_options;
+};
+
+} // namespace ctf
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_COMMANDOBJECTTHREADTRACEEXPORTCTF_H
diff --git a/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.cpp b/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.cpp
new file mode 100644
index 000000000000..08bc03d78303
--- /dev/null
+++ b/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.cpp
@@ -0,0 +1,53 @@
+//===-- TraceExporterCTF.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 "TraceExporterCTF.h"
+
+#include <memory>
+
+#include "CommandObjectThreadTraceExportCTF.h"
+#include "lldb/Core/PluginManager.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::ctf;
+using namespace llvm;
+
+LLDB_PLUGIN_DEFINE(TraceExporterCTF)
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+
+static CommandObjectSP
+GetThreadTraceExportCommand(CommandInterpreter &interpreter) {
+ return std::make_shared<CommandObjectThreadTraceExportCTF>(interpreter);
+}
+
+void TraceExporterCTF::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ "Chrome Trace Format Exporter", CreateInstance,
+ GetThreadTraceExportCommand);
+}
+
+void TraceExporterCTF::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+ConstString TraceExporterCTF::GetPluginNameStatic() {
+ static ConstString g_name("ctf");
+ return g_name;
+}
+
+ConstString TraceExporterCTF::GetPluginName() { return GetPluginNameStatic(); }
+
+uint32_t TraceExporterCTF::GetPluginVersion() { return 1; }
+
+Expected<TraceExporterUP> TraceExporterCTF::CreateInstance() {
+ return std::make_unique<TraceExporterCTF>();
+}
diff --git a/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.h b/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.h
new file mode 100644
index 000000000000..8f9e354ab0dd
--- /dev/null
+++ b/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.h
@@ -0,0 +1,42 @@
+//===-- TraceExporterCTF.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_SOURCE_PLUGINS_TRACE_EXPORTER_CTF_H
+#define LLDB_SOURCE_PLUGINS_TRACE_EXPORTER_CTF_H
+
+#include "lldb/Target/TraceExporter.h"
+
+namespace lldb_private {
+namespace ctf {
+
+/// Trace Exporter Plugin that can produce traces in Chrome Trace Format.
+/// Still in development.
+class TraceExporterCTF : public TraceExporter {
+public:
+ ~TraceExporterCTF() override = default;
+
+ /// PluginInterface protocol
+ /// \{
+ static llvm::Expected<lldb::TraceExporterUP> CreateInstance();
+
+ ConstString GetPluginName() override;
+
+ static void Initialize();
+
+ static void Terminate();
+
+ static ConstString GetPluginNameStatic();
+
+ uint32_t GetPluginVersion() override;
+ /// \}
+};
+
+} // namespace ctf
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_TRACE_EXPORTER_CTF_H
diff --git a/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTFOptions.td b/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTFOptions.td
new file mode 100644
index 000000000000..ce751f148d9f
--- /dev/null
+++ b/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTFOptions.td
@@ -0,0 +1,9 @@
+include "../../../../source/Commands/OptionsBase.td"
+
+let Command = "thread trace export ctf" in {
+ def thread_trace_export_ctf: Option<"tid", "t">,
+ Group<1>,
+ Arg<"ThreadIndex">,
+ Desc<"Export the trace for the specified thread index. Otherwise, the "
+ "currently selected thread will be used.">;
+}
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index c15b15e736fb..7150fdc78476 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -75,7 +75,7 @@
#include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h"
#include "Plugins/SymbolFile/PDB/PDBASTParser.h"
-#include <stdio.h>
+#include <cstdio>
#include <mutex>
@@ -163,7 +163,6 @@ void addOverridesForMethod(clang::CXXMethodDecl *decl) {
if (name.getNameKind() == clang::DeclarationName::CXXDestructorName)
if (auto *baseDtorDecl = base_record->getDestructor()) {
if (baseDtorDecl->isVirtual()) {
- path.Decls = baseDtorDecl;
decls.push_back(baseDtorDecl);
return true;
} else
@@ -171,12 +170,11 @@ void addOverridesForMethod(clang::CXXMethodDecl *decl) {
}
// Otherwise, search for name in the base class.
- for (path.Decls = base_record->lookup(name); !path.Decls.empty();
- path.Decls = path.Decls.slice(1)) {
+ for (path.Decls = base_record->lookup(name).begin();
+ path.Decls != path.Decls.end(); ++path.Decls) {
if (auto *method_decl =
- llvm::dyn_cast<clang::CXXMethodDecl>(path.Decls.front()))
+ llvm::dyn_cast<clang::CXXMethodDecl>(*path.Decls))
if (method_decl->isVirtual() && !isOverload(decl, method_decl)) {
- path.Decls = method_decl;
decls.push_back(method_decl);
return true;
}
@@ -479,6 +477,9 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) {
case clang::Language::OpenCL:
LangStd = LangStandard::lang_opencl10;
break;
+ case clang::Language::OpenCLCXX:
+ LangStd = LangStandard::lang_openclcpp;
+ break;
case clang::Language::CUDA:
LangStd = LangStandard::lang_cuda;
break;
@@ -686,8 +687,8 @@ void TypeSystemClang::SetTargetTriple(llvm::StringRef target_triple) {
void TypeSystemClang::SetExternalSource(
llvm::IntrusiveRefCntPtr<ExternalASTSource> &ast_source_up) {
ASTContext &ast = getASTContext();
- ast.setExternalSource(ast_source_up);
ast.getTranslationUnitDecl()->setHasExternalLexicalStorage(true);
+ ast.setExternalSource(ast_source_up);
}
ASTContext &TypeSystemClang::getASTContext() {
@@ -745,7 +746,7 @@ void TypeSystemClang::CreateASTContext() {
*m_diagnostics_engine_up, *m_file_manager_up);
m_ast_up = std::make_unique<ASTContext>(
*m_language_options_up, *m_source_manager_up, *m_identifier_table_up,
- *m_selector_table_up, *m_builtins_up);
+ *m_selector_table_up, *m_builtins_up, TU_Complete);
m_diagnostic_consumer_up = std::make_unique<NullDiagnosticConsumer>();
m_ast_up->getDiagnostics().setClient(m_diagnostic_consumer_up.get(), false);
@@ -1356,9 +1357,11 @@ CompilerType TypeSystemClang::CreateRecordType(
}
namespace {
- bool IsValueParam(const clang::TemplateArgument &argument) {
- return argument.getKind() == TemplateArgument::Integral;
- }
+/// Returns true iff the given TemplateArgument should be represented as an
+/// NonTypeTemplateParmDecl in the AST.
+bool IsValueParam(const clang::TemplateArgument &argument) {
+ return argument.getKind() == TemplateArgument::Integral;
+}
}
static TemplateParameterList *CreateTemplateParameterList(
@@ -1462,6 +1465,99 @@ void TypeSystemClang::CreateFunctionTemplateSpecializationInfo(
template_args_ptr, nullptr);
}
+/// Returns true if the given template parameter can represent the given value.
+/// For example, `typename T` can represent `int` but not integral values such
+/// as `int I = 3`.
+static bool TemplateParameterAllowsValue(NamedDecl *param,
+ const TemplateArgument &value) {
+ if (auto *type_param = llvm::dyn_cast<TemplateTypeParmDecl>(param)) {
+ // Compare the argument kind, i.e. ensure that <typename> != <int>.
+ if (value.getKind() != TemplateArgument::Type)
+ return false;
+ } else if (auto *type_param =
+ llvm::dyn_cast<NonTypeTemplateParmDecl>(param)) {
+ // Compare the argument kind, i.e. ensure that <typename> != <int>.
+ if (!IsValueParam(value))
+ return false;
+ // Compare the integral type, i.e. ensure that <int> != <char>.
+ if (type_param->getType() != value.getIntegralType())
+ return false;
+ } else {
+ // There is no way to create other parameter decls at the moment, so we
+ // can't reach this case during normal LLDB usage. Log that this happened
+ // and assert.
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
+ LLDB_LOG(log,
+ "Don't know how to compare template parameter to passed"
+ " value. Decl kind of parameter is: {0}",
+ param->getDeclKindName());
+ lldbassert(false && "Can't compare this TemplateParmDecl subclass");
+ // In release builds just fall back to marking the parameter as not
+ // accepting the value so that we don't try to fit an instantiation to a
+ // template that doesn't fit. E.g., avoid that `S<1>` is being connected to
+ // `template<typename T> struct S;`.
+ return false;
+ }
+ return true;
+}
+
+/// Returns true if the given class template declaration could produce an
+/// instantiation with the specified values.
+/// For example, `<typename T>` allows the arguments `float`, but not for
+/// example `bool, float` or `3` (as an integer parameter value).
+static bool ClassTemplateAllowsToInstantiationArgs(
+ ClassTemplateDecl *class_template_decl,
+ const TypeSystemClang::TemplateParameterInfos &instantiation_values) {
+
+ TemplateParameterList &params = *class_template_decl->getTemplateParameters();
+
+ // Save some work by iterating only once over the found parameters and
+ // calculate the information related to parameter packs.
+
+ // Contains the first pack parameter (or non if there are none).
+ llvm::Optional<NamedDecl *> pack_parameter;
+ // Contains the number of non-pack parameters.
+ size_t non_pack_params = params.size();
+ for (size_t i = 0; i < params.size(); ++i) {
+ NamedDecl *param = params.getParam(i);
+ if (param->isParameterPack()) {
+ pack_parameter = param;
+ non_pack_params = i;
+ break;
+ }
+ }
+
+ // The found template needs to have compatible non-pack template arguments.
+ // E.g., ensure that <typename, typename> != <typename>.
+ // The pack parameters are compared later.
+ if (non_pack_params != instantiation_values.args.size())
+ return false;
+
+ // Ensure that <typename...> != <typename>.
+ if (pack_parameter.hasValue() != instantiation_values.hasParameterPack())
+ return false;
+
+ // Compare the first pack parameter that was found with the first pack
+ // parameter value. The special case of having an empty parameter pack value
+ // always fits to a pack parameter.
+ // E.g., ensure that <int...> != <typename...>.
+ if (pack_parameter && !instantiation_values.packed_args->args.empty() &&
+ !TemplateParameterAllowsValue(
+ *pack_parameter, instantiation_values.packed_args->args.front()))
+ return false;
+
+ // Compare all the non-pack parameters now.
+ // E.g., ensure that <int> != <long>.
+ for (const auto pair : llvm::zip_first(instantiation_values.args, params)) {
+ const TemplateArgument &passed_arg = std::get<0>(pair);
+ NamedDecl *found_param = std::get<1>(pair);
+ if (!TemplateParameterAllowsValue(found_param, passed_arg))
+ return false;
+ }
+
+ return class_template_decl;
+}
+
ClassTemplateDecl *TypeSystemClang::CreateClassTemplateDecl(
DeclContext *decl_ctx, OptionalClangModuleID owning_module,
lldb::AccessType access_type, const char *class_name, int kind,
@@ -1475,12 +1571,22 @@ ClassTemplateDecl *TypeSystemClang::CreateClassTemplateDecl(
IdentifierInfo &identifier_info = ast.Idents.get(class_name);
DeclarationName decl_name(&identifier_info);
+ // Search the AST for an existing ClassTemplateDecl that could be reused.
clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name);
-
for (NamedDecl *decl : result) {
class_template_decl = dyn_cast<clang::ClassTemplateDecl>(decl);
- if (class_template_decl)
- return class_template_decl;
+ if (!class_template_decl)
+ continue;
+ // The class template has to be able to represents the instantiation
+ // values we received. Without this we might end up putting an instantiation
+ // with arguments such as <int, int> to a template such as:
+ // template<typename T> struct S;
+ // Connecting the instantiation to an incompatible template could cause
+ // problems later on.
+ if (!ClassTemplateAllowsToInstantiationArgs(class_template_decl,
+ template_param_infos))
+ continue;
+ return class_template_decl;
}
llvm::SmallVector<NamedDecl *, 8> template_param_decls;
@@ -1866,8 +1972,8 @@ TypeSystemClang::CreateUsingDeclaration(clang::DeclContext *current_decl_ctx,
clang::NestedNameSpecifierLoc(), clang::DeclarationNameInfo(), false);
SetOwningModule(using_decl, owning_module);
clang::UsingShadowDecl *shadow_decl = clang::UsingShadowDecl::Create(
- getASTContext(), current_decl_ctx, clang::SourceLocation(), using_decl,
- target);
+ getASTContext(), current_decl_ctx, clang::SourceLocation(),
+ target->getDeclName(), using_decl, target);
SetOwningModule(shadow_decl, owning_module);
using_decl->addShadowDecl(shadow_decl);
current_decl_ctx->addDecl(using_decl);
@@ -2114,11 +2220,10 @@ ParmVarDecl *TypeSystemClang::CreateParameterDeclaration(
return decl;
}
-void TypeSystemClang::SetFunctionParameters(FunctionDecl *function_decl,
- ParmVarDecl **params,
- unsigned num_params) {
+void TypeSystemClang::SetFunctionParameters(
+ FunctionDecl *function_decl, llvm::ArrayRef<ParmVarDecl *> params) {
if (function_decl)
- function_decl->setParams(ArrayRef<ParmVarDecl *>(params, num_params));
+ function_decl->setParams(params);
}
CompilerType
@@ -2470,42 +2575,6 @@ ClangASTMetadata *TypeSystemClang::GetMetadata(const clang::Type *object) {
return nullptr;
}
-bool TypeSystemClang::SetTagTypeKind(clang::QualType tag_qual_type,
- int kind) const {
- const clang::Type *clang_type = tag_qual_type.getTypePtr();
- if (clang_type) {
- const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(clang_type);
- if (tag_type) {
- clang::TagDecl *tag_decl =
- llvm::dyn_cast<clang::TagDecl>(tag_type->getDecl());
- if (tag_decl) {
- tag_decl->setTagKind((clang::TagDecl::TagKind)kind);
- return true;
- }
- }
- }
- return false;
-}
-
-bool TypeSystemClang::SetDefaultAccessForRecordFields(
- clang::RecordDecl *record_decl, int default_accessibility,
- int *assigned_accessibilities, size_t num_assigned_accessibilities) {
- if (record_decl) {
- uint32_t field_idx;
- clang::RecordDecl::field_iterator field, field_end;
- for (field = record_decl->field_begin(),
- field_end = record_decl->field_end(), field_idx = 0;
- field != field_end; ++field, ++field_idx) {
- // If no accessibility was assigned, assign the correct one
- if (field_idx < num_assigned_accessibilities &&
- assigned_accessibilities[field_idx] == clang::AS_none)
- field->setAccess((clang::AccessSpecifier)default_accessibility);
- }
- return true;
- }
- return false;
-}
-
clang::DeclContext *
TypeSystemClang::GetDeclContextForType(const CompilerType &type) {
return GetDeclContextForType(ClangUtil::GetQualType(type));
@@ -4697,7 +4766,6 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type,
case clang::BuiltinType::Void:
break;
- case clang::BuiltinType::Bool:
case clang::BuiltinType::Char_S:
case clang::BuiltinType::SChar:
case clang::BuiltinType::WChar_S:
@@ -4708,6 +4776,7 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type,
case clang::BuiltinType::Int128:
return lldb::eEncodingSint;
+ case clang::BuiltinType::Bool:
case clang::BuiltinType::Char_U:
case clang::BuiltinType::UChar:
case clang::BuiltinType::WChar_U:
@@ -4889,6 +4958,75 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type,
case clang::BuiltinType::SveFloat64x4:
break;
+ // RISC-V V builtin types.
+ case clang::BuiltinType::RvvInt8mf8:
+ case clang::BuiltinType::RvvInt8mf4:
+ case clang::BuiltinType::RvvInt8mf2:
+ case clang::BuiltinType::RvvInt8m1:
+ case clang::BuiltinType::RvvInt8m2:
+ case clang::BuiltinType::RvvInt8m4:
+ case clang::BuiltinType::RvvInt8m8:
+ case clang::BuiltinType::RvvUint8mf8:
+ case clang::BuiltinType::RvvUint8mf4:
+ case clang::BuiltinType::RvvUint8mf2:
+ case clang::BuiltinType::RvvUint8m1:
+ case clang::BuiltinType::RvvUint8m2:
+ case clang::BuiltinType::RvvUint8m4:
+ case clang::BuiltinType::RvvUint8m8:
+ case clang::BuiltinType::RvvInt16mf4:
+ case clang::BuiltinType::RvvInt16mf2:
+ case clang::BuiltinType::RvvInt16m1:
+ case clang::BuiltinType::RvvInt16m2:
+ case clang::BuiltinType::RvvInt16m4:
+ case clang::BuiltinType::RvvInt16m8:
+ case clang::BuiltinType::RvvUint16mf4:
+ case clang::BuiltinType::RvvUint16mf2:
+ case clang::BuiltinType::RvvUint16m1:
+ case clang::BuiltinType::RvvUint16m2:
+ case clang::BuiltinType::RvvUint16m4:
+ case clang::BuiltinType::RvvUint16m8:
+ case clang::BuiltinType::RvvInt32mf2:
+ case clang::BuiltinType::RvvInt32m1:
+ case clang::BuiltinType::RvvInt32m2:
+ case clang::BuiltinType::RvvInt32m4:
+ case clang::BuiltinType::RvvInt32m8:
+ case clang::BuiltinType::RvvUint32mf2:
+ case clang::BuiltinType::RvvUint32m1:
+ case clang::BuiltinType::RvvUint32m2:
+ case clang::BuiltinType::RvvUint32m4:
+ case clang::BuiltinType::RvvUint32m8:
+ case clang::BuiltinType::RvvInt64m1:
+ case clang::BuiltinType::RvvInt64m2:
+ case clang::BuiltinType::RvvInt64m4:
+ case clang::BuiltinType::RvvInt64m8:
+ case clang::BuiltinType::RvvUint64m1:
+ case clang::BuiltinType::RvvUint64m2:
+ case clang::BuiltinType::RvvUint64m4:
+ case clang::BuiltinType::RvvUint64m8:
+ case clang::BuiltinType::RvvFloat16mf4:
+ case clang::BuiltinType::RvvFloat16mf2:
+ case clang::BuiltinType::RvvFloat16m1:
+ case clang::BuiltinType::RvvFloat16m2:
+ case clang::BuiltinType::RvvFloat16m4:
+ case clang::BuiltinType::RvvFloat16m8:
+ case clang::BuiltinType::RvvFloat32mf2:
+ case clang::BuiltinType::RvvFloat32m1:
+ case clang::BuiltinType::RvvFloat32m2:
+ case clang::BuiltinType::RvvFloat32m4:
+ case clang::BuiltinType::RvvFloat32m8:
+ case clang::BuiltinType::RvvFloat64m1:
+ case clang::BuiltinType::RvvFloat64m2:
+ case clang::BuiltinType::RvvFloat64m4:
+ case clang::BuiltinType::RvvFloat64m8:
+ case clang::BuiltinType::RvvBool1:
+ case clang::BuiltinType::RvvBool2:
+ case clang::BuiltinType::RvvBool4:
+ case clang::BuiltinType::RvvBool8:
+ case clang::BuiltinType::RvvBool16:
+ case clang::BuiltinType::RvvBool32:
+ case clang::BuiltinType::RvvBool64:
+ break;
+
case clang::BuiltinType::IncompleteMatrixIdx:
break;
}
@@ -6365,7 +6503,7 @@ CompilerType TypeSystemClang::GetChildCompilerTypeAtIndex(
case clang::Type::RValueReference:
if (idx_is_valid) {
const clang::ReferenceType *reference_type =
- llvm::cast<clang::ReferenceType>(parent_qual_type.getTypePtr());
+ llvm::cast<clang::ReferenceType>(GetQualType(type).getTypePtr());
CompilerType pointee_clang_type =
GetType(reference_type->getPointeeType());
if (transparent_pointers && pointee_clang_type.IsAggregateType()) {
@@ -6536,10 +6674,11 @@ size_t TypeSystemClang::GetIndexOfChildMemberWithName(
if (cxx_record_decl->lookupInBases(
[decl_name](const clang::CXXBaseSpecifier *specifier,
clang::CXXBasePath &path) {
- path.Decls =
- specifier->getType()->getAsCXXRecordDecl()->lookup(
- decl_name);
- return !path.Decls.empty();
+ CXXRecordDecl *record =
+ specifier->getType()->getAsCXXRecordDecl();
+ auto r = record->lookup(decl_name);
+ path.Decls = r.begin();
+ return !r.empty();
},
paths)) {
clang::CXXBasePaths::const_paths_iterator path,
@@ -6562,9 +6701,10 @@ size_t TypeSystemClang::GetIndexOfChildMemberWithName(
->getDecl());
}
}
- for (clang::NamedDecl *path_decl : path->Decls) {
+ for (clang::DeclContext::lookup_iterator I = path->Decls, E;
+ I != E; ++I) {
child_idx = GetIndexForRecordChild(
- parent_record_decl, path_decl, omit_empty_base_classes);
+ parent_record_decl, *I, omit_empty_base_classes);
if (child_idx == UINT32_MAX) {
child_indexes.clear();
return 0;
@@ -9234,11 +9374,11 @@ CompilerType TypeSystemClang::DeclGetFunctionArgumentType(void *opaque_decl,
std::vector<CompilerDecl> TypeSystemClang::DeclContextFindDeclByName(
void *opaque_decl_ctx, ConstString name, const bool ignore_using_decls) {
std::vector<CompilerDecl> found_decls;
- if (opaque_decl_ctx) {
+ SymbolFile *symbol_file = GetSymbolFile();
+ if (opaque_decl_ctx && symbol_file) {
DeclContext *root_decl_ctx = (DeclContext *)opaque_decl_ctx;
std::set<DeclContext *> searched;
std::multimap<DeclContext *, DeclContext *> search_queue;
- SymbolFile *symbol_file = GetSymbolFile();
for (clang::DeclContext *decl_context = root_decl_ctx;
decl_context != nullptr && found_decls.empty();
@@ -9332,10 +9472,10 @@ uint32_t TypeSystemClang::CountDeclLevels(clang::DeclContext *frame_decl_ctx,
clang::DeclContext *child_decl_ctx,
ConstString *child_name,
CompilerType *child_type) {
- if (frame_decl_ctx) {
+ SymbolFile *symbol_file = GetSymbolFile();
+ if (frame_decl_ctx && symbol_file) {
std::set<DeclContext *> searched;
std::multimap<DeclContext *, DeclContext *> search_queue;
- SymbolFile *symbol_file = GetSymbolFile();
// Get the lookup scope for the decl we're trying to find.
clang::DeclContext *parent_decl_ctx = child_decl_ctx->getParent();
@@ -9581,7 +9721,8 @@ ScratchTypeSystemClang::ScratchTypeSystemClang(Target &target,
llvm::Triple triple)
: TypeSystemClang("scratch ASTContext", triple), m_triple(triple),
m_target_wp(target.shared_from_this()),
- m_persistent_variables(new ClangPersistentVariables) {
+ m_persistent_variables(
+ new ClangPersistentVariables(target.shared_from_this())) {
m_scratch_ast_source_up = CreateASTSource();
m_scratch_ast_source_up->InstallASTContext(*this);
llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source(
@@ -9649,7 +9790,8 @@ ScratchTypeSystemClang::CreateUtilityFunction(std::string text,
return {};
return std::make_unique<ClangUtilityFunction>(
- *target_sp.get(), std::move(text), std::move(name));
+ *target_sp.get(), std::move(text), std::move(name),
+ target_sp->GetDebugUtilityExpression());
}
PersistentExpressionState *
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index f37652ff477a..701e4ca42e39 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -9,7 +9,7 @@
#ifndef LLDB_SOURCE_PLUGINS_TYPESYSTEM_CLANG_TYPESYSTEMCLANG_H
#define LLDB_SOURCE_PLUGINS_TYPESYSTEM_CLANG_TYPESYSTEMCLANG_H
-#include <stdint.h>
+#include <cstdint>
#include <functional>
#include <initializer_list>
@@ -265,7 +265,7 @@ public:
clang::DeclContext::lookup_result result = decl_context->lookup(myName);
if (!result.empty()) {
- clang::NamedDecl *named_decl = result[0];
+ clang::NamedDecl *named_decl = *result.begin();
if (const RecordDeclType *record_decl =
llvm::dyn_cast<RecordDeclType>(named_decl))
compiler_type.SetCompilerType(
@@ -328,6 +328,8 @@ public:
(!packed_args || !packed_args->packed_args);
}
+ bool hasParameterPack() const { return static_cast<bool>(packed_args); }
+
llvm::SmallVector<const char *, 2> names;
llvm::SmallVector<clang::TemplateArgument, 2> args;
@@ -378,13 +380,6 @@ public:
bool isForwardDecl, bool isInternal,
ClangASTMetadata *metadata = nullptr);
- bool SetTagTypeKind(clang::QualType type, int kind) const;
-
- bool SetDefaultAccessForRecordFields(clang::RecordDecl *record_decl,
- int default_accessibility,
- int *assigned_accessibilities,
- size_t num_assigned_accessibilities);
-
// Returns a mask containing bits from the TypeSystemClang::eTypeXXX
// enumerations
@@ -421,7 +416,7 @@ public:
int storage, bool add_decl = false);
void SetFunctionParameters(clang::FunctionDecl *function_decl,
- clang::ParmVarDecl **params, unsigned num_params);
+ llvm::ArrayRef<clang::ParmVarDecl *> params);
CompilerType CreateBlockPointerType(const CompilerType &function_type);
diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
index 1bc071c2b161..65947c5f833b 100644
--- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -38,10 +38,10 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
ProcessSP process_sp(thread.GetProcess());
if (process_sp) {
Status error;
- const bool prefer_file_cache = true;
+ const bool force_live_memory = true;
if (process_sp->GetTarget().ReadMemory(
- range.GetBaseAddress(), prefer_file_cache, function_text.data(),
- range.GetByteSize(), error) != range.GetByteSize()) {
+ range.GetBaseAddress(), function_text.data(), range.GetByteSize(),
+ error, force_live_memory) != range.GetByteSize()) {
return false;
}
}
diff --git a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
index fe1275d5b0cf..402a70cd025f 100644
--- a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
+++ b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
@@ -51,12 +51,11 @@ bool UnwindAssembly_x86::GetNonCallSiteUnwindPlanFromAssembly(
ProcessSP process_sp(thread.GetProcess());
if (process_sp.get() == nullptr)
return false;
- const bool prefer_file_cache = true;
std::vector<uint8_t> function_text(func.GetByteSize());
Status error;
if (process_sp->GetTarget().ReadMemory(
- func.GetBaseAddress(), prefer_file_cache, function_text.data(),
- func.GetByteSize(), error) == func.GetByteSize()) {
+ func.GetBaseAddress(), function_text.data(), func.GetByteSize(),
+ error) == func.GetByteSize()) {
RegisterContextSP reg_ctx(thread.GetRegisterContext());
m_assembly_inspection_engine->Initialize(reg_ctx);
return m_assembly_inspection_engine->GetNonCallSiteUnwindPlanFromAssembly(
@@ -153,12 +152,11 @@ bool UnwindAssembly_x86::AugmentUnwindPlanFromCallSite(
return false;
if (m_assembly_inspection_engine == nullptr)
return false;
- const bool prefer_file_cache = true;
std::vector<uint8_t> function_text(func.GetByteSize());
Status error;
if (process_sp->GetTarget().ReadMemory(
- func.GetBaseAddress(), prefer_file_cache, function_text.data(),
- func.GetByteSize(), error) == func.GetByteSize()) {
+ func.GetBaseAddress(), function_text.data(), func.GetByteSize(),
+ error) == func.GetByteSize()) {
RegisterContextSP reg_ctx(thread.GetRegisterContext());
m_assembly_inspection_engine->Initialize(reg_ctx);
return m_assembly_inspection_engine->AugmentUnwindPlanFromCallSite(
@@ -185,10 +183,9 @@ bool UnwindAssembly_x86::GetFastUnwindPlan(AddressRange &func, Thread &thread,
ProcessSP process_sp = thread.GetProcess();
if (process_sp) {
Target &target(process_sp->GetTarget());
- const bool prefer_file_cache = true;
Status error;
- if (target.ReadMemory(func.GetBaseAddress(), prefer_file_cache,
- opcode_data.data(), 4, error) == 4) {
+ if (target.ReadMemory(func.GetBaseAddress(), opcode_data.data(), 4,
+ error) == 4) {
uint8_t i386_push_mov[] = {0x55, 0x89, 0xe5};
uint8_t x86_64_push_mov[] = {0x55, 0x48, 0x89, 0xe5};
@@ -220,12 +217,10 @@ bool UnwindAssembly_x86::FirstNonPrologueInsn(
if (m_assembly_inspection_engine == nullptr)
return false;
- const bool prefer_file_cache = true;
std::vector<uint8_t> function_text(func.GetByteSize());
Status error;
- if (target->ReadMemory(func.GetBaseAddress(), prefer_file_cache,
- function_text.data(), func.GetByteSize(),
- error) == func.GetByteSize()) {
+ if (target->ReadMemory(func.GetBaseAddress(), function_text.data(),
+ func.GetByteSize(), error) == func.GetByteSize()) {
size_t offset;
if (m_assembly_inspection_engine->FindFirstNonPrologueInstruction(
function_text.data(), func.GetByteSize(), offset)) {
diff --git a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
index f39dce1afaa6..487748812968 100644
--- a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
+++ b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
@@ -45,9 +45,9 @@ public:
/// are called. This one takes a vector of register name and lldb
/// register numbers.
struct lldb_reg_info {
- const char *name;
- uint32_t lldb_regnum;
- lldb_reg_info() : name(nullptr), lldb_regnum(LLDB_INVALID_REGNUM) {}
+ const char *name = nullptr;
+ uint32_t lldb_regnum = LLDB_INVALID_REGNUM;
+ lldb_reg_info() = default;
};
void Initialize(std::vector<lldb_reg_info> &reg_info);
diff --git a/lldb/source/Symbol/ArmUnwindInfo.cpp b/lldb/source/Symbol/ArmUnwindInfo.cpp
index f2887035e5cf..07852485f44e 100644
--- a/lldb/source/Symbol/ArmUnwindInfo.cpp
+++ b/lldb/source/Symbol/ArmUnwindInfo.cpp
@@ -68,7 +68,7 @@ ArmUnwindInfo::ArmUnwindInfo(ObjectFile &objfile, SectionSP &arm_exidx,
llvm::sort(m_exidx_entries.begin(), m_exidx_entries.end());
}
-ArmUnwindInfo::~ArmUnwindInfo() {}
+ArmUnwindInfo::~ArmUnwindInfo() = default;
// Read a byte from the unwind instruction stream with the given offset. Custom
// function is required because have to red in order of significance within
diff --git a/lldb/source/Symbol/Block.cpp b/lldb/source/Symbol/Block.cpp
index afcdf3e21e19..fc246ac8575d 100644
--- a/lldb/source/Symbol/Block.cpp
+++ b/lldb/source/Symbol/Block.cpp
@@ -25,7 +25,7 @@ Block::Block(lldb::user_id_t uid)
m_inlineInfoSP(), m_variable_list_sp(), m_parsed_block_info(false),
m_parsed_block_variables(false), m_parsed_child_blocks(false) {}
-Block::~Block() {}
+Block::~Block() = default;
void Block::GetDescription(Stream *s, Function *function,
lldb::DescriptionLevel level, Target *target) const {
diff --git a/lldb/source/Symbol/CompactUnwindInfo.cpp b/lldb/source/Symbol/CompactUnwindInfo.cpp
index 1bb7cd1fc05b..830fe5546c1c 100644
--- a/lldb/source/Symbol/CompactUnwindInfo.cpp
+++ b/lldb/source/Symbol/CompactUnwindInfo.cpp
@@ -167,7 +167,7 @@ CompactUnwindInfo::CompactUnwindInfo(ObjectFile &objfile, SectionSP &section_sp)
// destructor
-CompactUnwindInfo::~CompactUnwindInfo() {}
+CompactUnwindInfo::~CompactUnwindInfo() = default;
bool CompactUnwindInfo::GetUnwindPlan(Target &target, Address addr,
UnwindPlan &unwind_plan) {
diff --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp
index 822f0df4da37..588ed4976d65 100644
--- a/lldb/source/Symbol/CompileUnit.cpp
+++ b/lldb/source/Symbol/CompileUnit.cpp
@@ -224,18 +224,24 @@ uint32_t CompileUnit::FindLineEntry(uint32_t start_idx, uint32_t line,
if (file_indexes.empty())
return UINT32_MAX;
+ // TODO: Handle SourceLocationSpec column information
+ SourceLocationSpec location_spec(*file_spec_ptr, line, /*column=*/llvm::None,
+ /*check_inlines=*/false, exact);
+
LineTable *line_table = GetLineTable();
if (line_table)
return line_table->FindLineEntryIndexByFileIndex(
- start_idx, file_indexes, line, exact, line_entry_ptr);
+ start_idx, file_indexes, location_spec, line_entry_ptr);
return UINT32_MAX;
}
-void CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,
- uint32_t line, bool check_inlines,
- bool exact,
- SymbolContextItem resolve_scope,
- SymbolContextList &sc_list) {
+void CompileUnit::ResolveSymbolContext(
+ const SourceLocationSpec &src_location_spec,
+ SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
+ const FileSpec file_spec = src_location_spec.GetFileSpec();
+ const uint32_t line = src_location_spec.GetLine().getValueOr(0);
+ const bool check_inlines = src_location_spec.GetCheckInlines();
+
// 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
@@ -248,6 +254,18 @@ void CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,
if (!file_spec_matches_cu_file_spec && !check_inlines)
return;
+ SymbolContext sc(GetModule());
+ sc.comp_unit = this;
+
+ 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);
+ }
+ return;
+ }
+
uint32_t file_idx =
GetSupportFiles().FindFileIndex(0, file_spec, true);
while (file_idx != UINT32_MAX) {
@@ -259,23 +277,15 @@ void CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,
if (num_file_indexes == 0)
return;
- SymbolContext sc(GetModule());
- sc.comp_unit = this;
+ LineTable *line_table = sc.comp_unit->GetLineTable();
- if (line == 0) {
+ if (line_table == nullptr) {
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);
}
return;
}
- LineTable *line_table = sc.comp_unit->GetLineTable();
-
- if (line_table == nullptr)
- return;
-
uint32_t line_idx;
LineEntry line_entry;
@@ -284,21 +294,24 @@ void CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,
// 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);
+ 0, file_indexes.front(), src_location_spec, &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);
+ line_idx = line_table->FindLineEntryIndexByFileIndex(
+ 0, file_indexes, src_location_spec, &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;
-
+ const bool inlines = false;
+ const bool exact = true;
+ SourceLocationSpec found_entry(line_entry.file, line_entry.line,
+ line_entry.column, inlines, exact);
+
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
@@ -313,10 +326,10 @@ void CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,
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);
+ line_idx + 1, file_indexes.front(), found_entry, &line_entry);
else
line_idx = line_table->FindLineEntryIndexByFileIndex(
- line_idx + 1, file_indexes, found_line, true, &line_entry);
+ line_idx + 1, file_indexes, found_entry, &line_entry);
}
}
diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp
index 4f0c3b366af5..ac98352c235e 100644
--- a/lldb/source/Symbol/CompilerType.cpp
+++ b/lldb/source/Symbol/CompilerType.cpp
@@ -248,7 +248,7 @@ bool CompilerType::IsPointerToScalarType() const {
bool CompilerType::IsArrayOfScalarType() const {
CompilerType element_type;
- if (IsArrayType(&element_type, nullptr, nullptr))
+ if (IsArrayType(&element_type))
return element_type.IsScalarType();
return false;
}
diff --git a/lldb/source/Symbol/FuncUnwinders.cpp b/lldb/source/Symbol/FuncUnwinders.cpp
index 9a2671a08e86..d67c0a828eb3 100644
--- a/lldb/source/Symbol/FuncUnwinders.cpp
+++ b/lldb/source/Symbol/FuncUnwinders.cpp
@@ -55,7 +55,7 @@ FuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, AddressRange range)
/// destructor
-FuncUnwinders::~FuncUnwinders() {}
+FuncUnwinders::~FuncUnwinders() = default;
UnwindPlanSP FuncUnwinders::GetUnwindPlanAtCallSite(Target &target,
Thread &thread) {
diff --git a/lldb/source/Symbol/Function.cpp b/lldb/source/Symbol/Function.cpp
index 67013f6dd8b1..37479651fb45 100644
--- a/lldb/source/Symbol/Function.cpp
+++ b/lldb/source/Symbol/Function.cpp
@@ -32,7 +32,7 @@ FunctionInfo::FunctionInfo(const char *name, const Declaration *decl_ptr)
FunctionInfo::FunctionInfo(ConstString name, const Declaration *decl_ptr)
: m_name(name), m_declaration(decl_ptr) {}
-FunctionInfo::~FunctionInfo() {}
+FunctionInfo::~FunctionInfo() = default;
void FunctionInfo::Dump(Stream *s, bool show_fullpaths) const {
if (m_name)
@@ -74,7 +74,7 @@ InlineFunctionInfo::InlineFunctionInfo(ConstString name,
: FunctionInfo(name, decl_ptr), m_mangled(mangled),
m_call_decl(call_decl_ptr) {}
-InlineFunctionInfo::~InlineFunctionInfo() {}
+InlineFunctionInfo::~InlineFunctionInfo() = default;
void InlineFunctionInfo::Dump(Stream *s, bool show_fullpaths) const {
FunctionInfo::Dump(s, show_fullpaths);
@@ -238,7 +238,7 @@ Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid,
assert(comp_unit != nullptr);
}
-Function::~Function() {}
+Function::~Function() = default;
void Function::GetStartLineSourceInfo(FileSpec &source_file,
uint32_t &line_no) {
@@ -426,17 +426,16 @@ lldb::DisassemblerSP Function::GetInstructions(const ExecutionContext &exe_ctx,
bool prefer_file_cache) {
ModuleSP module_sp(GetAddressRange().GetBaseAddress().GetModule());
if (module_sp && exe_ctx.HasTargetScope()) {
- const bool prefer_file_cache = false;
return Disassembler::DisassembleRange(module_sp->GetArchitecture(), nullptr,
flavor, exe_ctx.GetTargetRef(),
- GetAddressRange(), prefer_file_cache);
+ GetAddressRange(), !prefer_file_cache);
}
return lldb::DisassemblerSP();
}
bool Function::GetDisassembly(const ExecutionContext &exe_ctx,
- const char *flavor, bool prefer_file_cache,
- Stream &strm) {
+ const char *flavor, Stream &strm,
+ bool prefer_file_cache) {
lldb::DisassemblerSP disassembler_sp =
GetInstructions(exe_ctx, flavor, prefer_file_cache);
if (disassembler_sp) {
diff --git a/lldb/source/Symbol/LineEntry.cpp b/lldb/source/Symbol/LineEntry.cpp
index a3907f4dd9c0..1b2801cd0368 100644
--- a/lldb/source/Symbol/LineEntry.cpp
+++ b/lldb/source/Symbol/LineEntry.cpp
@@ -14,9 +14,8 @@
using namespace lldb_private;
LineEntry::LineEntry()
- : range(), file(), line(LLDB_INVALID_LINE_NUMBER), column(0),
- is_start_of_statement(0), is_start_of_basic_block(0), is_prologue_end(0),
- is_epilogue_begin(0), is_terminal_entry(0) {}
+ : range(), file(), is_start_of_statement(0), is_start_of_basic_block(0),
+ is_prologue_end(0), is_epilogue_begin(0), is_terminal_entry(0) {}
LineEntry::LineEntry(const lldb::SectionSP &section_sp,
lldb::addr_t section_offset, lldb::addr_t byte_size,
@@ -253,9 +252,9 @@ AddressRange LineEntry::GetSameLineContiguousAddressRange(
void LineEntry::ApplyFileMappings(lldb::TargetSP target_sp) {
if (target_sp) {
- // Apply any file remappings to our file
- FileSpec new_file_spec;
- if (target_sp->GetSourcePathMap().FindFile(original_file, new_file_spec))
- file = new_file_spec;
+ // Apply any file remappings to our file.
+ if (auto new_file_spec =
+ target_sp->GetSourcePathMap().FindFile(original_file))
+ file = *new_file_spec;
}
}
diff --git a/lldb/source/Symbol/LineTable.cpp b/lldb/source/Symbol/LineTable.cpp
index 1d4a405ad47d..cd8d520ada78 100644
--- a/lldb/source/Symbol/LineTable.cpp
+++ b/lldb/source/Symbol/LineTable.cpp
@@ -34,7 +34,7 @@ LineTable::LineTable(CompileUnit *comp_unit,
}
// Destructor
-LineTable::~LineTable() {}
+LineTable::~LineTable() = default;
void LineTable::InsertLineEntry(lldb::addr_t file_addr, uint32_t line,
uint16_t column, uint16_t file_idx,
@@ -58,7 +58,7 @@ void LineTable::InsertLineEntry(lldb::addr_t file_addr, uint32_t line,
// Dump (&s, Address::DumpStyleFileAddress);
}
-LineSequence::LineSequence() {}
+LineSequence::LineSequence() = default;
void LineTable::LineSequenceImpl::Clear() { m_entries.clear(); }
@@ -303,91 +303,26 @@ bool LineTable::ConvertEntryAtIndexToLineEntry(uint32_t idx,
}
uint32_t LineTable::FindLineEntryIndexByFileIndex(
- uint32_t start_idx, const std::vector<uint32_t> &file_indexes,
- uint32_t line, bool exact, LineEntry *line_entry_ptr) {
+ uint32_t start_idx, uint32_t file_idx,
+ const SourceLocationSpec &src_location_spec, LineEntry *line_entry_ptr) {
+ auto file_idx_matcher = [](uint32_t file_index, uint16_t entry_file_idx) {
+ return file_index == entry_file_idx;
+ };
+ return FindLineEntryIndexByFileIndexImpl<uint32_t>(
- const size_t count = m_entries.size();
- size_t best_match = UINT32_MAX;
-
- for (size_t idx = start_idx; idx < count; ++idx) {
- // Skip line table rows that terminate the previous row (is_terminal_entry
- // is non-zero)
- if (m_entries[idx].is_terminal_entry)
- continue;
-
- if (!llvm::is_contained(file_indexes, m_entries[idx].file_idx))
- continue;
-
- // Exact match always wins. Otherwise try to find the closest line > the
- // desired line.
- // FIXME: Maybe want to find the line closest before and the line closest
- // after and
- // if they're not in the same function, don't return a match.
-
- if (m_entries[idx].line < line) {
- continue;
- } else if (m_entries[idx].line == line) {
- if (line_entry_ptr)
- ConvertEntryAtIndexToLineEntry(idx, *line_entry_ptr);
- return idx;
- } else if (!exact) {
- if (best_match == UINT32_MAX)
- best_match = idx;
- else if (m_entries[idx].line < m_entries[best_match].line)
- best_match = idx;
- }
- }
-
- if (best_match != UINT32_MAX) {
- if (line_entry_ptr)
- ConvertEntryAtIndexToLineEntry(best_match, *line_entry_ptr);
- return best_match;
- }
- return UINT32_MAX;
+ start_idx, file_idx, src_location_spec, line_entry_ptr, file_idx_matcher);
}
-uint32_t LineTable::FindLineEntryIndexByFileIndex(uint32_t start_idx,
- uint32_t file_idx,
- uint32_t line, bool exact,
- LineEntry *line_entry_ptr) {
- const size_t count = m_entries.size();
- size_t best_match = UINT32_MAX;
-
- for (size_t idx = start_idx; idx < count; ++idx) {
- // Skip line table rows that terminate the previous row (is_terminal_entry
- // is non-zero)
- if (m_entries[idx].is_terminal_entry)
- continue;
-
- if (m_entries[idx].file_idx != file_idx)
- continue;
-
- // Exact match always wins. Otherwise try to find the closest line > the
- // desired line.
- // FIXME: Maybe want to find the line closest before and the line closest
- // after and
- // if they're not in the same function, don't return a match.
-
- if (m_entries[idx].line < line) {
- continue;
- } else if (m_entries[idx].line == line) {
- if (line_entry_ptr)
- ConvertEntryAtIndexToLineEntry(idx, *line_entry_ptr);
- return idx;
- } else if (!exact) {
- if (best_match == UINT32_MAX)
- best_match = idx;
- else if (m_entries[idx].line < m_entries[best_match].line)
- best_match = idx;
- }
- }
+uint32_t LineTable::FindLineEntryIndexByFileIndex(
+ uint32_t start_idx, const std::vector<uint32_t> &file_idx,
+ const SourceLocationSpec &src_location_spec, LineEntry *line_entry_ptr) {
+ auto file_idx_matcher = [](const std::vector<uint32_t> &file_indexes,
+ uint16_t entry_file_idx) {
+ return llvm::is_contained(file_indexes, entry_file_idx);
+ };
- if (best_match != UINT32_MAX) {
- if (line_entry_ptr)
- ConvertEntryAtIndexToLineEntry(best_match, *line_entry_ptr);
- return best_match;
- }
- return UINT32_MAX;
+ return FindLineEntryIndexByFileIndexImpl<std::vector<uint32_t>>(
+ start_idx, file_idx, src_location_spec, line_entry_ptr, file_idx_matcher);
}
size_t LineTable::FineLineEntriesForFileIndex(uint32_t file_idx, bool append,
diff --git a/lldb/source/Symbol/ObjectFile.cpp b/lldb/source/Symbol/ObjectFile.cpp
index f5dcbc5467f7..101af01341a2 100644
--- a/lldb/source/Symbol/ObjectFile.cpp
+++ b/lldb/source/Symbol/ObjectFile.cpp
@@ -616,14 +616,6 @@ ObjectFile::GetSymbolTypeFromName(llvm::StringRef name,
return symbol_type_hint;
}
-ConstString ObjectFile::GetNextSyntheticSymbolName() {
- StreamString ss;
- ConstString file_name = GetModule()->GetFileSpec().GetFilename();
- ss.Printf("___lldb_unnamed_symbol%u$$%s", ++m_synthetic_symbol_idx,
- file_name.GetCString());
- return ConstString(ss.GetString());
-}
-
std::vector<ObjectFile::LoadableData>
ObjectFile::GetLoadableData(Target &target) {
std::vector<LoadableData> loadables;
diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp
index 8d099e0cc7e1..251f9104ad54 100644
--- a/lldb/source/Symbol/Symbol.cpp
+++ b/lldb/source/Symbol/Symbol.cpp
@@ -23,13 +23,12 @@ using namespace lldb;
using namespace lldb_private;
Symbol::Symbol()
- : SymbolContextScope(), m_uid(UINT32_MAX), m_type_data(0),
- m_type_data_resolved(false), m_is_synthetic(false), m_is_debug(false),
- m_is_external(false), m_size_is_sibling(false),
+ : SymbolContextScope(), m_type_data_resolved(false), m_is_synthetic(false),
+ m_is_debug(false), m_is_external(false), m_size_is_sibling(false),
m_size_is_synthesized(false), m_size_is_valid(false),
m_demangled_is_synthesized(false), m_contains_linker_annotations(false),
- m_is_weak(false), m_type(eSymbolTypeInvalid), m_mangled(), m_addr_range(),
- m_flags() {}
+ m_is_weak(false), m_type(eSymbolTypeInvalid), m_mangled(),
+ m_addr_range() {}
Symbol::Symbol(uint32_t symID, llvm::StringRef name, SymbolType type, bool external,
bool is_debug, bool is_trampoline, bool is_artificial,
@@ -57,8 +56,8 @@ Symbol::Symbol(uint32_t symID, const Mangled &mangled, SymbolType type,
m_size_is_synthesized(false),
m_size_is_valid(size_is_valid || range.GetByteSize() > 0),
m_demangled_is_synthesized(false),
- m_contains_linker_annotations(contains_linker_annotations),
- m_is_weak(false), m_type(type), m_mangled(mangled), m_addr_range(range),
+ m_contains_linker_annotations(contains_linker_annotations),
+ m_is_weak(false), m_type(type), m_mangled(mangled), m_addr_range(range),
m_flags(flags) {}
Symbol::Symbol(const Symbol &rhs)
@@ -120,7 +119,7 @@ bool Symbol::ValueIsAddress() const {
}
ConstString Symbol::GetDisplayName() const {
- return m_mangled.GetDisplayDemangledName();
+ return GetMangled().GetDisplayDemangledName();
}
ConstString Symbol::GetReExportedSymbolName() const {
@@ -203,7 +202,7 @@ void Symbol::GetDescription(Stream *s, lldb::DescriptionLevel level,
s->Printf(", value = 0x%16.16" PRIx64,
m_addr_range.GetBaseAddress().GetOffset());
}
- ConstString demangled = m_mangled.GetDemangledName();
+ ConstString demangled = GetMangled().GetDemangledName();
if (demangled)
s->Printf(", name=\"%s\"", demangled.AsCString());
if (m_mangled.GetMangledName())
@@ -219,7 +218,7 @@ void Symbol::Dump(Stream *s, Target *target, uint32_t index,
// Make sure the size of the symbol is up to date before dumping
GetByteSize();
- ConstString name = m_mangled.GetName(name_preference);
+ ConstString name = GetMangled().GetName(name_preference);
if (ValueIsAddress()) {
if (!m_addr_range.GetBaseAddress().Dump(s, nullptr,
Address::DumpStyleFileAddress))
@@ -331,9 +330,11 @@ uint32_t Symbol::GetPrologueByteSize() {
}
bool Symbol::Compare(ConstString name, SymbolType type) const {
- if (type == eSymbolTypeAny || m_type == type)
- return m_mangled.GetMangledName() == name ||
- m_mangled.GetDemangledName() == name;
+ if (type == eSymbolTypeAny || m_type == type) {
+ const Mangled &mangled = GetMangled();
+ return mangled.GetMangledName() == name ||
+ mangled.GetDemangledName() == name;
+ }
return false;
}
@@ -496,10 +497,10 @@ lldb::addr_t Symbol::GetLoadAddress(Target *target) const {
return LLDB_INVALID_ADDRESS;
}
-ConstString Symbol::GetName() const { return m_mangled.GetName(); }
+ConstString Symbol::GetName() const { return GetMangled().GetName(); }
ConstString Symbol::GetNameNoArguments() const {
- return m_mangled.GetName(Mangled::ePreferDemangledWithoutArguments);
+ return GetMangled().GetName(Mangled::ePreferDemangledWithoutArguments);
}
lldb::addr_t Symbol::ResolveCallableAddress(Target &target) const {
@@ -542,10 +543,9 @@ lldb::DisassemblerSP Symbol::GetInstructions(const ExecutionContext &exe_ctx,
bool prefer_file_cache) {
ModuleSP module_sp(m_addr_range.GetBaseAddress().GetModule());
if (module_sp && exe_ctx.HasTargetScope()) {
- const bool prefer_file_cache = false;
return Disassembler::DisassembleRange(module_sp->GetArchitecture(), nullptr,
flavor, exe_ctx.GetTargetRef(),
- m_addr_range, prefer_file_cache);
+ m_addr_range, !prefer_file_cache);
}
return lldb::DisassemblerSP();
}
@@ -567,3 +567,30 @@ bool Symbol::GetDisassembly(const ExecutionContext &exe_ctx, const char *flavor,
bool Symbol::ContainsFileAddress(lldb::addr_t file_addr) const {
return m_addr_range.ContainsFileAddress(file_addr);
}
+
+bool Symbol::IsSyntheticWithAutoGeneratedName() const {
+ if (!IsSynthetic())
+ return false;
+ if (!m_mangled)
+ return true;
+ ConstString demangled = m_mangled.GetDemangledName();
+ return demangled.GetStringRef().startswith(GetSyntheticSymbolPrefix());
+}
+
+void Symbol::SynthesizeNameIfNeeded() const {
+ if (m_is_synthetic && !m_mangled) {
+ // Synthetic symbol names don't mean anything, but they do uniquely
+ // identify individual symbols so we give them a unique name. The name
+ // starts with the synthetic symbol prefix, followed by a unique number.
+ // Typically the UserID of a real symbol is the symbol table index of the
+ // symbol in the object file's symbol table(s), so it will be the same
+ // every time you read in the object file. We want the same persistence for
+ // synthetic symbols so that users can identify them across multiple debug
+ // sessions, to understand crashes in those symbols and to reliably set
+ // breakpoints on them.
+ llvm::SmallString<256> name;
+ llvm::raw_svector_ostream os(name);
+ os << GetSyntheticSymbolPrefix() << GetID();
+ m_mangled.SetDemangledName(ConstString(os.str()));
+ }
+}
diff --git a/lldb/source/Symbol/SymbolContext.cpp b/lldb/source/Symbol/SymbolContext.cpp
index 8cfea35180fa..2e8fe1cec30e 100644
--- a/lldb/source/Symbol/SymbolContext.cpp
+++ b/lldb/source/Symbol/SymbolContext.cpp
@@ -26,9 +26,7 @@
using namespace lldb;
using namespace lldb_private;
-SymbolContext::SymbolContext()
- : target_sp(), module_sp(), comp_unit(nullptr), function(nullptr),
- block(nullptr), line_entry(), symbol(nullptr), variable(nullptr) {}
+SymbolContext::SymbolContext() : target_sp(), module_sp(), line_entry() {}
SymbolContext::SymbolContext(const ModuleSP &m, CompileUnit *cu, Function *f,
Block *b, LineEntry *le, Symbol *s)
@@ -53,7 +51,7 @@ SymbolContext::SymbolContext(SymbolContextScope *sc_scope)
sc_scope->CalculateSymbolContext(this);
}
-SymbolContext::~SymbolContext() {}
+SymbolContext::~SymbolContext() = default;
void SymbolContext::Clear(bool clear_target) {
if (clear_target)
@@ -71,8 +69,7 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
const Address &addr, bool show_fullpaths,
bool show_module, bool show_inlined_frames,
bool show_function_arguments,
- bool show_function_name,
- bool show_inline_callsite_line_info) const {
+ bool show_function_name) const {
bool dumped_something = false;
if (show_module && module_sp) {
if (show_fullpaths)
@@ -128,13 +125,14 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
s->Printf(" + %" PRIu64, inlined_function_offset);
}
}
- if (show_inline_callsite_line_info) {
- const Declaration &call_site = inlined_block_info->GetCallSite();
- if (call_site.IsValid()) {
- s->PutCString(" at ");
- call_site.DumpStopContext(s, show_fullpaths);
- }
- } else if (line_entry.IsValid()) {
+ // "line_entry" will always be valid as GetParentOfInlinedScope(...) will
+ // fill it in correctly with the calling file and line. Previous code
+ // was extracting the calling file and line from inlined_block_info and
+ // using it right away which is not correct. On the first call to this
+ // function "line_entry" will contain the actual line table entry. On
+ // susequent calls "line_entry" will contain the calling file and line
+ // from the previous inline info.
+ if (line_entry.IsValid()) {
s->PutCString(" at ");
line_entry.DumpStopContext(s, show_fullpaths);
}
@@ -928,7 +926,7 @@ SymbolContextSpecifier::SymbolContextSpecifier(const TargetSP &target_sp)
m_start_line(0), m_end_line(0), m_function_spec(), m_class_name(),
m_address_range_up(), m_type(eNothingSpecified) {}
-SymbolContextSpecifier::~SymbolContextSpecifier() {}
+SymbolContextSpecifier::~SymbolContextSpecifier() = default;
bool SymbolContextSpecifier::AddLineSpecification(uint32_t line_no,
SpecificationType type) {
@@ -1188,7 +1186,7 @@ void SymbolContextSpecifier::GetDescription(
SymbolContextList::SymbolContextList() : m_symbol_contexts() {}
-SymbolContextList::~SymbolContextList() {}
+SymbolContextList::~SymbolContextList() = default;
void SymbolContextList::Append(const SymbolContext &sc) {
m_symbol_contexts.push_back(sc);
diff --git a/lldb/source/Symbol/SymbolFile.cpp b/lldb/source/Symbol/SymbolFile.cpp
index 3f9cdefc8d41..152bbe8de6cb 100644
--- a/lldb/source/Symbol/SymbolFile.cpp
+++ b/lldb/source/Symbol/SymbolFile.cpp
@@ -97,10 +97,10 @@ SymbolFile::GetTypeSystemForLanguage(lldb::LanguageType language) {
return type_system_or_err;
}
-uint32_t SymbolFile::ResolveSymbolContext(const FileSpec &file_spec,
- uint32_t line, bool check_inlines,
- lldb::SymbolContextItem resolve_scope,
- SymbolContextList &sc_list) {
+uint32_t
+SymbolFile::ResolveSymbolContext(const SourceLocationSpec &src_location_spec,
+ lldb::SymbolContextItem resolve_scope,
+ SymbolContextList &sc_list) {
return 0;
}
diff --git a/lldb/source/Symbol/Symtab.cpp b/lldb/source/Symbol/Symtab.cpp
index 7f8424334708..313b451601ae 100644
--- a/lldb/source/Symbol/Symtab.cpp
+++ b/lldb/source/Symbol/Symtab.cpp
@@ -9,8 +9,6 @@
#include <map>
#include <set>
-#include "Plugins/Language/ObjC/ObjCLanguage.h"
-
#include "lldb/Core/Module.h"
#include "lldb/Core/RichManglingContext.h"
#include "lldb/Core/Section.h"
@@ -18,6 +16,7 @@
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Symtab.h"
+#include "lldb/Target/Language.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"
@@ -29,10 +28,19 @@ using namespace lldb_private;
Symtab::Symtab(ObjectFile *objfile)
: 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) {}
+ m_name_to_symbol_indices(), m_mutex(),
+ m_file_addr_to_index_computed(false), m_name_indexes_computed(false) {
+ m_name_to_symbol_indices.emplace(std::make_pair(
+ lldb::eFunctionNameTypeNone, UniqueCStringMap<uint32_t>()));
+ m_name_to_symbol_indices.emplace(std::make_pair(
+ lldb::eFunctionNameTypeBase, UniqueCStringMap<uint32_t>()));
+ m_name_to_symbol_indices.emplace(std::make_pair(
+ lldb::eFunctionNameTypeMethod, UniqueCStringMap<uint32_t>()));
+ m_name_to_symbol_indices.emplace(std::make_pair(
+ lldb::eFunctionNameTypeSelector, UniqueCStringMap<uint32_t>()));
+}
-Symtab::~Symtab() {}
+Symtab::~Symtab() = default;
void Symtab::Reserve(size_t count) {
// Clients should grab the mutex from this symbol table and lock it manually
@@ -51,7 +59,8 @@ uint32_t Symtab::AddSymbol(const Symbol &symbol) {
// Clients should grab the mutex from this symbol table and lock it manually
// when calling this function to avoid performance issues.
uint32_t symbol_idx = m_symbols.size();
- m_name_to_index.Clear();
+ auto &name_to_index = GetNameToSymbolIndexMap(lldb::eFunctionNameTypeNone);
+ name_to_index.Clear();
m_file_addr_to_index.Clear();
m_symbols.push_back(symbol);
m_file_addr_to_index_computed = false;
@@ -65,7 +74,8 @@ size_t Symtab::GetNumSymbols() const {
}
void Symtab::SectionFileAddressesChanged() {
- m_name_to_index.Clear();
+ auto &name_to_index = GetNameToSymbolIndexMap(lldb::eFunctionNameTypeNone);
+ name_to_index.Clear();
m_file_addr_to_index_computed = false;
}
@@ -240,6 +250,10 @@ static bool lldb_skip_name(llvm::StringRef mangled,
case Mangled::eManglingSchemeMSVC:
return false;
+ // No filters for this scheme yet. Include all names in indexing.
+ case Mangled::eManglingSchemeRustV0:
+ return false;
+
// Don't try and demangle things we can't categorize.
case Mangled::eManglingSchemeNone:
return true;
@@ -252,9 +266,24 @@ void Symtab::InitNameIndexes() {
if (!m_name_indexes_computed) {
m_name_indexes_computed = true;
LLDB_SCOPED_TIMER();
+
+ // Collect all loaded language plugins.
+ std::vector<Language *> languages;
+ Language::ForEach([&languages](Language *l) {
+ languages.push_back(l);
+ return true;
+ });
+
+ auto &name_to_index = GetNameToSymbolIndexMap(lldb::eFunctionNameTypeNone);
+ auto &basename_to_index =
+ GetNameToSymbolIndexMap(lldb::eFunctionNameTypeBase);
+ auto &method_to_index =
+ GetNameToSymbolIndexMap(lldb::eFunctionNameTypeMethod);
+ auto &selector_to_index =
+ GetNameToSymbolIndexMap(lldb::eFunctionNameTypeSelector);
// Create the name index vector to be able to quickly search by name
const size_t num_symbols = m_symbols.size();
- m_name_to_index.Reserve(num_symbols);
+ name_to_index.Reserve(num_symbols);
// The "const char *" in "class_contexts" and backlog::value_type::second
// must come from a ConstString::GetCString()
@@ -271,22 +300,24 @@ void Symtab::InitNameIndexes() {
// Don't let trampolines get into the lookup by name map If we ever need
// the trampoline symbols to be searchable by name we can remove this and
// then possibly add a new bool to any of the Symtab functions that
- // lookup symbols by name to indicate if they want trampolines.
- if (symbol->IsTrampoline())
+ // lookup symbols by name to indicate if they want trampolines. We also
+ // don't want any synthetic symbols with auto generated names in the
+ // name lookups.
+ if (symbol->IsTrampoline() || symbol->IsSyntheticWithAutoGeneratedName())
continue;
// If the symbol's name string matched a Mangled::ManglingScheme, it is
// stored in the mangled field.
Mangled &mangled = symbol->GetMangled();
if (ConstString name = mangled.GetMangledName()) {
- m_name_to_index.Append(name, value);
+ name_to_index.Append(name, value);
if (symbol->ContainsLinkerAnnotations()) {
// If the symbol has linker annotations, also add the version without
// the annotations.
ConstString stripped = ConstString(
m_objfile->StripLinkerSymbolAnnotations(name.GetStringRef()));
- m_name_to_index.Append(stripped, value);
+ name_to_index.Append(stripped, value);
}
const SymbolType type = symbol->GetType();
@@ -299,25 +330,29 @@ void Symtab::InitNameIndexes() {
// Symbol name strings that didn't match a Mangled::ManglingScheme, are
// stored in the demangled field.
if (ConstString name = mangled.GetDemangledName()) {
- m_name_to_index.Append(name, value);
+ name_to_index.Append(name, value);
if (symbol->ContainsLinkerAnnotations()) {
// If the symbol has linker annotations, also add the version without
// the annotations.
name = ConstString(
m_objfile->StripLinkerSymbolAnnotations(name.GetStringRef()));
- m_name_to_index.Append(name, value);
+ name_to_index.Append(name, value);
}
// If the demangled name turns out to be an ObjC name, and is a category
// name, add the version without categories to the index too.
- ObjCLanguage::MethodName objc_method(name.GetStringRef(), true);
- if (objc_method.IsValid(true)) {
- m_selector_to_index.Append(objc_method.GetSelector(), value);
-
- if (ConstString objc_method_no_category =
- objc_method.GetFullNameWithoutCategory(true))
- m_name_to_index.Append(objc_method_no_category, value);
+ for (Language *lang : languages) {
+ for (auto variant : lang->GetMethodNameVariants(name)) {
+ if (variant.GetType() & lldb::eFunctionNameTypeSelector)
+ selector_to_index.Append(variant.GetName(), value);
+ else if (variant.GetType() & lldb::eFunctionNameTypeFull)
+ name_to_index.Append(variant.GetName(), value);
+ else if (variant.GetType() & lldb::eFunctionNameTypeMethod)
+ method_to_index.Append(variant.GetName(), value);
+ else if (variant.GetType() & lldb::eFunctionNameTypeBase)
+ basename_to_index.Append(variant.GetName(), value);
+ }
}
}
}
@@ -326,14 +361,14 @@ void Symtab::InitNameIndexes() {
RegisterBacklogEntry(record.first, record.second, class_contexts);
}
- m_name_to_index.Sort();
- m_name_to_index.SizeToFit();
- m_selector_to_index.Sort();
- m_selector_to_index.SizeToFit();
- m_basename_to_index.Sort();
- m_basename_to_index.SizeToFit();
- m_method_to_index.Sort();
- m_method_to_index.SizeToFit();
+ name_to_index.Sort();
+ name_to_index.SizeToFit();
+ selector_to_index.Sort();
+ selector_to_index.SizeToFit();
+ basename_to_index.Sort();
+ basename_to_index.SizeToFit();
+ method_to_index.Sort();
+ method_to_index.SizeToFit();
}
}
@@ -356,10 +391,13 @@ void Symtab::RegisterMangledNameEntry(
// Register functions with no context.
if (decl_context.empty()) {
// This has to be a basename
- m_basename_to_index.Append(entry);
+ auto &basename_to_index =
+ GetNameToSymbolIndexMap(lldb::eFunctionNameTypeBase);
+ basename_to_index.Append(entry);
// If there is no context (no namespaces or class scopes that come before
// the function name) then this also could be a fullname.
- m_name_to_index.Append(entry);
+ auto &name_to_index = GetNameToSymbolIndexMap(lldb::eFunctionNameTypeNone);
+ name_to_index.Append(entry);
return;
}
@@ -368,10 +406,12 @@ void Symtab::RegisterMangledNameEntry(
const char *decl_context_ccstr = ConstString(decl_context).GetCString();
auto it = class_contexts.find(decl_context_ccstr);
+ auto &method_to_index =
+ GetNameToSymbolIndexMap(lldb::eFunctionNameTypeMethod);
// Register constructors and destructors. They are methods and create
// declaration contexts.
if (rmc.IsCtorOrDtor()) {
- m_method_to_index.Append(entry);
+ method_to_index.Append(entry);
if (it == class_contexts.end())
class_contexts.insert(it, decl_context_ccstr);
return;
@@ -379,7 +419,7 @@ void Symtab::RegisterMangledNameEntry(
// Register regular methods with a known declaration context.
if (it != class_contexts.end()) {
- m_method_to_index.Append(entry);
+ method_to_index.Append(entry);
return;
}
@@ -391,14 +431,18 @@ void Symtab::RegisterMangledNameEntry(
void Symtab::RegisterBacklogEntry(
const NameToIndexMap::Entry &entry, const char *decl_context,
const std::set<const char *> &class_contexts) {
+ auto &method_to_index =
+ GetNameToSymbolIndexMap(lldb::eFunctionNameTypeMethod);
auto it = class_contexts.find(decl_context);
if (it != class_contexts.end()) {
- m_method_to_index.Append(entry);
+ method_to_index.Append(entry);
} else {
// If we got here, we have something that had a context (was inside
// a namespace or class) yet we don't know the entry
- m_method_to_index.Append(entry);
- m_basename_to_index.Append(entry);
+ method_to_index.Append(entry);
+ auto &basename_to_index =
+ GetNameToSymbolIndexMap(lldb::eFunctionNameTypeBase);
+ basename_to_index.Append(entry);
}
}
@@ -586,6 +630,36 @@ void Symtab::SortSymbolIndexesByValue(std::vector<uint32_t> &indexes,
}
}
+uint32_t Symtab::GetNameIndexes(ConstString symbol_name,
+ std::vector<uint32_t> &indexes) {
+ auto &name_to_index = GetNameToSymbolIndexMap(lldb::eFunctionNameTypeNone);
+ const uint32_t count = name_to_index.GetValues(symbol_name, indexes);
+ if (count)
+ return count;
+ // Synthetic symbol names are not added to the name indexes, but they start
+ // with a prefix and end with a the symbol UserID. This allows users to find
+ // these symbols without having to add them to the name indexes. These
+ // queries will not happen very often since the names don't mean anything, so
+ // performance is not paramount in this case.
+ llvm::StringRef name = symbol_name.GetStringRef();
+ // String the synthetic prefix if the name starts with it.
+ if (!name.consume_front(Symbol::GetSyntheticSymbolPrefix()))
+ return 0; // Not a synthetic symbol name
+
+ // Extract the user ID from the symbol name
+ unsigned long long uid = 0;
+ if (getAsUnsignedInteger(name, /*Radix=*/10, uid))
+ return 0; // Failed to extract the user ID as an integer
+ Symbol *symbol = FindSymbolByID(uid);
+ if (symbol == nullptr)
+ return 0;
+ const uint32_t symbol_idx = GetIndexForSymbol(symbol);
+ if (symbol_idx == UINT32_MAX)
+ return 0;
+ indexes.push_back(symbol_idx);
+ return 1;
+}
+
uint32_t Symtab::AppendSymbolIndexesWithName(ConstString symbol_name,
std::vector<uint32_t> &indexes) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
@@ -595,7 +669,7 @@ uint32_t Symtab::AppendSymbolIndexesWithName(ConstString symbol_name,
if (!m_name_indexes_computed)
InitNameIndexes();
- return m_name_to_index.GetValues(symbol_name, indexes);
+ return GetNameIndexes(symbol_name, indexes);
}
return 0;
}
@@ -614,7 +688,7 @@ uint32_t Symtab::AppendSymbolIndexesWithName(ConstString symbol_name,
std::vector<uint32_t> all_name_indexes;
const size_t name_match_count =
- m_name_to_index.GetValues(symbol_name, all_name_indexes);
+ GetNameIndexes(symbol_name, all_name_indexes);
for (size_t i = 0; i < name_match_count; ++i) {
if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type,
symbol_visibility))
@@ -1035,45 +1109,18 @@ void Symtab::FindFunctionSymbols(ConstString name, uint32_t name_type_mask,
}
}
- if (name_type_mask & eFunctionNameTypeBase) {
- // From mangled names we can't tell what is a basename and what is a method
- // name, so we just treat them the same
- if (!m_name_indexes_computed)
- InitNameIndexes();
-
- if (!m_basename_to_index.IsEmpty()) {
- const UniqueCStringMap<uint32_t>::Entry *match;
- for (match = m_basename_to_index.FindFirstValueForName(name);
- match != nullptr;
- match = m_basename_to_index.FindNextValueForName(match)) {
- symbol_indexes.push_back(match->value);
- }
- }
- }
-
- if (name_type_mask & eFunctionNameTypeMethod) {
- if (!m_name_indexes_computed)
- InitNameIndexes();
-
- if (!m_method_to_index.IsEmpty()) {
- const UniqueCStringMap<uint32_t>::Entry *match;
- for (match = m_method_to_index.FindFirstValueForName(name);
- match != nullptr;
- match = m_method_to_index.FindNextValueForName(match)) {
- symbol_indexes.push_back(match->value);
- }
- }
- }
+ if (!m_name_indexes_computed)
+ InitNameIndexes();
- if (name_type_mask & eFunctionNameTypeSelector) {
- if (!m_name_indexes_computed)
- InitNameIndexes();
+ for (lldb::FunctionNameType type :
+ {lldb::eFunctionNameTypeBase, lldb::eFunctionNameTypeMethod,
+ lldb::eFunctionNameTypeSelector}) {
+ if (name_type_mask & type) {
+ auto map = GetNameToSymbolIndexMap(type);
- if (!m_selector_to_index.IsEmpty()) {
const UniqueCStringMap<uint32_t>::Entry *match;
- for (match = m_selector_to_index.FindFirstValueForName(name);
- match != nullptr;
- match = m_selector_to_index.FindNextValueForName(match)) {
+ for (match = map.FindFirstValueForName(name); match != nullptr;
+ match = map.FindNextValueForName(match)) {
symbol_indexes.push_back(match->value);
}
}
diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp
index df5dab19dbf3..5b4169d256d2 100644
--- a/lldb/source/Symbol/Type.cpp
+++ b/lldb/source/Symbol/Type.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <stdio.h>
+#include <cstdio>
#include "lldb/Core/Module.h"
#include "lldb/Utility/DataBufferHeap.h"
@@ -161,10 +161,8 @@ Type::Type(lldb::user_id_t uid, SymbolFile *symbol_file, ConstString name,
}
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_compiler_type_resolve_state(ResolveState::Unresolved) {
+ : std::enable_shared_from_this<Type>(), UserID(0),
+ m_name("<INVALID TYPE>") {
m_byte_size = 0;
m_byte_size_has_value = false;
}
@@ -730,7 +728,8 @@ ModuleSP Type::GetModule() {
ModuleSP Type::GetExeModule() {
if (m_compiler_type) {
SymbolFile *symbol_file = m_compiler_type.GetTypeSystem()->GetSymbolFile();
- return symbol_file->GetObjectFile()->GetModule();
+ if (symbol_file)
+ return symbol_file->GetObjectFile()->GetModule();
}
return ModuleSP();
}
diff --git a/lldb/source/Symbol/TypeList.cpp b/lldb/source/Symbol/TypeList.cpp
index f0506c7c5bfc..ace715d933ea 100644
--- a/lldb/source/Symbol/TypeList.cpp
+++ b/lldb/source/Symbol/TypeList.cpp
@@ -22,7 +22,7 @@ using namespace lldb_private;
TypeList::TypeList() : m_types() {}
// Destructor
-TypeList::~TypeList() {}
+TypeList::~TypeList() = default;
void TypeList::Insert(const TypeSP &type_sp) {
// Just push each type on the back for now. We will worry about uniquing
diff --git a/lldb/source/Symbol/TypeMap.cpp b/lldb/source/Symbol/TypeMap.cpp
index e810d3020073..2cda9b6c27d1 100644
--- a/lldb/source/Symbol/TypeMap.cpp
+++ b/lldb/source/Symbol/TypeMap.cpp
@@ -22,7 +22,7 @@ using namespace lldb_private;
TypeMap::TypeMap() : m_types() {}
// Destructor
-TypeMap::~TypeMap() {}
+TypeMap::~TypeMap() = default;
void TypeMap::Insert(const TypeSP &type_sp) {
// Just push each type on the back for now. We will worry about uniquing
diff --git a/lldb/source/Symbol/TypeSystem.cpp b/lldb/source/Symbol/TypeSystem.cpp
index 2adf36fa8276..252b06e269d6 100644
--- a/lldb/source/Symbol/TypeSystem.cpp
+++ b/lldb/source/Symbol/TypeSystem.cpp
@@ -35,7 +35,7 @@ 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() {}
+TypeSystem::~TypeSystem() = default;
static lldb::TypeSystemSP CreateInstanceHelper(lldb::LanguageType language,
Module *module, Target *target) {
@@ -178,10 +178,9 @@ TypeSystem::CreateUtilityFunction(std::string text, std::string name) {
#pragma mark TypeSystemMap
-TypeSystemMap::TypeSystemMap()
- : m_mutex(), m_map(), m_clear_in_progress(false) {}
+TypeSystemMap::TypeSystemMap() : m_mutex(), m_map() {}
-TypeSystemMap::~TypeSystemMap() {}
+TypeSystemMap::~TypeSystemMap() = default;
void TypeSystemMap::Clear() {
collection map;
diff --git a/lldb/source/Symbol/UnwindPlan.cpp b/lldb/source/Symbol/UnwindPlan.cpp
index d24cabed14ce..41bd8cd46ad8 100644
--- a/lldb/source/Symbol/UnwindPlan.cpp
+++ b/lldb/source/Symbol/UnwindPlan.cpp
@@ -217,6 +217,7 @@ void UnwindPlan::Row::Clear() {
m_cfa_value.SetUnspecified();
m_afa_value.SetUnspecified();
m_offset = 0;
+ m_unspecified_registers_are_undefined = false;
m_register_locations.clear();
}
@@ -242,11 +243,9 @@ void UnwindPlan::Row::Dump(Stream &s, const UnwindPlan *unwind_plan,
idx->second.Dump(s, unwind_plan, this, thread, verbose);
s.PutChar(' ');
}
- s.EOL();
}
-UnwindPlan::Row::Row()
- : m_offset(0), m_cfa_value(), m_afa_value(), m_register_locations() {}
+UnwindPlan::Row::Row() : m_cfa_value(), m_afa_value(), m_register_locations() {}
bool UnwindPlan::Row::GetRegisterInfo(
uint32_t reg_num,
@@ -256,6 +255,10 @@ bool UnwindPlan::Row::GetRegisterInfo(
register_location = pos->second;
return true;
}
+ if (m_unspecified_registers_are_undefined) {
+ register_location.SetUndefined();
+ return true;
+ }
return false;
}
@@ -348,10 +351,11 @@ bool UnwindPlan::Row::SetRegisterLocationToSame(uint32_t reg_num,
}
bool UnwindPlan::Row::operator==(const UnwindPlan::Row &rhs) const {
- return m_offset == rhs.m_offset &&
- m_cfa_value == rhs.m_cfa_value &&
- m_afa_value == rhs.m_afa_value &&
- m_register_locations == rhs.m_register_locations;
+ return m_offset == rhs.m_offset && m_cfa_value == rhs.m_cfa_value &&
+ m_afa_value == rhs.m_afa_value &&
+ m_unspecified_registers_are_undefined ==
+ rhs.m_unspecified_registers_are_undefined &&
+ m_register_locations == rhs.m_register_locations;
}
void UnwindPlan::AppendRow(const UnwindPlan::RowSP &row_sp) {
@@ -552,6 +556,7 @@ void UnwindPlan::Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const {
for (pos = begin; pos != end; ++pos) {
s.Printf("row[%u]: ", (uint32_t)std::distance(begin, pos));
(*pos)->Dump(s, this, thread, base_addr);
+ s.Printf("\n");
}
}
diff --git a/lldb/source/Symbol/UnwindTable.cpp b/lldb/source/Symbol/UnwindTable.cpp
index 3faa528a339f..fe69e41b3638 100644
--- a/lldb/source/Symbol/UnwindTable.cpp
+++ b/lldb/source/Symbol/UnwindTable.cpp
@@ -8,7 +8,7 @@
#include "lldb/Symbol/UnwindTable.h"
-#include <stdio.h>
+#include <cstdio>
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
@@ -83,7 +83,7 @@ void UnwindTable::Initialize() {
}
}
-UnwindTable::~UnwindTable() {}
+UnwindTable::~UnwindTable() = default;
llvm::Optional<AddressRange> UnwindTable::GetAddressRange(const Address &addr,
SymbolContext &sc) {
diff --git a/lldb/source/Symbol/Variable.cpp b/lldb/source/Symbol/Variable.cpp
index 62b16011fe66..89682fc39141 100644
--- a/lldb/source/Symbol/Variable.cpp
+++ b/lldb/source/Symbol/Variable.cpp
@@ -49,7 +49,7 @@ Variable::Variable(lldb::user_id_t uid, const char *name, const char *mangled,
m_artificial(artificial), m_loc_is_const_data(location_is_constant_data),
m_static_member(static_member) {}
-Variable::~Variable() {}
+Variable::~Variable() = default;
lldb::LanguageType Variable::GetLanguage() const {
lldb::LanguageType lang = m_mangled.GuessLanguage();
diff --git a/lldb/source/Symbol/VariableList.cpp b/lldb/source/Symbol/VariableList.cpp
index f7a441472bc0..b7a396edd701 100644
--- a/lldb/source/Symbol/VariableList.cpp
+++ b/lldb/source/Symbol/VariableList.cpp
@@ -20,7 +20,7 @@ using namespace lldb_private;
VariableList::VariableList() : m_variables() {}
// Destructor
-VariableList::~VariableList() {}
+VariableList::~VariableList() = default;
void VariableList::AddVariable(const VariableSP &var_sp) {
m_variables.push_back(var_sp);
diff --git a/lldb/source/Target/ABI.cpp b/lldb/source/Target/ABI.cpp
index f6a531136dcb..c3342caf8742 100644
--- a/lldb/source/Target/ABI.cpp
+++ b/lldb/source/Target/ABI.cpp
@@ -120,11 +120,13 @@ ValueObjectSP ABI::GetReturnValueObject(Thread &thread, CompilerType &ast_type,
const Value &result_value = live_valobj_sp->GetValue();
switch (result_value.GetValueType()) {
- case Value::eValueTypeHostAddress:
- case Value::eValueTypeFileAddress:
- // we don't do anything with these for now
+ case Value::ValueType::Invalid:
+ return {};
+ case Value::ValueType::HostAddress:
+ case Value::ValueType::FileAddress:
+ // we odon't do anything with these for now
break;
- case Value::eValueTypeScalar:
+ case Value::ValueType::Scalar:
expr_variable_sp->m_flags |=
ExpressionVariable::EVIsFreezeDried;
expr_variable_sp->m_flags |=
@@ -132,7 +134,7 @@ ValueObjectSP ABI::GetReturnValueObject(Thread &thread, CompilerType &ast_type,
expr_variable_sp->m_flags |=
ExpressionVariable::EVNeedsAllocation;
break;
- case Value::eValueTypeLoadAddress:
+ case Value::ValueType::LoadAddress:
expr_variable_sp->m_live_sp = live_valobj_sp;
expr_variable_sp->m_flags |=
ExpressionVariable::EVIsProgramReference;
diff --git a/lldb/source/Target/AssertFrameRecognizer.cpp b/lldb/source/Target/AssertFrameRecognizer.cpp
index cb671040d14f..a2315b6d63c6 100644
--- a/lldb/source/Target/AssertFrameRecognizer.cpp
+++ b/lldb/source/Target/AssertFrameRecognizer.cpp
@@ -22,6 +22,10 @@ namespace lldb_private {
struct SymbolLocation {
FileSpec module_spec;
std::vector<ConstString> symbols;
+
+ // The symbols are regular expressions. In such case all symbols are matched
+ // with their trailing @VER symbol version stripped.
+ bool symbols_are_regex = false;
};
/// Fetches the abort frame location depending on the current platform.
@@ -45,6 +49,8 @@ bool GetAbortLocation(llvm::Triple::OSType os, SymbolLocation &location) {
location.symbols.push_back(ConstString("raise"));
location.symbols.push_back(ConstString("__GI_raise"));
location.symbols.push_back(ConstString("gsignal"));
+ location.symbols.push_back(ConstString("pthread_kill"));
+ location.symbols_are_regex = true;
break;
default:
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
@@ -93,9 +99,33 @@ void RegisterAssertFrameRecognizer(Process *process) {
if (!GetAbortLocation(os, location))
return;
+ if (!location.symbols_are_regex) {
+ target.GetFrameRecognizerManager().AddRecognizer(
+ std::make_shared<AssertFrameRecognizer>(),
+ location.module_spec.GetFilename(), location.symbols,
+ /*first_instruction_only*/ false);
+ return;
+ }
+ std::string module_re = "^";
+ for (char c : location.module_spec.GetFilename().GetStringRef()) {
+ if (c == '.')
+ module_re += '\\';
+ module_re += c;
+ }
+ module_re += '$';
+ std::string symbol_re = "^(";
+ for (auto it = location.symbols.cbegin(); it != location.symbols.cend();
+ ++it) {
+ if (it != location.symbols.cbegin())
+ symbol_re += '|';
+ symbol_re += it->GetStringRef();
+ }
+ // Strip the trailing @VER symbol version.
+ symbol_re += ")(@.*)?$";
target.GetFrameRecognizerManager().AddRecognizer(
- StackFrameRecognizerSP(new AssertFrameRecognizer()),
- location.module_spec.GetFilename(), location.symbols,
+ std::make_shared<AssertFrameRecognizer>(),
+ std::make_shared<RegularExpression>(std::move(module_re)),
+ std::make_shared<RegularExpression>(std::move(symbol_re)),
/*first_instruction_only*/ false);
}
@@ -112,7 +142,7 @@ AssertFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame_sp) {
if (!GetAssertLocation(os, location))
return RecognizedStackFrameSP();
- const uint32_t frames_to_fetch = 5;
+ const uint32_t frames_to_fetch = 6;
const uint32_t last_frame_index = frames_to_fetch - 1;
StackFrameSP prev_frame_sp = nullptr;
diff --git a/lldb/source/Target/ExecutionContext.cpp b/lldb/source/Target/ExecutionContext.cpp
index 20932ee63dce..b5cf13582af1 100644
--- a/lldb/source/Target/ExecutionContext.cpp
+++ b/lldb/source/Target/ExecutionContext.cpp
@@ -395,8 +395,7 @@ bool ExecutionContext::HasFrameScope() const {
}
ExecutionContextRef::ExecutionContextRef()
- : m_target_wp(), m_process_wp(), m_thread_wp(),
- m_tid(LLDB_INVALID_THREAD_ID), m_stack_id() {}
+ : m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() {}
ExecutionContextRef::ExecutionContextRef(const ExecutionContext *exe_ctx)
: m_target_wp(), m_process_wp(), m_thread_wp(),
diff --git a/lldb/source/Target/JITLoaderList.cpp b/lldb/source/Target/JITLoaderList.cpp
index f5a90d58d588..92e841b5c94d 100644
--- a/lldb/source/Target/JITLoaderList.cpp
+++ b/lldb/source/Target/JITLoaderList.cpp
@@ -15,7 +15,7 @@ using namespace lldb_private;
JITLoaderList::JITLoaderList() : m_jit_loaders_vec(), m_jit_loaders_mutex() {}
-JITLoaderList::~JITLoaderList() {}
+JITLoaderList::~JITLoaderList() = default;
void JITLoaderList::Append(const JITLoaderSP &jit_loader_sp) {
std::lock_guard<std::recursive_mutex> guard(m_jit_loaders_mutex);
diff --git a/lldb/source/Target/Language.cpp b/lldb/source/Target/Language.cpp
index b1a8a9517f3f..7b35da5028ac 100644
--- a/lldb/source/Target/Language.cpp
+++ b/lldb/source/Target/Language.cpp
@@ -184,7 +184,7 @@ struct language_name_pair language_names[] = {
{"fortran03", eLanguageTypeFortran03},
{"fortran08", eLanguageTypeFortran08},
// Vendor Extensions
- {"mipsassem", eLanguageTypeMipsAssembler},
+ {"assembler", eLanguageTypeMipsAssembler},
{"renderscript", eLanguageTypeExtRenderScript},
// Now synonyms, in arbitrary order
{"objc", eLanguageTypeObjC},
@@ -196,7 +196,7 @@ static uint32_t num_languages =
LanguageType Language::GetLanguageTypeFromString(llvm::StringRef string) {
for (const auto &L : language_names) {
- if (string.equals_lower(L.name))
+ if (string.equals_insensitive(L.name))
return static_cast<LanguageType>(L.type);
}
@@ -448,7 +448,7 @@ void Language::GetDefaultExceptionResolverDescription(bool catch_on,
catch_on ? "on" : "off", throw_on ? "on" : "off");
}
// Constructor
-Language::Language() {}
+Language::Language() = default;
// Destructor
-Language::~Language() {}
+Language::~Language() = default;
diff --git a/lldb/source/Target/LanguageRuntime.cpp b/lldb/source/Target/LanguageRuntime.cpp
index f2e2febf8b88..be878d69fa00 100644
--- a/lldb/source/Target/LanguageRuntime.cpp
+++ b/lldb/source/Target/LanguageRuntime.cpp
@@ -259,6 +259,25 @@ BreakpointSP LanguageRuntime::CreateExceptionBreakpoint(
return exc_breakpt_sp;
}
+UnwindPlanSP
+LanguageRuntime::GetRuntimeUnwindPlan(Thread &thread, RegisterContext *regctx,
+ bool &behaves_like_zeroth_frame) {
+ ProcessSP process_sp = thread.GetProcess();
+ if (!process_sp.get())
+ return UnwindPlanSP();
+ if (process_sp->GetDisableLangRuntimeUnwindPlans() == true)
+ return UnwindPlanSP();
+ for (const lldb::LanguageType lang_type : Language::GetSupportedLanguages()) {
+ if (LanguageRuntime *runtime = process_sp->GetLanguageRuntime(lang_type)) {
+ UnwindPlanSP plan_sp = runtime->GetRuntimeUnwindPlan(
+ process_sp, regctx, behaves_like_zeroth_frame);
+ if (plan_sp.get())
+ return plan_sp;
+ }
+ }
+ return UnwindPlanSP();
+}
+
void LanguageRuntime::InitializeCommands(CommandObject *parent) {
if (!parent)
return;
diff --git a/lldb/source/Target/Memory.cpp b/lldb/source/Target/Memory.cpp
index a7ed1a3d97b7..806e92aa4ed5 100644
--- a/lldb/source/Target/Memory.cpp
+++ b/lldb/source/Target/Memory.cpp
@@ -26,7 +26,7 @@ MemoryCache::MemoryCache(Process &process)
m_L2_cache_line_byte_size(process.GetMemoryCacheLineSize()) {}
// Destructor
-MemoryCache::~MemoryCache() {}
+MemoryCache::~MemoryCache() = default;
void MemoryCache::Clear(bool clear_invalid_ranges) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
@@ -259,7 +259,7 @@ AllocatedBlock::AllocatedBlock(lldb::addr_t addr, uint32_t byte_size,
assert(byte_size > chunk_size);
}
-AllocatedBlock::~AllocatedBlock() {}
+AllocatedBlock::~AllocatedBlock() = default;
lldb::addr_t AllocatedBlock::ReserveBlock(uint32_t size) {
// We must return something valid for zero bytes.
@@ -329,7 +329,7 @@ bool AllocatedBlock::FreeBlock(addr_t addr) {
AllocatedMemoryCache::AllocatedMemoryCache(Process &process)
: m_process(process), m_mutex(), m_memory_map() {}
-AllocatedMemoryCache::~AllocatedMemoryCache() {}
+AllocatedMemoryCache::~AllocatedMemoryCache() = default;
void AllocatedMemoryCache::Clear() {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
diff --git a/lldb/source/Target/ModuleCache.cpp b/lldb/source/Target/ModuleCache.cpp
index 20661a7b7a25..dcdc0772b31a 100644
--- a/lldb/source/Target/ModuleCache.cpp
+++ b/lldb/source/Target/ModuleCache.cpp
@@ -17,7 +17,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileUtilities.h"
-#include <assert.h>
+#include <cassert>
#include <cstdio>
diff --git a/lldb/source/Target/PathMappingList.cpp b/lldb/source/Target/PathMappingList.cpp
index b22673f55471..b660c310ef31 100644
--- a/lldb/source/Target/PathMappingList.cpp
+++ b/lldb/source/Target/PathMappingList.cpp
@@ -37,8 +37,7 @@ namespace {
}
}
// PathMappingList constructor
-PathMappingList::PathMappingList()
- : m_pairs(), m_callback(nullptr), m_callback_baton(nullptr), m_mod_id(0) {}
+PathMappingList::PathMappingList() : m_pairs() {}
PathMappingList::PathMappingList(ChangedCallback callback, void *callback_baton)
: m_pairs(), m_callback(callback), m_callback_baton(callback_baton),
@@ -146,21 +145,37 @@ void PathMappingList::Clear(bool notify) {
bool PathMappingList::RemapPath(ConstString path,
ConstString &new_path) const {
- std::string remapped;
- if (RemapPath(path.GetStringRef(), remapped)) {
- new_path.SetString(remapped);
+ if (llvm::Optional<FileSpec> remapped = RemapPath(path.GetStringRef())) {
+ new_path.SetString(remapped->GetPath());
return true;
}
return false;
}
-bool PathMappingList::RemapPath(llvm::StringRef path,
- std::string &new_path) const {
- if (m_pairs.empty() || path.empty())
- return false;
+/// Append components to path, applying style.
+static void AppendPathComponents(FileSpec &path, llvm::StringRef components,
+ llvm::sys::path::Style style) {
+ auto component = llvm::sys::path::begin(components, style);
+ auto e = llvm::sys::path::end(components);
+ while (component != e &&
+ llvm::sys::path::is_separator(*component->data(), style))
+ ++component;
+ for (; component != e; ++component)
+ path.AppendPathComponent(*component);
+}
+
+llvm::Optional<FileSpec>
+PathMappingList::RemapPath(llvm::StringRef mapping_path,
+ bool only_if_exists) const {
+ if (m_pairs.empty() || mapping_path.empty())
+ return {};
LazyBool path_is_relative = eLazyBoolCalculate;
+
for (const auto &it : m_pairs) {
- auto prefix = it.first.GetStringRef();
+ llvm::StringRef prefix = it.first.GetStringRef();
+ // We create a copy of mapping_path because StringRef::consume_from
+ // effectively modifies the instance itself.
+ llvm::StringRef path = mapping_path;
if (!path.consume_front(prefix)) {
// Relative paths won't have a leading "./" in them unless "." is the
// only thing in the relative path so we need to work around "."
@@ -177,11 +192,13 @@ bool PathMappingList::RemapPath(llvm::StringRef path,
continue;
}
FileSpec remapped(it.second.GetStringRef());
- remapped.AppendPathComponent(path);
- new_path = remapped.GetPath();
- return true;
+ auto orig_style = FileSpec::GuessPathStyle(prefix).getValueOr(
+ llvm::sys::path::Style::native);
+ AppendPathComponents(remapped, path, orig_style);
+ if (!only_if_exists || FileSystem::Instance().Exists(remapped))
+ return remapped;
}
- return false;
+ return {};
}
bool PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) const {
@@ -190,56 +207,21 @@ bool PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) co
for (const auto &it : m_pairs) {
if (!path_ref.consume_front(it.second.GetStringRef()))
continue;
- fixed.SetFile(it.first.GetStringRef(), FileSpec::Style::native);
- fixed.AppendPathComponent(path_ref);
+ auto orig_file = it.first.GetStringRef();
+ auto orig_style = FileSpec::GuessPathStyle(orig_file).getValueOr(
+ llvm::sys::path::Style::native);
+ fixed.SetFile(orig_file, orig_style);
+ AppendPathComponents(fixed, path_ref, orig_style);
return true;
}
return false;
}
-bool PathMappingList::FindFile(const FileSpec &orig_spec,
- FileSpec &new_spec) const {
- if (m_pairs.empty())
- return false;
-
- std::string orig_path = orig_spec.GetPath();
-
- if (orig_path.empty())
- return false;
-
- bool orig_is_relative = orig_spec.IsRelative();
+llvm::Optional<FileSpec> PathMappingList::FindFile(const FileSpec &orig_spec) const {
+ if (auto remapped = RemapPath(orig_spec.GetPath(), /*only_if_exists=*/true))
+ return remapped;
- for (auto entry : m_pairs) {
- llvm::StringRef orig_ref(orig_path);
- llvm::StringRef prefix_ref = entry.first.GetStringRef();
- if (orig_ref.size() < prefix_ref.size())
- continue;
- // We consider a relative prefix or one of just "." to
- // mean "only apply to relative paths".
- bool prefix_is_relative = false;
-
- if (prefix_ref == ".") {
- prefix_is_relative = true;
- // Remove the "." since it will have been removed from the
- // FileSpec paths already.
- prefix_ref = prefix_ref.drop_front();
- } else {
- FileSpec prefix_spec(prefix_ref, FileSpec::Style::native);
- prefix_is_relative = prefix_spec.IsRelative();
- }
- if (prefix_is_relative != orig_is_relative)
- continue;
-
- if (orig_ref.consume_front(prefix_ref)) {
- new_spec.SetFile(entry.second.GetCString(), FileSpec::Style::native);
- new_spec.AppendPathComponent(orig_ref);
- if (FileSystem::Instance().Exists(new_spec))
- return true;
- }
- }
-
- new_spec.Clear();
- return false;
+ return {};
}
bool PathMappingList::Replace(ConstString path,
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 518a6934059e..8ecc66b592ea 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -10,6 +10,7 @@
#include <memory>
#include <mutex>
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/Threading.h"
@@ -68,6 +69,7 @@
#include "lldb/Utility/ProcessInfo.h"
#include "lldb/Utility/SelectHelper.h"
#include "lldb/Utility/State.h"
+#include "lldb/Utility/Timer.h"
using namespace lldb;
using namespace lldb_private;
@@ -83,16 +85,10 @@ using namespace std::chrono;
#define DISABLE_MEM_CACHE_DEFAULT true
#endif
-class ProcessOptionValueProperties : public OptionValueProperties {
+class ProcessOptionValueProperties
+ : public Cloneable<ProcessOptionValueProperties, OptionValueProperties> {
public:
- ProcessOptionValueProperties(ConstString name)
- : OptionValueProperties(name) {}
-
- // This constructor is used when creating ProcessOptionValueProperties when
- // it is part of a new lldb_private::Process instance. It will copy all
- // current global property values as needed
- ProcessOptionValueProperties(ProcessProperties *global_properties)
- : OptionValueProperties(*global_properties->GetValueProperties()) {}
+ ProcessOptionValueProperties(ConstString name) : Cloneable(name) {}
const Property *GetPropertyAtIndex(const ExecutionContext *exe_ctx,
bool will_modify,
@@ -131,10 +127,12 @@ enum {
#include "TargetPropertiesEnum.inc"
};
-class ProcessExperimentalOptionValueProperties : public OptionValueProperties {
+class ProcessExperimentalOptionValueProperties
+ : public Cloneable<ProcessExperimentalOptionValueProperties,
+ OptionValueProperties> {
public:
ProcessExperimentalOptionValueProperties()
- : OptionValueProperties(
+ : Cloneable(
ConstString(Properties::GetExperimentalSettingsName())) {}
};
@@ -157,8 +155,8 @@ ProcessProperties::ProcessProperties(lldb_private::Process *process)
ConstString("thread"), ConstString("Settings specific to threads."),
true, Thread::GetGlobalProperties()->GetValueProperties());
} else {
- m_collection_sp = std::make_shared<ProcessOptionValueProperties>(
- Process::GetGlobalProperties().get());
+ m_collection_sp =
+ OptionValueProperties::CreateLocalCopy(*Process::GetGlobalProperties());
m_collection_sp->SetValueChangedCallback(
ePropertyPythonOSPluginPath,
[this] { m_process->LoadOperatingSystemPlugin(true); });
@@ -204,6 +202,16 @@ FileSpec ProcessProperties::GetPythonOSPluginPath() const {
return m_collection_sp->GetPropertyAtIndexAsFileSpec(nullptr, idx);
}
+uint32_t ProcessProperties::GetVirtualAddressableBits() const {
+ const uint32_t idx = ePropertyVirtualAddressableBits;
+ return m_collection_sp->GetPropertyAtIndexAsUInt64(
+ nullptr, idx, g_process_properties[idx].default_uint_value);
+}
+
+void ProcessProperties::SetVirtualAddressableBits(uint32_t bits) {
+ const uint32_t idx = ePropertyVirtualAddressableBits;
+ m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, bits);
+}
void ProcessProperties::SetPythonOSPluginPath(const FileSpec &file) {
const uint32_t idx = ePropertyPythonOSPluginPath;
m_collection_sp->SetPropertyAtIndexAsFileSpec(nullptr, idx, file);
@@ -242,6 +250,18 @@ void ProcessProperties::SetStopOnSharedLibraryEvents(bool stop) {
m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, stop);
}
+bool ProcessProperties::GetDisableLangRuntimeUnwindPlans() const {
+ const uint32_t idx = ePropertyDisableLangRuntimeUnwindPlans;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_process_properties[idx].default_uint_value != 0);
+}
+
+void ProcessProperties::SetDisableLangRuntimeUnwindPlans(bool disable) {
+ const uint32_t idx = ePropertyDisableLangRuntimeUnwindPlans;
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, disable);
+ m_process->Flush();
+}
+
bool ProcessProperties::GetDetachKeepsStopped() const {
const uint32_t idx = ePropertyDetachKeepsStopped;
return m_collection_sp->GetPropertyAtIndexAsBoolean(
@@ -278,6 +298,13 @@ std::chrono::seconds ProcessProperties::GetUtilityExpressionTimeout() const {
return std::chrono::seconds(value);
}
+std::chrono::seconds ProcessProperties::GetInterruptTimeout() const {
+ const uint32_t idx = ePropertyInterruptTimeout;
+ uint64_t value = m_collection_sp->GetPropertyAtIndexAsUInt64(
+ nullptr, idx, g_process_properties[idx].default_uint_value);
+ return std::chrono::seconds(value);
+}
+
bool ProcessProperties::GetSteppingRunsAllThreads() const {
const uint32_t idx = ePropertySteppingRunsAllThreads;
return m_collection_sp->GetPropertyAtIndexAsBoolean(
@@ -466,25 +493,9 @@ void Process::Finalize() {
if (m_finalizing.exchange(true))
return;
- // Destroy this process if needed
- switch (GetPrivateState()) {
- case eStateConnected:
- case eStateAttaching:
- case eStateLaunching:
- case eStateStopped:
- case eStateRunning:
- case eStateStepping:
- case eStateCrashed:
- case eStateSuspended:
- DestroyImpl(false);
- break;
-
- case eStateInvalid:
- case eStateUnloaded:
- case eStateDetached:
- case eStateExited:
- break;
- }
+ // Destroy the process. This will call the virtual function DoDestroy under
+ // the hood, giving our derived class a chance to do the ncessary tear down.
+ DestroyImpl(false);
// Clear our broadcaster before we proceed with destroying
Broadcaster::Clear();
@@ -766,13 +777,30 @@ bool Process::HandleProcessStateChangedEvent(const EventSP &event_sp,
ThreadSP curr_thread(thread_list.GetSelectedThread());
ThreadSP thread;
StopReason curr_thread_stop_reason = eStopReasonInvalid;
- if (curr_thread) {
+ bool prefer_curr_thread = false;
+ if (curr_thread && curr_thread->IsValid()) {
curr_thread_stop_reason = curr_thread->GetStopReason();
+ switch (curr_thread_stop_reason) {
+ case eStopReasonNone:
+ case eStopReasonInvalid:
+ // Don't prefer the current thread if it didn't stop for a reason.
+ break;
+ case eStopReasonSignal: {
+ // We need to do the same computation we do for other threads
+ // below in case the current thread happens to be the one that
+ // stopped for the no-stop signal.
+ uint64_t signo = curr_thread->GetStopInfo()->GetValue();
+ if (process_sp->GetUnixSignals()->GetShouldStop(signo))
+ prefer_curr_thread = true;
+ } break;
+ default:
+ prefer_curr_thread = true;
+ break;
+ }
curr_thread_stop_info_sp = curr_thread->GetStopInfo();
}
- if (!curr_thread || !curr_thread->IsValid() ||
- curr_thread_stop_reason == eStopReasonInvalid ||
- curr_thread_stop_reason == eStopReasonNone) {
+
+ if (!prefer_curr_thread) {
// Prefer a thread that has just completed its plan over another
// thread as current thread.
ThreadSP plan_thread;
@@ -804,8 +832,12 @@ bool Process::HandleProcessStateChangedEvent(const EventSP &event_sp,
case eStopReasonWatchpoint:
case eStopReasonException:
case eStopReasonExec:
+ case eStopReasonFork:
+ case eStopReasonVFork:
+ case eStopReasonVForkDone:
case eStopReasonThreadExiting:
case eStopReasonInstrumentation:
+ case eStopReasonProcessorTrace:
if (!other_thread)
other_thread = thread;
break;
@@ -1311,8 +1343,8 @@ Status Process::ResumeSynchronous(Stream *stream) {
Status error = PrivateResume();
if (error.Success()) {
- StateType state =
- WaitForProcessToStop(llvm::None, nullptr, true, listener_sp, stream);
+ StateType state = WaitForProcessToStop(llvm::None, nullptr, true,
+ listener_sp, stream);
const bool must_be_alive =
false; // eStateExited is ok, so this must be false
if (!StateIsStoppedState(state, must_be_alive))
@@ -1356,8 +1388,8 @@ void Process::SetPrivateState(StateType new_state) {
if (m_finalizing)
return;
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STATE |
- LIBLLDB_LOG_PROCESS));
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(
+ LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_UNWIND));
bool state_changed = false;
LLDB_LOGF(log, "Process::SetPrivateState (%s)", StateAsCString(new_state));
@@ -2022,6 +2054,8 @@ size_t Process::ReadCStringFromMemory(addr_t addr, char *dst,
size_t Process::ReadMemoryFromInferior(addr_t addr, void *buf, size_t size,
Status &error) {
+ LLDB_SCOPED_TIMER();
+
if (buf == nullptr || size == 0)
return 0;
@@ -2448,6 +2482,11 @@ Status Process::Launch(ProcessLaunchInfo &launch_info) {
if (error.Fail())
return error;
+ // Listen and queue events that are broadcasted during the process launch.
+ ListenerSP listener_sp(Listener::MakeListener("LaunchEventHijack"));
+ HijackProcessEvents(listener_sp);
+ auto on_exit = llvm::make_scope_exit([this]() { RestoreProcessEvents(); });
+
if (PrivateStateThreadIsValid())
PausePrivateStateThread();
@@ -2856,8 +2895,10 @@ void Process::CompleteAttach() {
ProcessInstanceInfo process_info;
GetProcessInfo(process_info);
const ArchSpec &process_arch = process_info.GetArchitecture();
+ const ArchSpec &target_arch = GetTarget().GetArchitecture();
if (process_arch.IsValid() &&
- !GetTarget().GetArchitecture().IsExactMatch(process_arch)) {
+ target_arch.IsCompatibleMatch(process_arch) &&
+ !target_arch.IsExactMatch(process_arch)) {
GetTarget().SetArchitecture(process_arch);
LLDB_LOGF(log,
"Process::%s switching architecture to %s based on info "
@@ -3050,9 +3091,10 @@ Status Process::Halt(bool clear_thread_plans, bool use_run_lock) {
return Status();
}
- // Wait for 10 second for the process to stop.
- StateType state = WaitForProcessToStop(
- seconds(10), &event_sp, true, halt_listener_sp, nullptr, use_run_lock);
+ // Wait for the process halt timeout seconds for the process to stop.
+ StateType state =
+ WaitForProcessToStop(GetInterruptTimeout(), &event_sp, true,
+ halt_listener_sp, nullptr, use_run_lock);
RestoreProcessEvents();
if (state == eStateInvalid || !event_sp) {
@@ -3083,8 +3125,8 @@ Status Process::StopForDestroyOrDetach(lldb::EventSP &exit_event_sp) {
SendAsyncInterrupt();
// Consume the interrupt event.
- StateType state =
- WaitForProcessToStop(seconds(10), &exit_event_sp, true, listener_sp);
+ StateType state = WaitForProcessToStop(GetInterruptTimeout(),
+ &exit_event_sp, true, listener_sp);
RestoreProcessEvents();
@@ -3203,7 +3245,7 @@ Status Process::DestroyImpl(bool force_kill) {
error = StopForDestroyOrDetach(exit_event_sp);
}
- if (m_public_state.GetValue() != eStateRunning) {
+ if (m_public_state.GetValue() == eStateStopped) {
// Ditch all thread plans, and remove all our breakpoints: in case we
// have to restart the target to kill it, we don't want it hitting a
// breakpoint... Only do this if we've stopped, however, since if we
@@ -3374,14 +3416,14 @@ bool Process::ShouldBroadcastEvent(Event *event_ptr) {
should_resume = !m_thread_list.ShouldStop(event_ptr);
if (was_restarted || should_resume || m_resume_requested) {
- Vote stop_vote = m_thread_list.ShouldReportStop(event_ptr);
+ Vote report_stop_vote = m_thread_list.ShouldReportStop(event_ptr);
LLDB_LOGF(log,
"Process::ShouldBroadcastEvent: should_resume: %i state: "
- "%s was_restarted: %i stop_vote: %d.",
+ "%s was_restarted: %i report_stop_vote: %d.",
should_resume, StateAsCString(state), was_restarted,
- stop_vote);
+ report_stop_vote);
- switch (stop_vote) {
+ switch (report_stop_vote) {
case eVoteYes:
return_value = true;
break;
@@ -3819,9 +3861,7 @@ thread_result_t Process::RunPrivateStateThread(bool is_secondary_thread) {
// Process Event Data
-Process::ProcessEventData::ProcessEventData()
- : EventData(), m_process_wp(), m_state(eStateInvalid), m_restarted(false),
- m_update_state(0), m_interrupted(false) {}
+Process::ProcessEventData::ProcessEventData() : EventData(), m_process_wp() {}
Process::ProcessEventData::ProcessEventData(const ProcessSP &process_sp,
StateType state)
@@ -5536,6 +5576,26 @@ void Process::Flush() {
m_queue_list_stop_id = 0;
}
+lldb::addr_t Process::GetCodeAddressMask() {
+ if (m_code_address_mask == 0) {
+ if (uint32_t number_of_addressable_bits = GetVirtualAddressableBits()) {
+ lldb::addr_t address_mask = ~((1ULL << number_of_addressable_bits) - 1);
+ SetCodeAddressMask(address_mask);
+ }
+ }
+ return m_code_address_mask;
+}
+
+lldb::addr_t Process::GetDataAddressMask() {
+ if (m_data_address_mask == 0) {
+ if (uint32_t number_of_addressable_bits = GetVirtualAddressableBits()) {
+ lldb::addr_t address_mask = ~((1ULL << number_of_addressable_bits) - 1);
+ SetDataAddressMask(address_mask);
+ }
+ }
+ return m_data_address_mask;
+}
+
void Process::DidExec() {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
LLDB_LOGF(log, "Process::%s()", __FUNCTION__);
@@ -5591,6 +5651,8 @@ addr_t Process::ResolveIndirectFunction(const Address *address, Status &error) {
symbol ? symbol->GetName().AsCString() : "<UNKNOWN>");
function_addr = LLDB_INVALID_ADDRESS;
} else {
+ if (ABISP abi_sp = GetABI())
+ function_addr = abi_sp->FixCodeAddress(function_addr);
m_resolved_indirect_addresses.insert(
std::pair<addr_t, addr_t>(addr, function_addr));
}
@@ -5684,12 +5746,12 @@ void Process::PrintWarningUnsupportedLanguage(const SymbolContext &sc) {
LanguageType language = sc.GetLanguage();
if (language == eLanguageTypeUnknown)
return;
- auto type_system_or_err = sc.module_sp->GetTypeSystemForLanguage(language);
- if (auto err = type_system_or_err.takeError()) {
- llvm::consumeError(std::move(err));
+ LanguageSet plugins =
+ PluginManager::GetAllTypeSystemSupportedLanguagesForTypes();
+ if (!plugins[language]) {
PrintWarning(Process::Warnings::eWarningsUnsupportedLanguage,
sc.module_sp.get(),
- "This version of LLDB has no plugin for the %s language. "
+ "This version of LLDB has no plugin for the language \"%s\". "
"Inspection of frame variables will be limited.\n",
Language::GetNameForLanguageType(language));
}
@@ -5769,10 +5831,8 @@ Process::AdvanceAddressToNextBranchInstruction(Address default_stop_addr,
const char *plugin_name = nullptr;
const char *flavor = nullptr;
- const bool prefer_file_cache = true;
disassembler_sp = Disassembler::DisassembleRange(
- target.GetArchitecture(), plugin_name, flavor, GetTarget(), range_bounds,
- prefer_file_cache);
+ target.GetArchitecture(), plugin_name, flavor, GetTarget(), range_bounds);
if (disassembler_sp)
insn_list = &disassembler_sp->GetInstructionList();
@@ -5962,7 +6022,7 @@ UtilityFunction *Process::GetLoadImageUtilityFunction(
return m_dlopen_utility_func_up.get();
}
-llvm::Expected<TraceTypeInfo> Process::GetSupportedTraceType() {
+llvm::Expected<TraceSupportedResponse> Process::TraceSupported() {
if (!IsLiveDebugSession())
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"Can't trace a non-live process.");
@@ -6023,3 +6083,57 @@ bool Process::CallVoidArgVoidPtrReturn(const Address *address,
return false;
}
+
+llvm::Expected<const MemoryTagManager *> Process::GetMemoryTagManager() {
+ Architecture *arch = GetTarget().GetArchitecturePlugin();
+ const MemoryTagManager *tag_manager =
+ arch ? arch->GetMemoryTagManager() : nullptr;
+ if (!arch || !tag_manager) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "This architecture does not support memory tagging",
+ GetPluginName().GetCString());
+ }
+
+ if (!SupportsMemoryTagging()) {
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Process does not support memory tagging");
+ }
+
+ return tag_manager;
+}
+
+llvm::Expected<std::vector<lldb::addr_t>>
+Process::ReadMemoryTags(lldb::addr_t addr, size_t len) {
+ llvm::Expected<const MemoryTagManager *> tag_manager_or_err =
+ GetMemoryTagManager();
+ if (!tag_manager_or_err)
+ return tag_manager_or_err.takeError();
+
+ const MemoryTagManager *tag_manager = *tag_manager_or_err;
+ llvm::Expected<std::vector<uint8_t>> tag_data =
+ DoReadMemoryTags(addr, len, tag_manager->GetAllocationTagType());
+ if (!tag_data)
+ return tag_data.takeError();
+
+ return tag_manager->UnpackTagsData(*tag_data,
+ len / tag_manager->GetGranuleSize());
+}
+
+Status Process::WriteMemoryTags(lldb::addr_t addr, size_t len,
+ const std::vector<lldb::addr_t> &tags) {
+ llvm::Expected<const MemoryTagManager *> tag_manager_or_err =
+ GetMemoryTagManager();
+ if (!tag_manager_or_err)
+ return Status(tag_manager_or_err.takeError());
+
+ const MemoryTagManager *tag_manager = *tag_manager_or_err;
+ llvm::Expected<std::vector<uint8_t>> packed_tags =
+ tag_manager->PackTags(tags);
+ if (!packed_tags) {
+ return Status(packed_tags.takeError());
+ }
+
+ return DoWriteMemoryTags(addr, len, tag_manager->GetAllocationTagType(),
+ *packed_tags);
+}
diff --git a/lldb/source/Target/ProcessTrace.cpp b/lldb/source/Target/ProcessTrace.cpp
index 95f87745b724..c878a2ac4eb9 100644
--- a/lldb/source/Target/ProcessTrace.cpp
+++ b/lldb/source/Target/ProcessTrace.cpp
@@ -87,8 +87,6 @@ void ProcessTrace::RefreshStateAfterStop() {}
Status ProcessTrace::DoDestroy() { return Status(); }
-bool ProcessTrace::IsAlive() { return true; }
-
size_t ProcessTrace::ReadMemory(addr_t addr, void *buf, size_t size,
Status &error) {
// Don't allow the caching that lldb_private::Process::ReadMemory does since
diff --git a/lldb/source/Target/QueueItem.cpp b/lldb/source/Target/QueueItem.cpp
index 740b2a6771a2..7070812a10b0 100644
--- a/lldb/source/Target/QueueItem.cpp
+++ b/lldb/source/Target/QueueItem.cpp
@@ -27,7 +27,7 @@ QueueItem::QueueItem(QueueSP queue_sp, ProcessSP process_sp,
m_process_wp = process_sp;
}
-QueueItem::~QueueItem() {}
+QueueItem::~QueueItem() = default;
QueueItemKind QueueItem::GetKind() {
FetchEntireItem();
diff --git a/lldb/source/Target/RegisterContext.cpp b/lldb/source/Target/RegisterContext.cpp
index cdc7653cea6d..bd50a9486ef3 100644
--- a/lldb/source/Target/RegisterContext.cpp
+++ b/lldb/source/Target/RegisterContext.cpp
@@ -58,8 +58,8 @@ RegisterContext::GetRegisterInfoByName(llvm::StringRef reg_name,
for (uint32_t reg = start_idx; reg < num_registers; ++reg) {
const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
- if (reg_name.equals_lower(reg_info->name) ||
- reg_name.equals_lower(reg_info->alt_name))
+ if (reg_name.equals_insensitive(reg_info->name) ||
+ reg_name.equals_insensitive(reg_info->alt_name))
return reg_info;
}
return nullptr;
@@ -150,6 +150,20 @@ bool RegisterContext::SetPC(uint64_t pc) {
return success;
}
+bool RegisterContext::GetPCForSymbolication(Address &address) {
+ addr_t pc = GetPC(LLDB_INVALID_ADDRESS);
+ if (pc == LLDB_INVALID_ADDRESS)
+ return false;
+ TargetSP target_sp = m_thread.CalculateTarget();
+ if (!target_sp.get())
+ return false;
+
+ if (!BehavesLikeZerothFrame() && pc != 0)
+ pc--;
+ address.SetLoadAddress(pc, target_sp.get());
+ return true;
+}
+
bool RegisterContext::SetPC(Address addr) {
TargetSP target_sp = m_thread.CalculateTarget();
Target *target = target_sp.get();
diff --git a/lldb/source/Target/RegisterContextUnwind.cpp b/lldb/source/Target/RegisterContextUnwind.cpp
index f33f4180be23..1ce21e6306e0 100644
--- a/lldb/source/Target/RegisterContextUnwind.cpp
+++ b/lldb/source/Target/RegisterContextUnwind.cpp
@@ -24,6 +24,7 @@
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
@@ -57,10 +58,11 @@ RegisterContextUnwind::RegisterContextUnwind(Thread &thread,
m_fast_unwind_plan_sp(), m_full_unwind_plan_sp(),
m_fallback_unwind_plan_sp(), m_all_registers_available(false),
m_frame_type(-1), m_cfa(LLDB_INVALID_ADDRESS),
- m_afa(LLDB_INVALID_ADDRESS), m_start_pc(),
- m_current_pc(), m_current_offset(0), m_current_offset_backed_up_one(0),
- m_sym_ctx(sym_ctx), m_sym_ctx_valid(false), m_frame_number(frame_number),
- m_registers(), m_parent_unwind(unwind_lldb) {
+ m_afa(LLDB_INVALID_ADDRESS), m_start_pc(), m_current_pc(),
+ m_current_offset(0), m_current_offset_backed_up_one(0),
+ m_behaves_like_zeroth_frame(false), m_sym_ctx(sym_ctx),
+ m_sym_ctx_valid(false), m_frame_number(frame_number), m_registers(),
+ m_parent_unwind(unwind_lldb) {
m_sym_ctx.Clear(false);
m_sym_ctx_valid = false;
@@ -139,6 +141,12 @@ void RegisterContextUnwind::InitializeZerothFrame() {
if (abi)
current_pc = abi->FixCodeAddress(current_pc);
+ UnwindPlanSP lang_runtime_plan_sp = LanguageRuntime::GetRuntimeUnwindPlan(
+ m_thread, this, m_behaves_like_zeroth_frame);
+ if (lang_runtime_plan_sp.get()) {
+ UnwindLogMsg("This is an async frame");
+ }
+
// Initialize m_current_pc, an Address object, based on current_pc, an
// addr_t.
m_current_pc.SetLoadAddress(current_pc, &process->GetTarget());
@@ -202,6 +210,38 @@ void RegisterContextUnwind::InitializeZerothFrame() {
UnwindPlan::RowSP active_row;
lldb::RegisterKind row_register_kind = eRegisterKindGeneric;
+
+ // If we have LanguageRuntime UnwindPlan for this unwind, use those
+ // rules to find the caller frame instead of the function's normal
+ // UnwindPlans. The full unwind plan for this frame will be
+ // the LanguageRuntime-provided unwind plan, and there will not be a
+ // fast unwind plan.
+ if (lang_runtime_plan_sp.get()) {
+ active_row =
+ lang_runtime_plan_sp->GetRowForFunctionOffset(m_current_offset);
+ row_register_kind = lang_runtime_plan_sp->GetRegisterKind();
+ if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(),
+ m_cfa)) {
+ UnwindLogMsg("Cannot set cfa");
+ } else {
+ m_full_unwind_plan_sp = lang_runtime_plan_sp;
+ if (log) {
+ StreamString active_row_strm;
+ active_row->Dump(active_row_strm, lang_runtime_plan_sp.get(), &m_thread,
+ m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
+ UnwindLogMsg("async active row: %s", active_row_strm.GetData());
+ }
+ UnwindLogMsg("m_cfa = 0x%" PRIx64 " m_afa = 0x%" PRIx64, m_cfa, m_afa);
+ UnwindLogMsg(
+ "initialized async frame current pc is 0x%" PRIx64
+ " cfa is 0x%" PRIx64 " afa is 0x%" PRIx64,
+ (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()),
+ (uint64_t)m_cfa, (uint64_t)m_afa);
+
+ return;
+ }
+ }
+
if (m_full_unwind_plan_sp &&
m_full_unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
active_row =
@@ -283,6 +323,22 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
return;
}
+ ExecutionContext exe_ctx(m_thread.shared_from_this());
+ Process *process = exe_ctx.GetProcessPtr();
+
+ // Some languages may have a logical parent stack frame which is
+ // not a real stack frame, but the programmer would consider it to
+ // be the caller of the frame, e.g. Swift asynchronous frames.
+ //
+ // A LanguageRuntime may provide an UnwindPlan that is used in this
+ // stack trace base on the RegisterContext contents, intsead
+ // of the normal UnwindPlans we would use for the return-pc.
+ UnwindPlanSP lang_runtime_plan_sp = LanguageRuntime::GetRuntimeUnwindPlan(
+ m_thread, this, m_behaves_like_zeroth_frame);
+ if (lang_runtime_plan_sp.get()) {
+ UnwindLogMsg("This is an async frame");
+ }
+
addr_t pc;
if (!ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc)) {
UnwindLogMsg("could not get pc value");
@@ -290,8 +346,6 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
return;
}
- ExecutionContext exe_ctx(m_thread.shared_from_this());
- Process *process = exe_ctx.GetProcessPtr();
// Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs
// this will strip bit zero in case we read a PC from memory or from the LR.
ABI *abi = process->GetABI().get();
@@ -468,6 +522,8 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
// so do not decrement and recompute if the symbol we already found is a trap
// handler.
decr_pc_and_recompute_addr_range = false;
+ } else if (m_behaves_like_zeroth_frame) {
+ decr_pc_and_recompute_addr_range = false;
} else {
// Decrement to find the function containing the call.
decr_pc_and_recompute_addr_range = true;
@@ -522,12 +578,43 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
}
}
- // We've set m_frame_type and m_sym_ctx before this call.
- m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame();
-
UnwindPlan::RowSP active_row;
RegisterKind row_register_kind = eRegisterKindGeneric;
+ // If we have LanguageRuntime UnwindPlan for this unwind, use those
+ // rules to find the caller frame instead of the function's normal
+ // UnwindPlans. The full unwind plan for this frame will be
+ // the LanguageRuntime-provided unwind plan, and there will not be a
+ // fast unwind plan.
+ if (lang_runtime_plan_sp.get()) {
+ active_row =
+ lang_runtime_plan_sp->GetRowForFunctionOffset(m_current_offset);
+ row_register_kind = lang_runtime_plan_sp->GetRegisterKind();
+ if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(),
+ m_cfa)) {
+ UnwindLogMsg("Cannot set cfa");
+ } else {
+ m_full_unwind_plan_sp = lang_runtime_plan_sp;
+ if (log) {
+ StreamString active_row_strm;
+ active_row->Dump(active_row_strm, lang_runtime_plan_sp.get(), &m_thread,
+ m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
+ UnwindLogMsg("async active row: %s", active_row_strm.GetData());
+ }
+ UnwindLogMsg("m_cfa = 0x%" PRIx64 " m_afa = 0x%" PRIx64, m_cfa, m_afa);
+ UnwindLogMsg(
+ "initialized async frame current pc is 0x%" PRIx64
+ " cfa is 0x%" PRIx64 " afa is 0x%" PRIx64,
+ (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()),
+ (uint64_t)m_cfa, (uint64_t)m_afa);
+
+ return;
+ }
+ }
+
+ // We've set m_frame_type and m_sym_ctx before this call.
+ m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame();
+
// Try to get by with just the fast UnwindPlan if possible - the full
// UnwindPlan may be expensive to get (e.g. if we have to parse the entire
// eh_frame section of an ObjectFile for the first time.)
@@ -542,6 +629,8 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
StreamString active_row_strm;
active_row->Dump(active_row_strm, m_fast_unwind_plan_sp.get(), &m_thread,
m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
+ UnwindLogMsg("Using fast unwind plan '%s'",
+ m_fast_unwind_plan_sp->GetSourceName().AsCString());
UnwindLogMsg("active row: %s", active_row_strm.GetData());
}
} else {
@@ -556,6 +645,8 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(),
&m_thread,
m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
+ UnwindLogMsg("Using full unwind plan '%s'",
+ m_full_unwind_plan_sp->GetSourceName().AsCString());
UnwindLogMsg("active row: %s", active_row_strm.GetData());
}
}
@@ -625,6 +716,14 @@ bool RegisterContextUnwind::CheckIfLoopingStack() {
bool RegisterContextUnwind::IsFrameZero() const { return m_frame_number == 0; }
+bool RegisterContextUnwind::BehavesLikeZerothFrame() const {
+ if (m_frame_number == 0)
+ return true;
+ if (m_behaves_like_zeroth_frame)
+ return true;
+ return false;
+}
+
// Find a fast unwind plan for this frame, if possible.
//
// On entry to this method,
@@ -662,13 +761,6 @@ UnwindPlanSP RegisterContextUnwind::GetFastUnwindPlanForFrame() {
*m_thread.CalculateTarget(), m_thread);
if (unwind_plan_sp) {
if (unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
- if (log && log->GetVerbose()) {
- if (m_fast_unwind_plan_sp)
- UnwindLogMsgVerbose("frame, and has a fast UnwindPlan");
- else
- UnwindLogMsgVerbose("frame");
- }
m_frame_type = eNormalFrame;
return unwind_plan_sp;
} else {
@@ -702,10 +794,9 @@ UnwindPlanSP RegisterContextUnwind::GetFullUnwindPlanForFrame() {
"unable to get architectural default UnwindPlan from ABI plugin");
}
- bool behaves_like_zeroth_frame = false;
if (IsFrameZero() || GetNextFrame()->m_frame_type == eTrapHandlerFrame ||
GetNextFrame()->m_frame_type == eDebuggerFrame) {
- behaves_like_zeroth_frame = true;
+ m_behaves_like_zeroth_frame = true;
// If this frame behaves like a 0th frame (currently executing or
// interrupted asynchronously), all registers can be retrieved.
m_all_registers_available = true;
@@ -721,7 +812,7 @@ UnwindPlanSP RegisterContextUnwind::GetFullUnwindPlanForFrame() {
if ((!m_sym_ctx_valid ||
(m_sym_ctx.function == nullptr && m_sym_ctx.symbol == nullptr)) &&
- behaves_like_zeroth_frame && m_current_pc.IsValid()) {
+ m_behaves_like_zeroth_frame && m_current_pc.IsValid()) {
uint32_t permissions;
addr_t current_pc_addr =
m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr());
@@ -849,7 +940,7 @@ UnwindPlanSP RegisterContextUnwind::GetFullUnwindPlanForFrame() {
// Typically the NonCallSite UnwindPlan is the unwind created by inspecting
// the assembly language instructions
- if (behaves_like_zeroth_frame && process) {
+ if (m_behaves_like_zeroth_frame && process) {
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite(
process->GetTarget(), m_thread);
if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
@@ -1147,6 +1238,7 @@ enum UnwindLLDB::RegisterSearchResult
RegisterContextUnwind::SavedLocationForRegister(
uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc) {
RegisterNumber regnum(m_thread, eRegisterKindLLDB, lldb_regnum);
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
// Have we already found this register location?
if (!m_registers.empty()) {
@@ -1179,8 +1271,17 @@ RegisterContextUnwind::SavedLocationForRegister(
(int)unwindplan_registerkind);
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
+ // The architecture default unwind plan marks unknown registers as
+ // Undefined so that we don't forward them up the stack when a
+ // jitted stack frame may have overwritten them. But when the
+ // arch default unwind plan is used as the Fast Unwind Plan, we
+ // need to recognize this & switch over to the Full Unwind Plan
+ // to see what unwind rule that (more knoweldgeable, probably)
+ // UnwindPlan has. If the full UnwindPlan says the register
+ // location is Undefined, then it really is.
if (active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind),
- unwindplan_regloc)) {
+ unwindplan_regloc) &&
+ !unwindplan_regloc.IsUndefined()) {
UnwindLogMsg(
"supplying caller's saved %s (%d)'s location using FastUnwindPlan",
regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
@@ -1191,8 +1292,11 @@ RegisterContextUnwind::SavedLocationForRegister(
if (!have_unwindplan_regloc) {
// m_full_unwind_plan_sp being NULL means that we haven't tried to find a
// full UnwindPlan yet
- if (!m_full_unwind_plan_sp)
+ bool got_new_full_unwindplan = false;
+ if (!m_full_unwind_plan_sp) {
m_full_unwind_plan_sp = GetFullUnwindPlanForFrame();
+ got_new_full_unwindplan = true;
+ }
if (m_full_unwind_plan_sp) {
RegisterNumber pc_regnum(m_thread, eRegisterKindGeneric,
@@ -1202,6 +1306,16 @@ RegisterContextUnwind::SavedLocationForRegister(
m_full_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset);
unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind();
+ if (got_new_full_unwindplan && active_row.get() && log) {
+ StreamString active_row_strm;
+ ExecutionContext exe_ctx(m_thread.shared_from_this());
+ active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(),
+ &m_thread,
+ m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
+ UnwindLogMsg("Using full unwind plan '%s'",
+ m_full_unwind_plan_sp->GetSourceName().AsCString());
+ UnwindLogMsg("active row: %s", active_row_strm.GetData());
+ }
RegisterNumber return_address_reg;
// If we're fetching the saved pc and this UnwindPlan defines a
@@ -1521,7 +1635,7 @@ RegisterContextUnwind::SavedLocationForRegister(
DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr);
dwarfexpr.SetRegisterKind(unwindplan_registerkind);
Value cfa_val = Scalar(m_cfa);
- cfa_val.SetValueType(Value::eValueTypeLoadAddress);
+ cfa_val.SetValueType(Value::ValueType::LoadAddress);
Value result;
Status error;
if (dwarfexpr.Evaluate(&exe_ctx, this, 0, &cfa_val, nullptr, result,
@@ -1616,6 +1730,10 @@ bool RegisterContextUnwind::TryFallbackUnwindPlan() {
RegisterValue reg_value;
if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) {
old_caller_pc_value = reg_value.GetAsUInt64();
+ if (ProcessSP process_sp = m_thread.GetProcess()) {
+ if (ABISP abi = process_sp->GetABI())
+ old_caller_pc_value = abi->FixCodeAddress(old_caller_pc_value);
+ }
}
}
}
@@ -1671,6 +1789,10 @@ bool RegisterContextUnwind::TryFallbackUnwindPlan() {
if (ReadRegisterValueFromRegisterLocation(regloc, reg_info,
reg_value)) {
new_caller_pc_value = reg_value.GetAsUInt64();
+ if (ProcessSP process_sp = m_thread.GetProcess()) {
+ if (ABISP abi = process_sp->GetABI())
+ new_caller_pc_value = abi->FixCodeAddress(new_caller_pc_value);
+ }
}
}
}
@@ -1824,6 +1946,8 @@ bool RegisterContextUnwind::ReadFrameAddress(
reg_info, cfa_reg_contents, reg_info->byte_size, reg_value);
if (error.Success()) {
address = reg_value.GetAsUInt64();
+ if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
+ address = abi_sp->FixCodeAddress(address);
UnwindLogMsg(
"CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64
", CFA value is 0x%" PRIx64,
@@ -1878,6 +2002,8 @@ bool RegisterContextUnwind::ReadFrameAddress(
if (dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr, result,
&error)) {
address = result.GetScalar().ULongLong();
+ if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
+ address = abi_sp->FixCodeAddress(address);
UnwindLogMsg("CFA value set by DWARF expression is 0x%" PRIx64,
address);
@@ -2007,6 +2133,12 @@ bool RegisterContextUnwind::ReadGPRValue(lldb::RegisterKind register_kind,
}
if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) {
value = reg_value.GetAsUInt64();
+ if (pc_register) {
+ if (ProcessSP process_sp = m_thread.GetProcess()) {
+ if (ABISP abi = process_sp->GetABI())
+ value = abi->FixCodeAddress(value);
+ }
+ }
return true;
}
return false;
@@ -2048,7 +2180,19 @@ bool RegisterContextUnwind::ReadRegister(const RegisterInfo *reg_info,
lldb_regnum, regloc, m_frame_number - 1, is_pc_regnum))
return false;
- return ReadRegisterValueFromRegisterLocation(regloc, reg_info, value);
+ bool result = ReadRegisterValueFromRegisterLocation(regloc, reg_info, value);
+ if (result) {
+ if (is_pc_regnum && value.GetType() == RegisterValue::eTypeUInt64) {
+ addr_t reg_value = value.GetAsUInt64(LLDB_INVALID_ADDRESS);
+ if (reg_value != LLDB_INVALID_ADDRESS) {
+ if(ProcessSP process_sp = m_thread.GetProcess()) {
+ if (ABISP abi = process_sp->GetABI())
+ value = abi->FixCodeAddress(reg_value);
+ }
+ }
+ }
+ }
+ return result;
}
bool RegisterContextUnwind::WriteRegister(const RegisterInfo *reg_info,
diff --git a/lldb/source/Target/RegisterNumber.cpp b/lldb/source/Target/RegisterNumber.cpp
index 0ea9f212c693..e5610bf58854 100644
--- a/lldb/source/Target/RegisterNumber.cpp
+++ b/lldb/source/Target/RegisterNumber.cpp
@@ -26,9 +26,7 @@ RegisterNumber::RegisterNumber(lldb_private::Thread &thread,
}
}
-RegisterNumber::RegisterNumber()
- : m_reg_ctx_sp(), m_regnum(LLDB_INVALID_REGNUM),
- m_kind(lldb::kNumRegisterKinds), m_kind_regnum_map(), m_name(nullptr) {}
+RegisterNumber::RegisterNumber() : m_reg_ctx_sp(), m_kind_regnum_map() {}
void RegisterNumber::init(lldb_private::Thread &thread, lldb::RegisterKind kind,
uint32_t num) {
diff --git a/lldb/source/Target/RemoteAwarePlatform.cpp b/lldb/source/Target/RemoteAwarePlatform.cpp
index 3a186adca04c..b0c43ffa839e 100644
--- a/lldb/source/Target/RemoteAwarePlatform.cpp
+++ b/lldb/source/Target/RemoteAwarePlatform.cpp
@@ -437,3 +437,10 @@ Status RemoteAwarePlatform::KillProcess(const lldb::pid_t pid) {
return m_remote_platform_sp->KillProcess(pid);
return Status("the platform is not currently connected");
}
+
+size_t RemoteAwarePlatform::ConnectToWaitingProcesses(Debugger &debugger,
+ Status &error) {
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->ConnectToWaitingProcesses(debugger, error);
+ return Platform::ConnectToWaitingProcesses(debugger, error);
+}
diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp
index 131581567d73..cba51d266c5b 100644
--- a/lldb/source/Target/StackFrame.cpp
+++ b/lldb/source/Target/StackFrame.cpp
@@ -213,6 +213,35 @@ const Address &StackFrame::GetFrameCodeAddress() {
return m_frame_code_addr;
}
+// This can't be rewritten into a call to
+// RegisterContext::GetPCForSymbolication because this
+// StackFrame may have been constructed with a special pc,
+// e.g. tail-call artificial frames.
+Address StackFrame::GetFrameCodeAddressForSymbolication() {
+ Address lookup_addr(GetFrameCodeAddress());
+ if (!lookup_addr.IsValid())
+ return lookup_addr;
+ if (m_behaves_like_zeroth_frame)
+ return lookup_addr;
+
+ addr_t offset = lookup_addr.GetOffset();
+ if (offset > 0) {
+ lookup_addr.SetOffset(offset - 1);
+ } else {
+ // lookup_addr is the start of a section. We need do the math on the
+ // actual load address and re-compute the section. We're working with
+ // a 'noreturn' function at the end of a section.
+ TargetSP target_sp = CalculateTarget();
+ if (target_sp) {
+ addr_t addr_minus_one = lookup_addr.GetOpcodeLoadAddress(
+ target_sp.get(), AddressClass::eCode) -
+ 1;
+ lookup_addr.SetOpcodeLoadAddress(addr_minus_one, target_sp.get());
+ }
+ }
+ return lookup_addr;
+}
+
bool StackFrame::ChangePC(addr_t pc) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
// We can't change the pc value of a history stack frame - it is immutable.
@@ -288,30 +317,7 @@ StackFrame::GetSymbolContext(SymbolContextItem resolve_scope) {
// If this is not frame zero, then we need to subtract 1 from the PC value
// when doing address lookups since the PC will be on the instruction
// following the function call instruction...
-
- Address lookup_addr(GetFrameCodeAddress());
- if (!m_behaves_like_zeroth_frame && lookup_addr.IsValid()) {
- addr_t offset = lookup_addr.GetOffset();
- if (offset > 0) {
- lookup_addr.SetOffset(offset - 1);
-
- } else {
- // lookup_addr is the start of a section. We need do the math on the
- // actual load address and re-compute the section. We're working with
- // a 'noreturn' function at the end of a section.
- ThreadSP thread_sp(GetThread());
- if (thread_sp) {
- TargetSP target_sp(thread_sp->CalculateTarget());
- if (target_sp) {
- addr_t addr_minus_one =
- lookup_addr.GetLoadAddress(target_sp.get()) - 1;
- lookup_addr.SetLoadAddress(addr_minus_one, target_sp.get());
- } else {
- lookup_addr.SetOffset(offset - 1);
- }
- }
- }
- }
+ Address lookup_addr(GetFrameCodeAddressForSymbolication());
if (m_sc.module_sp) {
// We have something in our stack frame symbol context, lets check if we
@@ -1160,31 +1166,6 @@ StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp,
return valobj_sp;
}
-ValueObjectSP StackFrame::TrackGlobalVariable(const VariableSP &variable_sp,
- DynamicValueType use_dynamic) {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- if (IsHistorical())
- return ValueObjectSP();
-
- // Check to make sure we aren't already tracking this variable?
- ValueObjectSP valobj_sp(
- GetValueObjectForFrameVariable(variable_sp, use_dynamic));
- if (!valobj_sp) {
- // We aren't already tracking this global
- VariableList *var_list = GetVariableList(true);
- // If this frame has no variables, create a new list
- if (var_list == nullptr)
- m_variable_list_sp = std::make_shared<VariableList>();
-
- // Add the global/static variable to this frame
- m_variable_list_sp->AddVariable(variable_sp);
-
- // Now make a value object for it so we can track its changes
- valobj_sp = GetValueObjectForFrameVariable(variable_sp, use_dynamic);
- }
- return valobj_sp;
-}
-
bool StackFrame::IsInlined() {
if (m_sc.block == nullptr)
GetSymbolContext(eSymbolContextBlock);
@@ -1313,11 +1294,11 @@ lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) {
const char *plugin_name = nullptr;
const char *flavor = nullptr;
- const bool prefer_file_cache = false;
+ const bool force_live_memory = true;
DisassemblerSP disassembler_sp =
Disassembler::DisassembleRange(target_arch, plugin_name, flavor,
- *target_sp, pc_range, prefer_file_cache);
+ *target_sp, pc_range, force_live_memory);
if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) {
return ValueObjectSP();
@@ -1693,10 +1674,10 @@ lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg,
const char *plugin_name = nullptr;
const char *flavor = nullptr;
- const bool prefer_file_cache = false;
+ const bool force_live_memory = true;
DisassemblerSP disassembler_sp =
Disassembler::DisassembleRange(target_arch, plugin_name, flavor,
- *target_sp, pc_range, prefer_file_cache);
+ *target_sp, pc_range, force_live_memory);
if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) {
return ValueObjectSP();
diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp
index e4f5d3028366..061500152a49 100644
--- a/lldb/source/Target/StackFrameList.cpp
+++ b/lldb/source/Target/StackFrameList.cpp
@@ -131,6 +131,9 @@ void StackFrameList::ResetCurrentInlinedDepth() {
case eStopReasonWatchpoint:
case eStopReasonException:
case eStopReasonExec:
+ case eStopReasonFork:
+ case eStopReasonVFork:
+ case eStopReasonVForkDone:
case eStopReasonSignal:
// In all these cases we want to stop in the deepest frame.
m_current_inlined_pc = curr_pc;
@@ -522,27 +525,10 @@ void StackFrameList::GetFramesUpTo(uint32_t end_idx) {
SymbolContext unwind_sc = unwind_frame_sp->GetSymbolContext(
eSymbolContextBlock | eSymbolContextFunction);
Block *unwind_block = unwind_sc.block;
+ TargetSP target_sp = m_thread.CalculateTarget();
if (unwind_block) {
- Address curr_frame_address(unwind_frame_sp->GetFrameCodeAddress());
- TargetSP target_sp = m_thread.CalculateTarget();
- // Be sure to adjust the frame address to match the address that was
- // used to lookup the symbol context above. If we are in the first
- // concrete frame, then we lookup using the current address, else we
- // decrement the address by one to get the correct location.
- if (idx > 0) {
- if (curr_frame_address.GetOffset() == 0) {
- // If curr_frame_address points to the first address in a section
- // then after adjustment it will point to an other section. In that
- // case resolve the address again to the correct section plus
- // offset form.
- addr_t load_addr = curr_frame_address.GetOpcodeLoadAddress(
- target_sp.get(), AddressClass::eCode);
- curr_frame_address.SetOpcodeLoadAddress(
- load_addr - 1, target_sp.get(), AddressClass::eCode);
- } else {
- curr_frame_address.Slide(-1);
- }
- }
+ Address curr_frame_address(
+ unwind_frame_sp->GetFrameCodeAddressForSymbolication());
SymbolContext next_frame_sc;
Address next_frame_address;
@@ -840,105 +826,6 @@ void StackFrameList::Clear() {
m_concrete_frames_fetched = 0;
}
-void StackFrameList::Merge(std::unique_ptr<StackFrameList> &curr_up,
- lldb::StackFrameListSP &prev_sp) {
- std::unique_lock<std::recursive_mutex> current_lock, previous_lock;
- if (curr_up)
- current_lock = std::unique_lock<std::recursive_mutex>(curr_up->m_mutex);
- if (prev_sp)
- previous_lock = std::unique_lock<std::recursive_mutex>(prev_sp->m_mutex);
-
-#if defined(DEBUG_STACK_FRAMES)
- StreamFile s(stdout, false);
- s.PutCString("\n\nStackFrameList::Merge():\nPrev:\n");
- if (prev_sp)
- prev_sp->Dump(&s);
- else
- s.PutCString("NULL");
- s.PutCString("\nCurr:\n");
- if (curr_up)
- curr_up->Dump(&s);
- else
- s.PutCString("NULL");
- s.EOL();
-#endif
-
- if (!curr_up || curr_up->GetNumFrames(false) == 0) {
-#if defined(DEBUG_STACK_FRAMES)
- s.PutCString("No current frames, leave previous frames alone...\n");
-#endif
- curr_up.release();
- return;
- }
-
- if (!prev_sp || prev_sp->GetNumFrames(false) == 0) {
-#if defined(DEBUG_STACK_FRAMES)
- s.PutCString("No previous frames, so use current frames...\n");
-#endif
- // We either don't have any previous frames, or since we have more than one
- // current frames it means we have all the frames and can safely replace
- // our previous frames.
- prev_sp.reset(curr_up.release());
- return;
- }
-
- const uint32_t num_curr_frames = curr_up->GetNumFrames(false);
-
- if (num_curr_frames > 1) {
-#if defined(DEBUG_STACK_FRAMES)
- s.PutCString(
- "We have more than one current frame, so use current frames...\n");
-#endif
- // We have more than one current frames it means we have all the frames and
- // can safely replace our previous frames.
- prev_sp.reset(curr_up.release());
-
-#if defined(DEBUG_STACK_FRAMES)
- s.PutCString("\nMerged:\n");
- prev_sp->Dump(&s);
-#endif
- return;
- }
-
- StackFrameSP prev_frame_zero_sp(prev_sp->GetFrameAtIndex(0));
- StackFrameSP curr_frame_zero_sp(curr_up->GetFrameAtIndex(0));
- StackID curr_stack_id(curr_frame_zero_sp->GetStackID());
- StackID prev_stack_id(prev_frame_zero_sp->GetStackID());
-
-#if defined(DEBUG_STACK_FRAMES)
- const uint32_t num_prev_frames = prev_sp->GetNumFrames(false);
- s.Printf("\n%u previous frames with one current frame\n", num_prev_frames);
-#endif
-
- // We have only a single current frame
- // Our previous stack frames only had a single frame as well...
- if (curr_stack_id == prev_stack_id) {
-#if defined(DEBUG_STACK_FRAMES)
- s.Printf("\nPrevious frame #0 is same as current frame #0, merge the "
- "cached data\n");
-#endif
-
- curr_frame_zero_sp->UpdateCurrentFrameFromPreviousFrame(
- *prev_frame_zero_sp);
- // prev_frame_zero_sp->UpdatePreviousFrameFromCurrentFrame
- // (*curr_frame_zero_sp);
- // prev_sp->SetFrameAtIndex (0, prev_frame_zero_sp);
- } else if (curr_stack_id < prev_stack_id) {
-#if defined(DEBUG_STACK_FRAMES)
- s.Printf("\nCurrent frame #0 has a stack ID that is less than the previous "
- "frame #0, insert current frame zero in front of previous\n");
-#endif
- prev_sp->m_frames.insert(prev_sp->m_frames.begin(), curr_frame_zero_sp);
- }
-
- curr_up.release();
-
-#if defined(DEBUG_STACK_FRAMES)
- s.PutCString("\nMerged:\n");
- prev_sp->Dump(&s);
-#endif
-}
-
lldb::StackFrameSP
StackFrameList::GetStackFrameSPForStackFramePtr(StackFrame *stack_frame_ptr) {
const_iterator pos;
diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp
index 7e830c6e2bed..aeb97f1919eb 100644
--- a/lldb/source/Target/StopInfo.cpp
+++ b/lldb/source/Target/StopInfo.cpp
@@ -125,7 +125,7 @@ public:
BreakpointSiteSP bp_site_sp(
process_sp->GetBreakpointSiteList().FindByID(m_value));
if (bp_site_sp)
- return bp_site_sp->ValidForThisThread(&thread);
+ return bp_site_sp->ValidForThisThread(thread);
}
return false;
}
@@ -305,6 +305,20 @@ protected:
// location said we should stop. But that's better than not running
// all the callbacks.
+ // There's one other complication here. We may have run an async
+ // breakpoint callback that said we should stop. We only want to
+ // override that if another breakpoint action says we shouldn't
+ // stop. If nobody else has an opinion, then we should stop if the
+ // async callback says we should. An example of this is the async
+ // shared library load notification breakpoint and the setting
+ // stop-on-sharedlibrary-events.
+ // We'll keep the async value in async_should_stop, and track whether
+ // anyone said we should NOT stop in actually_said_continue.
+ bool async_should_stop = false;
+ if (m_should_stop_is_valid)
+ async_should_stop = m_should_stop;
+ bool actually_said_continue = false;
+
m_should_stop = false;
// We don't select threads as we go through them testing breakpoint
@@ -399,7 +413,7 @@ protected:
// The breakpoint site may have many locations associated with it,
// not all of them valid for this thread. Skip the ones that
// aren't:
- if (!bp_loc_sp->ValidForThisThread(thread_sp.get())) {
+ if (!bp_loc_sp->ValidForThisThread(*thread_sp)) {
if (log) {
LLDB_LOGF(log,
"Breakpoint %s hit on thread 0x%llx but it was not "
@@ -422,9 +436,10 @@ protected:
bool precondition_result =
bp_loc_sp->GetBreakpoint().EvaluatePrecondition(context);
- if (!precondition_result)
+ if (!precondition_result) {
+ actually_said_continue = true;
continue;
-
+ }
// Next run the condition for the breakpoint. If that says we
// should stop, then we'll run the callback for the breakpoint. If
// the callback says we shouldn't stop that will win.
@@ -462,11 +477,21 @@ protected:
// the condition fails. We've already bumped it by the time
// we get here, so undo the bump:
bp_loc_sp->UndoBumpHitCount();
+ actually_said_continue = true;
continue;
}
}
}
+ // We've done all the checks whose failure means "we consider lldb
+ // not to have hit the breakpoint". Now we're going to check for
+ // conditions that might continue after hitting. Start with the
+ // ignore count:
+ if (!bp_loc_sp->IgnoreCountShouldStop()) {
+ actually_said_continue = true;
+ continue;
+ }
+
// Check the auto-continue bit on the location, do this before the
// callback since it may change this, but that would be for the
// NEXT hit. Note, you might think you could check auto-continue
@@ -494,16 +519,22 @@ protected:
// When we figure out how to nest breakpoint hits then this will
// change.
- Debugger &debugger = thread_sp->CalculateTarget()->GetDebugger();
- bool old_async = debugger.GetAsyncExecution();
- debugger.SetAsyncExecution(true);
+ // Don't run async callbacks in PerformAction. They have already
+ // been taken into account with async_should_stop.
+ if (!bp_loc_sp->IsCallbackSynchronous()) {
+ Debugger &debugger = thread_sp->CalculateTarget()->GetDebugger();
+ bool old_async = debugger.GetAsyncExecution();
+ debugger.SetAsyncExecution(true);
- callback_says_stop = bp_loc_sp->InvokeCallback(&context);
+ callback_says_stop = bp_loc_sp->InvokeCallback(&context);
- debugger.SetAsyncExecution(old_async);
+ debugger.SetAsyncExecution(old_async);
- if (callback_says_stop && auto_continue_says_stop)
- m_should_stop = true;
+ if (callback_says_stop && auto_continue_says_stop)
+ m_should_stop = true;
+ else
+ actually_said_continue = true;
+ }
// If we are going to stop for this breakpoint, then remove the
// breakpoint.
@@ -517,9 +548,15 @@ protected:
// here.
if (HasTargetRunSinceMe()) {
m_should_stop = false;
+ actually_said_continue = true;
break;
}
}
+ // At this point if nobody actually told us to continue, we should
+ // give the async breakpoint callback a chance to weigh in:
+ if (!actually_said_continue && !m_should_stop) {
+ m_should_stop = async_should_stop;
+ }
}
// We've figured out what this stop wants to do, so mark it as valid so
// we don't compute it again.
@@ -1016,6 +1053,30 @@ public:
}
};
+// StopInfoProcessorTrace
+
+class StopInfoProcessorTrace : public StopInfo {
+public:
+ StopInfoProcessorTrace(Thread &thread, const char *description)
+ : StopInfo(thread, LLDB_INVALID_UID) {
+ if (description)
+ SetDescription(description);
+ }
+
+ ~StopInfoProcessorTrace() override = default;
+
+ StopReason GetStopReason() const override {
+ return eStopReasonProcessorTrace;
+ }
+
+ const char *GetDescription() override {
+ if (m_description.empty())
+ return "processor trace event";
+ else
+ return m_description.c_str();
+ }
+};
+
// StopInfoThreadPlan
class StopInfoThreadPlan : public StopInfo {
@@ -1133,6 +1194,11 @@ StopInfoSP StopInfo::CreateStopReasonWithException(Thread &thread,
return StopInfoSP(new StopInfoException(thread, description));
}
+StopInfoSP StopInfo::CreateStopReasonProcessorTrace(Thread &thread,
+ const char *description) {
+ return StopInfoSP(new StopInfoProcessorTrace(thread, description));
+}
+
StopInfoSP StopInfo::CreateStopReasonWithExec(Thread &thread) {
return StopInfoSP(new StopInfoExec(thread));
}
diff --git a/lldb/source/Target/StructuredDataPlugin.cpp b/lldb/source/Target/StructuredDataPlugin.cpp
index bd899d2f7681..20ed26a1a99a 100644
--- a/lldb/source/Target/StructuredDataPlugin.cpp
+++ b/lldb/source/Target/StructuredDataPlugin.cpp
@@ -23,14 +23,14 @@ public:
"Parent for per-plugin structured data commands",
"plugin structured-data <plugin>") {}
- ~CommandStructuredData() override {}
+ ~CommandStructuredData() override = default;
};
}
StructuredDataPlugin::StructuredDataPlugin(const ProcessWP &process_wp)
: PluginInterface(), m_process_wp(process_wp) {}
-StructuredDataPlugin::~StructuredDataPlugin() {}
+StructuredDataPlugin::~StructuredDataPlugin() = default;
bool StructuredDataPlugin::GetEnabled(ConstString type_name) const {
// By default, plugins are always enabled. Plugin authors should override
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 736864e021bb..1f8e8c54fa9e 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "lldb/Target/Target.h"
-#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/BreakpointPrecondition.h"
#include "lldb/Breakpoint/BreakpointResolver.h"
@@ -42,6 +41,7 @@
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/ABI.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/Process.h"
@@ -95,6 +95,7 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch,
m_watchpoint_list(), m_process_sp(), m_search_filter_sp(),
m_image_search_paths(ImageSearchPathsChanged, this),
m_source_manager_up(), m_stop_hooks(), m_stop_hook_next_id(0),
+ m_latest_stop_hook_id(0),
m_valid(true), m_suppress_stop_hooks(false),
m_is_dummy_target(is_dummy_target),
m_frame_recognizer_manager_up(
@@ -181,6 +182,7 @@ void Target::CleanupProcess() {
DisableAllWatchpoints(false);
ClearAllWatchpointHitCounts();
ClearAllWatchpointHistoricValues();
+ m_latest_stop_hook_id = 0;
}
void Target::DeleteCurrentProcess() {
@@ -371,9 +373,14 @@ BreakpointSP Target::CreateBreakpoint(const FileSpecList *containingModules,
if (move_to_nearest_code == eLazyBoolCalculate)
move_to_nearest_code = GetMoveToNearestCode() ? eLazyBoolYes : eLazyBoolNo;
+ SourceLocationSpec location_spec(remapped_file, line_no, column,
+ check_inlines,
+ !static_cast<bool>(move_to_nearest_code));
+ if (!location_spec)
+ return nullptr;
+
BreakpointResolverSP resolver_sp(new BreakpointResolverFileLine(
- nullptr, remapped_file, line_no, column, offset, check_inlines,
- skip_prologue, !static_cast<bool>(move_to_nearest_code)));
+ nullptr, offset, skip_prologue, location_spec));
return CreateBreakpoint(filter_sp, resolver_sp, internal, hardware, true);
}
@@ -819,6 +826,11 @@ WatchpointSP Target::CreateWatchpoint(lldb::addr_t addr, size_t size,
// Grab the list mutex while doing operations.
const bool notify = false; // Don't notify about all the state changes we do
// on creating the watchpoint.
+
+ // Mask off ignored bits from watchpoint address.
+ if (ABISP abi = m_process_sp->GetABI())
+ addr = abi->FixDataAddress(addr);
+
std::unique_lock<std::recursive_mutex> lock;
this->GetWatchpointList().GetListMutex(lock);
WatchpointSP matched_sp = m_watchpoint_list.FindByAddress(addr);
@@ -1149,9 +1161,7 @@ bool Target::RemoveAllWatchpoints(bool end_to_end) {
if (!ProcessIsValid())
return false;
- size_t num_watchpoints = m_watchpoint_list.GetSize();
- for (size_t i = 0; i < num_watchpoints; ++i) {
- WatchpointSP wp_sp = m_watchpoint_list.GetByIndex(i);
+ for (WatchpointSP wp_sp : m_watchpoint_list.Watchpoints()) {
if (!wp_sp)
return false;
@@ -1180,9 +1190,7 @@ bool Target::DisableAllWatchpoints(bool end_to_end) {
if (!ProcessIsValid())
return false;
- size_t num_watchpoints = m_watchpoint_list.GetSize();
- for (size_t i = 0; i < num_watchpoints; ++i) {
- WatchpointSP wp_sp = m_watchpoint_list.GetByIndex(i);
+ for (WatchpointSP wp_sp : m_watchpoint_list.Watchpoints()) {
if (!wp_sp)
return false;
@@ -1209,9 +1217,7 @@ bool Target::EnableAllWatchpoints(bool end_to_end) {
if (!ProcessIsValid())
return false;
- size_t num_watchpoints = m_watchpoint_list.GetSize();
- for (size_t i = 0; i < num_watchpoints; ++i) {
- WatchpointSP wp_sp = m_watchpoint_list.GetByIndex(i);
+ for (WatchpointSP wp_sp : m_watchpoint_list.Watchpoints()) {
if (!wp_sp)
return false;
@@ -1227,9 +1233,7 @@ bool Target::ClearAllWatchpointHitCounts() {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
LLDB_LOGF(log, "Target::%s\n", __FUNCTION__);
- size_t num_watchpoints = m_watchpoint_list.GetSize();
- for (size_t i = 0; i < num_watchpoints; ++i) {
- WatchpointSP wp_sp = m_watchpoint_list.GetByIndex(i);
+ for (WatchpointSP wp_sp : m_watchpoint_list.Watchpoints()) {
if (!wp_sp)
return false;
@@ -1243,9 +1247,7 @@ bool Target::ClearAllWatchpointHistoricValues() {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
LLDB_LOGF(log, "Target::%s\n", __FUNCTION__);
- size_t num_watchpoints = m_watchpoint_list.GetSize();
- for (size_t i = 0; i < num_watchpoints; ++i) {
- WatchpointSP wp_sp = m_watchpoint_list.GetByIndex(i);
+ for (WatchpointSP wp_sp : m_watchpoint_list.Watchpoints()) {
if (!wp_sp)
return false;
@@ -1263,9 +1265,7 @@ bool Target::IgnoreAllWatchpoints(uint32_t ignore_count) {
if (!ProcessIsValid())
return false;
- size_t num_watchpoints = m_watchpoint_list.GetSize();
- for (size_t i = 0; i < num_watchpoints; ++i) {
- WatchpointSP wp_sp = m_watchpoint_list.GetByIndex(i);
+ for (WatchpointSP wp_sp : m_watchpoint_list.Watchpoints()) {
if (!wp_sp)
return false;
@@ -1687,6 +1687,7 @@ bool Target::ModuleIsExcludedForUnconstrainedSearches(
size_t Target::ReadMemoryFromFileCache(const Address &addr, void *dst,
size_t dst_len, Status &error) {
+ LLDB_SCOPED_TIMER();
SectionSP section_sp(addr.GetSection());
if (section_sp) {
// If the contents of this section are encrypted, the on-disk file is
@@ -1717,8 +1718,8 @@ size_t Target::ReadMemoryFromFileCache(const Address &addr, void *dst,
return 0;
}
-size_t Target::ReadMemory(const Address &addr, bool prefer_file_cache,
- void *dst, size_t dst_len, Status &error,
+size_t Target::ReadMemory(const Address &addr, void *dst, size_t dst_len,
+ Status &error, bool force_live_memory,
lldb::addr_t *load_addr_ptr) {
error.Clear();
@@ -1753,10 +1754,31 @@ size_t Target::ReadMemory(const Address &addr, bool prefer_file_cache,
if (!resolved_addr.IsValid())
resolved_addr = addr;
- if (prefer_file_cache) {
- bytes_read = ReadMemoryFromFileCache(resolved_addr, dst, dst_len, error);
- if (bytes_read > 0)
- return bytes_read;
+ // If we read from the file cache but can't get as many bytes as requested,
+ // we keep the result around in this buffer, in case this result is the
+ // best we can do.
+ std::unique_ptr<uint8_t[]> file_cache_read_buffer;
+ size_t file_cache_bytes_read = 0;
+
+ // Read from file cache if read-only section.
+ if (!force_live_memory && resolved_addr.IsSectionOffset()) {
+ SectionSP section_sp(resolved_addr.GetSection());
+ if (section_sp) {
+ auto permissions = Flags(section_sp->GetPermissions());
+ bool is_readonly = !permissions.Test(ePermissionsWritable) &&
+ permissions.Test(ePermissionsReadable);
+ if (is_readonly) {
+ file_cache_bytes_read =
+ ReadMemoryFromFileCache(resolved_addr, dst, dst_len, error);
+ if (file_cache_bytes_read == dst_len)
+ return file_cache_bytes_read;
+ else if (file_cache_bytes_read > 0) {
+ file_cache_read_buffer =
+ std::make_unique<uint8_t[]>(file_cache_bytes_read);
+ std::memcpy(file_cache_read_buffer.get(), dst, file_cache_bytes_read);
+ }
+ }
+ }
}
if (ProcessIsValid()) {
@@ -1791,17 +1813,17 @@ size_t Target::ReadMemory(const Address &addr, bool prefer_file_cache,
*load_addr_ptr = load_addr;
return bytes_read;
}
- // If the address is not section offset we have an address that doesn't
- // resolve to any address in any currently loaded shared libraries and we
- // failed to read memory so there isn't anything more we can do. If it is
- // section offset, we might be able to read cached memory from the object
- // file.
- if (!resolved_addr.IsSectionOffset())
- return 0;
}
}
- if (!prefer_file_cache && resolved_addr.IsSectionOffset()) {
+ if (file_cache_read_buffer && file_cache_bytes_read > 0) {
+ // Reading from the process failed. If we've previously succeeded in reading
+ // something from the file cache, then copy that over and return that.
+ std::memcpy(dst, file_cache_read_buffer.get(), file_cache_bytes_read);
+ return file_cache_bytes_read;
+ }
+
+ if (!file_cache_read_buffer && resolved_addr.IsSectionOffset()) {
// If we didn't already try and read from the object file cache, then try
// it after failing to read from the process.
return ReadMemoryFromFileCache(resolved_addr, dst, dst_len, error);
@@ -1856,7 +1878,7 @@ size_t Target::ReadCStringFromMemory(const Address &addr, char *dst,
addr_t bytes_to_read =
std::min<addr_t>(bytes_left, cache_line_bytes_left);
size_t bytes_read =
- ReadMemory(address, false, curr_dst, bytes_to_read, error);
+ ReadMemory(address, curr_dst, bytes_to_read, error, true);
if (bytes_read == 0) {
result_error = error;
@@ -1884,15 +1906,15 @@ size_t Target::ReadCStringFromMemory(const Address &addr, char *dst,
return total_cstr_len;
}
-size_t Target::ReadScalarIntegerFromMemory(const Address &addr,
- bool prefer_file_cache,
- uint32_t byte_size, bool is_signed,
- Scalar &scalar, Status &error) {
+size_t Target::ReadScalarIntegerFromMemory(const Address &addr, uint32_t byte_size,
+ bool is_signed, Scalar &scalar,
+ Status &error,
+ bool force_live_memory) {
uint64_t uval;
if (byte_size <= sizeof(uval)) {
size_t bytes_read =
- ReadMemory(addr, prefer_file_cache, &uval, byte_size, error);
+ ReadMemory(addr, &uval, byte_size, error, force_live_memory);
if (bytes_read == byte_size) {
DataExtractor data(&uval, sizeof(uval), m_arch.GetSpec().GetByteOrder(),
m_arch.GetSpec().GetAddressByteSize());
@@ -1914,23 +1936,22 @@ size_t Target::ReadScalarIntegerFromMemory(const Address &addr,
}
uint64_t Target::ReadUnsignedIntegerFromMemory(const Address &addr,
- bool prefer_file_cache,
size_t integer_byte_size,
- uint64_t fail_value,
- Status &error) {
+ uint64_t fail_value, Status &error,
+ bool force_live_memory) {
Scalar scalar;
- if (ReadScalarIntegerFromMemory(addr, prefer_file_cache, integer_byte_size,
- false, scalar, error))
+ if (ReadScalarIntegerFromMemory(addr, integer_byte_size, false, scalar, error,
+ force_live_memory))
return scalar.ULongLong(fail_value);
return fail_value;
}
-bool Target::ReadPointerFromMemory(const Address &addr, bool prefer_file_cache,
- Status &error, Address &pointer_addr) {
+bool Target::ReadPointerFromMemory(const Address &addr, Status &error,
+ Address &pointer_addr,
+ bool force_live_memory) {
Scalar scalar;
- if (ReadScalarIntegerFromMemory(addr, prefer_file_cache,
- m_arch.GetSpec().GetAddressByteSize(), false,
- scalar, error)) {
+ if (ReadScalarIntegerFromMemory(addr, m_arch.GetSpec().GetAddressByteSize(),
+ false, scalar, error, force_live_memory)) {
addr_t pointer_vm_addr = scalar.ULongLong(LLDB_INVALID_ADDRESS);
if (pointer_vm_addr != LLDB_INVALID_ADDRESS) {
SectionLoadList &section_load_list = GetSectionLoadList();
@@ -2521,23 +2542,6 @@ SourceManager &Target::GetSourceManager() {
return *m_source_manager_up;
}
-ClangModulesDeclVendor *Target::GetClangModulesDeclVendor() {
- static std::mutex s_clang_modules_decl_vendor_mutex; // If this is contended
- // we can make it
- // per-target
-
- {
- std::lock_guard<std::mutex> guard(s_clang_modules_decl_vendor_mutex);
-
- if (!m_clang_modules_decl_vendor_up) {
- m_clang_modules_decl_vendor_up.reset(
- ClangModulesDeclVendor::Create(*this));
- }
- }
-
- return m_clang_modules_decl_vendor_up.get();
-}
-
Target::StopHookSP Target::CreateStopHook(StopHook::StopHookKind kind) {
lldb::user_id_t new_uid = ++m_stop_hook_next_id;
Target::StopHookSP stop_hook_sp;
@@ -2607,12 +2611,6 @@ bool Target::RunStopHooks() {
if (m_process_sp->GetState() != eStateStopped)
return false;
- // <rdar://problem/12027563> make sure we check that we are not stopped
- // because of us running a user expression since in that case we do not want
- // to run the stop-hooks
- if (m_process_sp->GetModIDRef().IsLastResumeForUserExpression())
- return false;
-
if (m_stop_hooks.empty())
return false;
@@ -2627,6 +2625,18 @@ bool Target::RunStopHooks() {
if (!any_active_hooks)
return false;
+ // <rdar://problem/12027563> make sure we check that we are not stopped
+ // because of us running a user expression since in that case we do not want
+ // to run the stop-hooks. Note, you can't just check whether the last stop
+ // was for a User Expression, because breakpoint commands get run before
+ // stop hooks, and one of them might have run an expression. You have
+ // to ensure you run the stop hooks once per natural stop.
+ uint32_t last_natural_stop = m_process_sp->GetModIDRef().GetLastNaturalStopID();
+ if (last_natural_stop != 0 && m_latest_stop_hook_id == last_natural_stop)
+ return false;
+
+ m_latest_stop_hook_id = last_natural_stop;
+
std::vector<ExecutionContext> exc_ctx_with_reasons;
ThreadList &cur_threadlist = m_process_sp->GetThreadList();
@@ -2925,6 +2935,28 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
launch_info.GetFlags().Set(eLaunchFlagDebug);
+ if (launch_info.IsScriptedProcess()) {
+ TargetPropertiesSP properties_sp = GetGlobalProperties();
+
+ if (!properties_sp) {
+ LLDB_LOGF(log, "Target::%s Couldn't fetch target global properties.",
+ __FUNCTION__);
+ return error;
+ }
+
+ // Only copy scripted process launch options.
+ ProcessLaunchInfo &default_launch_info =
+ const_cast<ProcessLaunchInfo &>(properties_sp->GetProcessLaunchInfo());
+
+ default_launch_info.SetProcessPluginName("ScriptedProcess");
+ default_launch_info.SetScriptedProcessClassName(
+ launch_info.GetScriptedProcessClassName());
+ default_launch_info.SetScriptedProcessDictionarySP(
+ launch_info.GetScriptedProcessDictionarySP());
+
+ SetProcessLaunchInfo(launch_info);
+ }
+
// Get the value of synchronous execution here. If you wait till after you
// have started to run, then you could have hit a breakpoint, whose command
// might switch the value, and then you'll pick up that incorrect value.
@@ -2950,7 +2982,7 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
// If we're not already connected to the process, and if we have a platform
// that can launch a process for debugging, go ahead and do that here.
if (state != eStateConnected && platform_sp &&
- platform_sp->CanDebugProcess()) {
+ platform_sp->CanDebugProcess() && !launch_info.IsScriptedProcess()) {
LLDB_LOGF(log, "Target::%s asking the platform to debug the process",
__FUNCTION__);
@@ -3053,7 +3085,38 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
void Target::SetTrace(const TraceSP &trace_sp) { m_trace_sp = trace_sp; }
-const TraceSP &Target::GetTrace() { return m_trace_sp; }
+TraceSP Target::GetTrace() { return m_trace_sp; }
+
+llvm::Expected<TraceSP> Target::CreateTrace() {
+ if (!m_process_sp)
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "A process is required for tracing");
+ if (m_trace_sp)
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "A trace already exists for the target");
+
+ llvm::Expected<TraceSupportedResponse> trace_type =
+ m_process_sp->TraceSupported();
+ if (!trace_type)
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(), "Tracing is not supported. %s",
+ llvm::toString(trace_type.takeError()).c_str());
+ if (llvm::Expected<TraceSP> trace_sp =
+ Trace::FindPluginForLiveProcess(trace_type->name, *m_process_sp))
+ m_trace_sp = *trace_sp;
+ else
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Couldn't create a Trace object for the process. %s",
+ llvm::toString(trace_sp.takeError()).c_str());
+ return m_trace_sp;
+}
+
+llvm::Expected<TraceSP> Target::GetTraceOrCreate() {
+ if (m_trace_sp)
+ return m_trace_sp;
+ return CreateTrace();
+}
Status Target::Attach(ProcessAttachInfo &attach_info, Stream *stream) {
auto state = eStateInvalid;
@@ -3349,7 +3412,7 @@ Target::StopHookCommandLine::HandleStop(ExecutionContext &exc_ctx,
// Force Async:
bool old_async = debugger.GetAsyncExecution();
debugger.SetAsyncExecution(true);
- debugger.GetCommandInterpreter().HandleCommands(GetCommands(), &exc_ctx,
+ debugger.GetCommandInterpreter().HandleCommands(GetCommands(), exc_ctx,
options, result);
debugger.SetAsyncExecution(old_async);
lldb::ReturnStatus status = result.GetStatus();
@@ -3615,15 +3678,10 @@ enum {
ePropertyExperimental,
};
-class TargetOptionValueProperties : public OptionValueProperties {
+class TargetOptionValueProperties
+ : public Cloneable<TargetOptionValueProperties, OptionValueProperties> {
public:
- TargetOptionValueProperties(ConstString name) : OptionValueProperties(name) {}
-
- // This constructor is used when creating TargetOptionValueProperties when it
- // is part of a new lldb_private::Target instance. It will copy all current
- // global property values as needed
- TargetOptionValueProperties(const TargetPropertiesSP &target_properties_sp)
- : OptionValueProperties(*target_properties_sp->GetValueProperties()) {}
+ TargetOptionValueProperties(ConstString name) : Cloneable(name) {}
const Property *GetPropertyAtIndex(const ExecutionContext *exe_ctx,
bool will_modify,
@@ -3654,11 +3712,12 @@ enum {
#include "TargetPropertiesEnum.inc"
};
-class TargetExperimentalOptionValueProperties : public OptionValueProperties {
+class TargetExperimentalOptionValueProperties
+ : public Cloneable<TargetExperimentalOptionValueProperties,
+ OptionValueProperties> {
public:
TargetExperimentalOptionValueProperties()
- : OptionValueProperties(
- ConstString(Properties::GetExperimentalSettingsName())) {}
+ : Cloneable(ConstString(Properties::GetExperimentalSettingsName())) {}
};
TargetExperimentalProperties::TargetExperimentalProperties()
@@ -3671,8 +3730,8 @@ TargetExperimentalProperties::TargetExperimentalProperties()
TargetProperties::TargetProperties(Target *target)
: Properties(), m_launch_info(), m_target(target) {
if (target) {
- m_collection_sp = std::make_shared<TargetOptionValueProperties>(
- Target::GetGlobalProperties());
+ m_collection_sp =
+ OptionValueProperties::CreateLocalCopy(*Target::GetGlobalProperties());
// Set callbacks to update launch_info whenever "settins set" updated any
// of these properties
@@ -4200,8 +4259,7 @@ void TargetProperties::SetNonStopModeEnabled(bool b) {
m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
}
-const ProcessLaunchInfo &TargetProperties::GetProcessLaunchInfo() {
- m_launch_info.SetArg0(GetArg0()); // FIXME: Arg0 callback doesn't work
+const ProcessLaunchInfo &TargetProperties::GetProcessLaunchInfo() const {
return m_launch_info;
}
@@ -4307,6 +4365,17 @@ void TargetProperties::DisableSTDIOValueChangedCallback() {
m_launch_info.GetFlags().Clear(lldb::eLaunchFlagDisableSTDIO);
}
+bool TargetProperties::GetDebugUtilityExpression() const {
+ const uint32_t idx = ePropertyDebugUtilityExpression;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+}
+
+void TargetProperties::SetDebugUtilityExpression(bool debug) {
+ const uint32_t idx = ePropertyDebugUtilityExpression;
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, debug);
+}
+
// Target::TargetEventData
Target::TargetEventData::TargetEventData(const lldb::TargetSP &target_sp)
diff --git a/lldb/source/Target/TargetList.cpp b/lldb/source/Target/TargetList.cpp
index 1e5856dd0b22..595799cfc92a 100644
--- a/lldb/source/Target/TargetList.cpp
+++ b/lldb/source/Target/TargetList.cpp
@@ -48,6 +48,7 @@ Status TargetList::CreateTarget(Debugger &debugger,
LoadDependentFiles load_dependent_files,
const OptionGroupPlatform *platform_options,
TargetSP &target_sp) {
+ std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
auto result = TargetList::CreateTargetInternal(
debugger, user_exe_path, triple_str, load_dependent_files,
platform_options, target_sp);
@@ -62,6 +63,7 @@ Status TargetList::CreateTarget(Debugger &debugger,
const ArchSpec &specified_arch,
LoadDependentFiles load_dependent_files,
PlatformSP &platform_sp, TargetSP &target_sp) {
+ std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
auto result = TargetList::CreateTargetInternal(
debugger, user_exe_path, specified_arch, load_dependent_files,
platform_sp, target_sp);
diff --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td
index 2d6a4358082a..8f627ad0f1a8 100644
--- a/lldb/source/Target/TargetProperties.td
+++ b/lldb/source/Target/TargetProperties.td
@@ -172,6 +172,9 @@ let Definition = "target" in {
def AutoInstallMainExecutable: Property<"auto-install-main-executable", "Boolean">,
DefaultTrue,
Desc<"Always install the main executable when connected to a remote platform.">;
+ def DebugUtilityExpression: Property<"debug-utility-expression", "Boolean">,
+ DefaultFalse,
+ Desc<"Enable debugging of LLDB-internal utility expressions.">;
}
let Definition = "process_experimental" in {
@@ -203,6 +206,10 @@ let Definition = "process" in {
Global,
DefaultFalse,
Desc<"If true, stop when a shared library is loaded or unloaded.">;
+ def DisableLangRuntimeUnwindPlans: Property<"disable-language-runtime-unwindplans", "Boolean">,
+ Global,
+ DefaultFalse,
+ Desc<"If true, LanguageRuntime plugins' UnwindPlans will not be used when backtracing.">;
def DetachKeepsStopped: Property<"detach-keeps-stopped", "Boolean">,
Global,
DefaultFalse,
@@ -223,9 +230,15 @@ let Definition = "process" in {
def UtilityExpressionTimeout: Property<"utility-expression-timeout", "UInt64">,
DefaultUnsignedValue<15>,
Desc<"The time in seconds to wait for LLDB-internal utility expressions.">;
+ def InterruptTimeout: Property<"interrupt-timeout", "UInt64">,
+ DefaultUnsignedValue<20>,
+ Desc<"The time in seconds to wait for an interrupt succeed in stopping the target.">;
def SteppingRunsAllThreads: Property<"run-all-threads", "Boolean">,
DefaultFalse,
Desc<"If true, stepping operations will run all threads. This is equivalent to setting the run-mode option to 'all-threads'.">;
+ def VirtualAddressableBits: Property<"virtual-addressable-bits", "UInt64">,
+ DefaultUnsignedValue<0>,
+ Desc<"The number of bits used for addressing. If the value is 39, then bits 0..38 are used for addressing. The default value of 0 means unspecified.">;
}
let Definition = "platform" in {
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index 049e458d8b19..b423f1b5f1fe 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -71,16 +71,10 @@ enum {
#include "TargetPropertiesEnum.inc"
};
-class ThreadOptionValueProperties : public OptionValueProperties {
+class ThreadOptionValueProperties
+ : public Cloneable<ThreadOptionValueProperties, OptionValueProperties> {
public:
- ThreadOptionValueProperties(ConstString name)
- : OptionValueProperties(name) {}
-
- // This constructor is used when creating ThreadOptionValueProperties when it
- // is part of a new lldb_private::Thread instance. It will copy all current
- // global property values as needed
- ThreadOptionValueProperties(ThreadProperties *global_properties)
- : OptionValueProperties(*global_properties->GetValueProperties()) {}
+ ThreadOptionValueProperties(ConstString name) : Cloneable(name) {}
const Property *GetPropertyAtIndex(const ExecutionContext *exe_ctx,
bool will_modify,
@@ -108,8 +102,8 @@ ThreadProperties::ThreadProperties(bool is_global) : Properties() {
std::make_shared<ThreadOptionValueProperties>(ConstString("thread"));
m_collection_sp->Initialize(g_thread_properties);
} else
- m_collection_sp = std::make_shared<ThreadOptionValueProperties>(
- Thread::GetGlobalProperties().get());
+ m_collection_sp =
+ OptionValueProperties::CreateLocalCopy(*Thread::GetGlobalProperties());
}
ThreadProperties::~ThreadProperties() = default;
@@ -530,7 +524,7 @@ bool Thread::RestoreRegisterStateFromCheckpoint(
return false;
}
-bool Thread::RestoreThreadStateFromCheckpoint(
+void Thread::RestoreThreadStateFromCheckpoint(
ThreadStateCheckpoint &saved_state) {
if (saved_state.stop_info_sp)
saved_state.stop_info_sp->MakeStopInfoValid();
@@ -539,7 +533,6 @@ bool Thread::RestoreThreadStateFromCheckpoint(
saved_state.current_inlined_depth);
GetPlans().RestoreCompletedPlanCheckpoint(
saved_state.m_completed_plan_checkpoint);
- return true;
}
StateType Thread::GetState() const {
@@ -830,6 +823,8 @@ bool Thread::ShouldStop(Event *event_ptr) {
ThreadPlan *plan_ptr = current_plan;
while ((plan_ptr = GetPreviousPlan(plan_ptr)) != nullptr) {
if (plan_ptr->PlanExplainsStop(event_ptr)) {
+ LLDB_LOGF(log, "Plan %s explains stop.", plan_ptr->GetName());
+
should_stop = plan_ptr->ShouldStop(event_ptr);
// plan_ptr explains the stop, next check whether plan_ptr is done,
@@ -861,10 +856,7 @@ bool Thread::ShouldStop(Event *event_ptr) {
}
if (!done_processing_current_plan) {
- bool over_ride_stop = current_plan->ShouldAutoContinue(event_ptr);
-
- LLDB_LOGF(log, "Plan %s explains stop, auto-continue %i.",
- current_plan->GetName(), over_ride_stop);
+ bool override_stop = false;
// We're starting from the base plan, so just let it decide;
if (current_plan->IsBasePlan()) {
@@ -885,20 +877,24 @@ bool Thread::ShouldStop(Event *event_ptr) {
if (should_stop)
current_plan->WillStop();
- // If a Master Plan wants to stop, and wants to stick on the stack,
- // we let it. Otherwise, see if the plan's parent wants to stop.
+ if (current_plan->ShouldAutoContinue(event_ptr)) {
+ override_stop = true;
+ LLDB_LOGF(log, "Plan %s auto-continue: true.",
+ current_plan->GetName());
+ }
+
+ // If a Master Plan wants to stop, we let it. Otherwise, see if the
+ // plan's parent wants to stop.
+ PopPlan();
if (should_stop && current_plan->IsMasterPlan() &&
!current_plan->OkayToDiscard()) {
- PopPlan();
break;
- } else {
- PopPlan();
+ }
- current_plan = GetCurrentPlan();
- if (current_plan == nullptr) {
- break;
- }
+ current_plan = GetCurrentPlan();
+ if (current_plan == nullptr) {
+ break;
}
} else {
break;
@@ -906,7 +902,7 @@ bool Thread::ShouldStop(Event *event_ptr) {
}
}
- if (over_ride_stop)
+ if (override_stop)
should_stop = false;
}
@@ -1181,14 +1177,6 @@ Status Thread::QueueThreadPlan(ThreadPlanSP &thread_plan_sp,
return status;
}
-void Thread::EnableTracer(bool value, bool single_stepping) {
- GetPlans().EnableTracer(value, single_stepping);
-}
-
-void Thread::SetTracer(lldb::ThreadPlanTracerSP &tracer_sp) {
- GetPlans().SetTracer(tracer_sp);
-}
-
bool Thread::DiscardUserThreadPlansUpToIndex(uint32_t plan_index) {
// Count the user thread plans from the back end to get the number of the one
// we want to discard:
@@ -1241,7 +1229,7 @@ Status Thread::UnwindInnermostExpression() {
return error;
}
-ThreadPlanSP Thread::QueueFundamentalPlan(bool abort_other_plans) {
+ThreadPlanSP Thread::QueueBasePlan(bool abort_other_plans) {
ThreadPlanSP thread_plan_sp(new ThreadPlanBase(*this));
QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
@@ -1289,16 +1277,10 @@ ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
lldb::RunMode stop_other_threads, Status &status,
LazyBool step_in_avoids_code_without_debug_info,
LazyBool step_out_avoids_code_without_debug_info) {
- ThreadPlanSP thread_plan_sp(
- new ThreadPlanStepInRange(*this, range, addr_context, stop_other_threads,
- step_in_avoids_code_without_debug_info,
- step_out_avoids_code_without_debug_info));
- ThreadPlanStepInRange *plan =
- static_cast<ThreadPlanStepInRange *>(thread_plan_sp.get());
-
- if (step_in_target)
- plan->SetStepInTarget(step_in_target);
-
+ ThreadPlanSP thread_plan_sp(new ThreadPlanStepInRange(
+ *this, range, addr_context, step_in_target, stop_other_threads,
+ step_in_avoids_code_without_debug_info,
+ step_out_avoids_code_without_debug_info));
status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
@@ -1321,11 +1303,12 @@ ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
ThreadPlanSP Thread::QueueThreadPlanForStepOut(
bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
- bool stop_other_threads, Vote stop_vote, Vote run_vote, uint32_t frame_idx,
- Status &status, LazyBool step_out_avoids_code_without_debug_info) {
+ bool stop_other_threads, Vote report_stop_vote, Vote report_run_vote,
+ uint32_t frame_idx, Status &status,
+ LazyBool step_out_avoids_code_without_debug_info) {
ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut(
- *this, addr_context, first_insn, stop_other_threads, stop_vote, run_vote,
- frame_idx, step_out_avoids_code_without_debug_info));
+ *this, addr_context, first_insn, stop_other_threads, report_stop_vote,
+ report_run_vote, frame_idx, step_out_avoids_code_without_debug_info));
status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
@@ -1333,13 +1316,14 @@ ThreadPlanSP Thread::QueueThreadPlanForStepOut(
ThreadPlanSP Thread::QueueThreadPlanForStepOutNoShouldStop(
bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
- bool stop_other_threads, Vote stop_vote, Vote run_vote, uint32_t frame_idx,
- Status &status, bool continue_to_next_branch) {
+ bool stop_other_threads, Vote report_stop_vote, Vote report_run_vote,
+ uint32_t frame_idx, Status &status, bool continue_to_next_branch) {
const bool calculate_return_value =
false; // No need to calculate the return value here.
ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut(
- *this, addr_context, first_insn, stop_other_threads, stop_vote, run_vote,
- frame_idx, eLazyBoolNo, continue_to_next_branch, calculate_return_value));
+ *this, addr_context, first_insn, stop_other_threads, report_stop_vote,
+ report_run_vote, frame_idx, eLazyBoolNo, continue_to_next_branch,
+ calculate_return_value));
ThreadPlanStepOut *new_plan =
static_cast<ThreadPlanStepOut *>(thread_plan_sp.get());
@@ -1695,12 +1679,20 @@ std::string Thread::StopReasonAsString(lldb::StopReason reason) {
return "exception";
case eStopReasonExec:
return "exec";
+ case eStopReasonFork:
+ return "fork";
+ case eStopReasonVFork:
+ return "vfork";
+ case eStopReasonVForkDone:
+ return "vfork done";
case eStopReasonPlanComplete:
return "plan complete";
case eStopReasonThreadExiting:
return "thread exiting";
case eStopReasonInstrumentation:
return "instrumentation break";
+ case eStopReasonProcessorTrace:
+ return "processor trace";
}
return "StopReason = " + std::to_string(reason);
diff --git a/lldb/source/Target/ThreadCollection.cpp b/lldb/source/Target/ThreadCollection.cpp
index 05b041c20dd0..8c2309795a4c 100644
--- a/lldb/source/Target/ThreadCollection.cpp
+++ b/lldb/source/Target/ThreadCollection.cpp
@@ -5,7 +5,7 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-#include <stdlib.h>
+#include <cstdlib>
#include <algorithm>
#include <mutex>
diff --git a/lldb/source/Target/ThreadList.cpp b/lldb/source/Target/ThreadList.cpp
index 032dcc9e5fbd..df2cc8ef6328 100644
--- a/lldb/source/Target/ThreadList.cpp
+++ b/lldb/source/Target/ThreadList.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <stdlib.h>
+#include <cstdlib>
#include <algorithm>
diff --git a/lldb/source/Target/ThreadPlan.cpp b/lldb/source/Target/ThreadPlan.cpp
index c7a00e2450c8..6b55f3912d11 100644
--- a/lldb/source/Target/ThreadPlan.cpp
+++ b/lldb/source/Target/ThreadPlan.cpp
@@ -20,9 +20,9 @@ using namespace lldb_private;
// ThreadPlan constructor
ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread,
- Vote stop_vote, Vote run_vote)
+ Vote report_stop_vote, Vote report_run_vote)
: m_process(*thread.GetProcess().get()), m_tid(thread.GetID()),
- m_stop_vote(stop_vote), m_run_vote(run_vote),
+ m_report_stop_vote(report_stop_vote), m_report_run_vote(report_run_vote),
m_takes_iteration_count(false), m_could_not_resolve_hw_bp(false),
m_thread(&thread), m_kind(kind), m_name(name), m_plan_complete_mutex(),
m_cached_plan_explains_stop(eLazyBoolCalculate), m_plan_complete(false),
@@ -50,7 +50,7 @@ Thread &ThreadPlan::GetThread() {
bool ThreadPlan::PlanExplainsStop(Event *event_ptr) {
if (m_cached_plan_explains_stop == eLazyBoolCalculate) {
bool actual_value = DoPlanExplainsStop(event_ptr);
- m_cached_plan_explains_stop = actual_value ? eLazyBoolYes : eLazyBoolNo;
+ CachePlanExplainsStop(actual_value);
return actual_value;
} else {
return m_cached_plan_explains_stop == eLazyBoolYes;
@@ -78,7 +78,7 @@ bool ThreadPlan::MischiefManaged() {
Vote ThreadPlan::ShouldReportStop(Event *event_ptr) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
- if (m_stop_vote == eVoteNoOpinion) {
+ if (m_report_stop_vote == eVoteNoOpinion) {
ThreadPlan *prev_plan = GetPreviousPlan();
if (prev_plan) {
Vote prev_vote = prev_plan->ShouldReportStop(event_ptr);
@@ -86,17 +86,17 @@ Vote ThreadPlan::ShouldReportStop(Event *event_ptr) {
return prev_vote;
}
}
- LLDB_LOG(log, "Returning vote: {0}", m_stop_vote);
- return m_stop_vote;
+ LLDB_LOG(log, "Returning vote: {0}", m_report_stop_vote);
+ return m_report_stop_vote;
}
Vote ThreadPlan::ShouldReportRun(Event *event_ptr) {
- if (m_run_vote == eVoteNoOpinion) {
+ if (m_report_run_vote == eVoteNoOpinion) {
ThreadPlan *prev_plan = GetPreviousPlan();
if (prev_plan)
return prev_plan->ShouldReportRun(event_ptr);
}
- return m_run_vote;
+ return m_report_run_vote;
}
void ThreadPlan::ClearThreadCache() { m_thread = nullptr; }
@@ -156,8 +156,7 @@ bool ThreadPlan::OkayToDiscard() {
}
lldb::StateType ThreadPlan::RunState() {
- if (m_tracer_sp && m_tracer_sp->TracingEnabled() &&
- m_tracer_sp->SingleStepEnabled())
+ if (m_tracer_sp && m_tracer_sp->TracingEnabled())
return eStateStepping;
else
return GetPlanRunState();
diff --git a/lldb/source/Target/ThreadPlanBase.cpp b/lldb/source/Target/ThreadPlanBase.cpp
index 650393d678e8..c6c4d97c1655 100644
--- a/lldb/source/Target/ThreadPlanBase.cpp
+++ b/lldb/source/Target/ThreadPlanBase.cpp
@@ -43,7 +43,7 @@ ThreadPlanBase::ThreadPlanBase(Thread &thread)
SetIsMasterPlan(true);
}
-ThreadPlanBase::~ThreadPlanBase() {}
+ThreadPlanBase::~ThreadPlanBase() = default;
void ThreadPlanBase::GetDescription(Stream *s, lldb::DescriptionLevel level) {
s->Printf("Base thread plan.");
@@ -70,8 +70,8 @@ Vote ThreadPlanBase::ShouldReportStop(Event *event_ptr) {
}
bool ThreadPlanBase::ShouldStop(Event *event_ptr) {
- m_stop_vote = eVoteYes;
- m_run_vote = eVoteYes;
+ m_report_stop_vote = eVoteYes;
+ m_report_run_vote = eVoteYes;
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
@@ -82,8 +82,8 @@ bool ThreadPlanBase::ShouldStop(Event *event_ptr) {
case eStopReasonInvalid:
case eStopReasonNone:
// This
- m_run_vote = eVoteNoOpinion;
- m_stop_vote = eVoteNo;
+ m_report_run_vote = eVoteNoOpinion;
+ m_report_stop_vote = eVoteNo;
return false;
case eStopReasonBreakpoint:
@@ -106,11 +106,11 @@ bool ThreadPlanBase::ShouldStop(Event *event_ptr) {
// with "restarted" so the UI will know to wait and expect the consequent
// "running".
if (stop_info_sp->ShouldNotify(event_ptr)) {
- m_stop_vote = eVoteYes;
- m_run_vote = eVoteYes;
+ m_report_stop_vote = eVoteYes;
+ m_report_run_vote = eVoteYes;
} else {
- m_stop_vote = eVoteNo;
- m_run_vote = eVoteNo;
+ m_report_stop_vote = eVoteNo;
+ m_report_run_vote = eVoteNo;
}
return false;
@@ -156,9 +156,9 @@ bool ThreadPlanBase::ShouldStop(Event *event_ptr) {
// We're not going to stop, but while we are here, let's figure out
// whether to report this.
if (stop_info_sp->ShouldNotify(event_ptr))
- m_stop_vote = eVoteYes;
+ m_report_stop_vote = eVoteYes;
else
- m_stop_vote = eVoteNo;
+ m_report_stop_vote = eVoteNo;
}
return false;
@@ -167,8 +167,8 @@ bool ThreadPlanBase::ShouldStop(Event *event_ptr) {
}
} else {
- m_run_vote = eVoteNoOpinion;
- m_stop_vote = eVoteNo;
+ m_report_run_vote = eVoteNoOpinion;
+ m_report_stop_vote = eVoteNo;
}
// If there's no explicit reason to stop, then we will continue.
@@ -185,8 +185,8 @@ bool ThreadPlanBase::DoWillResume(lldb::StateType resume_state,
bool current_plan) {
// Reset these to the default values so we don't set them wrong, then not get
// asked for a while, then return the wrong answer.
- m_run_vote = eVoteNoOpinion;
- m_stop_vote = eVoteNo;
+ m_report_run_vote = eVoteNoOpinion;
+ m_report_stop_vote = eVoteNo;
return true;
}
diff --git a/lldb/source/Target/ThreadPlanCallFunction.cpp b/lldb/source/Target/ThreadPlanCallFunction.cpp
index f525173f8a51..3699a507d058 100644
--- a/lldb/source/Target/ThreadPlanCallFunction.cpp
+++ b/lldb/source/Target/ThreadPlanCallFunction.cpp
@@ -454,8 +454,8 @@ void ThreadPlanCallFunction::SetStopOthers(bool new_value) {
m_subplan_sp->SetStopOthers(new_value);
}
-bool ThreadPlanCallFunction::RestoreThreadState() {
- return GetThread().RestoreThreadStateFromCheckpoint(m_stored_thread_state);
+void ThreadPlanCallFunction::RestoreThreadState() {
+ GetThread().RestoreThreadStateFromCheckpoint(m_stored_thread_state);
}
void ThreadPlanCallFunction::SetReturnValue() {
diff --git a/lldb/source/Target/ThreadPlanCallUserExpression.cpp b/lldb/source/Target/ThreadPlanCallUserExpression.cpp
index 00b01c76d900..9dddd850b6ab 100644
--- a/lldb/source/Target/ThreadPlanCallUserExpression.cpp
+++ b/lldb/source/Target/ThreadPlanCallUserExpression.cpp
@@ -43,7 +43,7 @@ ThreadPlanCallUserExpression::ThreadPlanCallUserExpression(
SetOkayToDiscard(false);
}
-ThreadPlanCallUserExpression::~ThreadPlanCallUserExpression() {}
+ThreadPlanCallUserExpression::~ThreadPlanCallUserExpression() = default;
void ThreadPlanCallUserExpression::GetDescription(
Stream *s, lldb::DescriptionLevel level) {
diff --git a/lldb/source/Target/ThreadPlanStack.cpp b/lldb/source/Target/ThreadPlanStack.cpp
index ad37669c31fd..d25602d25b91 100644
--- a/lldb/source/Target/ThreadPlanStack.cpp
+++ b/lldb/source/Target/ThreadPlanStack.cpp
@@ -39,6 +39,7 @@ ThreadPlanStack::ThreadPlanStack(const Thread &thread, bool make_null) {
void ThreadPlanStack::DumpThreadPlans(Stream &s,
lldb::DescriptionLevel desc_level,
bool include_internal) const {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
s.IndentMore();
PrintOneStack(s, "Active plan stack", m_plans, desc_level, include_internal);
PrintOneStack(s, "Completed plan stack", m_completed_plans, desc_level,
@@ -52,6 +53,7 @@ void ThreadPlanStack::PrintOneStack(Stream &s, llvm::StringRef stack_name,
const PlanStack &stack,
lldb::DescriptionLevel desc_level,
bool include_internal) const {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
// If the stack is empty, just exit:
if (stack.empty())
return;
@@ -80,6 +82,7 @@ void ThreadPlanStack::PrintOneStack(Stream &s, llvm::StringRef stack_name,
}
size_t ThreadPlanStack::CheckpointCompletedPlans() {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
m_completed_plan_checkpoint++;
m_completed_plan_store.insert(
std::make_pair(m_completed_plan_checkpoint, m_completed_plans));
@@ -87,6 +90,7 @@ size_t ThreadPlanStack::CheckpointCompletedPlans() {
}
void ThreadPlanStack::RestoreCompletedPlanCheckpoint(size_t checkpoint) {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
auto result = m_completed_plan_store.find(checkpoint);
assert(result != m_completed_plan_store.end() &&
"Asked for a checkpoint that didn't exist");
@@ -95,11 +99,13 @@ void ThreadPlanStack::RestoreCompletedPlanCheckpoint(size_t checkpoint) {
}
void ThreadPlanStack::DiscardCompletedPlanCheckpoint(size_t checkpoint) {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
m_completed_plan_store.erase(checkpoint);
}
void ThreadPlanStack::ThreadDestroyed(Thread *thread) {
// Tell the plan stacks that this thread is going away:
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
for (ThreadPlanSP plan : m_plans)
plan->ThreadDestroyed();
@@ -124,24 +130,11 @@ void ThreadPlanStack::ThreadDestroyed(Thread *thread) {
}
}
-void ThreadPlanStack::EnableTracer(bool value, bool single_stepping) {
- for (ThreadPlanSP plan : m_plans) {
- if (plan->GetThreadPlanTracer()) {
- plan->GetThreadPlanTracer()->EnableTracing(value);
- plan->GetThreadPlanTracer()->EnableSingleStep(single_stepping);
- }
- }
-}
-
-void ThreadPlanStack::SetTracer(lldb::ThreadPlanTracerSP &tracer_sp) {
- for (ThreadPlanSP plan : m_plans)
- plan->SetThreadPlanTracer(tracer_sp);
-}
-
void ThreadPlanStack::PushPlan(lldb::ThreadPlanSP new_plan_sp) {
// If the thread plan doesn't already have a tracer, give it its parent's
// tracer:
// The first plan has to be a base plan:
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
assert((m_plans.size() > 0 || new_plan_sp->IsBasePlan()) &&
"Zeroth plan must be a base plan");
@@ -154,6 +147,7 @@ void ThreadPlanStack::PushPlan(lldb::ThreadPlanSP new_plan_sp) {
}
lldb::ThreadPlanSP ThreadPlanStack::PopPlan() {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
assert(m_plans.size() > 1 && "Can't pop the base thread plan");
lldb::ThreadPlanSP plan_sp = std::move(m_plans.back());
@@ -164,6 +158,7 @@ lldb::ThreadPlanSP ThreadPlanStack::PopPlan() {
}
lldb::ThreadPlanSP ThreadPlanStack::DiscardPlan() {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
assert(m_plans.size() > 1 && "Can't discard the base thread plan");
lldb::ThreadPlanSP plan_sp = std::move(m_plans.back());
@@ -176,6 +171,7 @@ lldb::ThreadPlanSP ThreadPlanStack::DiscardPlan() {
// If the input plan is nullptr, discard all plans. Otherwise make sure this
// plan is in the stack, and if so discard up to and including it.
void ThreadPlanStack::DiscardPlansUpToPlan(ThreadPlan *up_to_plan_ptr) {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
int stack_size = m_plans.size();
if (up_to_plan_ptr == nullptr) {
@@ -203,6 +199,7 @@ void ThreadPlanStack::DiscardPlansUpToPlan(ThreadPlan *up_to_plan_ptr) {
}
void ThreadPlanStack::DiscardAllPlans() {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
int stack_size = m_plans.size();
for (int i = stack_size - 1; i > 0; i--) {
DiscardPlan();
@@ -211,6 +208,7 @@ void ThreadPlanStack::DiscardAllPlans() {
}
void ThreadPlanStack::DiscardConsultingMasterPlans() {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
while (true) {
int master_plan_idx;
bool discard = true;
@@ -244,11 +242,13 @@ void ThreadPlanStack::DiscardConsultingMasterPlans() {
}
lldb::ThreadPlanSP ThreadPlanStack::GetCurrentPlan() const {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
assert(m_plans.size() != 0 && "There will always be a base plan.");
return m_plans.back();
}
lldb::ThreadPlanSP ThreadPlanStack::GetCompletedPlan(bool skip_private) const {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
if (m_completed_plans.empty())
return {};
@@ -266,6 +266,7 @@ lldb::ThreadPlanSP ThreadPlanStack::GetCompletedPlan(bool skip_private) const {
lldb::ThreadPlanSP ThreadPlanStack::GetPlanByIndex(uint32_t plan_idx,
bool skip_private) const {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
uint32_t idx = 0;
for (lldb::ThreadPlanSP plan_sp : m_plans) {
@@ -279,6 +280,7 @@ lldb::ThreadPlanSP ThreadPlanStack::GetPlanByIndex(uint32_t plan_idx,
}
lldb::ValueObjectSP ThreadPlanStack::GetReturnValueObject() const {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
if (m_completed_plans.empty())
return {};
@@ -292,6 +294,7 @@ lldb::ValueObjectSP ThreadPlanStack::GetReturnValueObject() const {
}
lldb::ExpressionVariableSP ThreadPlanStack::GetExpressionVariable() const {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
if (m_completed_plans.empty())
return {};
@@ -304,19 +307,23 @@ lldb::ExpressionVariableSP ThreadPlanStack::GetExpressionVariable() const {
return {};
}
bool ThreadPlanStack::AnyPlans() const {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
// There is always a base plan...
return m_plans.size() > 1;
}
bool ThreadPlanStack::AnyCompletedPlans() const {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
return !m_completed_plans.empty();
}
bool ThreadPlanStack::AnyDiscardedPlans() const {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
return !m_discarded_plans.empty();
}
bool ThreadPlanStack::IsPlanDone(ThreadPlan *in_plan) const {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
for (auto plan : m_completed_plans) {
if (plan.get() == in_plan)
return true;
@@ -325,6 +332,7 @@ bool ThreadPlanStack::IsPlanDone(ThreadPlan *in_plan) const {
}
bool ThreadPlanStack::WasPlanDiscarded(ThreadPlan *in_plan) const {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
for (auto plan : m_discarded_plans) {
if (plan.get() == in_plan)
return true;
@@ -333,6 +341,7 @@ bool ThreadPlanStack::WasPlanDiscarded(ThreadPlan *in_plan) const {
}
ThreadPlan *ThreadPlanStack::GetPreviousPlan(ThreadPlan *current_plan) const {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
if (current_plan == nullptr)
return nullptr;
@@ -360,6 +369,7 @@ ThreadPlan *ThreadPlanStack::GetPreviousPlan(ThreadPlan *current_plan) const {
}
ThreadPlan *ThreadPlanStack::GetInnermostExpression() const {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
int stack_size = m_plans.size();
for (int i = stack_size - 1; i > 0; i--) {
@@ -370,11 +380,13 @@ ThreadPlan *ThreadPlanStack::GetInnermostExpression() const {
}
void ThreadPlanStack::ClearThreadCache() {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
for (lldb::ThreadPlanSP thread_plan_sp : m_plans)
thread_plan_sp->ClearThreadCache();
}
void ThreadPlanStack::WillResume() {
+ std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
m_completed_plans.clear();
m_discarded_plans.clear();
}
@@ -389,7 +401,7 @@ void ThreadPlanStackMap::Update(ThreadList &current_threads,
lldb::tid_t cur_tid = thread->GetID();
if (!Find(cur_tid)) {
AddThread(*thread.get());
- thread->QueueFundamentalPlan(true);
+ thread->QueueBasePlan(true);
}
}
}
@@ -402,7 +414,7 @@ void ThreadPlanStackMap::Update(ThreadList &current_threads,
std::vector<lldb::tid_t> missing_threads;
// If we are going to delete plans from the plan stack,
// then scan for absent TID's:
- for (auto thread_plans : m_plans_list) {
+ for (auto &thread_plans : m_plans_list) {
lldb::tid_t cur_tid = thread_plans.first;
ThreadSP thread_sp = current_threads.FindThreadByID(cur_tid);
if (!thread_sp)
@@ -417,7 +429,7 @@ void ThreadPlanStackMap::DumpPlans(Stream &strm,
lldb::DescriptionLevel desc_level,
bool internal, bool condense_if_trivial,
bool skip_unreported) {
- for (auto elem : m_plans_list) {
+ for (auto &elem : m_plans_list) {
lldb::tid_t tid = elem.first;
uint32_t index_id = 0;
ThreadSP thread_sp = m_process.GetThreadList().FindThreadByID(tid);
diff --git a/lldb/source/Target/ThreadPlanStepInRange.cpp b/lldb/source/Target/ThreadPlanStepInRange.cpp
index a03bd93ac638..69b4b918d467 100644
--- a/lldb/source/Target/ThreadPlanStepInRange.cpp
+++ b/lldb/source/Target/ThreadPlanStepInRange.cpp
@@ -33,14 +33,14 @@ uint32_t ThreadPlanStepInRange::s_default_flag_values =
ThreadPlanStepInRange::ThreadPlanStepInRange(
Thread &thread, const AddressRange &range,
- const SymbolContext &addr_context, lldb::RunMode stop_others,
- LazyBool step_in_avoids_code_without_debug_info,
+ const SymbolContext &addr_context, const char *step_into_target,
+ lldb::RunMode stop_others, LazyBool step_in_avoids_code_without_debug_info,
LazyBool step_out_avoids_code_without_debug_info)
: ThreadPlanStepRange(ThreadPlan::eKindStepInRange,
"Step Range stepping in", thread, range, addr_context,
stop_others),
ThreadPlanShouldStopHere(this), m_step_past_prologue(true),
- m_virtual_step(false) {
+ m_virtual_step(false), m_step_into_target(step_into_target) {
SetCallbacks();
SetFlagsToDefault();
SetupAvoidNoDebug(step_in_avoids_code_without_debug_info,
@@ -291,11 +291,10 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) {
}
void ThreadPlanStepInRange::SetAvoidRegexp(const char *name) {
- auto name_ref = llvm::StringRef::withNullAsEmpty(name);
if (m_avoid_regexp_up)
- *m_avoid_regexp_up = RegularExpression(name_ref);
+ *m_avoid_regexp_up = RegularExpression(name);
else
- m_avoid_regexp_up = std::make_unique<RegularExpression>(name_ref);
+ m_avoid_regexp_up = std::make_unique<RegularExpression>(name);
}
void ThreadPlanStepInRange::SetDefaultFlagValue(uint32_t new_value) {
diff --git a/lldb/source/Target/ThreadPlanStepInstruction.cpp b/lldb/source/Target/ThreadPlanStepInstruction.cpp
index c0da735c44b6..e34e41e8bce8 100644
--- a/lldb/source/Target/ThreadPlanStepInstruction.cpp
+++ b/lldb/source/Target/ThreadPlanStepInstruction.cpp
@@ -23,10 +23,11 @@ using namespace lldb_private;
ThreadPlanStepInstruction::ThreadPlanStepInstruction(Thread &thread,
bool step_over,
bool stop_other_threads,
- Vote stop_vote,
- Vote run_vote)
+ Vote report_stop_vote,
+ Vote report_run_vote)
: ThreadPlan(ThreadPlan::eKindStepInstruction,
- "Step over single instruction", thread, stop_vote, run_vote),
+ "Step over single instruction", thread, report_stop_vote,
+ report_run_vote),
m_instruction_addr(0), m_stop_other_threads(stop_other_threads),
m_step_over(step_over) {
m_takes_iteration_count = true;
diff --git a/lldb/source/Target/ThreadPlanStepOut.cpp b/lldb/source/Target/ThreadPlanStepOut.cpp
index 9f0749c0fdb3..86ccac2ec499 100644
--- a/lldb/source/Target/ThreadPlanStepOut.cpp
+++ b/lldb/source/Target/ThreadPlanStepOut.cpp
@@ -33,11 +33,11 @@ uint32_t ThreadPlanStepOut::s_default_flag_values = 0;
// ThreadPlanStepOut: Step out of the current frame
ThreadPlanStepOut::ThreadPlanStepOut(
Thread &thread, SymbolContext *context, bool first_insn, bool stop_others,
- Vote stop_vote, Vote run_vote, uint32_t frame_idx,
+ Vote report_stop_vote, Vote report_run_vote, uint32_t frame_idx,
LazyBool step_out_avoids_code_without_debug_info,
bool continue_to_next_branch, bool gather_return_value)
- : ThreadPlan(ThreadPlan::eKindStepOut, "Step out", thread, stop_vote,
- run_vote),
+ : ThreadPlan(ThreadPlan::eKindStepOut, "Step out", thread, report_stop_vote,
+ report_run_vote),
ThreadPlanShouldStopHere(this), m_step_from_insn(LLDB_INVALID_ADDRESS),
m_return_bp_id(LLDB_INVALID_BREAK_ID),
m_return_addr(LLDB_INVALID_ADDRESS), m_stop_others(stop_others),
diff --git a/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp b/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp
index f188d827faae..965a7b3a9960 100644
--- a/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp
+++ b/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp
@@ -36,7 +36,7 @@ ThreadPlanStepOverBreakpoint::ThreadPlanStepOverBreakpoint(Thread &thread)
m_breakpoint_addr);
}
-ThreadPlanStepOverBreakpoint::~ThreadPlanStepOverBreakpoint() {}
+ThreadPlanStepOverBreakpoint::~ThreadPlanStepOverBreakpoint() = default;
void ThreadPlanStepOverBreakpoint::GetDescription(
Stream *s, lldb::DescriptionLevel level) {
@@ -49,16 +49,6 @@ bool ThreadPlanStepOverBreakpoint::ValidatePlan(Stream *error) { return true; }
bool ThreadPlanStepOverBreakpoint::DoPlanExplainsStop(Event *event_ptr) {
StopInfoSP stop_info_sp = GetPrivateStopInfo();
if (stop_info_sp) {
- // It's a little surprising that we stop here for a breakpoint hit.
- // However, when you single step ONTO a breakpoint we still want to call
- // that a breakpoint hit, and trigger the actions, etc. Otherwise you
- // would see the
- // PC at the breakpoint without having triggered the actions, then you'd
- // continue, the PC wouldn't change,
- // and you'd see the breakpoint hit, which would be odd. So the lower
- // levels fake "step onto breakpoint address" and return that as a
- // breakpoint. So our trace step COULD appear as a breakpoint hit if the
- // next instruction also contained a breakpoint.
StopReason reason = stop_info_sp->GetStopReason();
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp
index 3c42cd750dad..896e647bbb52 100644
--- a/lldb/source/Target/ThreadPlanStepRange.cpp
+++ b/lldb/source/Target/ThreadPlanStepRange.cpp
@@ -264,10 +264,9 @@ InstructionList *ThreadPlanStepRange::GetInstructionsForAddress(
// Disassemble the address range given:
const char *plugin_name = nullptr;
const char *flavor = nullptr;
- const bool prefer_file_cache = true;
m_instruction_ranges[i] = Disassembler::DisassembleRange(
GetTarget().GetArchitecture(), plugin_name, flavor, GetTarget(),
- m_address_ranges[i], prefer_file_cache);
+ m_address_ranges[i]);
}
if (!m_instruction_ranges[i])
return nullptr;
diff --git a/lldb/source/Target/ThreadPlanStepThrough.cpp b/lldb/source/Target/ThreadPlanStepThrough.cpp
index 06b626935aba..6fc0312222fb 100644
--- a/lldb/source/Target/ThreadPlanStepThrough.cpp
+++ b/lldb/source/Target/ThreadPlanStepThrough.cpp
@@ -22,7 +22,6 @@ using namespace lldb_private;
// ThreadPlanStepThrough: If the current instruction is a trampoline, step
// through it If it is the beginning of the prologue of a function, step
// through that as well.
-// FIXME: At present only handles DYLD trampolines.
ThreadPlanStepThrough::ThreadPlanStepThrough(Thread &thread,
StackID &m_stack_id,
diff --git a/lldb/source/Target/ThreadPlanTracer.cpp b/lldb/source/Target/ThreadPlanTracer.cpp
index c00415f3c1ee..754ce655729c 100644
--- a/lldb/source/Target/ThreadPlanTracer.cpp
+++ b/lldb/source/Target/ThreadPlanTracer.cpp
@@ -35,11 +35,11 @@ using namespace lldb_private;
ThreadPlanTracer::ThreadPlanTracer(Thread &thread, lldb::StreamSP &stream_sp)
: m_process(*thread.GetProcess().get()), m_tid(thread.GetID()),
- m_single_step(true), m_enabled(false), m_stream_sp(stream_sp) {}
+ m_enabled(false), m_stream_sp(stream_sp) {}
ThreadPlanTracer::ThreadPlanTracer(Thread &thread)
: m_process(*thread.GetProcess().get()), m_tid(thread.GetID()),
- m_single_step(true), m_enabled(false), m_stream_sp() {}
+ m_enabled(false), m_stream_sp() {}
Stream *ThreadPlanTracer::GetLogStream() {
if (m_stream_sp)
@@ -75,7 +75,7 @@ void ThreadPlanTracer::Log() {
}
bool ThreadPlanTracer::TracerExplainsStop() {
- if (m_enabled && m_single_step) {
+ if (m_enabled) {
lldb::StopInfoSP stop_info = GetThread().GetStopInfo();
return (stop_info->GetStopReason() == eStopReasonTrace);
} else
@@ -191,7 +191,7 @@ void ThreadPlanAssemblyTracer::Log() {
for (int arg_index = 0; arg_index < num_args; ++arg_index) {
Value value;
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
value.SetCompilerType(intptr_type);
value_list.PushValue(value);
}
diff --git a/lldb/source/Target/ThreadSpec.cpp b/lldb/source/Target/ThreadSpec.cpp
index 1f6639379c45..ba4c3aa89455 100644
--- a/lldb/source/Target/ThreadSpec.cpp
+++ b/lldb/source/Target/ThreadSpec.cpp
@@ -17,9 +17,7 @@ const char *ThreadSpec::g_option_names[static_cast<uint32_t>(
ThreadSpec::OptionNames::LastOptionName)]{"Index", "ID", "Name",
"QueueName"};
-ThreadSpec::ThreadSpec()
- : m_index(UINT32_MAX), m_tid(LLDB_INVALID_THREAD_ID), m_name(),
- m_queue_name() {}
+ThreadSpec::ThreadSpec() : m_name(), m_queue_name() {}
std::unique_ptr<ThreadSpec> ThreadSpec::CreateFromStructuredData(
const StructuredData::Dictionary &spec_dict, Status &error) {
diff --git a/lldb/source/Target/Trace.cpp b/lldb/source/Target/Trace.cpp
index d19115b2d1f9..827f3264c096 100644
--- a/lldb/source/Target/Trace.cpp
+++ b/lldb/source/Target/Trace.cpp
@@ -13,6 +13,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Symbol/Function.h"
+#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Thread.h"
@@ -57,9 +58,10 @@ static Error createInvalidPlugInError(StringRef plugin_name) {
plugin_name.data());
}
-Expected<lldb::TraceSP> Trace::FindPlugin(Debugger &debugger,
- const json::Value &trace_session_file,
- StringRef session_file_dir) {
+Expected<lldb::TraceSP>
+Trace::FindPluginForPostMortemProcess(Debugger &debugger,
+ const json::Value &trace_session_file,
+ StringRef session_file_dir) {
JSONSimpleTraceSession json_session;
json::Path::Root root("traceSession");
if (!json::fromJSON(trace_session_file, json_session, root))
@@ -72,6 +74,20 @@ Expected<lldb::TraceSP> Trace::FindPlugin(Debugger &debugger,
return createInvalidPlugInError(json_session.trace.type);
}
+Expected<lldb::TraceSP>
+Trace::FindPluginForLiveProcess(llvm::StringRef plugin_name, Process &process) {
+ if (!process.IsLiveDebugSession())
+ return createStringError(inconvertibleErrorCode(),
+ "Can't trace non-live processes");
+
+ ConstString name(plugin_name);
+ if (auto create_callback =
+ PluginManager::GetTraceCreateCallbackForLiveProcess(name))
+ return create_callback(process);
+
+ return createInvalidPlugInError(plugin_name);
+}
+
Expected<StringRef> Trace::FindPluginSchema(StringRef name) {
ConstString plugin_name(name);
StringRef schema = PluginManager::GetTraceSchema(plugin_name);
@@ -81,188 +97,125 @@ Expected<StringRef> Trace::FindPluginSchema(StringRef name) {
return createInvalidPlugInError(name);
}
-static int GetNumberOfDigits(size_t num) {
- return num == 0 ? 1 : static_cast<int>(log10(num)) + 1;
+Error Trace::Start(const llvm::json::Value &request) {
+ if (!m_live_process)
+ return createStringError(inconvertibleErrorCode(),
+ "Tracing requires a live process.");
+ return m_live_process->TraceStart(request);
}
-/// Dump the symbol context of the given instruction address if it's different
-/// from the symbol context of the previous instruction in the trace.
-///
-/// \param[in] prev_sc
-/// The symbol context of the previous instruction in the trace.
-///
-/// \param[in] address
-/// The address whose symbol information will be dumped.
-///
-/// \return
-/// The symbol context of the current address, which might differ from the
-/// previous one.
-static SymbolContext DumpSymbolContext(Stream &s, const SymbolContext &prev_sc,
- Target &target, const Address &address) {
- AddressRange range;
- if (prev_sc.GetAddressRange(eSymbolContextEverything, 0,
- /*inline_block_range*/ false, range) &&
- range.ContainsFileAddress(address))
- return prev_sc;
-
- SymbolContext sc;
- address.CalculateSymbolContext(&sc, eSymbolContextEverything);
+Error Trace::Stop() {
+ if (!m_live_process)
+ return createStringError(inconvertibleErrorCode(),
+ "Tracing requires a live process.");
+ return m_live_process->TraceStop(
+ TraceStopRequest(GetPluginName().AsCString()));
+}
- if (!prev_sc.module_sp && !sc.module_sp)
- return sc;
- if (prev_sc.module_sp == sc.module_sp && !sc.function && !sc.symbol &&
- !prev_sc.function && !prev_sc.symbol)
- return sc;
+Error Trace::Stop(llvm::ArrayRef<lldb::tid_t> tids) {
+ if (!m_live_process)
+ return createStringError(inconvertibleErrorCode(),
+ "Tracing requires a live process.");
+ return m_live_process->TraceStop(
+ TraceStopRequest(GetPluginName().AsCString(), tids));
+}
- s.Printf(" ");
+Expected<std::string> Trace::GetLiveProcessState() {
+ if (!m_live_process)
+ return createStringError(inconvertibleErrorCode(),
+ "Tracing requires a live process.");
+ return m_live_process->TraceGetState(GetPluginName().AsCString());
+}
- if (!sc.module_sp)
- s.Printf("(none)");
- else if (!sc.function && !sc.symbol)
- s.Printf("%s`(none)",
- sc.module_sp->GetFileSpec().GetFilename().AsCString());
- else
- sc.DumpStopContext(&s, &target, address, /*show_fullpath*/ false,
- /*show_module*/ true, /*show_inlined_frames*/ false,
- /*show_function_arguments*/ true,
- /*show_function_name*/ true,
- /*show_inline_callsite_line_info*/ false);
- s.Printf("\n");
- return sc;
+Optional<size_t> Trace::GetLiveThreadBinaryDataSize(lldb::tid_t tid,
+ llvm::StringRef kind) {
+ auto it = m_live_thread_data.find(tid);
+ if (it == m_live_thread_data.end())
+ return None;
+ std::unordered_map<std::string, size_t> &single_thread_data = it->second;
+ auto single_thread_data_it = single_thread_data.find(kind.str());
+ if (single_thread_data_it == single_thread_data.end())
+ return None;
+ return single_thread_data_it->second;
}
-/// Dump an instruction given by its address using a given disassembler, unless
-/// the instruction is not present in the disassembler.
-///
-/// \param[in] disassembler
-/// A disassembler containing a certain instruction list.
-///
-/// \param[in] address
-/// The address of the instruction to dump.
-///
-/// \return
-/// \b true if the information could be dumped, \b false otherwise.
-static bool TryDumpInstructionInfo(Stream &s,
- const DisassemblerSP &disassembler,
- const ExecutionContext &exe_ctx,
- const Address &address) {
- if (!disassembler)
- return false;
+Optional<size_t> Trace::GetLiveProcessBinaryDataSize(llvm::StringRef kind) {
+ auto data_it = m_live_process_data.find(kind.str());
+ if (data_it == m_live_process_data.end())
+ return None;
+ return data_it->second;
+}
- if (InstructionSP instruction =
- disassembler->GetInstructionList().GetInstructionAtAddress(address)) {
- instruction->Dump(&s, /*show_address*/ false, /*show_bytes*/ false,
- /*max_opcode_byte_size*/ 0, &exe_ctx,
- /*sym_ctx*/ nullptr, /*prev_sym_ctx*/ nullptr,
- /*disassembly_addr_format*/ nullptr,
- /*max_address_text_size*/ 0);
- return true;
- }
+Expected<ArrayRef<uint8_t>>
+Trace::GetLiveThreadBinaryData(lldb::tid_t tid, llvm::StringRef kind) {
+ if (!m_live_process)
+ return createStringError(inconvertibleErrorCode(),
+ "Tracing requires a live process.");
+ llvm::Optional<size_t> size = GetLiveThreadBinaryDataSize(tid, kind);
+ if (!size)
+ return createStringError(
+ inconvertibleErrorCode(),
+ "Tracing data \"%s\" is not available for thread %" PRIu64 ".",
+ kind.data(), tid);
- return false;
+ TraceGetBinaryDataRequest request{GetPluginName().AsCString(), kind.str(),
+ static_cast<int64_t>(tid), 0,
+ static_cast<int64_t>(*size)};
+ return m_live_process->TraceGetBinaryData(request);
}
-/// Dump an instruction instruction given by its address.
-///
-/// \param[in] prev_disassembler
-/// The disassembler that was used to dump the previous instruction in the
-/// trace. It is useful to avoid recomputations.
-///
-/// \param[in] address
-/// The address of the instruction to dump.
-///
-/// \return
-/// A disassembler that contains the given instruction, which might differ
-/// from the previous disassembler.
-static DisassemblerSP
-DumpInstructionInfo(Stream &s, const SymbolContext &sc,
- const DisassemblerSP &prev_disassembler,
- ExecutionContext &exe_ctx, const Address &address) {
- // We first try to use the previous disassembler
- if (TryDumpInstructionInfo(s, prev_disassembler, exe_ctx, address))
- return prev_disassembler;
+Expected<ArrayRef<uint8_t>>
+Trace::GetLiveProcessBinaryData(llvm::StringRef kind) {
+ if (!m_live_process)
+ return createStringError(inconvertibleErrorCode(),
+ "Tracing requires a live process.");
+ llvm::Optional<size_t> size = GetLiveProcessBinaryDataSize(kind);
+ if (!size)
+ return createStringError(
+ inconvertibleErrorCode(),
+ "Tracing data \"%s\" is not available for the process.", kind.data());
- // Now we try using the current function's disassembler
- if (sc.function) {
- DisassemblerSP disassembler =
- sc.function->GetInstructions(exe_ctx, nullptr, true);
- if (TryDumpInstructionInfo(s, disassembler, exe_ctx, address))
- return disassembler;
- }
-
- // We fallback to disassembly one instruction
- Target &target = exe_ctx.GetTargetRef();
- const ArchSpec &arch = target.GetArchitecture();
- AddressRange range(address, arch.GetMaximumOpcodeByteSize() * 1);
- DisassemblerSP disassembler = Disassembler::DisassembleRange(
- arch, /*plugin_name*/ nullptr,
- /*flavor*/ nullptr, target, range, /*prefer_file_cache*/ true);
- if (TryDumpInstructionInfo(s, disassembler, exe_ctx, address))
- return disassembler;
- return nullptr;
+ TraceGetBinaryDataRequest request{GetPluginName().AsCString(), kind.str(),
+ None, 0, static_cast<int64_t>(*size)};
+ return m_live_process->TraceGetBinaryData(request);
}
-void Trace::DumpTraceInstructions(Thread &thread, Stream &s, size_t count,
- size_t end_position, bool raw) {
- size_t instructions_count = GetInstructionCount(thread);
- s.Printf("thread #%u: tid = %" PRIu64 ", total instructions = %zu\n",
- thread.GetIndexID(), thread.GetID(), instructions_count);
-
- if (count == 0 || end_position >= instructions_count)
+void Trace::RefreshLiveProcessState() {
+ if (!m_live_process)
return;
- size_t start_position =
- end_position + 1 < count ? 0 : end_position + 1 - count;
-
- int digits_count = GetNumberOfDigits(end_position);
- auto printInstructionIndex = [&](size_t index) {
- s.Printf(" [%*zu] ", digits_count, index);
- };
-
- bool was_prev_instruction_an_error = false;
- Target &target = thread.GetProcess()->GetTarget();
-
- SymbolContext sc;
- DisassemblerSP disassembler;
- ExecutionContext exe_ctx;
- target.CalculateExecutionContext(exe_ctx);
-
- TraverseInstructions(
- thread, start_position, TraceDirection::Forwards,
- [&](size_t index, Expected<lldb::addr_t> load_address) -> bool {
- if (load_address) {
- // We print an empty line after a sequence of errors to show more
- // clearly that there's a gap in the trace
- if (was_prev_instruction_an_error)
- s.Printf(" ...missing instructions\n");
-
- Address address;
- if (!raw) {
- target.GetSectionLoadList().ResolveLoadAddress(*load_address,
- address);
+ uint32_t new_stop_id = m_live_process->GetStopID();
+ if (new_stop_id == m_stop_id)
+ return;
- sc = DumpSymbolContext(s, sc, target, address);
- }
+ m_stop_id = new_stop_id;
+ m_live_thread_data.clear();
- printInstructionIndex(index);
- s.Printf("0x%016" PRIx64 " ", *load_address);
+ Expected<std::string> json_string = GetLiveProcessState();
+ if (!json_string) {
+ DoRefreshLiveProcessState(json_string.takeError());
+ return;
+ }
+ Expected<TraceGetStateResponse> live_process_state =
+ json::parse<TraceGetStateResponse>(*json_string, "TraceGetStateResponse");
+ if (!live_process_state) {
+ DoRefreshLiveProcessState(live_process_state.takeError());
+ return;
+ }
- if (!raw) {
- disassembler =
- DumpInstructionInfo(s, sc, disassembler, exe_ctx, address);
- }
+ for (const TraceThreadState &thread_state :
+ live_process_state->tracedThreads) {
+ for (const TraceBinaryData &item : thread_state.binaryData)
+ m_live_thread_data[thread_state.tid][item.kind] = item.size;
+ }
- was_prev_instruction_an_error = false;
- } else {
- printInstructionIndex(index);
- s << toString(load_address.takeError());
- was_prev_instruction_an_error = true;
- if (!raw)
- sc = SymbolContext();
- }
+ for (const TraceBinaryData &item : live_process_state->processBinaryData)
+ m_live_process_data[item.kind] = item.size;
- s.Printf("\n");
+ DoRefreshLiveProcessState(std::move(live_process_state));
+}
- return index < end_position;
- });
+uint32_t Trace::GetStopID() {
+ RefreshLiveProcessState();
+ return m_stop_id;
}
diff --git a/lldb/source/Target/TraceCursor.cpp b/lldb/source/Target/TraceCursor.cpp
new file mode 100644
index 000000000000..d0f69642cb90
--- /dev/null
+++ b/lldb/source/Target/TraceCursor.cpp
@@ -0,0 +1,35 @@
+//===-- TraceCursor.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/TraceCursor.h"
+
+#include "lldb/Target/ExecutionContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace llvm;
+
+TraceCursor::TraceCursor(lldb::ThreadSP thread_sp)
+ : m_exe_ctx_ref(ExecutionContext(thread_sp)) {}
+
+ExecutionContextRef &TraceCursor::GetExecutionContextRef() {
+ return m_exe_ctx_ref;
+}
+
+void TraceCursor::SetGranularity(
+ lldb::TraceInstructionControlFlowType granularity) {
+ m_granularity = granularity;
+}
+
+void TraceCursor::SetIgnoreErrors(bool ignore_errors) {
+ m_ignore_errors = ignore_errors;
+}
+
+void TraceCursor::SetForwards(bool forwards) { m_forwards = forwards; }
+
+bool TraceCursor::IsForwards() const { return m_forwards; }
diff --git a/lldb/source/Target/TraceExporter.cpp b/lldb/source/Target/TraceExporter.cpp
new file mode 100644
index 000000000000..1a6571dba4a0
--- /dev/null
+++ b/lldb/source/Target/TraceExporter.cpp
@@ -0,0 +1,32 @@
+//===-- TraceExporter.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 "lldb/Target/TraceExporter.h"
+
+#include "lldb/Core/PluginManager.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace llvm;
+
+static Error createInvalidPlugInError(StringRef plugin_name) {
+ return createStringError(
+ std::errc::invalid_argument,
+ "no trace expoter plug-in matches the specified type: \"%s\"",
+ plugin_name.data());
+}
+
+Expected<lldb::TraceExporterUP>
+TraceExporter::FindPlugin(llvm::StringRef plugin_name) {
+ ConstString name(plugin_name);
+ if (auto create_callback =
+ PluginManager::GetTraceExporterCreateCallback(name))
+ return create_callback();
+
+ return createInvalidPlugInError(plugin_name);
+}
diff --git a/lldb/source/Target/TraceInstructionDumper.cpp b/lldb/source/Target/TraceInstructionDumper.cpp
new file mode 100644
index 000000000000..dc1e86481c36
--- /dev/null
+++ b/lldb/source/Target/TraceInstructionDumper.cpp
@@ -0,0 +1,292 @@
+//===-- TraceInstructionDumper.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 "lldb/Target/TraceInstructionDumper.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/SectionLoadList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace llvm;
+
+TraceInstructionDumper::TraceInstructionDumper(lldb::TraceCursorUP &&cursor_up,
+ int initial_index, bool raw,
+ bool show_tsc)
+ : m_cursor_up(std::move(cursor_up)), m_index(initial_index), m_raw(raw),
+ m_show_tsc(show_tsc) {}
+
+/// \return
+/// Return \b true if the cursor could move one step.
+bool TraceInstructionDumper::TryMoveOneStep() {
+ if (!m_cursor_up->Next()) {
+ SetNoMoreData();
+ return false;
+ }
+ m_index += m_cursor_up->IsForwards() ? 1 : -1;
+ return true;
+}
+
+/// \return
+/// The number of characters that would be needed to print the given
+/// integer.
+static int GetNumberOfChars(int num) {
+ if (num == 0)
+ return 1;
+ return (num < 0 ? 1 : 0) + static_cast<int>(log10(abs(num))) + 1;
+}
+
+/// Helper struct that holds symbol, disassembly and address information of an
+/// instruction.
+struct InstructionSymbolInfo {
+ SymbolContext sc;
+ Address address;
+ lldb::addr_t load_address;
+ lldb::DisassemblerSP disassembler;
+ lldb::InstructionSP instruction;
+ lldb_private::ExecutionContext exe_ctx;
+};
+
+// This custom LineEntry validator is neded because some line_entries have
+// 0 as line, which is meaningless. Notice that LineEntry::IsValid only
+// checks that line is not LLDB_INVALID_LINE_NUMBER, i.e. UINT32_MAX.
+static bool IsLineEntryValid(const LineEntry &line_entry) {
+ return line_entry.IsValid() && line_entry.line > 0;
+}
+
+/// \return
+/// \b true if the provided line entries match line, column and source file.
+/// This function assumes that the line entries are valid.
+static bool FileLineAndColumnMatches(const LineEntry &a, const LineEntry &b) {
+ if (a.line != b.line)
+ return false;
+ if (a.column != b.column)
+ return false;
+ return a.file == b.file;
+}
+
+/// Compare the symbol contexts of the provided \a InstructionSymbolInfo
+/// objects.
+///
+/// \return
+/// \a true if both instructions belong to the same scope level analized
+/// in the following order:
+/// - module
+/// - symbol
+/// - function
+/// - line
+static bool
+IsSameInstructionSymbolContext(const InstructionSymbolInfo &prev_insn,
+ const InstructionSymbolInfo &insn) {
+ // module checks
+ if (insn.sc.module_sp != prev_insn.sc.module_sp)
+ return false;
+
+ // symbol checks
+ if (insn.sc.symbol != prev_insn.sc.symbol)
+ return false;
+
+ // function checks
+ if (!insn.sc.function && !prev_insn.sc.function)
+ return true;
+ else if (insn.sc.function != prev_insn.sc.function)
+ return false;
+
+ // line entry checks
+ const bool curr_line_valid = IsLineEntryValid(insn.sc.line_entry);
+ const bool prev_line_valid = IsLineEntryValid(prev_insn.sc.line_entry);
+ if (curr_line_valid && prev_line_valid)
+ return FileLineAndColumnMatches(insn.sc.line_entry,
+ prev_insn.sc.line_entry);
+ return curr_line_valid == prev_line_valid;
+}
+
+/// Dump the symbol context of the given instruction address if it's different
+/// from the symbol context of the previous instruction in the trace.
+///
+/// \param[in] prev_sc
+/// The symbol context of the previous instruction in the trace.
+///
+/// \param[in] address
+/// The address whose symbol information will be dumped.
+///
+/// \return
+/// The symbol context of the current address, which might differ from the
+/// previous one.
+static void
+DumpInstructionSymbolContext(Stream &s,
+ Optional<InstructionSymbolInfo> prev_insn,
+ InstructionSymbolInfo &insn) {
+ if (prev_insn && IsSameInstructionSymbolContext(*prev_insn, insn))
+ return;
+
+ s.Printf(" ");
+
+ if (!insn.sc.module_sp)
+ s.Printf("(none)");
+ else if (!insn.sc.function && !insn.sc.symbol)
+ s.Printf("%s`(none)",
+ insn.sc.module_sp->GetFileSpec().GetFilename().AsCString());
+ else
+ insn.sc.DumpStopContext(&s, insn.exe_ctx.GetTargetPtr(), insn.address,
+ /*show_fullpath=*/false,
+ /*show_module=*/true, /*show_inlined_frames=*/false,
+ /*show_function_arguments=*/true,
+ /*show_function_name=*/true);
+ s.Printf("\n");
+}
+
+static void DumpInstructionDisassembly(Stream &s, InstructionSymbolInfo &insn) {
+ if (!insn.instruction)
+ return;
+ s.Printf(" ");
+ insn.instruction->Dump(&s, /*show_address=*/false, /*show_bytes=*/false,
+ /*max_opcode_byte_size=*/0, &insn.exe_ctx, &insn.sc,
+ /*prev_sym_ctx=*/nullptr,
+ /*disassembly_addr_format=*/nullptr,
+ /*max_address_text_size=*/0);
+}
+
+void TraceInstructionDumper::SetNoMoreData() { m_no_more_data = true; }
+
+bool TraceInstructionDumper::HasMoreData() { return !m_no_more_data; }
+
+void TraceInstructionDumper::DumpInstructions(Stream &s, size_t count) {
+ ThreadSP thread_sp = m_cursor_up->GetExecutionContextRef().GetThreadSP();
+ if (!thread_sp) {
+ s.Printf("invalid thread");
+ return;
+ }
+
+ s.Printf("thread #%u: tid = %" PRIu64 "\n", thread_sp->GetIndexID(),
+ thread_sp->GetID());
+
+ int digits_count = GetNumberOfChars(
+ m_cursor_up->IsForwards() ? m_index + count - 1 : m_index - count + 1);
+ bool was_prev_instruction_an_error = false;
+
+ auto printMissingInstructionsMessage = [&]() {
+ s.Printf(" ...missing instructions\n");
+ };
+
+ auto printInstructionIndex = [&]() {
+ s.Printf(" [%*d] ", digits_count, m_index);
+
+ if (m_show_tsc) {
+ s.Printf("[tsc=");
+
+ if (Optional<uint64_t> timestamp = m_cursor_up->GetTimestampCounter())
+ s.Printf("0x%016" PRIx64, *timestamp);
+ else
+ s.Printf("unavailable");
+
+ s.Printf("] ");
+ }
+ };
+
+ InstructionSymbolInfo prev_insn_info;
+
+ Target &target = thread_sp->GetProcess()->GetTarget();
+ ExecutionContext exe_ctx;
+ target.CalculateExecutionContext(exe_ctx);
+ const ArchSpec &arch = target.GetArchitecture();
+
+ // Find the symbol context for the given address reusing the previous
+ // instruction's symbol context when possible.
+ auto calculateSymbolContext = [&](const Address &address) {
+ AddressRange range;
+ if (prev_insn_info.sc.GetAddressRange(eSymbolContextEverything, 0,
+ /*inline_block_range*/ false,
+ range) &&
+ range.Contains(address))
+ return prev_insn_info.sc;
+
+ SymbolContext sc;
+ address.CalculateSymbolContext(&sc, eSymbolContextEverything);
+ return sc;
+ };
+
+ // Find the disassembler for the given address reusing the previous
+ // instruction's disassembler when possible.
+ auto calculateDisass = [&](const Address &address, const SymbolContext &sc) {
+ if (prev_insn_info.disassembler) {
+ if (InstructionSP instruction =
+ prev_insn_info.disassembler->GetInstructionList()
+ .GetInstructionAtAddress(address))
+ return std::make_tuple(prev_insn_info.disassembler, instruction);
+ }
+
+ if (sc.function) {
+ if (DisassemblerSP disassembler =
+ sc.function->GetInstructions(exe_ctx, nullptr)) {
+ if (InstructionSP instruction =
+ disassembler->GetInstructionList().GetInstructionAtAddress(
+ address))
+ return std::make_tuple(disassembler, instruction);
+ }
+ }
+ // We fallback to a single instruction disassembler
+ AddressRange range(address, arch.GetMaximumOpcodeByteSize());
+ DisassemblerSP disassembler =
+ Disassembler::DisassembleRange(arch, /*plugin_name*/ nullptr,
+ /*flavor*/ nullptr, target, range);
+ return std::make_tuple(disassembler,
+ disassembler ? disassembler->GetInstructionList()
+ .GetInstructionAtAddress(address)
+ : InstructionSP());
+ };
+
+ for (size_t i = 0; i < count; i++) {
+ if (!HasMoreData()) {
+ s.Printf(" no more data\n");
+ break;
+ }
+
+ if (Error err = m_cursor_up->GetError()) {
+ if (!m_cursor_up->IsForwards() && !was_prev_instruction_an_error)
+ printMissingInstructionsMessage();
+
+ was_prev_instruction_an_error = true;
+
+ printInstructionIndex();
+ s << toString(std::move(err));
+ } else {
+ if (m_cursor_up->IsForwards() && was_prev_instruction_an_error)
+ printMissingInstructionsMessage();
+
+ was_prev_instruction_an_error = false;
+
+ InstructionSymbolInfo insn_info;
+
+ if (!m_raw) {
+ insn_info.load_address = m_cursor_up->GetLoadAddress();
+ insn_info.exe_ctx = exe_ctx;
+ insn_info.address.SetLoadAddress(insn_info.load_address, &target);
+ insn_info.sc = calculateSymbolContext(insn_info.address);
+ std::tie(insn_info.disassembler, insn_info.instruction) =
+ calculateDisass(insn_info.address, insn_info.sc);
+
+ DumpInstructionSymbolContext(s, prev_insn_info, insn_info);
+ }
+
+ printInstructionIndex();
+ s.Printf("0x%016" PRIx64, m_cursor_up->GetLoadAddress());
+
+ if (!m_raw)
+ DumpInstructionDisassembly(s, insn_info);
+
+ prev_insn_info = insn_info;
+ }
+
+ s.Printf("\n");
+ TryMoveOneStep();
+ }
+}
diff --git a/lldb/source/Target/UnwindLLDB.cpp b/lldb/source/Target/UnwindLLDB.cpp
index 980ad4d2e342..047147112f3b 100644
--- a/lldb/source/Target/UnwindLLDB.cpp
+++ b/lldb/source/Target/UnwindLLDB.cpp
@@ -420,6 +420,8 @@ bool UnwindLLDB::DoGetFrameInfoAtIndex(uint32_t idx, addr_t &cfa, addr_t &pc,
// too behaves like the zeroth frame (i.e. the pc might not
// be pointing just past a call in it)
behaves_like_zeroth_frame = true;
+ } else if (m_frames[idx]->reg_ctx_lldb_sp->BehavesLikeZerothFrame()) {
+ behaves_like_zeroth_frame = true;
} else {
behaves_like_zeroth_frame = false;
}
diff --git a/lldb/source/Utility/ArchSpec.cpp b/lldb/source/Utility/ArchSpec.cpp
index c13e2389cfed..74a437042345 100644
--- a/lldb/source/Utility/ArchSpec.cpp
+++ b/lldb/source/Utility/ArchSpec.cpp
@@ -291,8 +291,8 @@ static const ArchDefinitionEntry g_macho_arch_entries[] = {
{ArchSpec::eCore_arm_armv7m, llvm::MachO::CPU_TYPE_ARM, llvm::MachO::CPU_SUBTYPE_ARM_V7M, UINT32_MAX, SUBTYPE_MASK},
{ArchSpec::eCore_arm_armv7em, llvm::MachO::CPU_TYPE_ARM, llvm::MachO::CPU_SUBTYPE_ARM_V7EM, UINT32_MAX, SUBTYPE_MASK},
{ArchSpec::eCore_arm_arm64e, llvm::MachO::CPU_TYPE_ARM64, llvm::MachO::CPU_SUBTYPE_ARM64E, UINT32_MAX, SUBTYPE_MASK},
- {ArchSpec::eCore_arm_arm64, llvm::MachO::CPU_TYPE_ARM64, llvm::MachO::CPU_SUBTYPE_ARM64_V8, UINT32_MAX, SUBTYPE_MASK},
{ArchSpec::eCore_arm_arm64, llvm::MachO::CPU_TYPE_ARM64, llvm::MachO::CPU_SUBTYPE_ARM64_ALL, UINT32_MAX, SUBTYPE_MASK},
+ {ArchSpec::eCore_arm_arm64, llvm::MachO::CPU_TYPE_ARM64, llvm::MachO::CPU_SUBTYPE_ARM64_V8, UINT32_MAX, SUBTYPE_MASK},
{ArchSpec::eCore_arm_arm64, llvm::MachO::CPU_TYPE_ARM64, 13, UINT32_MAX, SUBTYPE_MASK},
{ArchSpec::eCore_arm_arm64_32, llvm::MachO::CPU_TYPE_ARM64_32, 0, UINT32_MAX, SUBTYPE_MASK},
{ArchSpec::eCore_arm_arm64_32, llvm::MachO::CPU_TYPE_ARM64_32, 1, UINT32_MAX, SUBTYPE_MASK},
@@ -464,7 +464,7 @@ static const ArchDefinition *FindArchDefinition(ArchitectureType arch_type) {
// Get an architecture definition by name.
static const CoreDefinition *FindCoreDefinition(llvm::StringRef name) {
for (unsigned int i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) {
- if (name.equals_lower(g_core_definitions[i].name))
+ if (name.equals_insensitive(g_core_definitions[i].name))
return &g_core_definitions[i];
}
return nullptr;
@@ -507,7 +507,7 @@ FindArchDefinitionEntry(const ArchDefinition *def, ArchSpec::Core core) {
//===----------------------------------------------------------------------===//
// Constructors and destructors.
-ArchSpec::ArchSpec() {}
+ArchSpec::ArchSpec() = default;
ArchSpec::ArchSpec(const char *triple_cstr) {
if (triple_cstr)
@@ -1118,18 +1118,6 @@ static bool cores_match(const ArchSpec::Core core1, const ArchSpec::Core core2,
return true;
break;
- case ArchSpec::eCore_arm_armv6m:
- if (!enforce_exact_match) {
- if (core2 == ArchSpec::eCore_arm_generic)
- return true;
- try_inverse = false;
- if (core2 == ArchSpec::eCore_arm_armv7)
- return true;
- if (core2 == ArchSpec::eCore_arm_armv6m)
- return true;
- }
- break;
-
case ArchSpec::kCore_hexagon_any:
if ((core2 >= ArchSpec::kCore_hexagon_first &&
core2 <= ArchSpec::kCore_hexagon_last) ||
@@ -1138,8 +1126,9 @@ static bool cores_match(const ArchSpec::Core core1, const ArchSpec::Core core2,
break;
// v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization
- // Cortex-M0 - ARMv6-M - armv6m Cortex-M3 - ARMv7-M - armv7m Cortex-M4 -
- // ARMv7E-M - armv7em
+ // Cortex-M0 - ARMv6-M - armv6m
+ // Cortex-M3 - ARMv7-M - armv7m
+ // Cortex-M4 - ARMv7E-M - armv7em
case ArchSpec::eCore_arm_armv7em:
if (!enforce_exact_match) {
if (core2 == ArchSpec::eCore_arm_generic)
@@ -1155,8 +1144,9 @@ static bool cores_match(const ArchSpec::Core core1, const ArchSpec::Core core2,
break;
// v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization
- // Cortex-M0 - ARMv6-M - armv6m Cortex-M3 - ARMv7-M - armv7m Cortex-M4 -
- // ARMv7E-M - armv7em
+ // Cortex-M0 - ARMv6-M - armv6m
+ // Cortex-M3 - ARMv7-M - armv7m
+ // Cortex-M4 - ARMv7E-M - armv7em
case ArchSpec::eCore_arm_armv7m:
if (!enforce_exact_match) {
if (core2 == ArchSpec::eCore_arm_generic)
@@ -1171,6 +1161,24 @@ static bool cores_match(const ArchSpec::Core core1, const ArchSpec::Core core2,
}
break;
+ // v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization
+ // Cortex-M0 - ARMv6-M - armv6m
+ // Cortex-M3 - ARMv7-M - armv7m
+ // Cortex-M4 - ARMv7E-M - armv7em
+ case ArchSpec::eCore_arm_armv6m:
+ if (!enforce_exact_match) {
+ if (core2 == ArchSpec::eCore_arm_generic)
+ return true;
+ if (core2 == ArchSpec::eCore_arm_armv7em)
+ return true;
+ if (core2 == ArchSpec::eCore_arm_armv7)
+ return true;
+ if (core2 == ArchSpec::eCore_arm_armv6m)
+ return true;
+ try_inverse = false;
+ }
+ break;
+
case ArchSpec::eCore_arm_armv7f:
case ArchSpec::eCore_arm_armv7k:
case ArchSpec::eCore_arm_armv7s:
diff --git a/lldb/source/Utility/Args.cpp b/lldb/source/Utility/Args.cpp
index ed61e1c16303..0334659ab7dd 100644
--- a/lldb/source/Utility/Args.cpp
+++ b/lldb/source/Utility/Args.cpp
@@ -194,7 +194,7 @@ Args &Args::operator=(const Args &rhs) {
}
// Destructor
-Args::~Args() {}
+Args::~Args() = default;
void Args::Dump(Stream &s, const char *label_name) const {
if (!label_name)
@@ -256,8 +256,6 @@ void Args::SetCommandString(llvm::StringRef command) {
m_argv.push_back(nullptr);
}
-size_t Args::GetArgumentCount() const { return m_entries.size(); }
-
const char *Args::GetArgumentAtIndex(size_t idx) const {
if (idx < m_argv.size())
return m_argv[idx];
@@ -388,6 +386,7 @@ std::string Args::GetShellSafeArgument(const FileSpec &shell,
static ShellDescriptor g_Shells[] = {{ConstString("bash"), " '\"<>()&"},
{ConstString("tcsh"), " '\"<>()&$"},
+ {ConstString("zsh"), " '\"<>()&;\\|"},
{ConstString("sh"), " '\"<>()&"}};
// safe minimal set
diff --git a/lldb/source/Utility/Broadcaster.cpp b/lldb/source/Utility/Broadcaster.cpp
index 342548c0b0e6..6e0672496321 100644
--- a/lldb/source/Utility/Broadcaster.cpp
+++ b/lldb/source/Utility/Broadcaster.cpp
@@ -19,8 +19,8 @@
#include <memory>
#include <utility>
-#include <assert.h>
-#include <stddef.h>
+#include <cassert>
+#include <cstddef>
using namespace lldb;
using namespace lldb_private;
diff --git a/lldb/source/Utility/ConstString.cpp b/lldb/source/Utility/ConstString.cpp
index 11f48d0fcaba..e5e1b2387e64 100644
--- a/lldb/source/Utility/ConstString.cpp
+++ b/lldb/source/Utility/ConstString.cpp
@@ -21,9 +21,9 @@
#include <array>
#include <utility>
-#include <inttypes.h>
-#include <stdint.h>
-#include <string.h>
+#include <cinttypes>
+#include <cstdint>
+#include <cstring>
using namespace lldb_private;
@@ -253,7 +253,7 @@ bool ConstString::Equals(ConstString lhs, ConstString rhs,
// perform case insensitive equality test
llvm::StringRef lhs_string_ref(lhs.GetStringRef());
llvm::StringRef rhs_string_ref(rhs.GetStringRef());
- return lhs_string_ref.equals_lower(rhs_string_ref);
+ return lhs_string_ref.equals_insensitive(rhs_string_ref);
}
int ConstString::Compare(ConstString lhs, ConstString rhs,
@@ -270,7 +270,7 @@ int ConstString::Compare(ConstString lhs, ConstString rhs,
if (case_sensitive) {
return lhs_string_ref.compare(rhs_string_ref);
} else {
- return lhs_string_ref.compare_lower(rhs_string_ref);
+ return lhs_string_ref.compare_insensitive(rhs_string_ref);
}
}
diff --git a/lldb/source/Utility/DataBufferLLVM.cpp b/lldb/source/Utility/DataBufferLLVM.cpp
index 235123a31cee..c5aeddd683f4 100644
--- a/lldb/source/Utility/DataBufferLLVM.cpp
+++ b/lldb/source/Utility/DataBufferLLVM.cpp
@@ -10,7 +10,7 @@
#include "llvm/Support/MemoryBuffer.h"
-#include <assert.h>
+#include <cassert>
using namespace lldb_private;
@@ -21,7 +21,7 @@ DataBufferLLVM::DataBufferLLVM(
"Cannot construct a DataBufferLLVM with a null buffer");
}
-DataBufferLLVM::~DataBufferLLVM() {}
+DataBufferLLVM::~DataBufferLLVM() = default;
uint8_t *DataBufferLLVM::GetBytes() {
return reinterpret_cast<uint8_t *>(Buffer->getBufferStart());
diff --git a/lldb/source/Utility/DataEncoder.cpp b/lldb/source/Utility/DataEncoder.cpp
index 7532ac1fdcaf..e88cd23c1d84 100644
--- a/lldb/source/Utility/DataEncoder.cpp
+++ b/lldb/source/Utility/DataEncoder.cpp
@@ -16,7 +16,7 @@
#include <cstddef>
-#include <string.h>
+#include <cstring>
using namespace lldb;
using namespace lldb_private;
@@ -24,8 +24,7 @@ using namespace llvm::support::endian;
// Default constructor.
DataEncoder::DataEncoder()
- : m_start(nullptr), m_end(nullptr),
- m_byte_order(endian::InlHostByteOrder()), m_addr_size(sizeof(void *)),
+ : m_byte_order(endian::InlHostByteOrder()), m_addr_size(sizeof(void *)),
m_data_sp() {}
// This constructor allows us to use data that is owned by someone else. The
diff --git a/lldb/source/Utility/DataExtractor.cpp b/lldb/source/Utility/DataExtractor.cpp
index 64b878d7dee7..bdd79fd9b411 100644
--- a/lldb/source/Utility/DataExtractor.cpp
+++ b/lldb/source/Utility/DataExtractor.cpp
@@ -33,9 +33,9 @@
#include <cstdint>
#include <string>
-#include <ctype.h>
-#include <inttypes.h>
-#include <string.h>
+#include <cctype>
+#include <cinttypes>
+#include <cstring>
using namespace lldb;
using namespace lldb_private;
@@ -120,9 +120,8 @@ static inline uint64_t ReadMaxInt64(const uint8_t *data, size_t byte_size,
}
DataExtractor::DataExtractor()
- : m_start(nullptr), m_end(nullptr),
- m_byte_order(endian::InlHostByteOrder()), m_addr_size(sizeof(void *)),
- m_data_sp(), m_target_byte_size(1) {}
+ : m_byte_order(endian::InlHostByteOrder()), m_addr_size(sizeof(void *)),
+ m_data_sp() {}
// This constructor allows us to use data that is owned by someone else. The
// data must stay around as long as this object is valid.
diff --git a/lldb/source/Utility/Event.cpp b/lldb/source/Utility/Event.cpp
index 50cc7f061dc6..4c07293c92df 100644
--- a/lldb/source/Utility/Event.cpp
+++ b/lldb/source/Utility/Event.cpp
@@ -17,7 +17,7 @@
#include <algorithm>
-#include <ctype.h>
+#include <cctype>
using namespace lldb;
using namespace lldb_private;
@@ -198,7 +198,7 @@ EventDataStructuredData::EventDataStructuredData(
: EventData(), m_process_sp(process_sp), m_object_sp(object_sp),
m_plugin_sp(plugin_sp) {}
-EventDataStructuredData::~EventDataStructuredData() {}
+EventDataStructuredData::~EventDataStructuredData() = default;
// EventDataStructuredData member functions
diff --git a/lldb/source/Utility/FileSpec.cpp b/lldb/source/Utility/FileSpec.cpp
index 1ec5d60e2780..bea3c6d6268b 100644
--- a/lldb/source/Utility/FileSpec.cpp
+++ b/lldb/source/Utility/FileSpec.cpp
@@ -24,10 +24,10 @@
#include <system_error>
#include <vector>
-#include <assert.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
+#include <cassert>
+#include <climits>
+#include <cstdio>
+#include <cstring>
using namespace lldb;
using namespace lldb_private;
@@ -499,9 +499,9 @@ void FileSpec::MakeAbsolute(const FileSpec &dir) {
void llvm::format_provider<FileSpec>::format(const FileSpec &F,
raw_ostream &Stream,
StringRef Style) {
- assert(
- (Style.empty() || Style.equals_lower("F") || Style.equals_lower("D")) &&
- "Invalid FileSpec style!");
+ assert((Style.empty() || Style.equals_insensitive("F") ||
+ Style.equals_insensitive("D")) &&
+ "Invalid FileSpec style!");
StringRef dir = F.GetDirectory().GetStringRef();
StringRef file = F.GetFilename().GetStringRef();
@@ -511,7 +511,7 @@ void llvm::format_provider<FileSpec>::format(const FileSpec &F,
return;
}
- if (Style.equals_lower("F")) {
+ if (Style.equals_insensitive("F")) {
Stream << (file.empty() ? "(empty)" : file);
return;
}
@@ -527,7 +527,7 @@ void llvm::format_provider<FileSpec>::format(const FileSpec &F,
Stream << GetPreferredPathSeparator(F.GetPathStyle());
}
- if (Style.equals_lower("D")) {
+ if (Style.equals_insensitive("D")) {
// We only want to print the directory, so now just exit.
if (dir.empty())
Stream << "(empty)";
diff --git a/lldb/source/Utility/GDBRemote.cpp b/lldb/source/Utility/GDBRemote.cpp
index f267d00fc97e..91f94de4dc0d 100644
--- a/lldb/source/Utility/GDBRemote.cpp
+++ b/lldb/source/Utility/GDBRemote.cpp
@@ -11,7 +11,7 @@
#include "lldb/Utility/Flags.h"
#include "lldb/Utility/Stream.h"
-#include <stdio.h>
+#include <cstdio>
using namespace lldb;
using namespace lldb_private::repro;
@@ -24,7 +24,7 @@ StreamGDBRemote::StreamGDBRemote(uint32_t flags, uint32_t addr_size,
ByteOrder byte_order)
: StreamString(flags, addr_size, byte_order) {}
-StreamGDBRemote::~StreamGDBRemote() {}
+StreamGDBRemote::~StreamGDBRemote() = default;
int StreamGDBRemote::PutEscapedBytes(const void *s, size_t src_len) {
int bytes_written = 0;
@@ -104,7 +104,7 @@ void GDBRemoteProvider::Keep() {
FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file);
std::error_code ec;
- llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text);
+ llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_TextWithCRLF);
if (ec)
return;
yaml::Output yout(os);
@@ -150,8 +150,8 @@ 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);
+ m_stream_up = std::make_unique<raw_fd_ostream>(
+ history_file.GetPath(), EC, sys::fs::OpenFlags::OF_TextWithCRLF);
return m_stream_up.get();
}
diff --git a/lldb/source/Utility/LLDBAssert.cpp b/lldb/source/Utility/LLDBAssert.cpp
index 6ae0ee50ef14..a8d8ef65a945 100644
--- a/lldb/source/Utility/LLDBAssert.cpp
+++ b/lldb/source/Utility/LLDBAssert.cpp
@@ -7,11 +7,15 @@
//===----------------------------------------------------------------------===//
#include "lldb/Utility/LLDBAssert.h"
-
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
+#if LLVM_SUPPORT_XCODE_SIGNPOSTS
+#include <os/log.h>
+#endif
+
using namespace llvm;
using namespace lldb_private;
@@ -24,6 +28,14 @@ void lldb_private::lldb_assert(bool expression, const char *expr_text,
// If asserts are enabled abort here.
assert(false && "lldb_assert failed");
+#if LLVM_SUPPORT_XCODE_SIGNPOSTS
+ if (__builtin_available(macos 10.12, iOS 10, tvOS 10, watchOS 3, *)) {
+ os_log_fault(OS_LOG_DEFAULT,
+ "Assertion failed: (%s), function %s, file %s, line %u\n",
+ expr_text, func, file, line);
+ }
+#endif
+
// 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.
diff --git a/lldb/source/Utility/Log.cpp b/lldb/source/Utility/Log.cpp
index 4df82f2bf4d7..ff654ec93e78 100644
--- a/lldb/source/Utility/Log.cpp
+++ b/lldb/source/Utility/Log.cpp
@@ -25,7 +25,7 @@
#include <mutex>
#include <utility>
-#include <assert.h>
+#include <cassert>
#if defined(_WIN32)
#include <process.h>
#else
@@ -60,17 +60,18 @@ uint32_t Log::GetFlags(llvm::raw_ostream &stream, const ChannelMap::value_type &
bool list_categories = false;
uint32_t flags = 0;
for (const char *category : categories) {
- if (llvm::StringRef("all").equals_lower(category)) {
+ if (llvm::StringRef("all").equals_insensitive(category)) {
flags |= UINT32_MAX;
continue;
}
- if (llvm::StringRef("default").equals_lower(category)) {
+ if (llvm::StringRef("default").equals_insensitive(category)) {
flags |= entry.second.m_channel.default_flags;
continue;
}
- auto cat = llvm::find_if(
- entry.second.m_channel.categories,
- [&](const Log::Category &c) { return c.name.equals_lower(category); });
+ auto cat = llvm::find_if(entry.second.m_channel.categories,
+ [&](const Log::Category &c) {
+ return c.name.equals_insensitive(category);
+ });
if (cat != entry.second.m_channel.categories.end()) {
flags |= cat->flag;
continue;
diff --git a/lldb/source/Utility/Logging.cpp b/lldb/source/Utility/Logging.cpp
index 435017e9d744..4648bec502c5 100644
--- a/lldb/source/Utility/Logging.cpp
+++ b/lldb/source/Utility/Logging.cpp
@@ -11,7 +11,7 @@
#include "llvm/ADT/ArrayRef.h"
-#include <stdarg.h>
+#include <cstdarg>
using namespace lldb_private;
diff --git a/lldb/source/Utility/ProcessInfo.cpp b/lldb/source/Utility/ProcessInfo.cpp
index 310d2b22b174..c9759bbe513e 100644
--- a/lldb/source/Utility/ProcessInfo.cpp
+++ b/lldb/source/Utility/ProcessInfo.cpp
@@ -22,8 +22,7 @@ using namespace lldb_private;
using namespace lldb_private::repro;
ProcessInfo::ProcessInfo()
- : m_executable(), m_arguments(), m_environment(), m_uid(UINT32_MAX),
- m_gid(UINT32_MAX), m_arch(), m_pid(LLDB_INVALID_PROCESS_ID) {}
+ : m_executable(), m_arguments(), m_environment(), m_arch() {}
ProcessInfo::ProcessInfo(const char *name, const ArchSpec &arch,
lldb::pid_t pid)
diff --git a/lldb/source/Utility/RegisterValue.cpp b/lldb/source/Utility/RegisterValue.cpp
index 7848f784d8f2..a298c70d370b 100644
--- a/lldb/source/Utility/RegisterValue.cpp
+++ b/lldb/source/Utility/RegisterValue.cpp
@@ -24,9 +24,9 @@
#include <tuple>
#include <vector>
-#include <assert.h>
-#include <inttypes.h>
-#include <stdio.h>
+#include <cassert>
+#include <cinttypes>
+#include <cstdio>
using namespace lldb;
using namespace lldb_private;
diff --git a/lldb/source/Utility/Reproducer.cpp b/lldb/source/Utility/Reproducer.cpp
index f302cce4436f..b63863c535fa 100644
--- a/lldb/source/Utility/Reproducer.cpp
+++ b/lldb/source/Utility/Reproducer.cpp
@@ -20,15 +20,6 @@ using namespace lldb_private::repro;
using namespace llvm;
using namespace llvm::yaml;
-static llvm::Optional<bool> GetEnv(const char *var) {
- std::string val = llvm::StringRef(getenv(var)).lower();
- if (val == "0" || val == "off")
- return false;
- if (val == "1" || val == "on")
- return true;
- return {};
-}
-
Reproducer &Reproducer::Instance() { return *InstanceImpl(); }
llvm::Error Reproducer::Initialize(ReproducerMode mode,
@@ -36,16 +27,6 @@ llvm::Error Reproducer::Initialize(ReproducerMode mode,
lldbassert(!InstanceImpl() && "Already initialized.");
InstanceImpl().emplace();
- // The environment can override the capture mode.
- if (mode != ReproducerMode::Replay) {
- if (llvm::Optional<bool> override = GetEnv("LLDB_CAPTURE_REPRODUCER")) {
- if (*override)
- mode = ReproducerMode::Capture;
- else
- mode = ReproducerMode::Off;
- }
- }
-
switch (mode) {
case ReproducerMode::Capture: {
if (!root) {
@@ -374,7 +355,7 @@ static llvm::Error addPaths(StringRef path,
SmallVector<StringRef, 0> paths;
(*buffer)->getBuffer().split(paths, '\0');
for (StringRef p : paths) {
- if (!p.empty())
+ if (!p.empty() && llvm::sys::fs::exists(p))
callback(p);
}
diff --git a/lldb/source/Utility/ReproducerInstrumentation.cpp b/lldb/source/Utility/ReproducerInstrumentation.cpp
index b274a10c98fd..e5bd2ba4b625 100644
--- a/lldb/source/Utility/ReproducerInstrumentation.cpp
+++ b/lldb/source/Utility/ReproducerInstrumentation.cpp
@@ -8,9 +8,9 @@
#include "lldb/Utility/ReproducerInstrumentation.h"
#include "lldb/Utility/Reproducer.h"
+#include <cstdio>
+#include <cstdlib>
#include <limits>
-#include <stdio.h>
-#include <stdlib.h>
#include <thread>
using namespace lldb_private;
@@ -193,8 +193,8 @@ unsigned ObjectToIndex::GetIndexForObjectImpl(const void *object) {
}
Recorder::Recorder()
- : m_serializer(nullptr), m_pretty_func(), m_pretty_args(),
- m_local_boundary(false), m_result_recorded(true),
+ : m_pretty_func(), m_pretty_args(),
+
m_sequence(std::numeric_limits<unsigned>::max()) {
if (!g_global_boundary) {
g_global_boundary = true;
diff --git a/lldb/source/Utility/ReproducerProvider.cpp b/lldb/source/Utility/ReproducerProvider.cpp
index ed016820db21..5145819b717c 100644
--- a/lldb/source/Utility/ReproducerProvider.cpp
+++ b/lldb/source/Utility/ReproducerProvider.cpp
@@ -39,7 +39,7 @@ YamlRecorder::Create(const FileSpec &filename) {
void VersionProvider::Keep() {
FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file);
std::error_code ec;
- llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text);
+ llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_TextWithCRLF);
if (ec)
return;
os << m_version << "\n";
@@ -108,7 +108,7 @@ void ProcessInfoProvider::Keep() {
FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file);
std::error_code ec;
- llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text);
+ llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_TextWithCRLF);
if (ec)
return;
llvm::yaml::Output yout(os);
@@ -153,7 +153,7 @@ void SymbolFileProvider::AddSymbolFile(const UUID *uuid,
void SymbolFileProvider::Keep() {
FileSpec file = this->GetRoot().CopyByAppendingPathComponent(Info::file);
std::error_code ec;
- llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text);
+ llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_TextWithCRLF);
if (ec)
return;
diff --git a/lldb/source/Utility/Scalar.cpp b/lldb/source/Utility/Scalar.cpp
index 9bf633d0c4e0..e0b26e89f3c1 100644
--- a/lldb/source/Utility/Scalar.cpp
+++ b/lldb/source/Utility/Scalar.cpp
@@ -160,7 +160,7 @@ void Scalar::GetValue(Stream *s, bool show_type) const {
case e_void:
break;
case e_int:
- s->PutCString(m_integer.toString(10));
+ s->PutCString(llvm::toString(m_integer, 10));
break;
case e_float:
llvm::SmallString<24> string;
diff --git a/lldb/source/Utility/SelectHelper.cpp b/lldb/source/Utility/SelectHelper.cpp
index 40c85bee6072..059f810e2194 100644
--- a/lldb/source/Utility/SelectHelper.cpp
+++ b/lldb/source/Utility/SelectHelper.cpp
@@ -25,7 +25,7 @@
#include <algorithm>
#include <chrono>
-#include <errno.h>
+#include <cerrno>
#if defined(_WIN32)
// Define NOMINMAX to avoid macros that conflict with std::min and std::max
#define NOMINMAX
diff --git a/lldb/source/Utility/Status.cpp b/lldb/source/Utility/Status.cpp
index e3c4284a8e8a..72fd087decc0 100644
--- a/lldb/source/Utility/Status.cpp
+++ b/lldb/source/Utility/Status.cpp
@@ -28,7 +28,7 @@
#ifdef _WIN32
#include <windows.h>
#endif
-#include <stdint.h>
+#include <cstdint>
namespace llvm {
class raw_ostream;
@@ -37,7 +37,7 @@ class raw_ostream;
using namespace lldb;
using namespace lldb_private;
-Status::Status() : m_code(0), m_type(eErrorTypeInvalid), m_string() {}
+Status::Status() : m_string() {}
Status::Status(ValueType err, ErrorType type)
: m_code(err), m_type(type), m_string() {}
diff --git a/lldb/source/Utility/Stream.cpp b/lldb/source/Utility/Stream.cpp
index a0623bfa6e54..a1e2de9da4d9 100644
--- a/lldb/source/Utility/Stream.cpp
+++ b/lldb/source/Utility/Stream.cpp
@@ -16,8 +16,8 @@
#include <string>
-#include <inttypes.h>
-#include <stddef.h>
+#include <cinttypes>
+#include <cstddef>
using namespace lldb;
using namespace lldb_private;
@@ -28,11 +28,11 @@ Stream::Stream(uint32_t flags, uint32_t addr_size, ByteOrder byte_order,
m_indent_level(0), m_forwarder(*this, colors) {}
Stream::Stream(bool colors)
- : m_flags(0), m_addr_size(4), m_byte_order(endian::InlHostByteOrder()),
- m_indent_level(0), m_forwarder(*this, colors) {}
+ : m_flags(0), m_byte_order(endian::InlHostByteOrder()),
+ m_forwarder(*this, colors) {}
// Destructor
-Stream::~Stream() {}
+Stream::~Stream() = default;
ByteOrder Stream::SetByteOrder(ByteOrder byte_order) {
ByteOrder old_byte_order = m_byte_order;
diff --git a/lldb/source/Utility/StreamString.cpp b/lldb/source/Utility/StreamString.cpp
index 190be588e887..745a85b75765 100644
--- a/lldb/source/Utility/StreamString.cpp
+++ b/lldb/source/Utility/StreamString.cpp
@@ -17,7 +17,7 @@ StreamString::StreamString(uint32_t flags, uint32_t addr_size,
ByteOrder byte_order)
: Stream(flags, addr_size, byte_order), m_packet() {}
-StreamString::~StreamString() {}
+StreamString::~StreamString() = default;
void StreamString::Flush() {
// Nothing to do when flushing a buffer based stream...
diff --git a/lldb/source/Utility/StringExtractor.cpp b/lldb/source/Utility/StringExtractor.cpp
index 0553a63a021e..d082c86f8463 100644
--- a/lldb/source/Utility/StringExtractor.cpp
+++ b/lldb/source/Utility/StringExtractor.cpp
@@ -11,9 +11,9 @@
#include <tuple>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
+#include <cctype>
+#include <cstdlib>
+#include <cstring>
static inline int xdigit_to_sint(char ch) {
if (ch >= 'a' && ch <= 'f')
@@ -26,7 +26,7 @@ static inline int xdigit_to_sint(char ch) {
}
// StringExtractor constructor
-StringExtractor::StringExtractor() : m_packet(), m_index(0) {}
+StringExtractor::StringExtractor() : m_packet() {}
StringExtractor::StringExtractor(llvm::StringRef packet_str)
: m_packet(), m_index(0) {
@@ -40,7 +40,7 @@ StringExtractor::StringExtractor(const char *packet_cstr)
}
// Destructor
-StringExtractor::~StringExtractor() {}
+StringExtractor::~StringExtractor() = default;
char StringExtractor::GetChar(char fail_value) {
if (m_index < m_packet.size()) {
diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp b/lldb/source/Utility/StringExtractorGDBRemote.cpp
index def096866426..29cf585bea56 100644
--- a/lldb/source/Utility/StringExtractorGDBRemote.cpp
+++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp
@@ -8,8 +8,11 @@
#include "lldb/Utility/StringExtractorGDBRemote.h"
-#include <ctype.h>
-#include <string.h>
+#include <cctype>
+#include <cstring>
+
+constexpr lldb::pid_t StringExtractorGDBRemote::AllProcesses;
+constexpr lldb::tid_t StringExtractorGDBRemote::AllThreads;
StringExtractorGDBRemote::ResponseType
StringExtractorGDBRemote::GetResponseType() const {
@@ -140,6 +143,11 @@ StringExtractorGDBRemote::GetServerPacketType() const {
return eServerPacketType_QListThreadsInStopReply;
break;
+ case 'M':
+ if (PACKET_STARTS_WITH("QMemTags"))
+ return eServerPacketType_QMemTags;
+ break;
+
case 'R':
if (PACKET_STARTS_WITH("QRestoreRegisterState:"))
return eServerPacketType_QRestoreRegisterState;
@@ -220,6 +228,8 @@ StringExtractorGDBRemote::GetServerPacketType() const {
return eServerPacketType_qMemoryRegionInfoSupported;
if (PACKET_STARTS_WITH("qModuleInfo:"))
return eServerPacketType_qModuleInfo;
+ if (PACKET_STARTS_WITH("qMemTags:"))
+ return eServerPacketType_qMemTags;
break;
case 'P':
@@ -300,18 +310,17 @@ StringExtractorGDBRemote::GetServerPacketType() const {
return eServerPacketType_jSignalsInfo;
if (PACKET_MATCHES("jThreadsInfo"))
return eServerPacketType_jThreadsInfo;
- if (PACKET_STARTS_WITH("jTraceBufferRead:"))
- return eServerPacketType_jTraceBufferRead;
- if (PACKET_STARTS_WITH("jTraceConfigRead:"))
- return eServerPacketType_jTraceConfigRead;
- if (PACKET_STARTS_WITH("jTraceMetaRead:"))
- return eServerPacketType_jTraceMetaRead;
- if (PACKET_STARTS_WITH("jTraceStart:"))
- return eServerPacketType_jTraceStart;
- if (PACKET_STARTS_WITH("jTraceStop:"))
- return eServerPacketType_jTraceStop;
- if (PACKET_MATCHES("jLLDBTraceSupportedType"))
- return eServerPacketType_jLLDBTraceSupportedType;
+
+ if (PACKET_MATCHES("jLLDBTraceSupported"))
+ return eServerPacketType_jLLDBTraceSupported;
+ if (PACKET_STARTS_WITH("jLLDBTraceStop:"))
+ return eServerPacketType_jLLDBTraceStop;
+ if (PACKET_STARTS_WITH("jLLDBTraceStart:"))
+ return eServerPacketType_jLLDBTraceStart;
+ if (PACKET_STARTS_WITH("jLLDBTraceGetState:"))
+ return eServerPacketType_jLLDBTraceGetState;
+ if (PACKET_STARTS_WITH("jLLDBTraceGetBinaryData:"))
+ return eServerPacketType_jLLDBTraceGetBinaryData;
break;
case 'v':
@@ -376,9 +385,7 @@ StringExtractorGDBRemote::GetServerPacketType() const {
return eServerPacketType_C;
case 'D':
- if (packet_size == 1)
- return eServerPacketType_D;
- break;
+ return eServerPacketType_D;
case 'g':
return eServerPacketType_g;
@@ -606,3 +613,46 @@ bool StringExtractorGDBRemote::ValidateResponse() const {
else
return true; // No validator, so response is valid
}
+
+llvm::Optional<std::pair<lldb::pid_t, lldb::tid_t>>
+StringExtractorGDBRemote::GetPidTid(lldb::pid_t default_pid) {
+ llvm::StringRef view = llvm::StringRef(m_packet).substr(m_index);
+ size_t initial_length = view.size();
+ lldb::pid_t pid = default_pid;
+ lldb::tid_t tid;
+
+ if (view.consume_front("p")) {
+ // process identifier
+ if (view.consume_front("-1")) {
+ // -1 is a special case
+ pid = AllProcesses;
+ } else if (view.consumeInteger(16, pid) || pid == 0) {
+ // not a valid hex integer OR unsupported pid 0
+ m_index = UINT64_MAX;
+ return llvm::None;
+ }
+
+ // "." must follow if we expect TID too; otherwise, we assume -1
+ if (!view.consume_front(".")) {
+ // update m_index
+ m_index += initial_length - view.size();
+
+ return {{pid, AllThreads}};
+ }
+ }
+
+ // thread identifier
+ if (view.consume_front("-1")) {
+ // -1 is a special case
+ tid = AllThreads;
+ } else if (view.consumeInteger(16, tid) || tid == 0 || pid == AllProcesses) {
+ // not a valid hex integer OR tid 0 OR pid -1 + a specific tid
+ m_index = UINT64_MAX;
+ return llvm::None;
+ }
+
+ // update m_index
+ m_index += initial_length - view.size();
+
+ return {{pid, tid}};
+}
diff --git a/lldb/source/Utility/StringLexer.cpp b/lldb/source/Utility/StringLexer.cpp
index 26185517e275..bda6e25ce7a3 100644
--- a/lldb/source/Utility/StringLexer.cpp
+++ b/lldb/source/Utility/StringLexer.cpp
@@ -9,7 +9,7 @@
#include "lldb/Utility/StringLexer.h"
#include <algorithm>
-#include <assert.h>
+#include <cassert>
#include <utility>
using namespace lldb_private;
diff --git a/lldb/source/Utility/StringList.cpp b/lldb/source/Utility/StringList.cpp
index d3896ca60ac9..baff34ae3a5e 100644
--- a/lldb/source/Utility/StringList.cpp
+++ b/lldb/source/Utility/StringList.cpp
@@ -14,8 +14,8 @@
#include "llvm/ADT/ArrayRef.h"
#include <algorithm>
-#include <stdint.h>
-#include <string.h>
+#include <cstdint>
+#include <cstring>
using namespace lldb_private;
@@ -33,7 +33,7 @@ StringList::StringList(const char **strv, int strc) : m_strings() {
}
}
-StringList::~StringList() {}
+StringList::~StringList() = default;
void StringList::AppendString(const char *str) {
if (str)
diff --git a/lldb/source/Utility/StructuredData.cpp b/lldb/source/Utility/StructuredData.cpp
index b349de7b0b78..fc10fa539e9e 100644
--- a/lldb/source/Utility/StructuredData.cpp
+++ b/lldb/source/Utility/StructuredData.cpp
@@ -11,8 +11,8 @@
#include "lldb/Utility/Status.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cerrno>
+#include <cinttypes>
#include <cstdlib>
-#include <inttypes.h>
using namespace lldb_private;
using namespace llvm;
diff --git a/lldb/source/Utility/TildeExpressionResolver.cpp b/lldb/source/Utility/TildeExpressionResolver.cpp
index 75d9c47e656d..6311ae062f1f 100644
--- a/lldb/source/Utility/TildeExpressionResolver.cpp
+++ b/lldb/source/Utility/TildeExpressionResolver.cpp
@@ -8,7 +8,7 @@
#include "lldb/Utility/TildeExpressionResolver.h"
-#include <assert.h>
+#include <cassert>
#include <system_error>
#include "llvm/ADT/STLExtras.h"
@@ -27,7 +27,7 @@ using namespace llvm;
namespace fs = llvm::sys::fs;
namespace path = llvm::sys::path;
-TildeExpressionResolver::~TildeExpressionResolver() {}
+TildeExpressionResolver::~TildeExpressionResolver() = default;
bool StandardTildeExpressionResolver::ResolveExact(
StringRef Expr, SmallVectorImpl<char> &Output) {
diff --git a/lldb/source/Utility/Timer.cpp b/lldb/source/Utility/Timer.cpp
index 7ead51069529..b59ce3b9f556 100644
--- a/lldb/source/Utility/Timer.cpp
+++ b/lldb/source/Utility/Timer.cpp
@@ -16,10 +16,10 @@
#include <utility>
#include <vector>
-#include <assert.h>
-#include <inttypes.h>
-#include <stdarg.h>
-#include <stdio.h>
+#include <cassert>
+#include <cinttypes>
+#include <cstdarg>
+#include <cstdio>
using namespace lldb_private;
@@ -33,6 +33,8 @@ static std::atomic<Timer::Category *> g_categories;
/// Allows llvm::Timer to emit signposts when supported.
static llvm::ManagedStatic<llvm::SignpostEmitter> Signposts;
+llvm::SignpostEmitter &lldb_private::GetSignposts() { return *Signposts; }
+
std::atomic<bool> Timer::g_quiet(true);
std::atomic<unsigned> Timer::g_display_depth(0);
static std::mutex &GetFileMutex() {
@@ -59,7 +61,6 @@ void Timer::SetQuiet(bool value) { g_quiet = value; }
Timer::Timer(Timer::Category &category, const char *format, ...)
: m_category(category), m_total_start(std::chrono::steady_clock::now()) {
- Signposts->startInterval(this, m_category.GetName());
TimerStack &stack = GetTimerStackForCurrentThread();
stack.push_back(this);
@@ -86,8 +87,6 @@ Timer::~Timer() {
auto total_dur = stop_time - m_total_start;
auto timer_dur = total_dur - m_child_duration;
- Signposts->endInterval(this, m_category.GetName());
-
TimerStack &stack = GetTimerStackForCurrentThread();
if (g_quiet && stack.size() <= g_display_depth) {
std::lock_guard<std::mutex> lock(GetFileMutex());
diff --git a/lldb/source/Utility/TraceGDBRemotePackets.cpp b/lldb/source/Utility/TraceGDBRemotePackets.cpp
new file mode 100644
index 000000000000..5c1326a5f353
--- /dev/null
+++ b/lldb/source/Utility/TraceGDBRemotePackets.cpp
@@ -0,0 +1,130 @@
+//===-- TraceGDBRemotePackets.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/Utility/TraceGDBRemotePackets.h"
+
+using namespace llvm;
+using namespace llvm::json;
+
+namespace lldb_private {
+/// jLLDBTraceSupported
+/// \{
+bool fromJSON(const json::Value &value, TraceSupportedResponse &packet,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("description", packet.description) &&
+ o.map("name", packet.name);
+}
+
+json::Value toJSON(const TraceSupportedResponse &packet) {
+ return json::Value(
+ Object{{"description", packet.description}, {"name", packet.name}});
+}
+/// \}
+
+/// jLLDBTraceStart
+/// \{
+bool TraceStartRequest::IsProcessTracing() const { return !(bool)tids; }
+
+bool fromJSON(const json::Value &value, TraceStartRequest &packet, Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("type", packet.type) && o.map("tids", packet.tids);
+}
+
+json::Value toJSON(const TraceStartRequest &packet) {
+ return json::Value(Object{{"tids", packet.tids}, {"type", packet.type}});
+}
+/// \}
+
+/// jLLDBTraceStop
+/// \{
+TraceStopRequest::TraceStopRequest(llvm::StringRef type,
+ const std::vector<lldb::tid_t> &tids_)
+ : type(type) {
+ tids.emplace();
+ for (lldb::tid_t tid : tids_)
+ tids->push_back(static_cast<int64_t>(tid));
+}
+
+bool TraceStopRequest::IsProcessTracing() const { return !(bool)tids; }
+
+bool fromJSON(const json::Value &value, TraceStopRequest &packet, Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("type", packet.type) && o.map("tids", packet.tids);
+}
+
+json::Value toJSON(const TraceStopRequest &packet) {
+ return json::Value(Object{{"type", packet.type}, {"tids", packet.tids}});
+}
+/// \}
+
+/// jLLDBTraceGetState
+/// \{
+bool fromJSON(const json::Value &value, TraceGetStateRequest &packet,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("type", packet.type);
+}
+
+json::Value toJSON(const TraceGetStateRequest &packet) {
+ return json::Value(Object{{"type", packet.type}});
+}
+
+bool fromJSON(const json::Value &value, TraceBinaryData &packet, Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("kind", packet.kind) && o.map("size", packet.size);
+}
+
+json::Value toJSON(const TraceBinaryData &packet) {
+ return json::Value(Object{{"kind", packet.kind}, {"size", packet.size}});
+}
+
+bool fromJSON(const json::Value &value, TraceThreadState &packet, Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("tid", packet.tid) &&
+ o.map("binaryData", packet.binaryData);
+}
+
+json::Value toJSON(const TraceThreadState &packet) {
+ return json::Value(
+ Object{{"tid", packet.tid}, {"binaryData", packet.binaryData}});
+}
+
+bool fromJSON(const json::Value &value, TraceGetStateResponse &packet,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("tracedThreads", packet.tracedThreads) &&
+ o.map("processBinaryData", packet.processBinaryData);
+}
+
+json::Value toJSON(const TraceGetStateResponse &packet) {
+ return json::Value(Object{{"tracedThreads", packet.tracedThreads},
+ {"processBinaryData", packet.processBinaryData}});
+}
+/// \}
+
+/// jLLDBTraceGetBinaryData
+/// \{
+json::Value toJSON(const TraceGetBinaryDataRequest &packet) {
+ return json::Value(Object{{"type", packet.type},
+ {"kind", packet.kind},
+ {"offset", packet.offset},
+ {"tid", packet.tid},
+ {"size", packet.size}});
+}
+
+bool fromJSON(const json::Value &value, TraceGetBinaryDataRequest &packet,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("type", packet.type) && o.map("kind", packet.kind) &&
+ o.map("tid", packet.tid) && o.map("offset", packet.offset) &&
+ o.map("size", packet.size);
+}
+/// \}
+
+} // namespace lldb_private
diff --git a/lldb/source/Utility/TraceIntelPTGDBRemotePackets.cpp b/lldb/source/Utility/TraceIntelPTGDBRemotePackets.cpp
new file mode 100644
index 000000000000..dbb93d8d1c5c
--- /dev/null
+++ b/lldb/source/Utility/TraceIntelPTGDBRemotePackets.cpp
@@ -0,0 +1,46 @@
+//===-- TraceIntelPTGDBRemotePackets.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/Utility/TraceIntelPTGDBRemotePackets.h"
+
+using namespace llvm;
+using namespace llvm::json;
+
+namespace lldb_private {
+
+bool fromJSON(const json::Value &value, TraceIntelPTStartRequest &packet,
+ Path path) {
+ ObjectMapper o(value, path);
+ if (!o || !fromJSON(value, (TraceStartRequest &)packet, path) ||
+ !o.map("enableTsc", packet.enableTsc) ||
+ !o.map("psbPeriod", packet.psbPeriod) ||
+ !o.map("threadBufferSize", packet.threadBufferSize) ||
+ !o.map("processBufferSizeLimit", packet.processBufferSizeLimit))
+ return false;
+ if (packet.tids && packet.processBufferSizeLimit) {
+ path.report("processBufferSizeLimit must be provided");
+ return false;
+ }
+ if (!packet.tids && !packet.processBufferSizeLimit) {
+ path.report("processBufferSizeLimit must not be provided");
+ return false;
+ }
+ return true;
+}
+
+json::Value toJSON(const TraceIntelPTStartRequest &packet) {
+ json::Value base = toJSON((const TraceStartRequest &)packet);
+ base.getAsObject()->try_emplace("threadBufferSize", packet.threadBufferSize);
+ base.getAsObject()->try_emplace("processBufferSizeLimit",
+ packet.processBufferSizeLimit);
+ base.getAsObject()->try_emplace("psbPeriod", packet.psbPeriod);
+ base.getAsObject()->try_emplace("enableTsc", packet.enableTsc);
+ return base;
+}
+
+} // namespace lldb_private
diff --git a/lldb/source/Utility/TraceOptions.cpp b/lldb/source/Utility/TraceOptions.cpp
deleted file mode 100644
index 292fb600e6ed..000000000000
--- a/lldb/source/Utility/TraceOptions.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-//===-- TraceOptions.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/Utility/TraceOptions.h"
-
-using namespace lldb_private;
-
-namespace llvm {
-namespace json {
-
-bool fromJSON(const Value &value, TraceTypeInfo &info, Path path) {
- ObjectMapper o(value, path);
- if (!o)
- return false;
- o.map("description", info.description);
- return o.map("name", info.name);
-}
-
-} // namespace json
-} // namespace llvm
diff --git a/lldb/source/Utility/UUID.cpp b/lldb/source/Utility/UUID.cpp
index 73088fb22db8..0adeb06e4c04 100644
--- a/lldb/source/Utility/UUID.cpp
+++ b/lldb/source/Utility/UUID.cpp
@@ -12,9 +12,9 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Format.h"
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
+#include <cctype>
+#include <cstdio>
+#include <cstring>
using namespace lldb_private;
diff --git a/lldb/source/Utility/UriParser.cpp b/lldb/source/Utility/UriParser.cpp
index 8169b0eee121..c6ed24985896 100644
--- a/lldb/source/Utility/UriParser.cpp
+++ b/lldb/source/Utility/UriParser.cpp
@@ -10,7 +10,7 @@
#include <string>
-#include <stdint.h>
+#include <cstdint>
#include <tuple>
using namespace lldb_private;
diff --git a/lldb/source/Utility/UserID.cpp b/lldb/source/Utility/UserID.cpp
index 8e0146b93498..5bae91a91288 100644
--- a/lldb/source/Utility/UserID.cpp
+++ b/lldb/source/Utility/UserID.cpp
@@ -9,7 +9,7 @@
#include "lldb/Utility/UserID.h"
#include "lldb/Utility/Stream.h"
-#include <inttypes.h>
+#include <cinttypes>
using namespace lldb;
using namespace lldb_private;
diff --git a/lldb/source/Utility/VASprintf.cpp b/lldb/source/Utility/VASprintf.cpp
index aea68dfff9f1..5d361edf06e6 100644
--- a/lldb/source/Utility/VASprintf.cpp
+++ b/lldb/source/Utility/VASprintf.cpp
@@ -12,9 +12,9 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include <assert.h>
-#include <stdarg.h>
-#include <stdio.h>
+#include <cassert>
+#include <cstdarg>
+#include <cstdio>
bool lldb_private::VASprintf(llvm::SmallVectorImpl<char> &buf, const char *fmt,
va_list args) {
diff --git a/lldb/source/Utility/VMRange.cpp b/lldb/source/Utility/VMRange.cpp
index 16c50d6e81b8..184531b4bb27 100644
--- a/lldb/source/Utility/VMRange.cpp
+++ b/lldb/source/Utility/VMRange.cpp
@@ -15,8 +15,8 @@
#include <iterator>
#include <vector>
-#include <stddef.h>
-#include <stdint.h>
+#include <cstddef>
+#include <cstdint>
using namespace lldb;
using namespace lldb_private;
diff --git a/lldb/source/lldb.cpp b/lldb/source/lldb.cpp
index 10fc2d7cf556..371902f6c1b5 100644
--- a/lldb/source/lldb.cpp
+++ b/lldb/source/lldb.cpp
@@ -6,14 +6,25 @@
//
//===----------------------------------------------------------------------===//
+#include "VCSVersion.inc"
#include "lldb/lldb-private.h"
+#include "clang/Basic/Version.h"
using namespace lldb;
using namespace lldb_private;
-#include "clang/Basic/Version.h"
+// LLDB_VERSION_STRING is set through a define so unlike the other defines
+// expanded with CMake, it lacks the double quotes.
+#define QUOTE(str) #str
+#define EXPAND_AND_QUOTE(str) QUOTE(str)
-#include "VCSVersion.inc"
+static const char *GetLLDBVersion() {
+#ifdef LLDB_VERSION_STRING
+ return EXPAND_AND_QUOTE(LLDB_VERSION_STRING);
+#else
+ return "lldb version " CLANG_VERSION_STRING;
+#endif
+}
static const char *GetLLDBRevision() {
#ifdef LLDB_REVISION
@@ -34,11 +45,10 @@ static const char *GetLLDBRepository() {
const char *lldb_private::GetVersion() {
static std::string g_version_str;
if (g_version_str.empty()) {
- g_version_str += "lldb version ";
- g_version_str += CLANG_VERSION_STRING;
-
+ const char *lldb_version = GetLLDBVersion();
const char *lldb_repo = GetLLDBRepository();
const char *lldb_rev = GetLLDBRevision();
+ g_version_str += lldb_version;
if (lldb_repo || lldb_rev) {
g_version_str += " (";
if (lldb_repo)